public virtual void DoUpdate(LFloat deltaTime, EntityAttri ownerAttri) { if (timer > counter * config.triggerInterval) { counter++; //trigger buff for (int i = 0; i < config.count; i++) { var at = config.Attris[i]; var type = (EEntityAttriType)System.Math.Abs(at.attriType); switch (type) { case EEntityAttriType.Hp: { ownerAttri.Hp += at.val + LMath.FloorToInt(at.percent * triggerAttri.Hp); break; } case EEntityAttriType.MaxHp: { ownerAttri.MaxHp += at.val + LMath.FloorToInt(at.percent * triggerAttri.Hp); break; } } } } }
public bool ContainsCircle(LVector2 circleCenter, LFloat radius) { var center = _bounds.center; var dx = LMath.Abs(circleCenter.x - center.x); var dy = LMath.Abs(circleCenter.y - center.y); if (dx > (_bounds.width / 2 + radius)) { return(false); } if (dy > (_bounds.height / 2 + radius)) { return(false); } if (dx <= (_bounds.width / 2)) { return(true); } if (dy <= (_bounds.height / 2)) { return(true); } var dsx = (dx - _bounds.width / 2); var dsy = (dy - _bounds.height / 2); var cornerDist = dsx * dsx + dsy * dsy; return(cornerDist <= (radius * radius)); }
public static ColliderPrefab CreateColliderPrefab(ColliderData data) { CBaseShape collider = null; if (LMath.Abs(data.deg - 45) < 1) { } //warning data.deg is unity deg //changed unity deg to ccw deg var collisionDeg = -data.deg + 90; if (data.radius > 0) { //circle collider = new CCircle(data.radius); } else { //obb collider = new COBB(data.size, collisionDeg); } collider.high = data.high; var colFab = new ColliderPrefab(); colFab.parts.Add(new ColliderPart() { transform = new CTransform2D(data.pos, data.y, data.deg), collider = collider }); return(colFab); }
public static LVector3 Transform(LVector3 point, LVector3 forward, LVector3 trans, LVector3 scale) { LVector3 up = LVector3.up; LVector3 vInt = Cross(LVector3.up, forward); return(LMath.Transform(ref point, ref vInt, ref up, ref forward, ref trans, ref scale)); }
public static LFloat Angle(LQuaternion a, LQuaternion b) { LQuaternion q = b * LQuaternion.Inverse(a); q.Normalize(); return(LMath.Acos(q.w)); }
public void DoAfterInit() { for (int i = 0; i < gridInfo.tileMaps.Length; i++) { var tilemap = gridInfo.tileMaps[i]; if (tilemap.isTagMap) { continue; } var tilemapMin = tilemap.min; var tilemapSize = tilemap.size; mapDataMin.x = LMath.Min(mapDataMin.x, tilemapMin.x); mapDataMin.y = LMath.Min(mapDataMin.y, tilemapMin.y); mapDataMax.x = LMath.Max(mapDataMax.y, tilemapMin.x + tilemapSize.x); mapDataMax.y = LMath.Max(mapDataMax.y, tilemapMin.y + tilemapSize.y); } mapDataSize = (mapDataMax - mapDataMin) + LVector2Int.one; mapDataIds = new ushort[mapDataSize.x, mapDataSize.y]; for (int x = 0; x < mapDataSize.x; x++) { for (int y = 0; y < mapDataSize.y; y++) { var pos = new Vector2Int(mapDataMin.x + x, mapDataMin.y + y); mapDataIds[x, y] = RawPos2TileId(pos, true); } } }
public LFloat GetMaxMoveDist(EDir dir, LVector2 fHeadPos, LVector2 fTargetHeadPos, LFloat borderSize) { var iTargetHeadPos = new LVector2Int(LMath.FloorToInt(fTargetHeadPos.x), LMath.FloorToInt(fTargetHeadPos.y)); var hasCollider = HasColliderWithBorder(dir, fTargetHeadPos, borderSize); var maxMoveDist = LFloat.MaxValue; if (hasCollider) { switch (dir) { case EDir.Up: maxMoveDist = iTargetHeadPos.y - fHeadPos.y; break; case EDir.Right: maxMoveDist = iTargetHeadPos.x - fHeadPos.x; break; case EDir.Down: maxMoveDist = fHeadPos.y - iTargetHeadPos.y - 1; break; case EDir.Left: maxMoveDist = fHeadPos.x - iTargetHeadPos.x - 1; break; } } return(maxMoveDist); }
/// <summary> /// /// </summary> /// <param name="o">射线起点</param> /// <param name="d">射线终点</param> /// <param name="min">矩形的左下角坐标</param> /// <param name="max">矩形的右上角坐标</param> /// <param name="tmin">返回距离</param> /// <returns></returns> public static bool TestRayAABB(LVector2 o, LVector2 d, LVector2 min, LVector2 max, out LFloat tmin) { tmin = LFloat.zero; LFloat tmax = LFloat.FLT_MAX; for (int i = 0; i < 2; i++) { if (LMath.Abs(d[i]) < LFloat.EPSILON) { if (o[i] < min[i] || o[i] > max[i]) { return(false); } } else { LFloat ood = LFloat.one / d[i]; LFloat t1 = (min[i] - o[i]) * ood; LFloat t2 = (max[i] - o[i]) * ood; if (t1 > t2) { var temp = t1; t1 = t2; t2 = temp; } tmin = LMath.Max(tmin, t1); tmax = LMath.Min(tmax, t2); if (tmin > tmax) { return(false); } } } return(true); }
/// <summary> /// 球形插值(无限制) /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="t"></param> /// <returns></returns> public static LQuaternion SlerpUnclamped(LQuaternion q1, LQuaternion q2, LFloat t) { LFloat dot = Dot(q1, q2); LQuaternion tmpQuat = new LQuaternion(); if (dot < 0) { dot = -dot; tmpQuat.Set(-q2.x, -q2.y, -q2.z, -q2.w); } else { tmpQuat = q2; } if (dot < 1) { LFloat angle = LMath.Acos(dot); LFloat sinadiv, sinat, sinaomt; sinadiv = 1 / LMath.Sin(angle); sinat = LMath.Sin(angle * t); sinaomt = LMath.Sin(angle * (1 - t)); tmpQuat.Set((q1.x * sinaomt + tmpQuat.x * sinat) * sinadiv, (q1.y * sinaomt + tmpQuat.y * sinat) * sinadiv, (q1.z * sinaomt + tmpQuat.z * sinat) * sinadiv, (q1.w * sinaomt + tmpQuat.w * sinat) * sinadiv); return(tmpQuat); } else { return(Lerp(q1, tmpQuat, t)); } }
private void UpdatePingVal(float deltaTime) { _pingTimer += deltaTime; if (_pingTimer > 0.5f) { _pingTimer = 0; DelayVal = (int)(_delays.Sum() / LMath.Max(_delays.Count, 1)); _delays.Clear(); PingVal = (int)(_pings.Sum() / LMath.Max(_pings.Count, 1)); _pings.Clear(); if (_minPing < _historyMinPing && _simulatorService._gameStartTimestampMs != -1) { _historyMinPing = _minPing; #if UNITY_EDITOR Debug.LogWarning( $"Recalc _gameStartTimestampMs {_simulatorService._gameStartTimestampMs} _guessServerStartTimestamp:{_guessServerStartTimestamp}"); #endif _simulatorService._gameStartTimestampMs = LMath.Min(_guessServerStartTimestamp, _simulatorService._gameStartTimestampMs); } _minPing = Int64.MaxValue; _maxPing = Int64.MinValue; } }
//http://geomalgorithms.com/ //https://stackoverflow.com/questions/1073336/circle-line-segment-collision-detection-algorithm public static bool TestRayCircle(LVector2 cPos, LFloat cR, LVector2 rB, LVector2 rDir, ref LFloat t) { var d = rDir; var f = rB - cPos; var a = LVector2.Dot(d, d); var b = 2 * LVector2.Dot(f, d); var c = LVector2.Dot(f, f) - cR * cR; var discriminant = b * b - 4 * a * c; if (discriminant < 0) { // no intersection return(false); } else { discriminant = LMath.Sqrt(discriminant); var t1 = (-b - discriminant) / (2 * a); var t2 = (-b + discriminant) / (2 * a); if (t1 >= 0) { t = t1; return(true); } if (t2 >= 0) { t = t2; return(true); } return(false); } }
public static bool TestAABBAABB(LVector2 posA, LFloat rA, LVector2 sizeA, LVector2 posB, LFloat rB, LVector2 sizeB) { var diff = posA - posB; var allRadius = rA + rB; //circle 判定 if (diff.sqrMagnitude > allRadius * allRadius) { return(false); } var absX = LMath.Abs(diff.x); var absY = LMath.Abs(diff.y); //AABB and AABB var allSize = sizeA + sizeB; if (absX > allSize.x) { return(false); } if (absY > allSize.y) { return(false); } return(true); }
public void Execute() { foreach (var entity in _moveRequest.GetEntities()) { var deltaTime = _gameStateService.DeltaTime; var mover = entity.move; var dir = entity.dir.value; var pos = entity.pos.value; var moveSpd = mover.moveSpd; //can move 判定 var dirVec = DirUtil.GetDirLVec(dir); var moveDist = (moveSpd * deltaTime); var fTargetHead = pos + (TankUtil.TANK_HALF_LEN + moveDist) * dirVec; var fPreviewHead = pos + (TankUtil.TANK_HALF_LEN + TankUtil.FORWARD_HEAD_DIST) * dirVec; LFloat maxMoveDist = moveSpd * deltaTime; var headPos = pos + (TankUtil.TANK_HALF_LEN) * dirVec; var dist = _gameCollisionService.GetMaxMoveDist(dir, headPos, fTargetHead); var dist2 = _gameCollisionService.GetMaxMoveDist(dir, headPos, fPreviewHead); maxMoveDist = LMath.Max(LFloat.zero, LMath.Min(maxMoveDist, dist, dist2)); var diffPos = maxMoveDist * dirVec; pos = pos + diffPos; entity.pos.value = pos; } }
public static void CheckBulletWithMap(LVector2Int iPos, GameEntity entity, IGameAudioService audioService, IMap2DService map2DService) { var unit = entity.unit; var bullet = entity.bullet; var id = map2DService.Pos2TileId(iPos, false); if (id != 0 && unit.health > 0) { //collide bullet with world if (id == TilemapUtil.TileID_Brick) { if (unit.camp == ECampType.Player) { audioService.PlayClipHitBrick(); } map2DService.ReplaceTile(iPos, id, 0); unit.health--; } else if (id == TilemapUtil.TileID_Iron) { if (!bullet.canDestoryIron) { if (unit.camp == ECampType.Player) { audioService.PlayClipHitIron(); } unit.health = 0; } else { if (unit.camp == ECampType.Player) { audioService.PlayClipDestroyIron(); } unit.health = LMath.Max(unit.health - 2, 0); map2DService.ReplaceTile(iPos, id, 0); } } else if (id == TilemapUtil.TileID_Grass) { if (bullet.canDestoryGrass) { if (unit.camp == ECampType.Player) { audioService.PlayClipDestroyGrass(); } unit.health -= 0; map2DService.ReplaceTile(iPos, id, 0); } } else if (id == TilemapUtil.TileID_Wall) { unit.health = 0; } } }
public void DoAfterInit() { for (int i = 0; i < this.gridInfo.tileMaps.Length; i++) { TileInfos tileInfos = this.gridInfo.tileMaps[i]; bool isTagMap = tileInfos.isTagMap; if (!isTagMap) { LVector2Int min = tileInfos.min; LVector2Int size = tileInfos.size; this.mapDataMin.x = LMath.Min(this.mapDataMin.x, min.x); this.mapDataMin.y = LMath.Min(this.mapDataMin.y, min.y); this.mapDataMax.x = LMath.Max(this.mapDataMax.y, min.x + size.x); this.mapDataMax.y = LMath.Max(this.mapDataMax.y, min.y + size.y); } } this.mapDataSize = this.mapDataMax - this.mapDataMin + LVector2Int.one; this.mapDataIds = new ushort[this.mapDataSize.x, this.mapDataSize.y]; for (int j = 0; j < this.mapDataSize.x; j++) { for (int k = 0; k < this.mapDataSize.y; k++) { LVector2Int pos = new LVector2Int(mapDataMin.x + j, mapDataMin.y + k); this.mapDataIds[j, k] = this.RawPos2TileId(pos, false); } } }
public static bool TestAABBOBB(LVector2 posA, LFloat rA, LVector2 sizeA, LVector2 posB, LFloat rB, LVector2 sizeB, LVector2 upB) { var diff = posA - posB; var allRadius = rA + rB; //circle 判定 if (diff.sqrMagnitude > allRadius * allRadius) { return(false); } var absUPX = LMath.Abs(upB.x); //abs(up dot aabb.right) var absUPY = LMath.Abs(upB.y); //abs(right dot aabb.right) { //轴 投影 AABBx var distX = absUPX * sizeB.y + absUPY * sizeB.x; if (LMath.Abs(diff.x) > distX + sizeA.x) { return(false); } //轴 投影 AABBy //absUPX is abs(right dot aabb.up) //absUPY is abs(up dot aabb.up) var distY = absUPY * sizeB.y + absUPX * sizeB.x; if (LMath.Abs(diff.y) > distY + sizeA.y) { return(false); } } { var right = new LVector2(upB.y, -upB.x); var diffPObbX = LVector2.Dot(diff, right); var diffPObbY = LVector2.Dot(diff, upB); //absUPX is abs(aabb.up dot right ) //absUPY is abs(aabb.right dot right) //轴 投影 OBBx var distX = absUPX * sizeA.y + absUPY * sizeA.x; if (LMath.Abs(diffPObbX) > distX + sizeB.x) { return(false); } //absUPX is abs(aabb.right dot up ) //absUPY is abs(aabb.up dot up) //轴 投影 OBBy var distY = absUPY * sizeA.y + absUPX * sizeA.x; if (LMath.Abs(diffPObbY) > distY + sizeB.y) { return(false); } } return(true); }
public OBB(LVector2 pos, LVector2 size, LVector2 up) { this.pos = pos; this.size = size; radius = size.magnitude; this.up = up; this.deg = LMath.Atan2(-up.x, up.y); }
public LFloat height; // 高 /** * 数据检测,客户端的顶点坐标和三角形数据有可能是重复的ç∂ * TODO 小三角形合并成大三角形或多边形;判断顶点是否在寻路层中,寻路层中的顶点不能作为路径点;两点所连线段是否穿过阻挡区,不穿过,直接获取坐标点 */ public void check(int scale) { amendmentSameVector(pathTriangles, pathVertices); scaleVector(pathVertices, scale); this.width = LMath.Abs(this.getEndX() - this.getStartX()); this.height = LMath.Abs(this.getEndZ() - this.getStartZ()); }
public static int3 floor(LVector3 vec) { return(new int3( LMath.FloorToInt(vec.x), LMath.FloorToInt(vec.y), LMath.FloorToInt(vec.z) )); }
public void DoUpdate(LFloat deltaTime) { if (!isEnable) { return; } if (!TestOnFloor(transform.Pos3)) { isSleep = false; } lastPos = transform.Pos3; lastDeg = transform.deg; if (!isSleep) { if (!isOnFloor) { Speed.y -= G * deltaTime; Speed.y = LMath.Max(MinYSpd, Speed.y); } var pos = transform.Pos3; pos += Speed * deltaTime; LFloat y = pos.y; //Test floor isOnFloor = TestOnFloor(transform.Pos3, ref y); if (isOnFloor && Speed.y <= 0) { Speed.y = LFloat.zero; } if (Speed.y <= 0) { pos.y = y; } //Test walls if (TestOnWall(ref pos)) { Speed.x = LFloat.zero; Speed.z = LFloat.zero; } if (isOnFloor) { var speedVal = Speed.magnitude - FloorFriction * deltaTime; speedVal = LMath.Max(speedVal, LFloat.zero); Speed = Speed.normalized * speedVal; if (speedVal < MinSleepSpeed) { isSleep = true; } } transform.Pos3 = pos; } }
public static LVector3 ToEulerAngles(LQuaternion rotation) { rotation.Normalize(); return(new LVector3( LMath.Atan2(2 * (rotation.w * rotation.z + rotation.x * rotation.y), 1 - 2 * (rotation.z * rotation.z + rotation.x * rotation.x)), LMath.Asin(2 * (rotation.w * rotation.x - rotation.y * rotation.z)), LMath.Atan2(2 * (rotation.w * rotation.y + rotation.z * rotation.x), 1 - 2 * (rotation.x * rotation.x + rotation.y * rotation.y)) )); }
public static LQuaternion AngleAxis(LFloat angle, LVector3 axis) { LFloat radian2 = angle * 0.5d * LMath.DegToRad; LFloat sina = LMath.Sin(radian2); LFloat cosa = LMath.Cos(radian2); axis = axis.normalized; return(new LQuaternion(sina * axis.x, sina * axis.y, sina * axis.z, cosa)); }
public void SetDeg(LFloat rdeg) { deg = rdeg; var rad = LMath.Deg2Rad * deg; var c = LMath.Cos(rad); var s = LMath.Sin(rad); up = new LVector2(-s, c); }
public static int Sqrt(int a) { if (a <= 0) { return(0); } return((int)LMath.Sqrt32((uint)a)); }
public static LVector3 normalizesafe(LVector3 x) { LFloat len = LMath.Dot(x, x); if (len > LFloat.EPSILON) { return(x * (LFloat.one / LMath.Sqrt(len))); } return(LVector3.zero); }
public static LVector3 Slerp(LVector3 from, LVector3 to, LFloat t) { t = LMath.Clamp(t, 0, 1); LFloat diff = Angle(from, to) * LMath.DegToRad; LFloat sind = LMath.Sin(diff); LFloat sintd = LMath.Sin(t * diff); LFloat sin1td = LMath.Sin((1 - t) * diff); return((sin1td / sind) * from + (sintd / sind) * to); }
internal void ApplyForceEffect(LFloat deltaTime) { bool sliding = mLinearVelocity.sqrMagnitude > 0; bool rotating = mAngularVelocity > 0; // linear velocity LVector2 va = mUserForce * mMassInverse; if (!mIsFixed) { va += LPhysicsStatic2D.LGravity * mGravityScale; } if (sliding && mLinearDrag > 0) { LFloat da = mLinearDrag * mMassInverse; LFloat minr = (mLinearVelocity / deltaTime).sqrMagnitude; if (da * da >= minr) { va = LVector2.zero; mLinearVelocity = LVector2.zero; } else { va -= da * mLinearVelocity.normalized; } } if (va != LVector2.zero) { mLinearVelocity += va * deltaTime; } // angular velocity LFloat ra = mUserTorque * mInertiaInverse; if (rotating && mAngularDrag > 0) { LFloat da = mAngularDrag * mInertiaInverse; LFloat minr = mAngularVelocity / deltaTime; if (da >= minr) { ra = 0; mAngularVelocity = 0; } else { ra -= da * LMath.Sign(ra); } } if (ra != 0) { mAngularVelocity += ra * deltaTime; } }
public LFloat Estimate(Triangle node, Triangle endNode) { LFloat dst2; LFloat minDst2 = LFloat.MaxValue; A_AB = (node.a).Add(node.b) * LFloat.half; A_AB = (node.b).Add(node.c) * LFloat.half; A_AB = (node.c).Add(node.a) * LFloat.half; B_AB = (endNode.a).Add(endNode.b) * LFloat.half; B_BC = (endNode.b).Add(endNode.c) * LFloat.half; B_CA = (endNode.c).Add(endNode.a) * LFloat.half; if ((dst2 = A_AB.dst2(B_AB)) < minDst2) { minDst2 = dst2; } if ((dst2 = A_AB.dst2(B_BC)) < minDst2) { minDst2 = dst2; } if ((dst2 = A_AB.dst2(B_CA)) < minDst2) { minDst2 = dst2; } if ((dst2 = A_BC.dst2(B_AB)) < minDst2) { minDst2 = dst2; } if ((dst2 = A_BC.dst2(B_BC)) < minDst2) { minDst2 = dst2; } if ((dst2 = A_BC.dst2(B_CA)) < minDst2) { minDst2 = dst2; } if ((dst2 = A_CA.dst2(B_AB)) < minDst2) { minDst2 = dst2; } if ((dst2 = A_CA.dst2(B_BC)) < minDst2) { minDst2 = dst2; } if ((dst2 = A_CA.dst2(B_CA)) < minDst2) { minDst2 = dst2; } return((LFloat)LMath.Sqrt(minDst2)); }
public static LFloat RoundIfNear(LFloat val, LFloat roundDist) { var roundVal = LMath.Round(val); var diff = LMath.Abs(val - roundVal); if (diff < roundDist) { return(roundVal); } return(val); }
void DrawCurve() { for (int i = 1; i <= _segmentNum; i++) { float t = i / ( float )_segmentNum; int nodeIndex = 0; Vector3 pixel = LMath.BezierCurve(controlPoints[nodeIndex].position, controlPoints[nodeIndex + 1].position, controlPoints[nodeIndex + 2].position, t); lineRenderer.positionCount = i; lineRenderer.SetPosition(i - 1, pixel); } }