Ejemplo n.º 1
0
        private static Collision CircleVsCircle( PhysCircle bodyA, PhysCircle bodyB, float elapsed )
        {
            Collision result = new Collision();

              Vector2 normal;

              // if intersecting at t = 0
              Vector2 popoutPos = Vector2.Zero;
              bool popout = false;

              float totalRadius = bodyA.Radius + bodyB.Radius;
              if ( Vector2.DistanceSquared( bodyA.Position, bodyB.Position ) < .95f * ( totalRadius * totalRadius ) )
              {
            if ( !bodyA.Flags.HasFlags( BodyFlags.Ghost ) && !bodyB.Flags.HasFlags( BodyFlags.Ghost ) )
            {
              normal = Vector2.Normalize( bodyA.Position - bodyB.Position );
              popoutPos = bodyB.Position + 1.0001f * totalRadius * normal - bodyA.Velocity * elapsed;
              popout = true;
            }
            else
            {
              return new Collision( true, 0f, bodyA, bodyB, Vector2.Zero, Vector2.Zero );
            }
              }

              // if not intersecting at t = 0
              Vector2 relVel = Vector2.Subtract( bodyA.Velocity, bodyB.Velocity );
              Vector2 relVelByT = Vector2.Multiply( relVel, elapsed );
              Vector2 posAtT = Vector2.Add( bodyA.Position, relVelByT );

              float time;
              if ( Geometry.SegmentVsCircle( out time, out normal, bodyA.Position, posAtT, bodyB.Position, bodyA.Radius + bodyB.Radius ) )
              {
            float timeStep = Math.Max( 0f, time * elapsed );
            result.Time = timeStep;
            result.Collided = true;
            result.Normal = normal;
            result.BodyA = bodyA;
            result.BodyB = bodyB;

            Vector2 dispAtCollision = ( bodyB.Position + bodyB.Velocity * timeStep ) - ( bodyA.Position + bodyA.Velocity * timeStep );
            result.Intersection = bodyA.Position + ( bodyA.Radius / ( bodyA.Radius + bodyB.Radius ) ) * dispAtCollision;
              }

              if ( popout && !result.Collided )
            bodyA.Position = popoutPos;
              return result;
        }
