Пример #1
0
        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);
                    }
                }
            }
        }
Пример #2
0
        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;
        }
Пример #3
0
 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;
 }
Пример #4
0
        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;
        }
Пример #5
0
        /// <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;
        }
Пример #6
0
 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;
 }
Пример #7
0
        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();
            }
        }
Пример #8
0
        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);
                }
            }
        }
Пример #10
0
        /// <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;

        }
Пример #11
0
 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;
 }