Example #1
0
        void handleTopDownAdditionalPhysics(PhysicalProperties entityProps, IPhysicsObject entity, IPhysicsObject[] neighbours, GameTime gameTime)
        {
            // Gravity

            if (entityProps.HasGravity)
            {
                if (entityProps.Velocity.X != 0)
                {
                    var lerped = MathHelper.Lerp(entityProps.Velocity.X, 0, physSettings.Friction);

                    if (Math.Abs(lerped) < 2)
                    {
                        lerped = 0;
                    }

                    entityProps.Velocity.X = lerped;
                }

                if (entityProps.Velocity.Y != 0)
                {
                    var lerped = MathHelper.Lerp(entityProps.Velocity.Y, 0, physSettings.Friction);

                    if (Math.Abs(lerped) < 2)
                    {
                        lerped = 0;
                    }

                    entityProps.Velocity.Y = lerped;
                }
            }
        }
Example #2
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);
        }
Example #3
0
        void handlePlatformerAdditionalPhysics(PhysicalProperties entityProps, IPhysicsObject entity, IPhysicsObject[] neighbours, GameTime gameTime)
        {
            // [ Grounded flag ]

            if (physSettings.HasGravity && entity.IsCollisionEnabled)
            {
                var groundedArea = new RectangleF(
                    entity.CollisionBox.X + (entity.CollisionBox.Width / 2),
                    entity.CollisionBox.Y + entity.CollisionBox.Height,
                    1, 1);

                var groundingIntersections = neighbours.Where(n => groundedArea.IntersectsWith(n.CollisionBox));

                var triggerOverlapEvents = false;

                if (!entityProps.IsGrounded && groundingIntersections.Any())
                {
                    entityProps.IsGrounded = true;
                    triggerOverlapEvents   = true;
                }
                else if (entityProps.IsGrounded && !groundingIntersections.Any())
                {
                    entityProps.IsGrounded = false;
                    triggerOverlapEvents   = true;
                }

                if (triggerOverlapEvents)
                {
                    foreach (var groundings in groundingIntersections)
                    {
                        groundings.OnOverlapping(entity);
                        entity.OnOverlapping(groundings);
                    }
                }
            }

            // [ Gravity ]

            if (physSettings.HasGravity && entityProps.HasGravity && !entityProps.IsGrounded)
            {
                // factors weight into equation
                entityProps.Velocity.Y = MathHelper.Clamp(
                    entityProps.Velocity.Y + (physSettings.Gravity * entityProps.Weight),
                    -physSettings.TerminalVelocity,
                    physSettings.TerminalVelocity);
            }

            // [ Friction ]

            if (physSettings.HasGravity &&
                physSettings.HasFriction &&
                entityProps.IsGrounded &&
                entityProps.Velocity.X != 0)
            {
                var lerped = MathHelper.Lerp(entityProps.Velocity.X, 0, physSettings.Friction);
                if (Math.Abs(lerped) < 2)
                {
                    lerped = 0;
                }

                entityProps.Velocity.X = lerped;
            }
        }