/// <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; } } } } } }