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