예제 #1
0
        /// <summary>
        /// Checks all collisions within the entities known collision cells
        /// </summary>
        /// <param name="entity">Entity to check.</param>
        protected override void Process(Entity entity)
        {
            var collision = entity.GetComponent <CollisionComponent>();
            var sprite    = entity.GetComponent <SpriteTransform>();

            var center = Vector2.Zero;

            if (sprite != null)
            {
                center = sprite.Target.Origin;
            }

            if (collision != null)
            {
                var neighbours = _map.GetCollisions(entity, collision);

                var boxCount = collision.Boxes.Count;

                // Check collisions for all of the entities AABB's for all neighbours
                for (int b = 0; b < boxCount; b++)
                {
                    var box = collision.Boxes[b];

                    // Move the box to align with the entities new position
                    if (sprite != null)
                    {
                        box.Width  += sprite.Bounds.Width - box.Width;
                        box.Height += sprite.Bounds.Height - box.Height;
                        box.X      += sprite.Target.Position.X - box.X - (sprite.Bounds.Width / 2);
                        box.Y      += sprite.Target.Position.Y - box.Y - (sprite.Bounds.Height / 2);

                        collision.Boxes[b] = box;
                    }

                    // Do narrow phase checking for each neighbour
                    foreach (var n in neighbours)
                    {
                        var neighbourCollision = n.GetComponent <CollisionComponent>();
                        collision.Event = HandleCollisions(box, neighbourCollision);

                        if (collision.Event)
                        {
                            // Update collision information for other systems' use
                            collision.Collider          = n;
                            neighbourCollision.Event    = true;
                            neighbourCollision.Collider = entity;
                            break;
                        }
                    }

                    // Do tilemap collision checking
                    if (_tileMap != null)
                    {
                        var physics  = entity.GetComponent <PhysicsComponent>();
                        var movement = entity.GetComponent <Movement>();
                        if (physics != null && movement != null)
                        {
                            // Get all tiles surrounding the entity
                            var top    = (int)Math.Floor(box.Top / _tileMap.TileSize.Y);
                            var left   = (int)Math.Floor(box.Left / _tileMap.TileSize.X);
                            var right  = Math.Ceiling(box.Right / _tileMap.TileSize.X) - 1;
                            var bottom = Math.Ceiling(box.Bottom / _tileMap.TileSize.X) - 1;

                            int xSide = 1;
                            int ySide = 1;

                            // Check all the tiles around the entity, updating the negative velocity
                            // of their movement based on the direction a collision was found
                            for (int x = left; x <= right; x++)
                            {
                                for (int y = top; y <= bottom; y++)
                                {
                                    var tileAABB = new Rectangle(
                                        x * _tileMap.TileSize.X,
                                        y * _tileMap.TileSize.Y,
                                        _tileMap.TileSize.X,
                                        _tileMap.TileSize.Y
                                        );

                                    // Check collision for that tile and alter velocity if collision was found
                                    if (_tileMap[x, y].Flag == TileFlag.Impassable && box.Intersects(tileAABB))
                                    {
                                        physics.Velocity  = new Vector2(xSide * 5, ySide * 5);
                                        movement.Position = movement.LastPosition;
                                    }

                                    ySide -= 2;
                                }

                                xSide -= 2;
                            }
                        }
                    }
                }
            }
        }