Exemple #1
0
        public void ApplyPhysics(PhysicalProperties entityProps, IPhysicsObject entity, GameTime gameTime)
        {
            var delta      = (float)gameTime.ElapsedGameTime.TotalSeconds;
            var lastPos    = entityProps.Position;
            var neighbours = new IPhysicsObject[0];

            var overlappingObjs = new List <IPhysicsObject>();

            // [ Y ]

            entityProps.Position.Y += (entityProps.Velocity.Y * delta);

            // get new neighbours since objects have probably moved
            neighbours = chunkMap.GetNearbyCollidables(entity);

            // overlaps
            if (entity.IsOverlappingEnabled)
            {
                var overlaps = neighbours.Where(n => n.IsOverlappingEnabled && entity.OverlapBox.IntersectsWith(n.OverlapBox));

                foreach (var overlap in overlaps)
                {
                    overlap.OnOverlapping(entity);
                    entity.OnOverlapping(overlap);

                    if (!overlappingObjs.Contains(overlap))
                    {
                        overlappingObjs.Add(overlap);
                    }
                }
            }

            // collision
            if (entity.IsCollisionEnabled)
            {
                var collisions = neighbours.Where(n => n.IsCollisionEnabled && entity.CollisionBox.IntersectsWith(n.CollisionBox));

                var hasCollided = false;

                foreach (var collision in collisions)
                {
                    if (hasCollided)
                    {
                        continue;
                    }

                    hasCollided = true;

                    var up = entityProps.Velocity.Y < 0;
                    entityProps.Velocity.Y = 0;

                    if (up)
                    {
                        entityProps.Position.Y = collision.CollisionBox.Bottom + 1;
                    }
                    else
                    {
                        entityProps.Position.Y = collision.CollisionBox.Top - entity.CollisionBox.Height;
                    }

                    collision.OnCollision(entity);
                    entity.OnCollision(collision);
                }
            }


            // [ X ]

            entityProps.Position.X = entityProps.Position.X + (entityProps.Velocity.X * delta);
            // get new neighbours since objects have probably moved
            neighbours = chunkMap.GetNearbyCollidables(entity);

            if (entity.IsOverlappingEnabled)
            {
                // overlaps
                var overlaps = neighbours.Where(n => n.IsOverlappingEnabled && entity.OverlapBox.IntersectsWith(n.OverlapBox));

                foreach (var overlap in overlaps)
                {
                    overlap.OnOverlapping(entity);
                    entity.OnOverlapping(overlap);

                    if (!overlappingObjs.Contains(overlap))
                    {
                        overlappingObjs.Add(overlap);
                    }
                }
            }

            if (entity.IsCollisionEnabled)
            {
                // collision
                var collisions = neighbours.Where(n => n.IsCollisionEnabled && entity.CollisionBox.IntersectsWith(n.CollisionBox));

                var hasCollided = false;

                foreach (var collision in collisions)
                {
                    if (hasCollided)
                    {
                        continue;
                    }

                    hasCollided = true;

                    entityProps.Velocity.X = 0;
                    entityProps.Position.X = lastPos.X;

                    collision.OnCollision(entity);
                    entity.OnCollision(collision);
                }
            }

            // track overlappers
            entityProps.OverlappingObjects = overlappingObjs;

            // get new neighbours since objects have probably moved
            neighbours = chunkMap.GetNearbyCollidables(entity);

            switch (physSettings.PhysicsType)
            {
            case PhysicsType.Platformer:
                handlePlatformerAdditionalPhysics(entityProps, entity, neighbours, gameTime);
                break;

            case PhysicsType.Topdown:
                handleTopDownAdditionalPhysics(entityProps, entity, neighbours, gameTime);
                break;
            }

            // [ Chunk map update ]

            chunkMap.UpdateEntity(entity);
        }