Ejemplo n.º 2
0
        private static Collision CircleVsPolygon( PhysCircle bodyA, PhysPolygon bodyB, float elapsed )
        {
            Vector2 relVel, relVelByT, posAtT;
              Vector2.Subtract( ref bodyA.Velocity, ref bodyB.Velocity, out relVel );
              Vector2.Multiply( ref relVel, elapsed, out relVelByT );
              Vector2.Add( ref bodyA.Position, ref relVelByT, out posAtT );

              Vector2[] verts = bodyB.TransformedVertices;
              Vector2 lastVert = verts.Last();

              Collision bestResult = new Collision();
              bestResult.Time = float.MaxValue;

              Vector2 popoutPos = Vector2.Zero;
              Vector2 popoutNormal = Vector2.Zero;
              Vector2 popoutIsect = Vector2.Zero;
              int popoutPriority = 0;

              int nVerts = verts.Length;
              for ( int i = 0; i < nVerts; ++i )
              {
            Vector2 vert = verts[i];
            Vector2 edge = Vector2.Subtract( vert, lastVert );
            Vector2 n = new Vector2( edge.Y, -edge.X );

            float time;
            Vector2 normal;

            // ball is moving towards the segment
            if ( Vector2.Dot( n, relVel ) < 0.0f )
            {
              n.Normalize();
              Vector2 offset = Vector2.Multiply( n, bodyA.Radius );
              Vector2 q0 = lastVert + offset;
              Vector2 q1 = vert + offset;

              // check if intersecting segment at elapsed = 0
              if ( Geometry.SegmentVsCircle( out time, out normal, lastVert, vert, bodyA.Position, bodyA.Radius ) )
              {
            if ( time < .95f && popoutPriority != 1 )
            {
              float dot = Vector2.Dot( normal, -n );
              if ( dot > 0f )
              {
                popoutNormal = -normal;
                popoutIsect = edge * time;
                popoutPos = bodyA.Position + n * 1.0001f * bodyA.Radius * ( 1f - dot ) - bodyA.Velocity * elapsed;
                popoutPriority = 1;
              }
            }
              }

              if ( Geometry.SegmentVsSegment( out time, bodyA.Position, posAtT, q0, q1 ) )
              {
            // if collision with segment (and polygon is convex), we're done
            if ( bodyB.Convex )
              return new Collision( true, time * elapsed, bodyA, bodyB, n, bodyA.Position + elapsed * time * ( bodyA.Velocity ) - n * bodyA.Radius );
            else if ( time * elapsed < bestResult.Time )
              bestResult = new Collision( true, time * elapsed, bodyA, bodyB, n, bodyA.Position + elapsed * time * ( bodyA.Velocity ) - n * bodyA.Radius );
              }
            }

            // CHECK CORNER
            // inside circle?
            if ( Vector2.DistanceSquared( bodyA.Position, vert ) < ( bodyA.Radius * bodyA.Radius ) )
            {
              if ( popoutPriority == 0 )
              {
            popoutPriority = 2;
            normal = Vector2.Normalize( bodyA.Position - vert );
            popoutPos = vert + bodyA.Radius * normal;
            popoutNormal = normal;
            popoutIsect = vert;
              }
            }

            // intersecting circle
            if ( Geometry.SegmentVsCircle( out time, out normal, bodyA.Position, posAtT, vert, bodyA.Radius ) )
            {
              // additional checks to see if hitting correct sector of circle
              if ( Vector2.Dot( normal, edge ) > 0.0f )
              {
            Vector2 nextVert = verts[( i + 1 ) % nVerts];
            Vector2 edge2;
            Vector2.Subtract( ref nextVert, ref vert, out edge2 );
            if ( Vector2.Dot( normal, edge2 ) < 0.0f )
            {
              if ( bodyB.Convex )
                return new Collision( true, time * elapsed, bodyA, bodyB, normal, vert + elapsed * time * bodyB.Velocity );
              else if ( time * elapsed < bestResult.Time )
                bestResult = new Collision( true, time * elapsed, bodyA, bodyB, normal, vert + elapsed * time * bodyB.Velocity );
            }
              }
            }

            lastVert = vert;
              }

              // hack to keep objects from penetrating in rare cases
              if ( !bestResult.Collided && popoutPriority != 0 )
              {
            if ( !bodyA.Flags.HasFlags( BodyFlags.Ghost ) && !bodyB.Flags.HasFlags( BodyFlags.Ghost ) )
              bodyA.Position = popoutPos;
            else return new Collision( true, 0, bodyA, bodyB, popoutNormal, popoutIsect );
              }

              return bestResult;
        }
Ejemplo n.º 3
0
        public bool HandlePowerupCollision( Collision result )
        {
            if ( owner != null ) return true; // maybe have the powerup avoid the player?

              Player player = result.BodyB.Parent as Player;
              if ( player != null && player.Powerup == null )
              {
            UpdateSelf -= SineWave;
            UpdateSelf += LockToPlayer;

            owner = player;
            LockToPlayerSpring.SetSource( Body.Position - player.BoundingCircle.Position );
            LockToPlayerSpring.SetDest( new Vector2( 0f, .75f * Player.Size ) );
            SizeSpring.SetDest( .3f );
            RotationSpring.Active = false;

            CollectedAt = screen.AccumulatedTime;

            player.Powerup = this;

            owner.Position = new Vector3( owner.BoundingCircle.Position, 0 );
            GameCore.Instance.AudioManager.Play3DCue( "sillySpin", owner, 1f );
              }

              return true;
        }
