Exemplo n.º 1
0
        public void Update(GameTime gameTime)
        {
            CurrentTime = gameTime;
            var currentFrameBodies = Bodies.ToList();

            //Update each body.
            foreach (var body in currentFrameBodies)
            {
                //Check if the body moved. If it did, mark as dirty and update delta position.
                //If not, just update its sensors.
                Vector2 deltaPosition = body.Speed * gameTime.ElapsedGameTime.Milliseconds;
                if (deltaPosition.X != 0 || deltaPosition.Y != 0)
                {
                    MarkAsDirty(body, deltaPosition);
                }
                else
                {
                    UpdateBodySensors(body);
                }

                //Apply gravity if not on ground.
                body.Speed += Gravity * body.GravityScale *
                              gameTime.ElapsedGameTime.Milliseconds;
            }

            //Update dirty bodies.
            foreach (var pair in dirtyBodies)
            {
                PhysicBody body        = pair.Key;
                Vector2    translation = pair.Value;
                Vector2    penetration = Vector2.Zero;

                //Body to tile collision.
                bool collided = false;

                if (body.IsTangible)
                {
                    collided = HandleTileCollisionY(body, translation.Y, out penetration.Y);
                }
                body.Position.Y += translation.Y - penetration.Y;
                if (body.IsTangible)
                {
                    collided |= HandleTileCollisionX(body, translation.X, out penetration.X);
                }
                body.Position.X += translation.X - penetration.X;

                //Tilemap collision response.
                if (collided)
                {
                    TileMapCollisionInfo info = new TileMapCollisionInfo();
                    info.GameTime    = CurrentTime;
                    info.Penetration = penetration;
                    body.TileMapCollision(info);
                }

                //Body-to-body collision testing.
                foreach (var other in currentFrameBodies)
                {
                    collided = (body.MaskBits & other.CategoryBits) != 0 && (other.MaskBits & body.CategoryBits) != 0 &&
                               body != other && body.WorldBounds.Intersects(other.WorldBounds, out penetration);
                    if (collided)
                    {
                        if (Math.Abs(penetration.X) > Math.Abs(penetration.Y))
                        {
                            penetration.X = 0;
                        }
                        else
                        {
                            penetration.Y = 0;
                        }

                        if (body.IsTangible && other.Type == CollisionTypes.Solid)
                        {
                            body.Position -= penetration;
                            if (penetration.Y * body.Speed.Y > 0)
                            {
                                body.Speed.Y = 0;
                            }
                            else if (penetration.X * body.Speed.X > 0)
                            {
                                body.Speed.X = 0;
                            }

                            BodyCollisionInfo infoOther = new BodyCollisionInfo();
                            infoOther.GameTime      = CurrentTime;
                            infoOther.Penetration   = -penetration;
                            infoOther.CollidingBody = body;
                            other.BodyCollision(infoOther);
                        }

                        BodyCollisionInfo info = new BodyCollisionInfo();
                        info.GameTime      = CurrentTime;
                        info.Penetration   = penetration;
                        info.CollidingBody = other;
                        body.BodyCollision(info);
                    }
                }

                //Update sensors.
                UpdateBodySensors(body);
            }
            dirtyBodies.Clear();

            //Update global sensors.
            foreach (var sensor in Sensors)
            {
                sensor.State = CheckSolid(sensor.Area, sensor.MaskBits, sensor.CategoryBits);
            }
        }
 internal void TileMapCollision(TileMapCollisionInfo info)
 {
     TileMapCollisionEvent?.Invoke(info);
 }