/// <summary>
        /// Gets the list of grid positions that a game object occupies (either 1, 2, or 4 different positions).
        /// </summary>
        /// <param name="gameObject">The game object to check.</param>
        /// <returns></returns>
        private List<int> GetGridPositions(GameObject gameObject)
        {
            // Create new list of grid positions
            var positions = new List<int>();

            // Get the bounding rectangle of the game object
            var boundBox = gameObject.BoundingBox;

            // Get the grid position for each corner of the game object's bounding box
            // Bottom left
            int gridPos = GetGridPosition(boundBox.MinX, boundBox.MinY);
            positions.Add(gridPos);

            // Top left
            gridPos = GetGridPosition(boundBox.MinX, boundBox.MaxY);
            if (!positions.Contains(gridPos)) positions.Add(gridPos);

            // Top right
            gridPos = GetGridPosition(boundBox.MaxX, boundBox.MaxY);
            if (!positions.Contains(gridPos)) positions.Add(gridPos);

            // Bottom right
            gridPos = GetGridPosition(boundBox.MaxX, boundBox.MinY);
            if (!positions.Contains(gridPos)) positions.Add(gridPos);

            // Return the list of positions
            return positions;
        }
 public CollisionEventArgs(GameObject sourceObject, GameObject hitObject)
 {
     SourceObject = sourceObject;
     HitObject = hitObject;
 }
        /// <summary>
        /// Updates the grid position of the specified game object.
        /// </summary>
        /// <param name="gameObject">The game object to update.</param>
        public void UpdateLocation(GameObject gameObject)
        {
            // We're finished if there's no game object to update (could happen for an object that has had a collision)
            if (gameObject == null) return;

            // Get the grid positions that the game object occupies
            var gridPositions = GetGridPositions(gameObject);

            // Add the game object to each grid position list that it occupies
            foreach (var gridPos in gridPositions)
            {
                // Initialize the list of game objects for the grid position if necessary
                if (!_gridBins.ContainsKey(gridPos)) _gridBins.Add(gridPos, new List<GameObject>());

                // Get the list of game objects associated with the grid position
                var gameObjectList = _gridBins[gridPos];

                // Add the game object to this position's game object list if it's not already in there
                if (!gameObjectList.Contains(gameObject)) gameObjectList.Add(gameObject);
            }

            // Add the list of positions to the game object bins list
            if (_gameObjectBins.ContainsKey(gameObject)) _gameObjectBins.Remove(gameObject);
            _gameObjectBins.Add(gameObject, gridPositions);
        }
        /// <summary>
        /// Checks for a collision for the specified game object.
        /// </summary>
        /// <param name="sourceObject">The game object to check.</param>
        public void CheckCollision(GameObject sourceObject)
        {
            // We're finished if there's no game object to check (could happen for an object that has had a collision)
            if (sourceObject == null) return;

            // Get the grid positions for the specified game object
            var gridPositions = _gameObjectBins[sourceObject];

            // Check each game object list for the grid positions and see if there are any possible collisions
            foreach (var position in gridPositions)
            {
                // Get the list of game objects at this position
                var gameObjectList = _gridBins[position];

                // Only check if there's more than one game object in a grid position
                if (gameObjectList.Count > 1)
                {
                    foreach (var go in gameObjectList)
                    {
                        // Obviously, checking collisions against the same object is right out
                        if (go == sourceObject) continue;

                        // Same type objects don't collide with each other (e.g. Enemy with enemy)
                        if (go.Type == sourceObject.Type) continue;

                        // Ship and ship bullets can't collide with each other
                        if ((go.Type == GameObjectType.Ship && sourceObject.Type == GameObjectType.ShipBullet) || (go.Type == GameObjectType.ShipBullet && sourceObject.Type == GameObjectType.Ship))
                            continue;

                        // Enemy ships and enemy bullets can't collide with each other
                        if ((go.Type == GameObjectType.Enemy && sourceObject.Type == GameObjectType.EnemyBullet) || (go.Type == GameObjectType.EnemyBullet && sourceObject.Type == GameObjectType.Enemy))
                            continue;

                        // All other collisions are valid, so check for a real collision (Cocos2d-XNA will give you the point of collision, but I don't
                        // care about it here)
                        CCPoint collisionPoint;
                        if (sourceObject.CollidesWith(go, out collisionPoint))
                        {
                            // Let any subscribers know that a collision has occurred
                            if (Collision != null)
                                Collision(this, new CollisionEventArgs(sourceObject, go));
                            return;
                        }
                    }
                }
            }
        }