Ejemplo n.º 4
0
        public bool HandleShakeCollision( Collision result )
        {
            if ( owner == null && result.BodyB.Parent is Player )
              {
            owner = (Player)result.BodyB.Parent;
            if ( !Screen.GameOver )
              owner.HUD.AddPoints( 1 );

            Screen.PhysicsSpace.RemoveBody( result.BodyA );
            Screen.ObjectTable.MoveToTrash( this );
            alive = false;

            owner.Position = new Vector3( owner.BoundingCircle.Position, 0 );
            GameCore.Instance.AudioManager.Play3DCue( "collect", owner, .8f );

            // make sparkle particles
            PixieParticleSystem system = Screen.PixieParticleSystem;
            for ( int i = 0; i < 20; ++i )
            {
              Vector3 pos = rand.NextVector3();
              if ( pos != Vector3.Zero )
              {
            pos.Normalize();
            pos *= ( 1.25f * Body.Radius * (float)rand.NextDouble() );
              }
              system.AddParticle( new Vector3( Body.Position, Player.Size ) + pos, Vector3.Zero/*.5f * pos*/ );
            }
              }

              return true;
        }
Ejemplo n.º 5
0
        private bool HandlePlayerCollision( Collision result )
        {
            Player player = result.BodyB.Parent as Player;
              if ( player != null && player != parent && !player.Seizuring && !pwntPlayers.Contains( player ) )
              {
            player.TakeLaserUpAss( result );
            pwntPlayers.Add( player );

            IAudioEmitter emitter = DummyAudioEmitter.InstanceAtPos( new Vector3( result.Intersection, 0 ) );
            GameCore.Instance.AudioManager.Play3DCue( "laserHit", emitter, 1 );
              }

              return true;
        }
Ejemplo n.º 6
0
        public bool HandleGoldenShakeCollision( Collision result )
        {
            if ( owner != null ) return true; // maybe have the powerup avoid the player?

              Player player = result.BodyB.Parent as Player;
              if ( player != null )
              {
            if ( player.Powerup != null )
              player.Powerup.Use();

            UpdateSelf -= SineWave;
            UpdateSelf += LockToPlayer;

            owner = player;
            LockToPlayerSpring.SetSource( Body.Position - player.BoundingCircle.Position );
            LockToPlayerSpring.SetDest( new Vector2( 0f, .75f * Player.Size ) );
            SizeSpring.SetDest( .3f );
            RotationSpring.Active = false;

            player.HUD.AddPoints( 7 );

            player.Powerup = this;

            owner.Position = new Vector3( owner.BoundingCircle.Position, 0 );
            GameCore.Instance.AudioManager.Play3DCue( "collect", owner, .9f );
            GameCore.Instance.AudioManager.Play2DCue( "fanfare", 1f );

            GameplayScreen.Instance.EndGame();
              }

              return true;
        }
Ejemplo n.º 7
0
        private bool KillSelfIfPwnt( Collision result )
        {
            Player player = result.BodyB.Parent as Player;

              if ( player != null && ( player.Respawning || player.Crushing ) )
              {
            if ( !BoundingPolygon.Flags.HasFlags( BodyFlags.Ghost ) )
            {
              // remove the block
              BoundingPolygon.Flags |= BodyFlags.Ghost;
              Screen.PhysicsSpace.RemoveBody( BoundingPolygon );
              Screen.ObjectTable.MoveToTrash( this );
              alive = false;

              // rumble the controller
              if ( player.PlayerIndex.IsHuman() )
            GameCore.Instance.Rumble.RumbleLow( player.PlayerIndex, .25f, .3f );

              // add the exploding block particle system
              Vector3 position = new Vector3( BoundingPolygon.Position, 0f );
              ModelExplosion explosion = ModelExplosion.CreateExplosion( position, Size,
                                                                     ShatteredModel, explosionSettings );
              Screen.ParticleManager.Add( explosion );
              GameCore.Instance.AudioManager.Play3DCue( "blockExplosion", DummyAudioEmitter.InstanceAtPos( position ), 1f );

              return false;
            }
              }
              return true;
        }
