private ClipQuadTree<TerrainData>[] GetTerrainInView(
            TerrainComponent cTerrain,
            Vector3 translation,
            Vector3 scale,
            int widthPadding,
            int heightPadding)
        {
            var rect = new Rectangle(
                cTerrain.Terrain.Bounds.X - (int)translation.X - widthPadding,
                cTerrain.Terrain.Bounds.Y - (int)translation.Y - heightPadding,
                (int)Math.Ceiling(this.graphics.Viewport.Width / scale.X) + widthPadding,
                (int)Math.Ceiling(this.graphics.Viewport.Height / scale.Y) + heightPadding);

            return cTerrain.Terrain.GetNodesIntersecting(rect).ToArray();
        }
        /// <summary>
        /// Draw the TerrainComponent sprites.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch.</param>
        /// <param name="cameraTranslateX">The camera x translation value.</param>
        /// <param name="cameraTranslateY">The camera y translation value.</param>
        /// <param name="cameraScaleX">The camera x scale value.</param>
        /// <param name="cameraScaleY">The camera y scale value.</param>
        private void DrawTerrainComponents(
            SpriteBatch spriteBatch,
            Matrix transform,
            ClipQuadTree<TerrainData>[] terrainBlocks,
            TerrainComponent cTerrain)
        {
            // Begin the sprite batch with the camera transform
            spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, transform);

            foreach (ClipQuadTree<TerrainData> terrainBlock in terrainBlocks)
            {
                // Don't draw anything if no terrain exists here
                TerrainMaterial material = terrainBlock.Data.Material;
                if (material == TerrainMaterial.None)
                {
                    continue;
                }

                // Calculate the bounds of this terrain block in on-screen coordinates
                var screenBounds = new Rectangle(
                    terrainBlock.Bounds.X,
                    terrainBlock.Bounds.Y,
                    terrainBlock.Bounds.Length,
                    terrainBlock.Bounds.Length);

                // Tile the terrain within the bounds
                this.DrawTiledTerrain(spriteBatch, material, screenBounds);
            }

            // Draw fringe sprites for each terrain block
            foreach (ClipQuadTree<TerrainData> terrainBlock in terrainBlocks)
            {
                // Don't draw anything if no terrain exists here
                TerrainMaterial material = terrainBlock.Data.Material;
                if (material == TerrainMaterial.None)
                {
                    continue;
                }

                // Draw the fringe tiles
                this.DrawTerrainFringe(spriteBatch, material, terrainBlock.Bounds, cTerrain.PathNodes);
            }

            /*
            // DEBUG: Draw path components
            Texture2D debugTexture = new Texture2D(this.graphics, 1, 1);
            debugTexture.SetData<Color>(new Color[] { Color.White });
            foreach (PathComponent path in this.EntityManager.GetComponents(typeof(PathComponent)))
            {
                for (int i = 0; i < path.Nodes.Length - 1; i++)
                {
                    PathNode p1 = path.Nodes[i];
                    PathNode p2 = path.Nodes[i + 1];

                    int width = Math.Abs(p2.X - p1.X);
                    if (width == 0) width = 1;

                    int height = Math.Abs(p2.Y - p1.Y);
                    if (height == 0) height = 1;

                    spriteBatch.Draw(
                        debugTexture,
                        new Rectangle(p1.X, p1.Y, width, height),
                        (p1.Type == PathNodeType.Normal) ? Color.Red : Color.Yellow);
                }
            }
            */

            spriteBatch.End();
        }
        private void CreateTestPath(WorldContext world, TerrainComponent terrain, Point start, Point goal)
        {
            var testEntity = world.EntityManager.CreateEntity();

            // Create the path finder
            var pathFinder = new PathFinder(terrain);

            // Find the nodes along the path
            PathNode[] path;
            if (pathFinder.FindPath(start, goal, 1, 1, out path))
            {
                // Create the path component
                world.EntityManager.AddComponent(testEntity, new PathComponent(path));
            }
        }
        /// <summary>
        /// Draw the game.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch.</param>
        /// <param name="cameraTranslateX">The camera x translation value.</param>
        /// <param name="cameraTranslateY">The camera y translation value.</param>
        /// <param name="cameraScaleX">The camera x scale value.</param>
        /// <param name="cameraScaleY">The camera y scale value.</param>
        private void DrawGame(
            SpriteBatch spriteBatch,
            Matrix terrainTransform,
            Matrix spriteTransform,
            ClipQuadTree<TerrainData>[] terrainBlocks,
            TerrainComponent cTerrain)
        {
            // Draw the terrain
            this.DrawTerrainComponents(spriteBatch, terrainTransform, terrainBlocks, cTerrain);

            // Draw the sprites
            this.DrawSpriteComponents(spriteBatch, spriteTransform);
        }
        /// <summary>
        /// Create a terrain entity from a bitmap image.
        /// </summary>
        /// <param name="world">The world context.</param>
        /// <param name="x">The top-left X position in world-coordinates.</param>
        /// <param name="y">The top-left Y position in world-coordinates.</param>
        /// <param name="scale">The scale ratio for the terrain.</param>
        /// <param name="isCollidable">Indicates whether the terrain can be collided with.</param>
        /// <param name="terrainBitmapName">The name of the terrain bitmap.</param>
        /// <param name="currentTime">The current time used as the terrain creation time.</param>
        /// <returns>The entity.</returns>
        public Entity CreateTerrain(
            WorldContext world,
            float x,
            float y,
            float scale,
            bool isCollidable,
            string terrainBitmapName,
            TimeSpan currentTime)
        {
            Entity entity = world.EntityManager.CreateEntity();

            // Load the terrain texture
            Texture2D texture = world.Resources.Load<Texture2D>(terrainBitmapName);

            // Create the terrain quad tree
            var terrainFactory = new TerrainFactory();
            ClipQuadTree<TerrainData> terrainQuadTree = terrainFactory.CreateTerrainQuadTree(texture, currentTime);

            // Build the path nodes from the terrain quad tree
            var pathBuilder = new PathBuilder(terrainQuadTree, 30, 5);
            Dictionary<Point, LinkedPathNode> pathNodes = pathBuilder.BuildPathNodes();

            // Create the terrain component
            var cTerrain = new TerrainComponent(terrainQuadTree, isCollidable, pathNodes);

            // Create the physics body. Initially this has no fixtures, as those are populated dynamically
            var body = new Body(world.Physics);
            var cPhysics = new PhysicsComponent(body);

            // Add components to entity
            world.EntityManager.AddComponent(entity, cTerrain);
            world.EntityManager.AddComponent(entity, cPhysics);
            world.EntityManager.AddComponent(entity, new PositionComponent(body, new Vector2(x, y)));
            world.EntityManager.AddComponent(entity, new ScaleComponent(scale));

            return entity;
        }