public bool BeginContact(Contact contact) { Body bodyA = contact.FixtureA.Body; Body bodyB = contact.FixtureB.Body; // get the speed of impact between the two bodies Manifold worldManifold; contact.GetManifold (out worldManifold); ManifoldPoint p = worldManifold.Points [0]; Vector2 vA = bodyA.GetLinearVelocityFromLocalPoint (p.LocalPoint); Vector2 vB = bodyB.GetLinearVelocityFromLocalPoint (p.LocalPoint); float approachVelocity = Math.Abs (Vector2.Dot (vB - vA, worldManifold.LocalNormal)); //deduct hitpoints from both bodies ProcessContact (contact, bodyA, approachVelocity); ProcessContact (contact, bodyB, approachVelocity); return true; }
public void Initialize(Contact[] contacts, int count, Body toiBody) { _count = count; _toiBody = toiBody; if (_constraints.Length < _count) { _constraints = new TOIConstraint[Math.Max(_constraints.Length * 2, _count)]; } for (int i = 0; i < _count; ++i) { Contact contact = contacts[i]; Fixture fixtureA = contact.FixtureA; Fixture fixtureB = contact.FixtureB; Shape shapeA = fixtureA.Shape; Shape shapeB = fixtureB.Shape; float radiusA = shapeA.Radius; float radiusB = shapeB.Radius; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; Manifold manifold; contact.GetManifold(out manifold); Debug.Assert(manifold.PointCount > 0); TOIConstraint constraint = _constraints[i]; constraint.BodyA = bodyA; constraint.BodyB = bodyB; constraint.LocalNormal = manifold.LocalNormal; constraint.LocalPoint = manifold.LocalPoint; constraint.Type = manifold.Type; constraint.PointCount = manifold.PointCount; constraint.Radius = radiusA + radiusB; for (int j = 0; j < constraint.PointCount; ++j) { constraint.LocalPoints[j] = manifold.Points[j].LocalPoint; } _constraints[i] = constraint; } }
public void Reset(Contact[] contacts, int contactCount, float impulseRatio) { _contacts = contacts; _constraintCount = contactCount; // grow the array if (Constraints == null || Constraints.Length < _constraintCount) { Constraints = new ContactConstraint[_constraintCount * 2]; for (int i = 0; i < _constraintCount * 2; i++) { Constraints[i] = new ContactConstraint(); } } for (int i = 0; i < _constraintCount; ++i) { Contact contact = contacts[i]; Fixture fixtureA = contact.FixtureA; Fixture fixtureB = contact.FixtureB; Shape shapeA = fixtureA.Shape; Shape shapeB = fixtureB.Shape; float radiusA = shapeA.Radius; float radiusB = shapeB.Radius; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; Manifold manifold; contact.GetManifold(out manifold); float friction = Settings.MixFriction(fixtureA.Friction, fixtureB.Friction); float restitution = Settings.MixRestitution(fixtureA.Restitution, fixtureB.Restitution); Vector2 vA = bodyA.LinearVelocityInternal; Vector2 vB = bodyB.LinearVelocityInternal; float wA = bodyA.AngularVelocityInternal; float wB = bodyB.AngularVelocityInternal; Debug.Assert(manifold.PointCount > 0); WorldManifold worldManifold = new WorldManifold(ref manifold, ref bodyA.Xf, radiusA, ref bodyB.Xf, radiusB); ContactConstraint cc = Constraints[i]; cc.BodyA = bodyA; cc.BodyB = bodyB; cc.Manifold = manifold; cc.Normal = worldManifold.Normal; cc.PointCount = manifold.PointCount; cc.Friction = friction; cc.LocalNormal = manifold.LocalNormal; cc.LocalPoint = manifold.LocalPoint; cc.Radius = radiusA + radiusB; cc.Type = manifold.Type; for (int j = 0; j < cc.PointCount; ++j) { ManifoldPoint cp = manifold.Points[j]; ContactConstraintPoint ccp = cc.Points[j]; ccp.NormalImpulse = impulseRatio * cp.NormalImpulse; ccp.TangentImpulse = impulseRatio * cp.TangentImpulse; ccp.LocalPoint = cp.LocalPoint; ccp.rA = worldManifold.Points[j] - bodyA.Sweep.c; ccp.rB = worldManifold.Points[j] - bodyB.Sweep.c; #if MATH_OVERLOADS float rnA = MathUtils.Cross(ccp.rA, cc.Normal); float rnB = MathUtils.Cross(ccp.rB, cc.Normal); #else float rnA = ccp.rA.X * cc.Normal.Y - ccp.rA.Y * cc.Normal.X; float rnB = ccp.rB.X * cc.Normal.Y - ccp.rB.Y * cc.Normal.X; #endif rnA *= rnA; rnB *= rnB; float kNormal = bodyA.InvMass + bodyB.InvMass + bodyA.InvI * rnA + bodyB.InvI * rnB; Debug.Assert(kNormal > Settings.Epsilon); ccp.NormalMass = 1.0f / kNormal; #if MATH_OVERLOADS Vector2 tangent = MathUtils.Cross(cc.Normal, 1.0f); float rtA = MathUtils.Cross(ccp.rA, tangent); float rtB = MathUtils.Cross(ccp.rB, tangent); #else Vector2 tangent = new Vector2(cc.Normal.Y, -cc.Normal.X); float rtA = ccp.rA.X * tangent.Y - ccp.rA.Y * tangent.X; float rtB = ccp.rB.X * tangent.Y - ccp.rB.Y * tangent.X; #endif rtA *= rtA; rtB *= rtB; float kTangent = bodyA.InvMass + bodyB.InvMass + bodyA.InvI * rtA + bodyB.InvI * rtB; Debug.Assert(kTangent > Settings.Epsilon); ccp.TangentMass = 1.0f / kTangent; // Setup a velocity bias for restitution. ccp.VelocityBias = 0.0f; float vRel = Vector2.Dot(cc.Normal, vB + MathUtils.Cross(wB, ccp.rB) - vA - MathUtils.Cross(wA, ccp.rA)); if (vRel < -Settings.VelocityThreshold) { ccp.VelocityBias = -restitution * vRel; } } // If we have two points, then prepare the block solver. if (cc.PointCount == 2) { ContactConstraintPoint ccp1 = cc.Points[0]; ContactConstraintPoint ccp2 = cc.Points[1]; float invMassA = bodyA.InvMass; float invIA = bodyA.InvI; float invMassB = bodyB.InvMass; float invIB = bodyB.InvI; float rn1A = MathUtils.Cross(ccp1.rA, cc.Normal); float rn1B = MathUtils.Cross(ccp1.rB, cc.Normal); float rn2A = MathUtils.Cross(ccp2.rA, cc.Normal); float rn2B = MathUtils.Cross(ccp2.rB, cc.Normal); float k11 = invMassA + invMassB + invIA * rn1A * rn1A + invIB * rn1B * rn1B; float k22 = invMassA + invMassB + invIA * rn2A * rn2A + invIB * rn2B * rn2B; float k12 = invMassA + invMassB + invIA * rn1A * rn2A + invIB * rn1B * rn2B; // Ensure a reasonable condition number. const float k_maxConditionNumber = 100.0f; if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) { // K is safe to invert. cc.K = new Mat22(new Vector2(k11, k12), new Vector2(k12, k22)); cc.NormalMass = cc.K.Inverse; } else { // The constraints are redundant, just use one. // TODO_ERIN use deepest? cc.PointCount = 1; } } if (fixtureA.PostSolve != null) { fixtureA.PostSolve(cc); } if (fixtureB.PostSolve != null) { fixtureB.PostSolve(cc); } } }
protected override void PostSolve(Contact contact, ContactConstraint impulse) { if (_broke) { // The body already broke. return; } // Should the body break? float maxImpulse = 0.0f; Manifold manifold; contact.GetManifold(out manifold); for (int i = 0; i < manifold.PointCount; ++i) { maxImpulse = Math.Max(maxImpulse, impulse.Points[i].NormalImpulse); } if (maxImpulse > 40.0f) { // Flag the body for breaking. _break = true; } }
private bool PlayerEnemyOnCollision(Fixture fixtureA, Fixture fixtureB, Contact contact) { if (!((fixtureB.CollisionFilter.CollisionCategories & (Category)Global.CollisionCategories.Light) == (Category)Global.CollisionCategories.Light) && !((fixtureB.CollisionFilter.CollisionCategories & (Category)Global.CollisionCategories.Enemy) == (Category)Global.CollisionCategories.Enemy)) { Vector2 down = new Vector2(0.0f, 1.0f); Manifold manifold; contact.GetManifold(out manifold); float angle = Math.Abs(Vector2.Dot(manifold.LocalNormal, down)); if (angle > 0.99f) { OnGround = true; groundCache.Add(fixtureB); } if (angle < 0.15f && angle > -0.15f) { OnWall = true; } } if ((fixtureB.CollisionFilter.CollisionCategories & (Category)Global.CollisionCategories.PlayerBullet) == (Category)Global.CollisionCategories.PlayerBullet) { // decrement enemy health Health -= 50; } return true; }
bool OnCollision(Fixture fixtureA, Fixture fixtureB, Contact contact) { Vector2 movementBefore = body.LinearVelocity; body.LinearVelocity = new Vector2(body.LinearVelocity.X, 0); Block block=null; foreach (Entity e in game.entities) { if (e is Block) { Block b = (Block)e; if(b.fixture.Equals(fixtureB)) { block = b; } } } if (contact.IsTouching()) { if (isMagnet(fixtureB)) return true; Manifold colis = new Manifold(); contact.GetManifold(out colis); Vector2 pColis = colis.LocalNormal; if (pColis.X == 0 && pColis.Y == 1) { onGround = true; modes = Modes.GROUND; return true; } if (pColis.X != 0 && pColis.Y == 0) { collisionRec = getBlockFromFixture(fixtureB); if (fixtureB.Body.Rotation % 45 != 0) { onGround = true; modes = Modes.GROUND; return false; } if (onGround) { modes = Modes.WALL; return false; } float direction = inputState.GetJoyDirection(); float x = (float)Math.Sin(direction); if (pColis.X > 0) isWallOnRight = true; else isWallOnRight = false; float xMomentum = 0; if (movementBefore.Y > 0) { xMomentum = Math.Abs(body.LinearVelocity.X * 0.3f); } else if (movementBefore.Y < 0) { xMomentum = -Math.Abs(body.LinearVelocity.X * 0.8f); } XboxInput xbi = (XboxInput)inputState; if (xbi.getYDirection() < 0 || Keyboard.GetState().IsKeyDown(Keys.Up) || Keyboard.GetState().IsKeyDown(Keys.W)) xMomentum += xbi.getYDirection() * 4f; else xMomentum = 0; body.LinearVelocity = new Vector2(0, body.LinearVelocity.Y + xMomentum); //body.IgnoreGravity = true; onGround = true; onGround = true; modes = Modes.WALL; ignoreInput = 2; return false; } } return true; }
public static float GetMaxCollisionForce(Contact contact) { float maxImpulse = 0.0f; Manifold manifold; contact.GetManifold(out manifold); for (int i = 0; i < manifold.PointCount; ++i) { maxImpulse = Math.Max(maxImpulse, manifold.Points[i].NormalImpulse); } return maxImpulse; }
private bool Body_OnCollision(Fixture fixturea, Fixture fixtureb, Contact contact) { if (!Convert.ToString(fixtureb.UserData).Equals("wall") && !Convert.ToString(fixtureb.UserData).Contains("ship")) { if (fixtureb.Body.IsBullet) { String data = Convert.ToString(fixtureb.UserData); String[] splitdata = data.Split(':'); String shotType = splitdata[0]; int shotEffect = Convert.ToInt32(splitdata[1]); switch (shotType) { case ("standard"): { this.damageTaken += (shotEffect / 2); break; } } } } else { if (fixedJoint == null && Convert.ToString(fixtureb.UserData).Contains("ship")) { Manifold manifold; contact.GetManifold(out manifold); fixedJoint = new DistanceJoint(base.mSpriteBody, fixtureb.Body, new Vector2(0, 0), manifold.Points[0].LocalPoint); fixedJoint.CollideConnected = true; mworld.AddJoint(fixedJoint); } this.contactMade = true; } return true; }