Ejemplo n.º 8
0
        public static void ResolveCollision( Collision result )
        {
            PhysBody bodyA = result.BodyA;
              PhysBody bodyB = result.BodyB;

              bodyA.Touching = bodyB;
              bodyB.Touching = bodyA;

              bodyA.TouchNormal = result.Normal;
              bodyB.TouchNormal = -result.Normal;

              if ( !bodyA.OnCollision( result ) || !bodyB.OnCollision( result.GetInvert() ) )
            return;

              float e = Math.Min( bodyA.Elasticity, bodyB.Elasticity );
              float u = Math.Max( bodyA.Friction, bodyB.Friction );
              Vector2 n = result.Normal;

              // adjust normal in case of floating point error
              if ( n.X == 0f && Math.Abs( n.Y ) != 1f )
            n.Y = Math.Sign( n.Y );
              else if ( n.Y == 0f && Math.Abs( n.X ) != 1f )
            n.X = Math.Sign( n.X );

              Vector2 rA = result.Intersection - bodyA.Position;
              Vector2 rB = result.Intersection - bodyB.Position;
              Vector2 vA = bodyA.Velocity + Geometry.Perp( rA ) * -bodyA.AngularVelocity;
              Vector2 vB = bodyB.Velocity + Geometry.Perp( rB ) * -bodyB.AngularVelocity;
              Vector2 vAB = vA - vB;
              Vector2 fricDir = -( vAB - Vector2.Dot( vAB, n ) * n );

              if ( fricDir != Vector2.Zero )
            fricDir.Normalize();
              if ( float.IsInfinity( fricDir.X ) || float.IsInfinity( fricDir.Y ) )
            fricDir = Vector2.Zero;

              float oneByMassA = 1f / bodyA.Mass;
              float oneByMassB = 1f / bodyB.Mass;
              float oneByIA = 1f / bodyA.MomentOfInertia;
              float oneByIB = 1f / bodyB.MomentOfInertia;

              if ( bodyB.Flags.HasFlags( BodyFlags.Anchored ) )
              {
            oneByMassB = 0f;
            oneByIB = 0f;
              }

              float dotASq = Geometry.PerpDot( rA, n ); dotASq *= dotASq;
              float dotBSq = Geometry.PerpDot( rB, n ); dotBSq *= dotBSq;
              float jc = Vector2.Dot( vAB, n ) / ( oneByMassA + oneByMassB + dotASq * oneByIA + dotBSq * oneByIB );

              if ( jc > -.7f )
            jc = -.7f;

              dotASq = Geometry.PerpDot( rA, fricDir ); dotASq *= dotASq;
              dotBSq = Geometry.PerpDot( rB, fricDir ); dotBSq *= dotBSq;
              float jf = Vector2.Dot( vAB, fricDir ) / ( oneByMassA + oneByMassB + dotASq * oneByIA + dotBSq * oneByIB );

              if ( Math.Abs( jf ) > Math.Abs( jc * u ) )
            jf = Math.Abs( jc * u ) * Math.Sign( jc );

              Vector2 impulse = ( jc * -( 1f + e ) ) * n - jf * fricDir;

              bodyA.LastImpulse = impulse;
              bodyB.LastImpulse = -impulse;

              bodyA.Velocity += ( impulse * oneByMassA );
              bodyB.Velocity -= ( impulse * oneByMassB );

              bodyA.AngularVelocity += ( Geometry.PerpDot( rA, impulse ) * oneByIA );
              bodyB.AngularVelocity -= ( Geometry.PerpDot( rB, impulse ) * oneByIB );

              bodyA.OnResponse( result );
              bodyB.OnResponse( result.GetInvert() );

              bodyA.CollisionList.Add( bodyB );
              bodyB.CollisionList.Add( bodyA );
        }
