/// <summary> /// Creates map /// </summary> /// <param name="width">Width of the map</param> /// <param name="height">Height of the map</param> /// <returns>Array of tiles</returns> public static WorldTile[] GenerateMap(int width, int height) { bool[,] cells = new bool[width, height]; // Fill map with 1 or 0 randomly UH.Loops(width, height, (x, y) => cells[x, y] = x == 0 || y == 0 || x == width - 1 || y == height - 1 || RandomService.GetRandomBool(_generatorWallRoomRation)); // Simulation for (int i = 0; i < _generatorSteps; i++) { cells = SimulationStep(cells); } // Set map WorldTile[] map = new WorldTile[width * height]; UH.Loops(width, height, (x, y) => map[y * width + x] = new WorldTile(y * width + x, x, y, cells[x, y], new CollisionType[0])); // Set walls' collisions UH.Loops(width, height, (x, y) => { WorldTile tile = map[y * width + x]; if (!tile.IsWall) { return; } List <CollisionType> collision = new List <CollisionType>( ); if (x - 1 < 0 || !map[y * width + x - 1].IsWall) { collision.Add(CollisionType.Left); } if (x + 1 >= width || !map[y * width + x + 1].IsWall) { collision.Add(CollisionType.Right); } if (y - 1 < 0 || !map[(y - 1) * width + x].IsWall) { collision.Add(CollisionType.Top); } if (y + 1 >= height || !map[(y + 1) * width + x].IsWall) { collision.Add(CollisionType.Bottom); } tile.Collisions = collision.ToArray( ); }); return(map); }
/// <summary> /// Cellular automaton step /// </summary> /// <param name="original">Original walls map</param> /// <returns>Transformed walls map</returns> private static bool[,] SimulationStep(bool[,] original) { int width = original.GetLength(0); int height = original.GetLength(1); bool[,] data = new bool[width, height]; UH.Loops(width, height, (x, y) => { int walls = WallCountAround(original, x, y); if (walls > 4) { data[x, y] = true; } else if (walls < 4) { data[x, y] = false; } }); return(data); }
/// <summary> /// How many walls are around given point /// </summary> /// <param name="original">Original walls map</param> /// <param name="centerX">Point's X</param> /// <param name="centerY">Point's Y</param> /// <returns>Amount of walls around given point</returns> private static int WallCountAround(bool[,] original, int centerX, int centerY) { int width = original.GetLength(0); int height = original.GetLength(1); int result = 0; UH.Loops(3, 3, (x, y) => { int targetX = centerX - 1 + x; int targetY = centerY - 1 + y; if (targetX == centerX && targetY == centerY) { return; } if (targetX < 0 || targetX >= width || targetY < 0 || targetY >= height || original[targetX, targetY]) { result++; } }); return(result); }
/// <summary> /// Render state /// </summary> /// <param name="time"><see cref="GameTime"/></param> public override void Render(GameTime time) { DH.RenderScene(_gameplayScene, _camera, () => { foreach (WorldTile tile in _level.Map) { if (!tile.IsWall) { float distance = (float)Math.Sqrt(Math.Pow(tile.DisplayX - _player.X, 2) + Math.Pow(tile.DisplayY - _player.Y, 2)); float percentage = 1 - (distance < 350 ? 0 : (distance - 350) / 700); DH.Raw(_content.TEXGround.Texture, tile.DisplayX - 16, tile.DisplayY - 16, color: ColorsManager.Get(percentage)); } } if (_config.DebugMode) { foreach (WorldTile tile in _level.Map) { if (tile.Collisions.Contains(CollisionType.Left)) { DH.Line(tile.DisplayX, tile.DisplayY, tile.DisplayX, tile.DisplayY + tile.Size, 8, Color.Red); } if (tile.Collisions.Contains(CollisionType.Right)) { DH.Line(tile.DisplayX + tile.Size, tile.DisplayY, tile.DisplayX + tile.Size, tile.DisplayY + tile.Size, 8, Color.Red); } if (tile.Collisions.Contains(CollisionType.Top)) { DH.Line(tile.DisplayX, tile.DisplayY, tile.DisplayX + tile.Size, tile.DisplayY, 8, Color.Red); } if (tile.Collisions.Contains(CollisionType.Bottom)) { DH.Line(tile.DisplayX, tile.DisplayY + tile.Size, tile.DisplayX + tile.Size, tile.DisplayY + tile.Size, 8, Color.Red); } } } _player.Display(time); }); DH.RenderScene(Scene, () => { DH.Scene(_gameplayScene); DH.Text(_content.GetFont( ), _player.Name, 15, 15, false); // Mini-map UH.Loops(_level.Width, _level.Height, (x, y) => { if (!_level.Map[y * _level.Width + x].IsWall) { DH.Raw(_content.Pixel, _config.ViewWidth - 16 - _level.Width * 4 + x * 4, _config.ViewHeight - 16 - _level.Height * 4 + y * 4, 4, 4, (_player.OnMapX == x && _player.OnMapY == y ? Color.Red : Color.Gray) * .5f ); } }); if (_config.DebugMode) { DH.Text(_debugFont, $"{(int)(1 / time.ElapsedGameTime.TotalSeconds)} FPS", _config.WindowWidth - 10, 10, false, ColorsManager.DarkGray, AlignType.RT); DH.Text(_debugFont, $"Mouse ({_input.MouseX}, {_input.MouseY})", _config.WindowWidth - 10, 25, false, ColorsManager.DarkGray, AlignType.RT); DH.Text(_debugFont, $"Player ({_player.X:0.0}, {_player.Y:0.0}) ({_player.OnMapX}, {_player.OnMapY})", _config.WindowWidth - 10, 40, false, ColorsManager.DarkGray, AlignType.RT); DH.Text(_debugFont, $"Camera ({_camera.Target.X:0.0}, {_camera.Target.Y:0.0})", _config.WindowWidth - 10, 55, false, ColorsManager.DarkGray, AlignType.RT); DH.Text(_debugFont, $"Scale {_camera.Scale:0.00}x", _config.WindowWidth - 10, 70, false, ColorsManager.DarkGray, AlignType.RT); DH.Line(0, _config.WindowHeight / 2, _config.WindowWidth, _config.WindowHeight / 2, 1, ColorsManager.DarkestGray * .5f); DH.Line(_config.WindowWidth / 2, 0, _config.WindowWidth / 2, _config.WindowHeight, 1, ColorsManager.DarkestGray * .5f); } }); }