public override void Update(GameTime time) { using (new PerformanceReporter(Game)) { if (Game.Match.State != SessionState.Running) { return; } var worldState = Game.Match.World; float elapsedSeconds = (float)time.ElapsedGameTime.TotalSeconds; PreparePhysicsEngine(worldState); PhysicsStep(worldState, elapsedSeconds); // Update shots var shots = (from e in worldState.Entities where e is Shot select(e as Shot)) .ToArray(); foreach (var shot in shots) { if (shot.ShotType == Shot.ShotType_T.InstantHit) { Vector2 targetPos = Vector2.Zero; Fixture targetFixture = null; Func <Fixture, Vector2, Vector2, float, float> raycastCallback = (Fixture fixture, Vector2 position, Vector2 normal, float fraction) => { targetFixture = fixture; targetPos = position; return(fraction); }; PhysicsWorld.RayCast(raycastCallback, shot.Position, shot.Position + 100 * shot.Velocity); if (TerrainBodies.Contains(targetFixture.Body)) { // Shot collides with terrain shot.OnTerrainCollision(worldState.StaticGeometry, targetPos); } else if (EntityIdByPhysicsBody.ContainsKey(targetFixture.Body)) { int entityId = EntityIdByPhysicsBody[targetFixture.Body]; Entity entity = worldState.EntityById(entityId); // Mutual collision entity.OnEntityCollision(shot); shot.OnEntityCollision(entity); } worldState.RemoveEntity(shot); } else { shot.update(elapsedSeconds); } } } }
public static bool hasLineOfSight(Vector2 eye, Vector2 farthestGaze, Predicate<Fixture> belongsToTarget, World w) { bool hasLOS = false; w.RayCast((f, p, n, fr) => { if (belongsToTarget(f)) hasLOS = true; return 0; // terminate the ray cast }, eye, farthestGaze); return hasLOS; }
public bool InLight(World w, Light2D light) { List<float> fractions = new List<float>(); for (float i = -24f; i <= 24f; i += 24f) { Vector2 start = light.Position * MainGame.PIXEL_TO_METER; Vector2 end = torso.Position + Vector2.UnitY * i * MainGame.PIXEL_TO_METER - start; end.Normalize(); end *= (light.Range - 32) * MainGame.PIXEL_TO_METER; end += start; fractions.Clear(); float foundFr = (end - start).Length(); w.RayCast((f, p, n, fr) => { this.p = p; if (f.Body.UserData == this) foundFr = fr; if (f.Body.UserData == "hasshadow" || f.UserData == "hasshadow" || f.Body.UserData == this) { fractions.Add(fr); return fr; } else return -1; }, start, end); fractions.Sort(); if (fractions.Count > 0 && fractions[0] == foundFr) return true; } return false; }
public void Update(World w) { // Animate texture currentTexture.Update(); if (!onGround) { if (currentTexture != texJump) currentTexture = texJump; int frame = (int)(torso.LinearVelocity.Y * MainGame.METER_TO_PIXEL) / 16 + 3; if (frame < 0) frame = 0; else if (frame > 8) frame = 8; texJump.Frame = frame; } // Walking if (Keyboard.GetState().IsKeyDown(Keys.A)) { facingLeft = true; axis.MotorSpeed = 2.5f * -MathHelper.TwoPi; if (onGround) { currentTexture = texRun; } if (!onGround && torso.LinearVelocity.X > -2) torso.ApplyForce(ref leftAirForce); } else if (Keyboard.GetState().IsKeyDown(Keys.D)) { facingLeft = false; axis.MotorSpeed = 2.5f * MathHelper.TwoPi; if (onGround) { currentTexture = texRun; } if (!onGround && torso.LinearVelocity.X < 2) torso.ApplyForce(ref rightAirForce); } else { if (onGround) currentTexture = texIdle; axis.MotorSpeed = 0; } if (!onGround) axis.MotorEnabled = false; else axis.MotorEnabled = true; // Check if you're standing on something onGround = false; start = legs.Position + new Vector2(0, 24 * MainGame.PIXEL_TO_METER); end = start + new Vector2(0, 24 * MainGame.PIXEL_TO_METER); for (int i = -30; i <= 30; i += 15) { start.X = legs.Position.X + i * MainGame.PIXEL_TO_METER; end.X = legs.Position.X + i * MainGame.PIXEL_TO_METER; w.RayCast((f, p, n, fr) => { normal = n; if (f != null) onGround = true; else onGround = false; return 0; }, start, end); if (onGround) break; } // Jump if (Keyboard.GetState().IsKeyDown(Keys.W)) { if (!pressW) { if (onGround) { if (Keyboard.GetState().IsKeyDown(Keys.A)) torso.LinearVelocity -= 0.7f * Vector2.UnitX; if (Keyboard.GetState().IsKeyDown(Keys.D)) torso.LinearVelocity += 0.7f * Vector2.UnitX; torso.LinearVelocity = new Vector2(torso.LinearVelocity.X, -8); holdW = true; } pressW = true; } } else { pressW = false; holdW = false; } if (holdW && torso.LinearVelocity.Y < 0) torso.ApplyForce(jumpForce); prevVelocity = torso.LinearVelocity; }
/// <summary> /// This is a high-level function to cuts fixtures inside the given world, using the start and end points. /// Note: We don't support cutting when the start or end is inside a shape. /// </summary> /// <param name="world">The world.</param> /// <param name="start">The startpoint.</param> /// <param name="end">The endpoint.</param> /// <returns>True if the cut was performed.</returns> public static bool Cut(World world, Vector2 start, Vector2 end) { List<Fixture> fixtures = new List<Fixture>(); List<Vector2> entryPoints = new List<Vector2>(); List<Vector2> exitPoints = new List<Vector2>(); //We don't support cutting when the start or end is inside a shape. if (world.TestPoint(start) != null || world.TestPoint(end) != null) return false; //Get the entry points world.RayCast((f, p, n, fr) => { fixtures.Add(f); entryPoints.Add(p); return 1; }, start, end); //Reverse the ray to get the exitpoints world.RayCast((f, p, n, fr) => { exitPoints.Add(p); return 1; }, end, start); //We only have a single point. We need at least 2 if (entryPoints.Count + exitPoints.Count < 2) return false; for (int i = 0; i < fixtures.Count; i++) { // can't cut circles or edges yet ! if (fixtures[i].Shape.ShapeType != ShapeType.Polygon) continue; if (fixtures[i].Body.BodyType != BodyType.Static) { //Split the shape up into two shapes Vertices first; Vertices second; SplitShape(fixtures[i], entryPoints[i], exitPoints[i], out first, out second); //Delete the original shape and create two new. Retain the properties of the body. if (first.CheckPolygon() == PolygonError.NoError) { Body firstFixture = BodyFactory.CreatePolygon(world, first, fixtures[i].Shape.Density, fixtures[i].Body.Position); firstFixture.Rotation = fixtures[i].Body.Rotation; firstFixture.LinearVelocity = fixtures[i].Body.LinearVelocity; firstFixture.AngularVelocity = fixtures[i].Body.AngularVelocity; firstFixture.BodyType = BodyType.Dynamic; } if (second.CheckPolygon() == PolygonError.NoError) { Body secondFixture = BodyFactory.CreatePolygon(world, second, fixtures[i].Shape.Density, fixtures[i].Body.Position); secondFixture.Rotation = fixtures[i].Body.Rotation; secondFixture.LinearVelocity = fixtures[i].Body.LinearVelocity; secondFixture.AngularVelocity = fixtures[i].Body.AngularVelocity; secondFixture.BodyType = BodyType.Dynamic; } world.RemoveBody(fixtures[i].Body); } } return true; }
public static bool WithinLineOfSight(World world, Vector2 startPosition, Vector2 endPosition) { if (startPosition == endPosition) return true; bool found = true; world.RayCast((f, pt, n, fr) => { if (f.CollisionCategories == Category.Cat2) { found = false; return 0; } return 1; }, startPosition, endPosition); return found; }
static void Main() { window = new RenderWindow(new VideoMode(1280, 720), "", Styles.Close); window.SetFramerateLimit(60); window.Closed += (sender, eventArgs) => window.Close(); shipTex = new Texture("Ship.png"); asteroidTex = new Texture("Asteroid.png"); var shipSpr = new Sprite(shipTex); shipSpr.Origin = new Vector2f(shipTex.Size.X / 2f, shipTex.Size.Y / 2f); var asteroidSpr = new Sprite(asteroidTex); asteroidSpr.Origin = new Vector2f(asteroidTex.Size.X / 2f, asteroidTex.Size.Y / 2f); world = new World(new Vector2(0, 0)); var debugView = new SFMLDebugView(world); debugView.AppendFlags(DebugViewFlags.Shape); CreateBounds(20, 11.25f); var ship = CreateShip(); ship.Position = new Vector2(3, 1); ship.Rotation = 1.7f; var ship2 = CreateShip(); ship2.Position = new Vector2(3, 1); ship2.Rotation = 1.7f; var asteroid = CreateAsteroid(); asteroid.Position = new Vector2(4, 4); window.KeyPressed += (sender, eventArgs) => { if (eventArgs.Code == Keyboard.Key.Space) { CreateBullets(ship); } }; while (window.IsOpen()) { window.DispatchEvents(); if (Keyboard.IsKeyPressed(Keyboard.Key.W)) { ship.ApplyForce(ship.GetWorldVector(new Vector2(0.0f, -25.0f))); } if (Keyboard.IsKeyPressed(Keyboard.Key.S)) { ship.ApplyForce(ship.GetWorldVector(new Vector2(0.0f, 25.0f))); } if (Keyboard.IsKeyPressed(Keyboard.Key.A)) { ship.ApplyTorque(-10); } if (Keyboard.IsKeyPressed(Keyboard.Key.D)) { ship.ApplyTorque(10); } world.Step(1f / 60); window.Clear(Color.Black); shipSpr.Position = new Vector2f(ship.Position.X * 64, ship.Position.Y * 64); shipSpr.Rotation = (ship.Rotation * (180 / (float)Math.PI)); window.Draw(shipSpr); asteroidSpr.Position = new Vector2f(asteroid.Position.X * 64, asteroid.Position.Y * 64); asteroidSpr.Rotation = (asteroid.Rotation * (180 / (float)Math.PI)); window.Draw(asteroidSpr); var start = ship.Position; var step = (float)(2 * Math.PI) / 200; byte col = 0; var line = new VertexArray(PrimitiveType.Lines, 2); line[0] = new Vertex(new Vector2f(start.X * 64, start.Y * 64), Color.White); for (var dir = 0f; dir <= 2 * Math.PI; dir += step) { float min = 100; byte res = 255; var point = start + LengthDir(dir, 20); world.RayCast((f, p, n, fr) => { if (fr > min) return 1; min = fr; res = (byte)(fr * 255); point = p; return fr; }, start, point); line[0] = new Vertex(new Vector2f(start.X * 64, start.Y * 64), new Color(col, 0, 0)); line[1] = new Vertex(new Vector2f(point.X * 64, point.Y * 64), new Color(col, 0, 0)); window.Draw(line); col++; } debugView.Draw(window); window.Display(); } }
protected override void beforeLoadBodies(World world, CustomProperties customWorldProperties) { int moduleEndPointsCount = _map.moduleEndPointsCount; Vector2 size = _map.moduleEndPoints[moduleEndPointsCount - 1] - _map.moduleEndPoints[moduleEndPointsCount - 2]; Vector2 randomFactor = new Vector2(Helpers.randomBetween(_rng, 0f, 1f), Helpers.randomBetween(_rng, 0f, 1f)); bool attachToCeiling = false; _offset = _map.moduleEndPoints[_map.moduleEndPoints.Count - 2] + size * randomFactor; if (customWorldProperties.tryGetBool("attachToCeiling", out attachToCeiling) && attachToCeiling) { Vector2 point = Vector2.Zero; // Raycast for a ceiling using the random position world.RayCast( (f, p, n, fr) => { if (f.Body.UserData == null) { return -1; } if (EntityManager.getCeilingComponent((int)f.Body.UserData) != null) { _offset = p; return fr; } else { return -1; } }, _offset + new Vector2(0f, 1000f), _offset + new Vector2(0f, -1000f)); } base.beforeLoadBodies(world, customWorldProperties); }
/// <summary> /// This is a high-level function to cuts fixtures inside the given world, using the start and end points. /// </summary> /// <param name="world">The world.</param> /// <param name="start">The startpoint.</param> /// <param name="end">The endpoint.</param> /// <param name="thickness">The thickness of the cut</param> public static void Cut(World world, Vector2 start, Vector2 end, float thickness) { List<Fixture> fixtures = new List<Fixture>(); List<Vector2> entryPoints = new List<Vector2>(); List<Vector2> exitPoints = new List<Vector2>(); // Get the entry points world.RayCast((f, p, n, fr) => { fixtures.Add(f); entryPoints.Add(p); return 1; }, start, end); // Reverse the ray to get the exitpoints world.RayCast((f, p, n, fr) => { exitPoints.Add(p); return 1; }, end, start); // We only have a single point. We need at least 2 if (entryPoints.Count + exitPoints.Count < 2) return; // There should be as many entry as exit points if (entryPoints.Count != exitPoints.Count) { if (entryPoints.Count > exitPoints.Count) { entryPoints.RemoveAt(entryPoints.Count - 1); fixtures.RemoveAt(fixtures.Count - 1); } if (exitPoints.Count > entryPoints.Count) { exitPoints.RemoveAt(exitPoints.Count - 1); fixtures.RemoveAt(fixtures.Count - 1); } } for (int i = 0; i < fixtures.Count; i++) { // can't cut circles yet ! if (fixtures[i].Shape.ShapeType != ShapeType.Polygon) continue; if (fixtures[i].Body.BodyType != BodyType.Static) { // Split the shape up into two shapes Vertices first; Vertices second; SplitShape(fixtures[i], entryPoints[i], exitPoints[i], thickness, out first, out second); // Delete the original shape and create two new. Retain the properties of the body. Fixture firstFixture = FixtureFactory.CreatePolygon(world, first, fixtures[i].Density, fixtures[i].Body.Position); firstFixture.Body.BodyType = BodyType.Dynamic; Fixture secondFixture = FixtureFactory.CreatePolygon(world, second, fixtures[i].Density, fixtures[i].Body.Position); secondFixture.Body.BodyType = BodyType.Dynamic; world.RemoveBody(fixtures[i].Body); } } }
/// <summary> /// This is a high-level function to cuts fixtures inside the given world, using the start and end points. /// Note: We don't support cutting when the start or end is inside a shape. /// </summary> /// <param name="world">The world.</param> /// <param name="start">The startpoint.</param> /// <param name="end">The endpoint.</param> /// <param name="thickness">The thickness of the cut</param> public static Vector2 Cut(World world, Vector2 start, Vector2 end, float thickness, Category collisionCategories = Category.None) { // The left side of the cut will remain part of the existing body; // the right side will be made into a new body List<Fixture> fixtures = new List<Fixture>(); List<Vector2> entryPoints = new List<Vector2>(); List<Vector2> exitPoints = new List<Vector2>(); List<RayCastResult> results = new List<RayCastResult>(); //float blockingFraction = float.MaxValue; Vector2 stoppingPoint = end; //We don't support cutting when the start or end is inside a shape. //if (world.TestPoint(start) != null || world.TestPoint(end) != null) // return; //Get the entry points world.RayCast((f, p, n, fr) => { RayCastResult r = new RayCastResult(); r.f = f; r.p = p; r.fr = fr; results.Add(r); return 1; }, start, end); results = results.OrderBy(p => p.fr).ToList(); foreach (RayCastResult r in results) { if ((r.f.CollisionCategories & collisionCategories) != Category.None) { stoppingPoint = r.p; break; } if (!r.f.TestPoint(ref end)) { if (world.FixtureCut != null) world.FixtureCut(r.f); fixtures.Add(r.f); entryPoints.Add(r.p); } } //Reverse the ray to get the exitpoints world.RayCast((f, p, n, fr) => { if (fixtures.Contains(f)) { exitPoints.Add(p); } return 1; }, end, start); Debug.Assert(entryPoints.Count == exitPoints.Count && entryPoints.Count == fixtures.Count); //Fixture containsEnd = world.TestPoint(end); //if (containsEnd != null) //{ // entryPoints.RemoveAt(0); // fixtures.Remove(containsEnd); //} //Fixture containsStart = world.TestPoint(start); //if (containsStart != null) //{ // exitPoints.RemoveAt(exitPoints.Count - 1); // fixtures.Remove(containsStart); //} //We only have a single point. We need at least 2 if (entryPoints.Count + exitPoints.Count < 2) return stoppingPoint; var query = (from fix in fixtures select fix.Body).Distinct(); foreach (Body b in query) { if (b == null || b.BodyType == BodyType.Static) continue; ContactEdge edge = b.ContactList; while (edge != null) { Contact c = edge.Contact; edge = edge.Next; world.ContactManager.Destroy(c); } List<Body> leftBodies = new List<Body>(); List<Body> rightBodies = new List<Body>(); //Body rightBody = new Body(world); List<Joint> leftJoints = new List<Joint>(); List<Joint> rightJoints = new List<Joint>(); foreach (Joint j in b.JointList) { if (isLeft(start, end, j.WorldAnchorA)) leftJoints.Add(j); else rightJoints.Add(j); } //List<Fixture> leftList = new List<Fixture>(); //List<Fixture> rightList = new List<Fixture>(); Fixture[] bodyFixtures = new Fixture[b.FixtureList.Count]; b.FixtureList.CopyTo(bodyFixtures); b.FixtureList.Clear(); //leftBodies.Add(b); // For each fixture that was sliced through... foreach (Fixture fix in (from f in bodyFixtures where fixtures.Contains(f) select f)) { int i = fixtures.IndexOf(fix); // split this in half and put the halves in the over/under lists Vertices first; Vertices second; SplitShape(fix, entryPoints[i], exitPoints[i], thickness, out first, out second); if (!SanityCheck(first) || !SanityCheck(second)) { continue; } PolygonShape leftShape = new PolygonShape(first, fix.Shape.Density); PolygonShape rightShape = new PolygonShape(second, fix.Shape.Density); if (!b.FixtureList.Any()) { if (leftShape.MassData.Area > rightShape.MassData.Area) { b.CreateFixture(leftShape, fix.UserData); leftBodies.Add(b); GlomFixture(world, b, rightBodies, rightShape, fix.UserData, rightJoints); } else { b.CreateFixture(rightShape, fix.UserData); rightBodies.Add(b); GlomFixture(world, b, leftBodies, leftShape, fix.UserData, leftJoints); } } else { GlomFixture(world, b, leftBodies, leftShape, fix.UserData, leftJoints); GlomFixture(world, b, rightBodies, rightShape, fix.UserData, rightJoints); } } // for each fixture that was NOT sliced through... foreach (Fixture fix in (from f in bodyFixtures where !fixtures.Contains(f) select f)) { if (isLeft(start, end, fix)) { GlomFixture(world, b, leftBodies, fix.Shape, fix.UserData, leftJoints); } else { GlomFixture(world, b, rightBodies, fix.Shape, fix.UserData, rightJoints); //rightBody.CreateFixture(fix.Shape.Clone(), fix.UserData); } } foreach (Body bod in leftBodies.Concat(rightBodies)) { bod.ResetMassData(); bod.BodyType = BodyType.Dynamic; bod.Rotation = b.Rotation; bod.LinearVelocity = b.LinearVelocity; bod.AngularVelocity = b.AngularVelocity; bod.Position = b.Position; } //b.JointList = null; //world.RemoveBody(b); foreach (Fixture f in bodyFixtures) { b.DestroyFixture(f); } world.ProcessChanges(); } return stoppingPoint; }
void RayCast(World world) { switch(Direction) { case direction.floor: RayDirection.X = 0; RayDirection.Y = 1; break; case direction.leftwall: RayDirection.X = -1; RayDirection.Y = 0; break; case direction.rightwall: RayDirection.X = 1; RayDirection.Y = 0; break; case direction.ceiling: RayDirection.X = 0; RayDirection.Y = -1; break; default: RayDirection.X = 0; RayDirection.Y = 1; break; } raycastingFixtures = world.RayCast(_body.Position, new Vector2(_body.Position.X+(RayLength*RayDirection.X) , _body.Position.Y+(RayLength*RayDirection.Y))); debugString = raycastingFixtures.Count.ToString(); hitting = raycastingFixtures.Count == 0 ? false : true; }