1 module gamemap; 2 3 import nudsfml.graphics; 4 5 import std.algorithm; 6 import std.conv; 7 import std.string; 8 import std.format; 9 10 import gameentity; 11 12 enum TileTypes { 13 None = -1, 14 Floor = 0, 15 Wall = 1, 16 WallShadow = 2, 17 } 18 19 struct Tile { 20 int id; 21 int type = TileTypes.None; 22 Vector2f offset; 23 Vector2f pos; 24 } 25 26 class GameMap { 27 Tile [] tiles; 28 IntRect [] tileRects; 29 30 int width; 31 int height; 32 int gridWidth; 33 int gridHeight; 34 int tileWidth; 35 int tileHeight; 36 37 float frameChange = 1f / 15f; 38 float currentFrame = 0f; 39 int currentFrameIndex = 0; 40 int currentMaxFrameIndex = 30; 41 42 Entity [] entities; 43 44 Texture tex; 45 46 AppleEntity addApple(int x, int y) { 47 AppleEntity apple = new AppleEntity(tex); 48 apple.mapLocation = Vector2i(x, y); 49 apple.position = Vector2f(x*gridWidth, y*gridHeight); 50 entities ~= apple; 51 sortEntities(); 52 return apple; 53 } 54 55 void addSnake(ref SnakeEntity snakepart){ 56 entities ~= snakepart; 57 sortEntities(); 58 } 59 60 void sortEntities() { 61 entities.sort!((a,b) => a.position.y < b.position.y); 62 } 63 64 void update(float deltaTime){ 65 foreach(ref entity; entities) { 66 entity.update(deltaTime); 67 } 68 currentFrame += deltaTime;; 69 if(currentFrame > frameChange){ 70 currentFrame = 0f; 71 currentFrameIndex++; 72 if(currentFrameIndex > currentMaxFrameIndex){ 73 currentFrameIndex = 0; 74 } 75 76 } 77 } 78 79 80 81 enum Direction { 82 Up = 1, 83 Right = 2, 84 Down = 4, 85 Left = 8 86 } 87 88 89 90 this(){ 91 width = 32; 92 height = 24; 93 gridWidth = 32; 94 gridHeight = 32; 95 tileWidth = 32; 96 tileHeight = 48; 97 98 tiles.length = (width * height *2); 99 100 for (int y = 0; y < 4; y++){ 101 for (int x = 0; x < 16; x++){ 102 tileRects ~= IntRect(x * tileWidth, y * tileHeight, tileWidth, tileHeight); 103 } 104 } 105 106 tex = new Texture; 107 tex.loadFromFile("data/snaketiles.png"); 108 109 createMap(); 110 } 111 112 int getIndex(int x, int y, int layer = 0){ 113 int index = (layer * width * height) + (y * width) + x; 114 115 if ( index < 0 || index > (width * height * 2)){ 116 return -1; 117 } 118 return index; 119 } 120 121 void createMap(){ 122 for(int i = 0; i < width; i++){ 123 for(int j = 0; j < height; j++){ 124 if(i == 0 || i == width - 1 || j == 0 || j == height - 1){ 125 tiles[i + j * width].type = TileTypes.Wall; 126 } 127 else{ 128 tiles[i + j * width].type = TileTypes.Floor; 129 } 130 getTile(i,j).pos = Vector2f(i * gridWidth,j * gridHeight); 131 getTile(i, j).offset = Vector2f(0,-16); 132 } 133 } 134 135 calcWallIndexes(); 136 calcWallShadows(); 137 138 139 } 140 141 void calcWallShadows(){ 142 //calc shadows 143 for(int y = 1 ; y < height; y++){ 144 for(int x = 0; x < width; x++){ 145 int index = getIndex(x,y - 1); 146 if(tiles[index].type == TileTypes.Wall && tiles[getIndex(x,y)].type == TileTypes.Floor){ 147 tiles[getIndex(x,y,1)].id = 16*3+1; // using magic numbers 148 tiles[getIndex(x,y,1)].type = TileTypes.WallShadow; 149 } else { 150 tiles[getIndex(x,y,1)].type = TileTypes.None; 151 tiles[getIndex(x,y,1)].offset = Vector2f(0,-16); 152 } 153 } 154 } 155 } 156 157 158 159 void calcWallIndexes(){ 160 //convert forloop to a function to make it easier to read 161 for(int y = 0 ; y < height; y++){ 162 for(int x = 0; x < width; x++){ 163 int index = getIndex(x,y); 164 if(tiles[index].type == TileTypes.Wall){ 165 tiles[index].id = 0 + calcTileNeighbors(x,y); 166 } else { 167 tiles[index].id = 32; // + random_number(0,3); 168 } 169 } 170 } 171 } 172 173 int addToTileset(IntRect rect) { 174 int id = tileRects.length.to!int; 175 tileRects ~= rect; 176 177 return id; 178 } 179 180 int calcTileNeighbors(int x, int y) { 181 int neighbors = 0; 182 auto t = getTile(x,y); 183 if (x > 0) { 184 if (getTile(x - 1, y).type == t.type) { 185 neighbors += Direction.Left; 186 } 187 } 188 if (x < width - 1) { 189 if (getTile(x + 1, y).type == t.type) { 190 neighbors += Direction.Right; 191 } 192 } 193 if (y > 0) { 194 if (getTile(x, y - 1).type == t.type) { 195 neighbors += Direction.Up; 196 } 197 } 198 if (y < height - 1) { 199 if (getTile(x,y + 1).type == t.type) { 200 neighbors += Direction.Down; 201 } 202 } 203 return neighbors; 204 } 205 206 ref Tile getTile(int x, int y) { 207 return tiles[x + y * width]; 208 } 209 210 void draw(Vector2f pos, RenderTarget target) { 211 import std.stdio; 212 RectangleShape rect = new RectangleShape(); 213 rect.fillColor = Color.White; 214 rect.size = Vector2f(tileWidth, tileHeight); 215 rect.setTexture(tex); 216 int entityIndex = 0; 217 for (int y = 0; y < height; y++) { 218 for (int x = 0; x < width; x++) { 219 for(int l = 0; l < 2; l++){ 220 int index = getIndex(x,y,l); 221 if(tiles[index].type != TileTypes.None){ 222 rect.position = pos + Vector2f(gridWidth * x, gridHeight * y ) + tiles[index].offset; 223 224 rect.textureRect = tileRects[tiles[index].id]; 225 target.draw(rect); 226 } 227 } 228 } 229 //writeln("Y: ", y); 230 if (entityIndex < entities.length ) { 231 while (entities[entityIndex].position.y < ((y - 1) * gridHeight)) { 232 // writeln(format("%d pos(%f,%f)", entityIndex, entities[entityIndex].position.x, entities[entityIndex].position.y)); 233 entities[entityIndex].draw(target); 234 entityIndex++; 235 if(entityIndex >= entities.length){ 236 break; 237 } 238 } 239 } 240 } 241 } 242 }