예제 #1
0
        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;
        }
예제 #2
0
        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;
            }
        }
예제 #3
0
        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;
            }
        }
예제 #5
0
        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;
        }
예제 #6
0
        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;

        }
예제 #8
0
        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;
        }