static unsafe void CheckRaycastHit(ref Physics.PhysicsWorld world, RaycastInput input, RaycastHit hit, string failureMessage) { // Fetch the leaf collider ChildCollider leaf; { Physics.RigidBody body = world.Bodies[hit.RigidBodyIndex]; Collider.GetLeafCollider(body.Collider, body.WorldFromBody, hit.ColliderKey, out leaf); } // Check that the hit position matches the fraction float3 hitPosition = input.Ray.Origin + input.Ray.Direction * hit.Fraction; Assert.Less(math.length(hitPosition - hit.Position), tolerance, failureMessage + ": inconsistent fraction and position"); // Query the hit position and check that it's on the surface of the shape PointDistanceInput pointInput = new PointDistanceInput { Position = math.transform(math.inverse(leaf.TransformFromChild), hit.Position), MaxDistance = float.MaxValue }; DistanceHit distanceHit; leaf.Collider->CalculateDistance(pointInput, out distanceHit); if (((ConvexCollider *)leaf.Collider)->ConvexHull.ConvexRadius > 0.0f) { // Convex raycast approximates radius, so it's possible that the hit position is not exactly on the shape, but must at least be outside Assert.Greater(distanceHit.Distance, -tolerance, failureMessage); } else { Assert.AreEqual(distanceHit.Distance, 0.0f, tolerance, failureMessage); } }
//the same as DrawJumpRange except it shows what areas the player can currently fall to private void DrawFallRange(Graphics displayDevice) { Physics.RigidBody temp = new Physics.RigidBody(); temp.Shape = new Physics.Circle(7); temp.SetPosition(new Physics.Vector2D()); //draw a grid of dots 40 units apart for (int i = -700; i < 700; i += 40) { for (int j = -360; j < 400; j += 40) { //calculate the position of the dot temp.Position.X = playerCharacter.playerBody.Position.X + i; temp.Position.X -= temp.Position.X % 40; temp.Position.Y = playerCharacter.playerBody.Position.Y + j; temp.Position.Y -= temp.Position.Y % 40; //set colour based on ability to fall to calculated position if (physEng.CanPlayerFallFromTo(playerCharacter, playerCharacter.playerBody.Position, temp.Position)) { temp.Shape.mColor = Color.Black; } else { temp.Shape.mColor = Color.White; } //draw a dot at that position mRenderer.Draw(temp, displayDevice); } } }
public unsafe void RigidBodyCalculateDistancePointTest() { Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.0f; var queryPos = new float3(-10, -10, -10); rigidbody.Collider = (Collider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr(); var pointDistanceInput = new PointDistanceInput(); pointDistanceInput.Position = queryPos; pointDistanceInput.Filter = CollisionFilter.Default; var closestHit = new DistanceHit(); var allHits = new NativeList <DistanceHit>(Allocator.Temp); // OK case : with enough max distance pointDistanceInput.MaxDistance = 10000.0f; Assert.IsTrue(rigidbody.CalculateDistance(pointDistanceInput)); Assert.IsTrue(rigidbody.CalculateDistance(pointDistanceInput, out closestHit)); Assert.IsTrue(rigidbody.CalculateDistance(pointDistanceInput, ref allHits)); // Fail case : not enough max distance pointDistanceInput.MaxDistance = 1; Assert.IsFalse(rigidbody.CalculateDistance(pointDistanceInput)); Assert.IsFalse(rigidbody.CalculateDistance(pointDistanceInput, out closestHit)); Assert.IsFalse(rigidbody.CalculateDistance(pointDistanceInput, ref allHits)); }
static unsafe void GetHitLeaf(ref Physics.PhysicsWorld world, int rigidBodyIndex, ColliderKey colliderKey, MTransform queryFromWorld, out ChildCollider leaf, out MTransform queryFromTarget) { Physics.RigidBody body = world.Bodies[rigidBodyIndex]; Collider.GetLeafCollider(body.Collider, body.WorldFromBody, colliderKey, out leaf); MTransform worldFromLeaf = new MTransform(leaf.TransformFromChild); queryFromTarget = Math.Mul(queryFromWorld, worldFromLeaf); }
//Draw a given point as a circle with radius 3, with colour Azure public void Draw(Physics.Vector2D point, Graphics g) { Physics.RigidBody temp = new Physics.RigidBody(); temp.SetPosition(point); temp.Shape = new Physics.Circle(3); temp.Shape.mColor = Color.Azure; Draw(temp, g); }
protected internal override void OnLoad() { base.OnLoad(); var shape = CreateCollisionShape(); rigidBody = Bullet.CreateRigidBody(Mass, GameObject.Transform.WorldTransform, shape, CollideGroup, CollideMask); rigidBody.tag = this; SetIgnore(true); }
//Adds a dynamic box to the world static public unsafe void addDynamicBoxToWorld(Physics.PhysicsWorld world, int index, Vector3 pos, Quaternion orientation, Vector3 size) { Assert.IsTrue(index < world.NumDynamicBodies, "Dynamic body index is out of range in addDynamicBoxToWorld"); Unity.Collections.NativeSlice <Physics.RigidBody> dynamicBodies = world.DynamicBodies; Physics.RigidBody rb = dynamicBodies[index]; BlobAssetReference <Physics.Collider> collider = Unity.Physics.BoxCollider.Create(pos, orientation, size, .01f); rb.Collider = (Collider *)collider.GetUnsafePtr(); dynamicBodies[index] = rb; }
public unsafe void RigidBodyCalculateAabb_SphereColliderTest() { Physics.RigidBody rigidbodySphere = Unity.Physics.RigidBody.Zero; const float convexRadius = 1.0f; rigidbodySphere.Collider = (Collider *)SphereCollider.Create(float3.zero, convexRadius).GetUnsafePtr(); var sphereAabb = rigidbodySphere.CalculateAabb(); var sphere = (Collider *)SphereCollider.Create(float3.zero, convexRadius).GetUnsafePtr(); Assert.IsTrue(sphereAabb.Equals(sphere->CalculateAabb())); }
public unsafe void RigidBodyCalculateAabb_BoxColliderTest() { Physics.RigidBody rigidbodyBox = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.2f; rigidbodyBox.Collider = (Collider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr(); var boxAabb = rigidbodyBox.CalculateAabb(); var box = (BoxCollider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr(); Assert.IsTrue(boxAabb.Equals(box->CalculateAabb())); }
//Draw the nodes and connections associated with all the rigidbodies, and any current AI paths through the rigidbody graph private void DrawRigidbodyGraph(Graphics displayDevice) { Physics.RigidBody temp = new Physics.RigidBody(); temp.Shape = new Physics.Circle(5); AI.NodeIndex previousNode; //for each rigidbody, draw it's core node, all its child nodes, and all its connections foreach (AI.Node rb in AIgraph.topLevelNode.internalNodes) { //draw the node temp.SetPosition(AIgraph.topLevelNode.GetNodePosition(rb.index)); temp.Shape.mColor = Color.DarkOrange; mRenderer.Draw(temp, displayDevice); //draw its children foreach (AI.Node nd in rb.internalNodes) { temp.SetPosition(AIgraph.topLevelNode.GetNodePosition(nd.index)); temp.Shape.mColor = Color.Chocolate; mRenderer.Draw(temp, displayDevice); } //draw its connections foreach (AI.Connection rbconn in rb.connections) { mRenderer.DrawLine(rb.position, AIgraph.topLevelNode.GetNodePosition(rbconn.destination), displayDevice, Color.FromArgb(9, Color.Black)); } //draw each Ai's current high level path if (AIgraph.topLevelNode.lastPaths != null) { foreach (List <AI.NodeIndex> lastPath in AIgraph.topLevelNode.lastPaths) { previousNode = null; if (lastPath != null) { foreach (AI.NodeIndex node in lastPath) { previousNode = AIgraph.topLevelNode.GetNode(node).previousNode; if (previousNode != null) { mRenderer.DrawLine(AIgraph.topLevelNode.GetNodePosition(previousNode), AIgraph.topLevelNode.GetNodePosition(node), displayDevice, Color.FromArgb(129, Color.Black)); } } } } } } }
public unsafe void RigidBodyCalculateDistanceTest() { const float size = 1.0f; const float convexRadius = 0.0f; const float sphereRadius = 1.0f; var queryPos = new float3(-10, -10, -10); BlobAssetReference <Collider> boxCollider = BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = size, BevelRadius = convexRadius }); BlobAssetReference <Collider> sphereCollider = SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = sphereRadius }); var rigidBody = new Physics.RigidBody { WorldFromBody = RigidTransform.identity, Collider = boxCollider }; var colliderDistanceInput = new ColliderDistanceInput { Collider = (Collider *)sphereCollider.GetUnsafePtr(), Transform = new RigidTransform(quaternion.identity, queryPos) }; var closestHit = new DistanceHit(); var allHits = new NativeList <DistanceHit>(Allocator.Temp); // OK case : with enough max distance colliderDistanceInput.MaxDistance = 10000.0f; Assert.IsTrue(rigidBody.CalculateDistance(colliderDistanceInput)); Assert.IsTrue(rigidBody.CalculateDistance(colliderDistanceInput, out closestHit)); Assert.IsTrue(rigidBody.CalculateDistance(colliderDistanceInput, ref allHits)); // Fail case : not enough max distance colliderDistanceInput.MaxDistance = 1; Assert.IsFalse(rigidBody.CalculateDistance(colliderDistanceInput)); Assert.IsFalse(rigidBody.CalculateDistance(colliderDistanceInput, out closestHit)); Assert.IsFalse(rigidBody.CalculateDistance(colliderDistanceInput, ref allHits)); boxCollider.Dispose(); sphereCollider.Dispose(); }
//check all dynamic objects for collisions against dynamic and static objects, then resolve them public void updateCollisions() { //Check collisions of all dynamic objects for (int i = dynamicPhysicsObjects.Count - 1; i >= 0; i--) { Physics.RigidBody a = dynamicPhysicsObjects[i]; //against other dynamic objects for (int j = dynamicPhysicsObjects.Count - 1; j >= 0; j--) { if (i != j) { Physics.RigidBody b = dynamicPhysicsObjects[j]; if (a.Shape.IsCollided(b.Shape, a.Position, b.Position)) { Physics.Vector2D normal = a.Shape.GetCollisionNormal(b.Shape, a.Position, b.Position); Physics.CollisionPairData pair = new Physics.CollisionPairData(); pair.BodyA = a; pair.BodyB = b; pair.ContactNormal = normal; mCollisionResponder.AddCollisionPair(pair); } } } //and against all static objects for (int j = staticPhysicsObjects.Count - 1; j >= 0; j--) { Physics.RigidBody b = staticPhysicsObjects[j]; if (a.Shape.IsCollided(b.Shape, a.Position, b.Position)) { Physics.Vector2D normal = a.Shape.GetCollisionNormal(b.Shape, a.Position, b.Position); Physics.CollisionPairData pair = new Physics.CollisionPairData(); pair.BodyA = a; pair.BodyB = b; pair.ContactNormal = normal; mCollisionResponder.AddCollisionPair(pair); } } mCollisionResponder.ResolveAllPairs(playerCharacter); } }
public unsafe void RigidBodyCalculateAabb_SphereColliderTest() { var geometry = new SphereGeometry { Center = float3.zero, Radius = 1.0f }; Physics.RigidBody rigidbodySphere = Unity.Physics.RigidBody.Zero; rigidbodySphere.Collider = (Collider *)SphereCollider.Create(geometry).GetUnsafePtr(); var sphereAabb = rigidbodySphere.CalculateAabb(); var sphere = (Collider *)SphereCollider.Create(geometry).GetUnsafePtr(); Assert.IsTrue(sphereAabb.Equals(sphere->CalculateAabb())); }
//Adds a static box to the world static public unsafe void addStaticBoxToWorld(Physics.PhysicsWorld world, int index, Vector3 pos, Quaternion orientation, Vector3 size) { Assert.IsTrue(index < world.NumStaticBodies, "Static body index is out of range in addStaticBoxToWorld"); Unity.Collections.NativeSlice <Physics.RigidBody> staticBodies = world.StaticBodies; Physics.RigidBody rb = staticBodies[index]; BlobAssetReference <Physics.Collider> collider = Unity.Physics.BoxCollider.Create(new BoxGeometry { Center = pos, Orientation = orientation, Size = size, BevelRadius = 0.01f }); rb.Collider = (Collider *)collider.GetUnsafePtr(); staticBodies[index] = rb; }
//Draw the local nodes and their connections of the rigidbody with index stored in "showLocalNodes" private void DrawLocalNodes(Graphics displayDevice) { Physics.RigidBody temp = new Physics.RigidBody(); temp.Shape = new Physics.Circle(5); //reset showLocalNodes to it's null value if it has been incremented above the number of rigidbodies if (showLocalNodes >= AIgraph.topLevelNode.internalNodes.Count) { showLocalNodes = -1; } else { foreach (AI.Node nd in AIgraph.topLevelNode.internalNodes[showLocalNodes].internalNodes) { //draw the node temp.SetPosition(AIgraph.topLevelNode.GetNodePosition(nd.index)); temp.Shape.mColor = Color.Chocolate; mRenderer.Draw(temp, displayDevice); //draw its connections foreach (AI.Connection ndconn in nd.connections) { if (ndconn.connType == AI.CONNECTION_TYPE.JUMP) { mRenderer.DrawLine(temp.Position, AIgraph.topLevelNode.GetNodePosition(ndconn.destination), displayDevice, Color.DarkOrange); } else if (ndconn.connType == AI.CONNECTION_TYPE.FALL) { mRenderer.DrawLine(temp.Position, AIgraph.topLevelNode.GetNodePosition(ndconn.destination), displayDevice, Color.DarkMagenta); } else { mRenderer.DrawLine(temp.Position, AIgraph.topLevelNode.GetNodePosition(ndconn.destination), displayDevice, Color.Black); } } } } //also draw the player's current node, if the player has one AI.Node nearestNode = AIgraph.GetNodeAtPoint(playerCharacter.playerBody.Position); if (nearestNode != null) { temp.SetPosition(AIgraph.topLevelNode.GetNodePosition(nearestNode.index)); temp.Shape.mColor = Color.Black; mRenderer.Draw(temp, displayDevice); } }
public unsafe void RigidBodyCastColliderTest() { Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.0f; const float sphereRadius = 1.0f; var rayStartOK = new float3(-10, -10, -10); var rayEndOK = new float3(10, 10, 10); var rayStartFail = new float3(-10, 10, -10); var rayEndFail = new float3(10, 10, 10); rigidbody.Collider = (Collider *)BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = size, BevelRadius = convexRadius }).GetUnsafePtr(); var colliderCastInput = new ColliderCastInput(); var closestHit = new ColliderCastHit(); var allHits = new NativeList <ColliderCastHit>(Allocator.Temp); // OK case : Sphere hits the box collider colliderCastInput.Start = rayStartOK; colliderCastInput.End = rayEndOK; colliderCastInput.Collider = (Collider *)SphereCollider.Create( new SphereGeometry { Center = float3.zero, Radius = sphereRadius } ).GetUnsafePtr(); Assert.IsTrue(rigidbody.CastCollider(colliderCastInput)); Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, out closestHit)); Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, ref allHits)); // Fail case : wrong direction colliderCastInput.Start = rayStartFail; colliderCastInput.End = rayEndFail; Assert.IsFalse(rigidbody.CastCollider(colliderCastInput)); Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, out closestHit)); Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, ref allHits)); }
//Adds a dynamic box to the world static public unsafe void addDynamicBoxToWorld(Physics.PhysicsWorld world, int index, Vector3 pos, Quaternion orientation, Vector3 size) { Assert.IsTrue(index < world.NumDynamicBodies, "Dynamic body index is out of range in addDynamicBoxToWorld"); NativeArray <Physics.RigidBody> dynamicBodies = world.DynamicBodies; Physics.RigidBody rb = dynamicBodies[index]; BlobAssetReference <Collider> collider = BoxCollider.Create(new BoxGeometry { Center = pos, Orientation = orientation, Size = size, BevelRadius = 0.01f }); rb.Collider = collider; dynamicBodies[index] = rb; }
public unsafe void RigidBodyCalculateAabb_BoxColliderTest() { var geometry = new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = 1.0f, BevelRadius = 0.2f }; Physics.RigidBody rigidbodyBox = Unity.Physics.RigidBody.Zero; rigidbodyBox.Collider = (Collider *)BoxCollider.Create(geometry).GetUnsafePtr(); var boxAabb = rigidbodyBox.CalculateAabb(); var boxCollider = (BoxCollider *)BoxCollider.Create(geometry).GetUnsafePtr(); Assert.IsTrue(boxAabb.Equals(boxCollider->CalculateAabb())); }
public unsafe void RigidBodyCastRayTest() { Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.0f; var rayStartOK = new float3(-10, -10, -10); var rayEndOK = new float3(10, 10, 10); var rayStartFail = new float3(-10, 10, -10); var rayEndFail = new float3(10, 10, 10); rigidbody.Collider = BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = size, BevelRadius = convexRadius }); var raycastInput = new RaycastInput(); var closestHit = new RaycastHit(); var allHits = new NativeList <RaycastHit>(Allocator.Temp); // OK case : Ray hits the box collider raycastInput.Start = rayStartOK; raycastInput.End = rayEndOK; raycastInput.Filter = CollisionFilter.Default; Assert.IsTrue(rigidbody.CastRay(raycastInput)); Assert.IsTrue(rigidbody.CastRay(raycastInput, out closestHit)); Assert.IsTrue(rigidbody.CastRay(raycastInput, ref allHits)); // Fail Case : wrong direction raycastInput.Start = rayStartFail; raycastInput.End = rayEndFail; Assert.IsFalse(rigidbody.CastRay(raycastInput)); Assert.IsFalse(rigidbody.CastRay(raycastInput, out closestHit)); Assert.IsFalse(rigidbody.CastRay(raycastInput, ref allHits)); }
public unsafe void RigidBodyCastColliderTest() { Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.0f; const float sphereRadius = 1.0f; var rayStartOK = new float3(-10, -10, -10); var rayEndOK = new float3(10, 10, 10); var rayStartFail = new float3(-10, 10, -10); var rayEndFail = new float3(10, 10, 10); rigidbody.Collider = (Collider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr(); var colliderCastInput = new ColliderCastInput(); var closestHit = new ColliderCastHit(); var allHits = new NativeList <ColliderCastHit>(Allocator.Temp); // OK case : Sphere hits the box collider float3 rayDir = rayEndOK - rayStartOK; colliderCastInput.Position = rayStartOK; colliderCastInput.Direction = rayDir; colliderCastInput.Collider = (Collider *)SphereCollider.Create(float3.zero, sphereRadius).GetUnsafePtr(); Assert.IsTrue(rigidbody.CastCollider(colliderCastInput)); Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, out closestHit)); Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, ref allHits)); // Fail case : wrong direction rayDir = rayEndFail - rayStartFail; colliderCastInput.Position = rayStartFail; colliderCastInput.Direction = rayDir; Assert.IsFalse(rigidbody.CastCollider(colliderCastInput)); Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, out closestHit)); Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, ref allHits)); }
//Draw the short term paths of all AI and display the current number of active AI private void DrawAIPath(Graphics displayDevice) { //write the number of AI currently active in the top right of the screen mRenderer.Draw(AIgraph.paths.Count().ToString(), new Physics.Vector2D(1200, 10), displayDevice); //draw all short term paths Physics.RigidBody temp = new Physics.RigidBody(); AI.NodeIndex previousNode; for (int i = 0; i < AIgraph.paths.Count(); ++i) { //Draw the AI's current destination node temp.Shape = new Physics.Circle(8); temp.Shape.mColor = Color.BlueViolet; temp.SetPosition(AIgraph.topLevelNode.GetNodePosition(AIgraph.GetNextDestination(i, AIgraph.GetNodeAtPoint(mAImanager.aiControllers[i].AIPlayer.playerBody.Position)))); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } //draw all nodes in the short term path temp.Shape.mColor = Color.Green; temp.Shape = new Physics.Circle(5); foreach (AI.NodeIndex node in AIgraph.paths[i]) { //draw the node temp.SetPosition(AIgraph.topLevelNode.GetNodePosition(node)); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } //draw the connection between that node and the previous node previousNode = AIgraph.topLevelNode.GetNode(node).previousNode; if (previousNode != null) { mRenderer.DrawArrow(AIgraph.topLevelNode.GetNodePosition(previousNode), temp.Position, displayDevice); } } } }
public unsafe void RigidBodyCastRayTest() { Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.0f; var rayStartOK = new float3(-10, -10, -10); var rayEndOK = new float3(10, 10, 10); var rayStartFail = new float3(-10, 10, -10); var rayEndFail = new float3(10, 10, 10); rigidbody.Collider = (Collider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr(); var raycastInput = new RaycastInput(); var closestHit = new RaycastHit(); var allHits = new NativeList <RaycastHit>(Allocator.Temp); // OK case : Ray hits the box collider float3 rayDir = rayEndOK - rayStartOK; raycastInput.Ray.Origin = rayStartOK; raycastInput.Ray.Direction = rayDir; raycastInput.Filter = CollisionFilter.Default; Assert.IsTrue(rigidbody.CastRay(raycastInput)); Assert.IsTrue(rigidbody.CastRay(raycastInput, out closestHit)); Assert.IsTrue(rigidbody.CastRay(raycastInput, ref allHits)); // Fail Case : wrong direction rayDir = rayEndFail - rayStartFail; raycastInput.Ray.Origin = rayStartFail; raycastInput.Ray.Direction = rayDir; Assert.IsFalse(rigidbody.CastRay(raycastInput)); Assert.IsFalse(rigidbody.CastRay(raycastInput, out closestHit)); Assert.IsFalse(rigidbody.CastRay(raycastInput, ref allHits)); }
public void Draw(Physics.RigidBody rb, Graphics g) { //colour is dependant on the colour specified in the rigidbody mBrush.Color = rb.Shape.mColor; //a different draw method is needed for boxes than for circles if (rb.Shape is Physics.Circle) { float radius = ((Physics.Circle)rb.Shape).Radius; float diameter = ((Physics.Circle)rb.Shape).Radius * 2.0f; //draw an ellipse with width and height that match the diameter of the circle //the position of the camera is used to determine where the object is drawn g.FillEllipse(mBrush, rb.Position.X - radius + cameraLocation.X, rb.Position.Y - radius + cameraLocation.Y, diameter, diameter ); } else if (rb.Shape is Physics.Box) { //Create the four points that are to be drawn PointF[] pts = new PointF[4]; Physics.Box box = ((Physics.Box)rb.Shape); int index = 0; //the position of the camera is used to determine where the object is drawn foreach (Physics.Vector2D vert in box.Vertices) { pts[index].X = rb.Position.X + vert.X + cameraLocation.X; pts[index++].Y = rb.Position.Y + vert.Y + cameraLocation.Y; } //fill the polygon defined by the above points g.FillPolygon(mBrush, pts); } }
//given a rigidbody, create its node and its child nodes, then return its node public static Node CreateNodesFromRB(Physics.RigidBody theRB, NodeIndex parentIndex, int localIndex) { //create the node for the rigidbody Node rigidBody = new Node(theRB.Position, new NodeIndex(parentIndex, localIndex), NODE_TYPE.RIGIDBODY); //this temporary position is used to place the child nodes Physics.Vector2D nodePosition = new Physics.Vector2D(); nodePosition.Y = theRB.Shape.ComputeAABB().MIN.Y - (Physics.Player.playerRadius + 1); //Create the leftmost fall node nodePosition.X = theRB.Shape.ComputeAABB().MIN.X - (Physics.Player.playerRadius + 1); rigidBody.AddNode(new Node(new Physics.Vector2D(nodePosition), new NodeIndex(rigidBody.index, rigidBody.internalNodes.Count), NODE_TYPE.FALL)); //Move the node position so it is not above a sheer drop nodePosition.X = theRB.Shape.ComputeAABB().MIN.X + (Physics.Player.playerRadius / 2); //Create the regular nodes an even distance apart float surfaceWidth = theRB.Shape.ComputeAABB().MAX.X - theRB.Shape.ComputeAABB().MIN.X; int numberOfNodes = (int)(surfaceWidth / (Physics.Player.playerRadius * 2) + 0.5); float step = (surfaceWidth - Physics.Player.playerRadius) / numberOfNodes; for (int i = 0; i <= numberOfNodes; ++i) { rigidBody.AddNode(new Node(new Physics.Vector2D(nodePosition), new NodeIndex(rigidBody.index, rigidBody.internalNodes.Count), NODE_TYPE.FLOOR)); nodePosition.X += step; } //Create the rightmost fall node nodePosition.X = theRB.Shape.ComputeAABB().MAX.X + (Physics.Player.playerRadius + 1); rigidBody.AddNode(new Node(new Physics.Vector2D(nodePosition), new NodeIndex(rigidBody.index, rigidBody.internalNodes.Count), NODE_TYPE.FALL)); return(rigidBody); }
private void InitialiseDefaults(float chosenRadius, int chosenSpeed) { //create the player's rigidbody playerBody = new Physics.RigidBody(); playerBody.type = RBTypes.PLAYER; playerBody.Shape = new Physics.Circle(chosenRadius); playerBody.Shape.mColor = System.Drawing.Color.Firebrick; playerBody.SetDynamic(); playerBody.Mass = 120; //set speed to the input speed, and update all variables calculated using speed SetSpeed(chosenSpeed); for (int i = 0; i < (int)CONTROLS.NUM_OF_CONTROLS; ++i) { controls[i] = false; } gunForce = 300; gunReload = 0.0f; collisionCooldown = 0.0f; won = false; }
private void CreateObjects() { Physics.RigidBody newBody = new Physics.RigidBody(); //declare the colours used System.Drawing.Color wallColour = System.Drawing.Color.DarkSlateGray; System.Drawing.Color furnitureColour = System.Drawing.Color.Brown; System.Drawing.Color cloudColour = System.Drawing.Color.LightGray; System.Drawing.Color liftColour = System.Drawing.Color.BlueViolet; System.Drawing.Color goalColour = System.Drawing.Color.Gold; System.Drawing.Color wreckingBallColour = System.Drawing.Color.Black; //create the ground floor newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(1700, 80); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(400, 700)); thePhysicsEngine.addRigidBody(newBody); //front desk newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(200, 40); newBody.Shape.mColor = furnitureColour; newBody.SetPosition(new Physics.Vector2D(1100, 640)); thePhysicsEngine.addRigidBody(newBody); //Create the left wall //bottom bit newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(40, 650); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(0, 275)); thePhysicsEngine.addRigidBody(newBody); //top bit newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(40, 300); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(0, -300)); thePhysicsEngine.addRigidBody(newBody); //create the right wall //Top bit newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(40, 850); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(1200, -25)); thePhysicsEngine.addRigidBody(newBody); //bottom bit newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(40, 200); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(1200, 650)); thePhysicsEngine.addRigidBody(newBody); //breakaway bit newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(40, 149); newBody.Shape.mColor = wallColour; newBody.Mass = 4000.0f; newBody.SetPosition(new Physics.Vector2D(1200, 475)); newBody.SetDynamic(); thePhysicsEngine.addRigidBody(newBody); //create the first floor //floor newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(1000, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(500, 550)); thePhysicsEngine.addRigidBody(newBody); //stairs float width = 400, height = 20; float Xpos = 200, Ypos = 530; for (int i = 0; i < 9; ++i) { newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(width, height); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(Xpos, Ypos)); thePhysicsEngine.addRigidBody(newBody); width -= 40; Ypos -= 20; Xpos -= 20; } //create the second floor //left bit newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(250, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(425, 300)); thePhysicsEngine.addRigidBody(newBody); //right bit newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(500, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(950, 300)); thePhysicsEngine.addRigidBody(newBody); //fallen bit newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(145, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(620, 302)); newBody.SetDynamic(); thePhysicsEngine.addRigidBody(newBody); //girdir to hold the fallen piece up newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(10, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(550, 313)); thePhysicsEngine.addRigidBody(newBody); //create the fragmented floor //piece 1 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(130, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(940, 220)); thePhysicsEngine.addRigidBody(newBody); //piece 2 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(190, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(650, 130)); thePhysicsEngine.addRigidBody(newBody); //piece 3 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(100, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(400, 90)); thePhysicsEngine.addRigidBody(newBody); //extra step for balcony newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(50, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(250, 20)); thePhysicsEngine.addRigidBody(newBody); //create jumping "puzzle" //piece 4 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(80, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(730, 50)); thePhysicsEngine.addRigidBody(newBody); //piece 5 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(70, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(850, -20)); thePhysicsEngine.addRigidBody(newBody); //piece 6 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(30, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(900, -80)); thePhysicsEngine.addRigidBody(newBody); //piece 7 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(80, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(1000, -50)); thePhysicsEngine.addRigidBody(newBody); //piece 8 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(80, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(1100, -170)); thePhysicsEngine.addRigidBody(newBody); //piece 9 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(70, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(800, -150)); thePhysicsEngine.addRigidBody(newBody); //piece 9 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(30, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(700, -30)); thePhysicsEngine.addRigidBody(newBody); //piece 10 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(60, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(600, -80)); thePhysicsEngine.addRigidBody(newBody); //piece 11 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(40, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(670, -160)); thePhysicsEngine.addRigidBody(newBody); //piece 12 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(70, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(950, -230)); thePhysicsEngine.addRigidBody(newBody); //piece 13 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(130, 10); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(1120, -310)); thePhysicsEngine.addRigidBody(newBody); //create balcony newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(400, 20); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(-50, -50)); thePhysicsEngine.addRigidBody(newBody); //lip newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(10, 40); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(-245, -70)); thePhysicsEngine.addRigidBody(newBody); //create clouds outside balcony //cloud 1 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(40, 40); newBody.Shape.mColor = cloudColour; newBody.SetPosition(new Physics.Vector2D(-350, -100)); thePhysicsEngine.addRigidBody(newBody); //cloud 2 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(50, 50); newBody.Shape.mColor = cloudColour; newBody.SetPosition(new Physics.Vector2D(-490, -130)); thePhysicsEngine.addRigidBody(newBody); //cloud 3 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(90, 70); newBody.Shape.mColor = cloudColour; newBody.SetPosition(new Physics.Vector2D(-600, -170)); thePhysicsEngine.addRigidBody(newBody); //cloud 4 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(150, 100); newBody.Shape.mColor = cloudColour; newBody.SetPosition(new Physics.Vector2D(-800, -230)); thePhysicsEngine.addRigidBody(newBody); //cloud 5 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(350, 160); newBody.Shape.mColor = cloudColour; newBody.SetPosition(new Physics.Vector2D(-300, -370)); thePhysicsEngine.addRigidBody(newBody); //cloud 6 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(50, 30); newBody.Shape.mColor = cloudColour; newBody.SetPosition(new Physics.Vector2D(-600, -350)); thePhysicsEngine.addRigidBody(newBody); //cloud 7 newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(700, 500); newBody.Shape.mColor = cloudColour; newBody.SetPosition(new Physics.Vector2D(-1100, -700)); thePhysicsEngine.addRigidBody(newBody); //create the roof newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(900, 40); newBody.Shape.mColor = wallColour; newBody.SetPosition(new Physics.Vector2D(450, -450)); thePhysicsEngine.addRigidBody(newBody); //create the lifts Physics.MovingPlatform newPlatform; Physics.Shape platShape; platShape = new Physics.Box(60, 10); platShape.mColor = liftColour; newPlatform = new Physics.MovingPlatform(platShape, new Physics.Vector2D(180, -60), new Physics.Vector2D(180, -300), 30f, 1.0f); newPlatform.platform.staticFriction = 0.7f; newPlatform.platform.dynamicFriction = 0.6f; thePhysicsEngine.addMovingPlatform(newPlatform); platShape = new Physics.Box(60, 10); platShape.mColor = liftColour; newPlatform = new Physics.MovingPlatform(platShape, new Physics.Vector2D(700, -280), new Physics.Vector2D(240, -280), 50f, 1.0f); newPlatform.platform.staticFriction = 0.7f; newPlatform.platform.dynamicFriction = 0.6f; thePhysicsEngine.addMovingPlatform(newPlatform); //the final lift to the goal platShape = new Physics.Box(80, 20); platShape.mColor = liftColour; newPlatform = new Physics.MovingPlatform(platShape, new Physics.Vector2D(960, -800), new Physics.Vector2D(960, -400), 10f, 1.0f); newPlatform.platform.staticFriction = 0.7f; newPlatform.platform.dynamicFriction = 0.6f; thePhysicsEngine.addMovingPlatform(newPlatform); //The goal platform newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Box(200, 20); newBody.Shape.mColor = goalColour; newBody.type = Physics.RBTypes.GOAL; newBody.SetPosition(new Physics.Vector2D(800, -800)); thePhysicsEngine.addRigidBody(newBody); //add the wrecking ball //the moving arm platShape = new Physics.Box(10, 10); platShape.mColor = liftColour; newPlatform = new Physics.MovingPlatform(platShape, new Physics.Vector2D(1300, 330), new Physics.Vector2D(1550, 330), 50f, 1.0f); newPlatform.platform.staticFriction = 1.0f; newPlatform.platform.dynamicFriction = 0.9f; thePhysicsEngine.addMovingPlatform(newPlatform); //the ball newBody = new Physics.RigidBody(); newBody.Shape = new Physics.Circle(40); newBody.Shape.mColor = wreckingBallColour; newBody.SetPosition(new Physics.Vector2D(1300, 510)); newBody.Mass = 2000; newBody.SetDynamic(); thePhysicsEngine.addRigidBody(newBody); //the chain Physics.SpringJoint wreckingBallChain = new Physics.SpringJoint(newPlatform.platform, newBody); wreckingBallChain.RestLength = 180; wreckingBallChain.Stiffness = 1000000; wreckingBallChain.Dampen = 1; thePhysicsEngine.springs.Add(wreckingBallChain); }
public unsafe void ManifoldQueryTest() { const uint seed = 0x98765432; Random rnd = new Random(seed); int numWorlds = 1000; uint dbgWorld = 0; if (dbgWorld > 0) { numWorlds = 1; } for (int iWorld = 0; iWorld < numWorlds; iWorld++) { // Save state to repro this query without doing everything that came before it if (dbgWorld > 0) { rnd.state = dbgWorld; } uint worldState = rnd.state; Physics.PhysicsWorld world = TestUtils.GenerateRandomWorld(ref rnd, rnd.NextInt(1, 20), 3.0f); // Manifold test // TODO would be nice if we could change the world collision tolerance for (int iBodyA = 0; iBodyA < world.NumBodies; iBodyA++) { for (int iBodyB = iBodyA + 1; iBodyB < world.NumBodies; iBodyB++) { Physics.RigidBody bodyA = world.Bodies[iBodyA]; Physics.RigidBody bodyB = world.Bodies[iBodyB]; if (bodyA.Collider->Type == ColliderType.Mesh && bodyB.Collider->Type == ColliderType.Mesh) { continue; // TODO - no mesh-mesh manifold support yet } // Build manifolds BlockStream contacts = new BlockStream(1, 0, Allocator.Temp); BlockStream.Writer contactWriter = contacts; contactWriter.BeginForEachIndex(0); ManifoldQueries.BodyBody(ref world, new BodyIndexPair { BodyAIndex = iBodyA, BodyBIndex = iBodyB }, 1.0f, ref contactWriter); contactWriter.EndForEachIndex(); // Read each manifold BlockStream.Reader contactReader = contacts; contactReader.BeginForEachIndex(0); int manifoldIndex = 0; while (contactReader.RemainingItemCount > 0) { string failureMessage = iWorld + " (" + worldState + ") " + iBodyA + " vs " + iBodyB + " #" + manifoldIndex; manifoldIndex++; // Read the manifold header ContactHeader header = contactReader.Read <ContactHeader>(); ConvexConvexManifoldQueries.Manifold manifold = new ConvexConvexManifoldQueries.Manifold(); manifold.NumContacts = header.NumContacts; manifold.Normal = header.Normal; // Get the leaf shapes ChildCollider leafA, leafB; { Collider.GetLeafCollider(bodyA.Collider, bodyA.WorldFromBody, header.ColliderKeys.ColliderKeyA, out leafA); Collider.GetLeafCollider(bodyB.Collider, bodyB.WorldFromBody, header.ColliderKeys.ColliderKeyB, out leafB); } // Read each contact point int minIndex = 0; for (int iContact = 0; iContact < header.NumContacts; iContact++) { // Read the contact and find the closest ContactPoint contact = contactReader.Read <ContactPoint>(); manifold[iContact] = contact; if (contact.Distance < manifold[minIndex].Distance) { minIndex = iContact; } // Check that the contact point is on or inside the shape CheckPointOnSurface(ref leafA, contact.Position + manifold.Normal * contact.Distance, failureMessage + " contact " + iContact + " leaf A"); CheckPointOnSurface(ref leafB, contact.Position, failureMessage + " contact " + iContact + " leaf B"); } // Check the closest point { ContactPoint closestPoint = manifold[minIndex]; RigidTransform aFromWorld = math.inverse(leafA.TransformFromChild); DistanceQueries.Result result = new DistanceQueries.Result { PositionOnAinA = math.transform(aFromWorld, closestPoint.Position + manifold.Normal * closestPoint.Distance), NormalInA = math.mul(aFromWorld.rot, manifold.Normal), Distance = closestPoint.Distance }; MTransform aFromB = new MTransform(math.mul(aFromWorld, leafB.TransformFromChild)); float referenceDistance = DistanceQueries.ConvexConvex(leafA.Collider, leafB.Collider, aFromB).Distance; ValidateDistanceResult(result, ref ((ConvexCollider *)leafA.Collider)->ConvexHull, ref ((ConvexCollider *)leafB.Collider)->ConvexHull, aFromB, referenceDistance, failureMessage + " closest point"); } // Check that the manifold is flat CheckManifoldFlat(ref manifold, manifold.Normal, failureMessage + ": non-flat A"); CheckManifoldFlat(ref manifold, float3.zero, failureMessage + ": non-flat B"); } contacts.Dispose(); } } world.Dispose(); // TODO leaking memory if the test fails } }
//the same as the above method but for falling //this method is effectively just copy/pasted from Player.FallCollidesWithRB() with modifications to display the results private void DrawFallCullingPoints(Graphics displayDevice) { Physics.RigidBody temp = new Physics.RigidBody(); temp.Shape = new Physics.Circle(3); temp.Shape.mColor = Color.OrangeRed; //store the start and endpoints of the fall Physics.Vector2D source = playerCharacter.playerBody.Position; Physics.Vector2D destination = jumpDestination; if (destination == null) { destination = new Physics.Vector2D(0, 0); } Physics.Vector2D displacement = destination - source; Tuple <float, float> timeToFall = Physics.SuvatEquations.TfromSUA(displacement.Y, 0.0f, 98); if (timeToFall == null) { return; } if (float.IsNaN(timeToFall.Item1) && float.IsNaN(timeToFall.Item2)) { return; } //calculate the acceleration needed to fall to the destination float acceleration = Physics.SuvatEquations.AfromSUT(displacement.X, 0.0f, Math.Max(timeToFall.Item1, timeToFall.Item2)); //calculate the four points where the path defined by acceleration could potentially collide with the rigidbody Tuple <float, float> timeToReach; float leftmostX; float leftmostY; float righttmostX; float righttmostY; float topY; float topX; float bottomY; float bottomX; //draw the points where the fall arc could collide with each rigidbody foreach (Physics.RigidBody RB in physEng.staticPhysicsObjects) { //obtain the X positions of the sides of the rigidbody leftmostX = (RB.Position.X + RB.Shape.ComputeAABB().MIN.X) - source.X; righttmostX = (RB.Position.X + RB.Shape.ComputeAABB().MAX.X) - source.X; //obtain the Y positions of the top and bottom of the rigidbody topY = (RB.Position.Y + RB.Shape.ComputeAABB().MIN.Y) - source.Y; bottomY = (RB.Position.Y + RB.Shape.ComputeAABB().MAX.Y) - source.Y; //calculate the time to reach the left side of the rigidbody timeToReach = Physics.SuvatEquations.TfromSUA(leftmostX, 0.0f, acceleration); //calculate the first Y position, draw the first point, calculate the second, draw the second point leftmostY = Physics.SuvatEquations.SfromUAT(0.0f, 98, timeToReach.Item1); if (!float.IsNaN(leftmostY)) { mRenderer.Draw(temp, displayDevice); temp.SetPosition(new Physics.Vector2D(leftmostX, leftmostY) + source); } leftmostY = Physics.SuvatEquations.SfromUAT(0.0f, 98, timeToReach.Item2); if (!float.IsNaN(leftmostY)) { mRenderer.Draw(temp, displayDevice); temp.SetPosition(new Physics.Vector2D(leftmostX, leftmostY) + source); } //calculate the time to reach the right side of the rigidbody timeToReach = Physics.SuvatEquations.TfromSUA(righttmostX, 0.0f, acceleration); //calculate the first Y position, draw the first point, calculate the second, draw the second point righttmostY = Physics.SuvatEquations.SfromUAT(0.0f, 98, timeToReach.Item1); if (!float.IsNaN(righttmostY)) { mRenderer.Draw(temp, displayDevice); temp.SetPosition(new Physics.Vector2D(righttmostX, righttmostY) + source); } righttmostY = Physics.SuvatEquations.SfromUAT(0.0f, 98, timeToReach.Item2); if (!float.IsNaN(righttmostY)) { mRenderer.Draw(temp, displayDevice); temp.SetPosition(new Physics.Vector2D(righttmostX, righttmostY) + source); } //calculate the time to reach the top of the rigidbody timeToReach = Physics.SuvatEquations.TfromSUA(topY, 0.0f, 98); //calculate the first X position, draw the first point, calculate the second, draw the second point topX = Physics.SuvatEquations.SfromUAT(0.0f, acceleration, timeToReach.Item1); if (!float.IsNaN(topX)) { mRenderer.Draw(temp, displayDevice); temp.SetPosition(new Physics.Vector2D(topX, topY) + source); } topX = Physics.SuvatEquations.SfromUAT(0.0f, acceleration, timeToReach.Item2); if (!float.IsNaN(topX)) { mRenderer.Draw(temp, displayDevice); temp.SetPosition(new Physics.Vector2D(topX, topY) + source); } //calculate the time to reach the bottom of the rigidbody timeToReach = Physics.SuvatEquations.TfromSUA(bottomY, 0.0f, 98); //calculate the first X position, draw the first point, calculate the second, draw the second point bottomX = Physics.SuvatEquations.SfromUAT(0.0f, acceleration, timeToReach.Item1); if (!float.IsNaN(bottomX)) { mRenderer.Draw(temp, displayDevice); temp.SetPosition(new Physics.Vector2D(bottomX, bottomY) + source); } bottomX = Physics.SuvatEquations.SfromUAT(0.0f, acceleration, timeToReach.Item2); if (!float.IsNaN(bottomX)) { mRenderer.Draw(temp, displayDevice); temp.SetPosition(new Physics.Vector2D(bottomX, bottomY) + source); } } }
//draw the points of the player's jump arc at each edge of every rigidbody //Used to debug the method that determines if a jump collides with a rigidbody //this method is effectively just copy/pasted from Player.JumpCollidesWithRB() with modifications to display the results private void DrawJumpCullingPoints(Graphics displayDevice) { Physics.RigidBody temp = new Physics.RigidBody(); temp.Shape = new Physics.Circle(3); temp.Shape.mColor = Color.OrangeRed; //store the list of positions at each edge of a box rigidbody Tuple <Tuple <Physics.Vector2D, Physics.Vector2D, Physics.Vector2D, Physics.Vector2D>, Tuple <Physics.Vector2D, Physics.Vector2D, Physics.Vector2D, Physics.Vector2D> > possibleCollisionPoints; //for every static rigidbody foreach (Physics.RigidBody RB in physEng.staticPhysicsObjects) { //obtain the list of coordinates possibleCollisionPoints = playerCharacter.GetBoxCollisionPoints(RB, playerCharacter.playerBody.Position, 0.0f, 15.0f, physEng.gravity); //draw each valid coordinate as a small red circle if (possibleCollisionPoints != null) { temp.SetPosition(possibleCollisionPoints.Item1.Item1); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } temp.SetPosition(possibleCollisionPoints.Item1.Item2); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } temp.SetPosition(possibleCollisionPoints.Item1.Item3); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } temp.SetPosition(possibleCollisionPoints.Item1.Item4); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } temp.SetPosition(possibleCollisionPoints.Item2.Item1); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } temp.SetPosition(possibleCollisionPoints.Item2.Item2); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } temp.SetPosition(possibleCollisionPoints.Item2.Item3); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } temp.SetPosition(possibleCollisionPoints.Item2.Item4); if (temp.Position != null) { mRenderer.Draw(temp, displayDevice); } } } }
//draw the jump arc of a specified player to a specified destination //if specified destination is null then draw the jump assuming the player jumped with no acceleration or deceleration //This function is useful for debugging the "Player.GetJumpFromSourceToDest()", "Player.GetJumpYFromX()", and "Player.GetJumpXFromY()" methods private void DrawJumpArc(Graphics displayDevice, Physics.Player thePlayer, Physics.Vector2D goal) { //a temporary variable used in draw calls Physics.RigidBody temp = new Physics.RigidBody(); //stores how long the player accelerates after hitting jump float accelerationTime = 0.0f; //if a goal was specified // calculate the amount of time the player would need to accelerate after jumping in order to reach the goal // draw the goal point if (goal != null) { accelerationTime = thePlayer.GetJumpFromSourceToDest(thePlayer.playerBody.Position, goal, physEng.gravity); //draw the goal temp.Shape = new Physics.Circle(6); temp.Shape.mColor = Color.Purple; temp.SetPosition(goal); mRenderer.Draw(temp, displayDevice); } //set the object to be drawn to a circle of radius 3 temp.Shape = new Physics.Circle(3); //Temporary variable used to store the coordinates returned from the GetJumpYFromX() and GetJumpXFromY() methods Tuple <Physics.Vector2D, Physics.Vector2D> resultingPoints; //loop through the 1200 X coordinates around the player, calculating the Y position of the jump at that point //Draw a circle at each combined X,Y coordinate in Green temp.Shape.mColor = Color.Green; for (int i = -600; i < 600; i += 1) { //Get the two possible X,Y coords of the jump given a specific X coord resultingPoints = thePlayer.GetJumpYFromX(thePlayer.playerBody.Position, accelerationTime, 15.0f, physEng.gravity, thePlayer.playerBody.Position.X - i); //draw any valid returned coordinates if (resultingPoints.Item1 != null) { temp.SetPosition(resultingPoints.Item1); mRenderer.Draw(temp, displayDevice); } if (resultingPoints.Item2 != null) { temp.SetPosition(resultingPoints.Item2); mRenderer.Draw(temp, displayDevice); } } //loop through the 1200 Y coordinates around the player, calculating the X position of the jump at that point //Draw a circle at each combined X,Y coordinate in red temp.Shape.mColor = Color.OrangeRed; for (int i = -600; i < 600; i += 10) { //Get the two possible X,Y coords of the jump given a specific Y coord resultingPoints = thePlayer.GetJumpXFromY(thePlayer.playerBody.Position, accelerationTime, 15.0f, physEng.gravity, thePlayer.playerBody.Position.Y - i); //draw any valid returned coordinates if (resultingPoints.Item1 != null) { temp.SetPosition(resultingPoints.Item1); mRenderer.Draw(temp, displayDevice); } if (resultingPoints.Item2 != null) { temp.SetPosition(resultingPoints.Item2); mRenderer.Draw(temp, displayDevice); } } }