static bool CollideCircles(CircleShape circleA, ref FSTransform firstTransform, CircleShape circleB, ref FSTransform secondTransform, out FSCollisionResult result) { result = new FSCollisionResult(); Collision.CollideCircles(ref _manifold, circleA, ref firstTransform, circleB, ref secondTransform); if (_manifold.PointCount > 0) { // this is essentically directly from ContactSolver.WorldManifold.Initialize. To avoid doing the extra math twice we duplicate this code // here because it doesnt return some values we need to calculate separation var pointA = MathUtils.Mul(ref firstTransform, _manifold.LocalPoint); var pointB = MathUtils.Mul(ref secondTransform, _manifold.Points[0].LocalPoint); result.Normal = pointA - pointB; Vector2Ext.Normalize(ref result.Normal); var cA = pointA - circleA.Radius * result.Normal; var cB = pointB + circleB.Radius * result.Normal; result.Point = 0.5f * (cA + cB); result.Point *= FSConvert.SimToDisplay; var separation = Vector2.Dot(pointA - pointB, result.Normal) - circleA.Radius - circleB.Radius; result.MinimumTranslationVector = result.Normal * Math.Abs(separation); #if DEBUG_FSCOLLISIONS Debug.drawPixel(result.point, 5, Color.Red, 0.2f); Debug.drawLine(result.point, result.point + result.normal * 20, Color.Yellow, 0.2f); #endif return(true); } return(false); }
/// <summary> /// builds the Polygon edge normals. These are lazily created and updated only by the edgeNormals getter /// </summary> void BuildEdgeNormals() { // for boxes we only require 2 edges since the other 2 are parallel var totalEdges = isBox ? 2 : Points.Length; if (_edgeNormals == null || _edgeNormals.Length != totalEdges) { _edgeNormals = new Vector2[totalEdges]; } Vector2 p2; for (var i = 0; i < totalEdges; i++) { var p1 = Points[i]; if (i + 1 >= Points.Length) { p2 = Points[0]; } else { p2 = Points[i + 1]; } var perp = Vector2Ext.Perpendicular(ref p1, ref p2); Vector2Ext.Normalize(ref perp); _edgeNormals[i] = perp; } return; }
/// <summary> /// iterates all the edges of the polygon and gets the closest point on any edge to point. Returns via out the squared distance /// to the closest point and the normal of the edge it is on. point should be in the space of the Polygon (point - poly.position) /// </summary> /// <returns>The closest point on polygon to point.</returns> /// <param name="point">Point.</param> /// <param name="distanceSquared">Distance squared.</param> /// <param name="edgeNormal">Edge normal.</param> public static Vector2 GetClosestPointOnPolygonToPoint(Vector2[] points, Vector2 point, out float distanceSquared, out Vector2 edgeNormal) { distanceSquared = float.MaxValue; edgeNormal = Vector2.Zero; var closestPoint = Vector2.Zero; float tempDistanceSquared; for (var i = 0; i < points.Length; i++) { var j = i + 1; if (j == points.Length) { j = 0; } var closest = ShapeCollisions.ClosestPointOnLine(points[i], points[j], point); Vector2.DistanceSquared(ref point, ref closest, out tempDistanceSquared); if (tempDistanceSquared < distanceSquared) { distanceSquared = tempDistanceSquared; closestPoint = closest; // get the normal of the line var line = points[j] - points[i]; edgeNormal.X = -line.Y; edgeNormal.Y = line.X; } } Vector2Ext.Normalize(ref edgeNormal); return(closestPoint); }
public override Vector2 getPosition() { // we need a position that's far enough away to be safe // calculate the vector from them to us, then make sure it's at least the approach distance // 1. get dir to me var dirToMe = Vector2Ext.Normalize(nt.Position - mind.state.me.body.pos); // 2. scale to minimum range, find resultant (away) var targetAway = approachRange * -dirToMe; return(targetAway); }
static bool CollideEdgeAndCircle(EdgeShape edge, ref FSTransform edgeTransform, CircleShape circle, ref FSTransform circleTransform, out FSCollisionResult result) { result = new FSCollisionResult(); Collision.CollideEdgeAndCircle(ref _manifold, edge, ref edgeTransform, circle, ref circleTransform); if (_manifold.PointCount > 0) { // code adapted from PositionSolverManifold.Initialize if (_manifold.Type == ManifoldType.Circles) { // this is essentically directly from ContactSolver.WorldManifold.Initialize. To avoid doing the extra math twice we duplicate this code // here because it doesnt return some values we need to calculate separation var pointA = MathUtils.Mul(ref edgeTransform, _manifold.LocalPoint); var pointB = MathUtils.Mul(ref circleTransform, _manifold.Points[0].LocalPoint); result.Normal = pointA - pointB; Vector2Ext.Normalize(ref result.Normal); var cA = pointA - edge.Radius * result.Normal; var cB = pointB + circle.Radius * result.Normal; result.Point = 0.5f * (cA + cB); result.Point *= FSConvert.SimToDisplay; var separation = Vector2.Dot(pointA - pointB, result.Normal) - edge.Radius - circle.Radius; // Ensure normal points from A to B Vector2.Negate(ref result.Normal, out result.Normal); result.MinimumTranslationVector = result.Normal * Math.Abs(separation); } else // FaceA { result.Normal = MathUtils.Mul(edgeTransform.Q, _manifold.LocalNormal); var planePoint = MathUtils.Mul(ref edgeTransform, _manifold.LocalPoint); var clipPoint = MathUtils.Mul(ref circleTransform, _manifold.Points[0].LocalPoint); var separation = Vector2.Dot(clipPoint - planePoint, result.Normal) - edge.Radius - circle.Radius; result.Point = (clipPoint - result.Normal * circle.Radius) * FSConvert.SimToDisplay; result.MinimumTranslationVector = result.Normal * -separation; } #if DEBUG_FSCOLLISIONS Debug.drawPixel(result.point, 5, Color.Red, 0.2f); Debug.drawLine(result.point, result.point + result.normal * 20, Color.Yellow, 0.2f); #endif return(true); } return(false); }
public void Update() { if (CanAccelearte) { CurrentSpeed += Acceleration * Time.DeltaTime; if (CurrentSpeed > MaxSpeed) { CurrentSpeed = MaxSpeed; CanAccelearte = false; } } var motion = Vector2Ext.Normalize(player.Position - Entity.Position) * CurrentSpeed * Time.DeltaTime; mover.ApplyMovement(motion); }
/// <summary> /// works for circles whos center is in the box as well as just overlapping with the center out of the box. /// </summary> /// <returns><c>true</c>, if to box was circled, <c>false</c> otherwise.</returns> /// <param name="circle">First.</param> /// <param name="box">Second.</param> /// <param name="result">Result.</param> public static bool CircleToBox(Circle circle, Box box, out CollisionResult result) { result = new CollisionResult(); var closestPointOnBounds = box.bounds.GetClosestPointOnRectangleBorderToPoint(circle.position, out result.Normal); // deal with circles whos center is in the box first since its cheaper to see if we are contained if (box.ContainsPoint(circle.position)) { result.Point = closestPointOnBounds; // calculate mtv. Find the safe, non-collided position and get the mtv from that. var safePlace = closestPointOnBounds + result.Normal * circle.Radius; result.MinimumTranslationVector = circle.position - safePlace; return(true); } float sqrDistance; Vector2.DistanceSquared(ref closestPointOnBounds, ref circle.position, out sqrDistance); // see if the point on the box is less than radius from the circle if (sqrDistance == 0) { result.MinimumTranslationVector = result.Normal * circle.Radius; } else if (sqrDistance <= circle.Radius * circle.Radius) { result.Normal = circle.position - closestPointOnBounds; var depth = result.Normal.Length() - circle.Radius; result.Point = closestPointOnBounds; Vector2Ext.Normalize(ref result.Normal); result.MinimumTranslationVector = depth * result.Normal; return(true); } return(false); }
public float getTargetAngle() { var dirToTarget = Vector2Ext.Normalize(getPosition() - mind.state.me.body.pos); return(dirToTarget.ScreenSpaceAngle()); }
public void OnTriggerEnter(Collider other, Collider local) { var hitEntity = other.Entity; switch (other.Tag) { case Constants.Colliders.THING: { if (hitEntity.HasComponent <Capsule>()) { var capsule = hitEntity.GetComponent <Capsule>(); if (!capsule.acquired && Time.TotalTime > capsule.firstAvailableAt) { // apply the capsule var gotEnergy = capsule.energy; me.core.energy += gotEnergy; capsule.acquire(); // blow it up // send signal to mind if (me.mind.control) { me.mind.signal(new ItemSignals.CapsuleAcquiredSignal(capsule, gotEnergy)); } } } break; } case Constants.Colliders.SHOOT: { if (hitEntity.HasComponent <Shooter>()) { var shooter = hitEntity.GetComponent <Shooter>(); if (shooter.firing) { // ouch me.core.energy -= Constants.Mechanics.SHOOT_DRAIN; me.core.clamp(); // send signal to mind if (me.mind.control) { me.mind.signal(new PhysicalSignals.ShotSignal(shooter)); } } } break; } } if (other.Tag == Constants.Colliders.LANE) { // lanes multiply velocity velocity *= laneFactor; drag = Vector2.Zero; } if (other.Tag == Constants.Mechanics.TRIGGER_GRAVITY) { var gravThing = other.Entity; var succ = true; if (gravThing.HasComponent <Capsule>()) { var cap = gravThing.GetComponent <Capsule>(); if (Time.TotalTime < cap.firstAvailableAt) { succ = false; } } if (succ) { var thingBody = gravThing.GetComponent <KinBody>(); var toMe = Entity.Position - gravThing.Position; var toMeDir = Vector2Ext.Normalize(toMe); var dist = toMe.Length(); var velInfluence = Mathf.Clamp(velocity.Length(), 1f, 10f); var gravForce = (gravityFactor * mass * velInfluence) / (dist * dist); thingBody.velocity += gravForce * toMeDir; } } }