Ejemplo n.º 9
0
        private bool HandleCollisionResponse( Collision result )
        {
            PhysCircle circle = BoundingCircle;

              // keep track of last time of collision (for jumping)
              lastCollision = Screen.AccumulatedTime;

              // set emitter position
              SparkParticleSystem sparkSystem = Screen.SparkParticleSystem;

              string sound = null;
              if ( result.BodyB.Parent is FloorBlock )
            sound = pvBlockSound;
              if ( result.BodyB.Parent is Boundary || result.BodyB.Parent is Shelves )
            sound = pvCageSound;

              if ( sound != null )
              {
            float impulse = result.BodyA.LastImpulse.Length();
            if ( impulse > 10f )
            {
              float volume = Math.Min( 1f, impulse / ( 100 * BoundingCircle.Mass ) );
              soundPosition = new Vector3( result.Intersection, 0 );
              GameCore.Instance.AudioManager.Play3DCue( sound, this, volume );
              if ( PlayerIndex.IsHuman() )
            GameCore.Instance.Rumble.RumbleHigh( PlayerIndex, .2f, .15f );
            }
              }

              //// play collision sound
              //Player playerB = result.BodyB.Parent as Player;
              //if ( playerB != null )
              //{
              //  float impulseMag = result.BodyB.LastImpulse.Length();
              //  //if ( impulseMag > .5f )
              //  {
              //    float volume = Math.Min( .85f, impulseMag / 30f );
              //    soundPosition = new Vector3( result.Intersection, 0 );
              //    Screen.AudioManager.Play3DCue( plasticHitSound, this, volume );
              //  }
              //}

              Vector3 position = new Vector3( result.Intersection, 0f );
              //emitter.Position = position;

              // spit some particles
              Vector2 r = Vector2.Normalize( result.Intersection - result.BodyA.Position );
              Vector2 vp = circle.AngularVelocity * circle.Radius * new Vector2( -r.Y, r.X );
              Vector2 dir = circle.Velocity;

              Vector2 vpn = Vector2.Normalize( vp );
              Vector3 direction = new Vector3( particleCoordU * vpn + particleCoordV * -r, 0f );
              //factory.Direction = new Vector3( particleCoordU * vpn + particleCoordV * -r, 0f );

              Vector2 sum = vp + dir;
              if ( sum != Vector2.Zero )
              {
            float sumLength = sum.Length();
            if ( sumLength > .25f )
            {
              float coneAngle = MathHelper.ToRadians( 30 );
              Vector3 velocity = random.NextConeDirection( random.NextFloat( 2, 4 ) * direction, coneAngle );
              sparkSystem.AddParticle( position, velocity );
            }
              }

              return true;
        }
Ejemplo n.º 10
0
        private bool HandleCollision( Collision result )
        {
            //Player playerB = result.BodyB.Parent as Player;
              //if ( playerB != null )
              //{
              //  // squash him if he's tiny and touching another object
              //  if ( playerB.Scale < squashSize * Size )//&& result.BodyB.Touching != result.BodyA )
              //  {
              //    Debug.WriteLine( "Squash!" );
              //  }
              //}

              // play collision sound
              Player playerB = result.BodyB.Parent as Player;
              if ( playerB != null )
              {
            float relVelMag = ( result.BodyA.Velocity - result.BodyB.Velocity ).Length();
            if ( relVelMag > 3f )
            {
              float volume = Math.Min( .75f, relVelMag / 100f );
              soundPosition = new Vector3( result.Intersection, 0 );
              GameCore.Instance.AudioManager.Play3DCue( pvpSound, this, volume );
              if ( PlayerIndex.IsHuman() )
            GameCore.Instance.Rumble.RumbleHigh( PlayerIndex, .2f, .15f );
            }
              }

              return true;
        }
Ejemplo n.º 11
0
        public void TakeLaserUpAss( Collision result )
        {
            if ( Respawning ) return;

              seizureBegin = Screen.AccumulatedTime;
              seizureCollision = result;
              BoundingCircle.Flags |= BodyFlags.Anchored;
              BoundingCircle.Velocity = Vector2.Zero;
              BoundingCircle.AngularVelocity = 0;

              if ( PlayerIndex.IsHuman() )
            GameCore.Instance.Rumble.RumbleHigh( PlayerIndex, .4f, seizureDuration );
        }