private LaserBeam( GameplayScreen screen ) : base(screen) { body = new PhysPolygon( 0f, beamThickness, Vector2.Zero, 1f ); body.Collided += HandlePlayerCollision; body.Flags = BodyFlags.Anchored | BodyFlags.Ghost; }
FloorBlock( GameplayScreen screen ) : base(screen) { BoundingPolygon = new PhysPolygon( Size, Height, Vector2.Zero, 1 ); BoundingPolygon.Elasticity = 1f; BoundingPolygon.Friction = 1.5f; BoundingPolygon.Flags = BodyFlags.Anchored; BoundingPolygon.Parent = this; BoundingPolygon.Collided += KillSelfIfPwnt; }
private static float GetMomentOfInertia( PhysPolygon poly ) { float sum = 0f; foreach ( Vector2 vert in poly.Vertices ) sum += ( vert - poly.Position ).LengthSquared(); return ( ( poly.Mass / poly.Vertices.Length ) * sum ); }
public Boundary( GameplayScreen screen, float left, float right, float rowStart, float rowSpacing ) : base(screen) { Left = left; Right = right; lastFrame = new GameTime( TimeSpan.FromSeconds( 0 ), TimeSpan.FromSeconds( 0 ), TimeSpan.FromSeconds( 1f / 30f ), TimeSpan.FromSeconds( 1f / 60 ) ); this.rowSpacing = rowSpacing; this.rowStart = rowStart; minHoleDist = ( FloorBlock.Height + Size ) / 2f; lastHole = rowStart; lastGoldenShake = 0; DrawOrder = 7; // this is for objects, such as powerups and players, so they can travel through the tubes objects = new List<BoundaryTubeObject>( 10 ); for ( int i = 0; i < 10; ++i ) objects.Add( new BoundaryTubeObject() ); // left polygon polyLeft = new PhysPolygon( polyWidth, 100f, new Vector2( left - halfPolyWidth, 0f ), 1f ); polyLeft.Elasticity = 1f; polyLeft.Friction = 1.5f; polyLeft.Flags = BodyFlags.Anchored; polyLeft.Parent = this; screen.PhysicsSpace.AddBody( polyLeft ); // right polygon polyRight = new PhysPolygon( polyWidth, 100f, new Vector2( right + halfPolyWidth, 0f ), 1f ); polyRight.Elasticity = 1f; polyRight.Friction = 1.5f; polyRight.Flags = BodyFlags.Anchored; polyRight.Parent = this; screen.PhysicsSpace.AddBody( polyRight ); // model cageModel = Screen.Content.Load<InstancedModel>( "Models/cageTile" ); cageHoleModel = Screen.Content.Load<InstancedModel>( "Models/cageHole" ); teeModel = Screen.Content.Load<InstancedModel>( "Models/tubeTee" ); cupModel = Screen.Content.Load<InstancedModel>( "Models/tubeCup" ); Camera camera = screen.Camera; float dist = camera.Position.Z + Size / 2f; float tanFovyOverTwo = (float)Math.Tan( camera.Fov / 2f ); deathLine = dist * tanFovyOverTwo + Size / 2f; topLine = camera.Position.Y + deathLine - Size; lastTopY = camera.Position.Y + deathLine; rows = (int)Math.Ceiling( 2f * deathLine / Size ); nTransforms = rows * 2; rotateL = new Matrix( 0, 0,-1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 ); rotateR = new Matrix( 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1 ); rotateZ = new Matrix( 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); flip = new Matrix(-1, 0, 0, 0, 0,-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); scale = Matrix.CreateScale( Size ); sidePieces = new SidePiece[nTransforms]; for ( int i = 0; i < nTransforms; ++i ) { sidePieces[i] = new SidePiece(); SidePiece piece = sidePieces[i]; int row = i % rows; bool onLeftSide = i / rows == 0; piece.Hole = false; piece.CagePosition = new Vector3( onLeftSide ? Left : Right, topLine - row * Size, 0f ); Matrix scaleRotate = scale * ( onLeftSide ? rotateL : rotateR ); piece.CageTransform = scaleRotate * Matrix.CreateTranslation( piece.CagePosition ); piece.TubePosition = piece.CagePosition + new Vector3( onLeftSide ? -Size / 2 : Size / 2, 0, 0 ); piece.TubeTransform = scale * Matrix.CreateTranslation( piece.TubePosition ); piece.Tube = TubePattern.Cup; } }
private static Collision PolygonVsPolygon( PhysPolygon bodyA, PhysPolygon bodyB, float elapsed ) { return new Collision(); }
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; }