diff options
| author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-05-29 21:57:33 -0400 |
|---|---|---|
| committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-05-29 21:57:33 -0400 |
| commit | c055e37e57ff365f5ae62d265d4b2140fbdc348a (patch) | |
| tree | 03dcba961433d3a2a188c777ddc1978275b9203d | |
| parent | 9b1c8e98592cc0e5cec471720498e7bb2a60a449 (diff) | |
| download | ether-c055e37e57ff365f5ae62d265d4b2140fbdc348a.tar.gz ether-c055e37e57ff365f5ae62d265d4b2140fbdc348a.tar.bz2 ether-c055e37e57ff365f5ae62d265d4b2140fbdc348a.zip | |
abstracted map data into a class to allow for zooming out
| -rw-r--r-- | src/main.cpp | 366 | ||||
| -rw-r--r-- | src/map.h | 127 |
2 files changed, 316 insertions, 177 deletions
| diff --git a/src/main.cpp b/src/main.cpp index c39cdb6..9534678 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <fov.h> | 7 | #include <fov.h> |
| 8 | #include <iostream> | 8 | #include <iostream> |
| 9 | #include "util.h" | 9 | #include "util.h" |
| 10 | #include "map.h" | ||
| 10 | 11 | ||
| 11 | class sdl_error : public std::logic_error { | 12 | class sdl_error : public std::logic_error { |
| 12 | public: | 13 | public: |
| @@ -75,49 +76,51 @@ struct Kickup { | |||
| 75 | size_t chain; | 76 | size_t chain; |
| 76 | }; | 77 | }; |
| 77 | 78 | ||
| 78 | class Map { | 79 | struct MapData { |
| 80 | Tile tile = Tile::Floor; | ||
| 81 | bool lit = false; | ||
| 82 | bool wasLit = false; | ||
| 83 | double visibility = 0.0; | ||
| 84 | }; | ||
| 85 | |||
| 86 | class Game { | ||
| 79 | public: | 87 | public: |
| 80 | 88 | ||
| 81 | Map() : | 89 | Game() : |
| 82 | tiles(VIEW_WIDTH*VIEW_HEIGHT, Tile::Floor), | 90 | map(-VIEW_WIDTH/2, -VIEW_HEIGHT/2, VIEW_WIDTH, VIEW_HEIGHT) |
| 83 | lighting(VIEW_WIDTH*VIEW_HEIGHT, false), | ||
| 84 | lightStrength(VIEW_WIDTH*VIEW_HEIGHT, 0.0) | ||
| 85 | { | 91 | { |
| 86 | } | 92 | } |
| 87 | 93 | ||
| 88 | std::vector<Tile> tiles; | 94 | Map<MapData> map; |
| 89 | std::vector<bool> lighting; | ||
| 90 | std::vector<bool> oldLighting; | ||
| 91 | std::vector<double> lightStrength; | ||
| 92 | std::list<Kickup> kickups; | 95 | std::list<Kickup> kickups; |
| 93 | int lightedSpots = 0; | 96 | int lightedSpots = 0; |
| 94 | bool dirtyLighting = true; | 97 | bool dirtyLighting = true; |
| 95 | size_t numLamps = 0; | 98 | size_t numLamps = 0; |
| 96 | size_t numDust = 0; | 99 | size_t numDust = 0; |
| 97 | }; | ||
| 98 | 100 | ||
| 99 | int player_x = VIEW_WIDTH / 2; | 101 | int player_x = 0; |
| 100 | int player_y = VIEW_HEIGHT / 2; | 102 | int player_y = 0; |
| 101 | bool renderPlayer = true; | 103 | bool renderPlayer = true; |
| 104 | }; | ||
| 102 | 105 | ||
| 103 | void render( | 106 | void render( |
| 104 | SDL_Renderer* ren, | 107 | SDL_Renderer* ren, |
| 105 | const Map& map, | 108 | const Game& game, |
| 106 | bool drawDark = true) | 109 | bool drawDark = true) |
| 107 | { | 110 | { |
| 108 | SDL_SetRenderDrawColor(ren, rand() % 255, rand() % 255, rand() % 255, 255); | 111 | SDL_SetRenderDrawColor(ren, rand() % 255, rand() % 255, rand() % 255, 255); |
| 109 | SDL_RenderClear(ren); | 112 | SDL_RenderClear(ren); |
| 110 | 113 | ||
| 111 | for (int y = 0; y < VIEW_HEIGHT; y++) | 114 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) |
| 112 | { | 115 | { |
| 113 | for (int x = 0; x < VIEW_WIDTH; x++) | 116 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) |
| 114 | { | 117 | { |
| 115 | bool draw = true; | 118 | bool draw = true; |
| 116 | 119 | ||
| 117 | if ((player_x == x && player_y == y) && renderPlayer) | 120 | if ((game.player_x == x && game.player_y == y) && game.renderPlayer) |
| 118 | { | 121 | { |
| 119 | SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); | 122 | SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); |
| 120 | } else if (!map.lighting.at(x+VIEW_WIDTH*y)) | 123 | } else if (!game.map.at(x,y).lit) |
| 121 | { | 124 | { |
| 122 | if (drawDark) | 125 | if (drawDark) |
| 123 | { | 126 | { |
| @@ -126,7 +129,7 @@ void render( | |||
| 126 | draw = false; | 129 | draw = false; |
| 127 | } | 130 | } |
| 128 | } else { | 131 | } else { |
| 129 | switch (map.tiles.at(x+y*VIEW_WIDTH)) | 132 | switch (game.map.at(x,y).tile) |
| 130 | { | 133 | { |
| 131 | case Tile::Floor: | 134 | case Tile::Floor: |
| 132 | { | 135 | { |
| @@ -156,10 +159,15 @@ void render( | |||
| 156 | 159 | ||
| 157 | if (draw) | 160 | if (draw) |
| 158 | { | 161 | { |
| 159 | SDL_Rect rect{x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT}; | 162 | SDL_Rect rect { |
| 163 | game.map.getTrueX(x) * TILE_WIDTH, | ||
| 164 | game.map.getTrueY(y) * TILE_HEIGHT, | ||
| 165 | TILE_WIDTH, | ||
| 166 | TILE_HEIGHT}; | ||
| 167 | |||
| 160 | SDL_RenderFillRect(ren, &rect); | 168 | SDL_RenderFillRect(ren, &rect); |
| 161 | 169 | ||
| 162 | int alpha = (1.0 - map.lightStrength.at(x+y*VIEW_WIDTH)) * 255; | 170 | int alpha = (1.0 - game.map.at(x,y).visibility) * 255; |
| 163 | SDL_SetRenderDrawColor(ren, 40, 40, 40, alpha); | 171 | SDL_SetRenderDrawColor(ren, 40, 40, 40, alpha); |
| 164 | SDL_RenderFillRect(ren, &rect); | 172 | SDL_RenderFillRect(ren, &rect); |
| 165 | } | 173 | } |
| @@ -169,115 +177,132 @@ void render( | |||
| 169 | SDL_RenderPresent(ren); | 177 | SDL_RenderPresent(ren); |
| 170 | } | 178 | } |
| 171 | 179 | ||
| 172 | void incrementIfSet(Map& map, int& count, int x, int y, int w, int h, Tile val = Tile::Wall) | 180 | void incrementIfSet(Game& game, int& count, int x, int y, Tile val = Tile::Wall) |
| 173 | { | 181 | { |
| 174 | if ((x >= 0) && (x < w) && (y >= 0) && (y < h) && (map.tiles[x+w*y] == val)) | 182 | if (game.map.inBounds(x, y) && game.map.at(x,y).tile == val) |
| 175 | { | 183 | { |
| 176 | count++; | 184 | count++; |
| 177 | } | 185 | } |
| 178 | } | 186 | } |
| 179 | 187 | ||
| 180 | void tick(Map& map, int x1 = 0, int y1 = 0, int x2 = VIEW_WIDTH, int y2 = VIEW_HEIGHT, bool onlyDark = false) | 188 | void tick( |
| 189 | Game& game, | ||
| 190 | int x1, | ||
| 191 | int y1, | ||
| 192 | int x2, | ||
| 193 | int y2, | ||
| 194 | bool invert = false, | ||
| 195 | bool onlyDark = false) | ||
| 181 | { | 196 | { |
| 182 | std::vector<Tile> temp(map.tiles); | 197 | Map<MapData> temp(game.map); |
| 183 | 198 | ||
| 184 | for (int y = std::max(y1, 0); y < std::min(y2, VIEW_HEIGHT); y++) | 199 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) |
| 185 | { | 200 | { |
| 186 | for (int x = std::max(x1, 0); x < std::min(x2, VIEW_WIDTH); x++) | 201 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) |
| 187 | { | 202 | { |
| 188 | if (onlyDark && map.lighting[x+y*VIEW_WIDTH]) | 203 | if (invert == (x >= x1 && x < x2 && y >= y1 && y < y2)) |
| 204 | { | ||
| 205 | continue; | ||
| 206 | } | ||
| 207 | |||
| 208 | if (onlyDark && game.map.at(x,y).lit) | ||
| 189 | { | 209 | { |
| 190 | continue; | 210 | continue; |
| 191 | } | 211 | } |
| 192 | 212 | ||
| 193 | if (map.tiles[x+y*VIEW_WIDTH] == Tile::Lamp) | 213 | if (game.map.at(x,y).tile == Tile::Lamp) |
| 194 | { | 214 | { |
| 195 | continue; | 215 | continue; |
| 196 | } | 216 | } |
| 197 | 217 | ||
| 198 | int count = 0; | 218 | int count = 0; |
| 199 | 219 | ||
| 200 | incrementIfSet(map, count, x-1, y-1, VIEW_WIDTH, VIEW_HEIGHT); | 220 | incrementIfSet(game, count, x-1, y-1); |
| 201 | incrementIfSet(map, count, x-1, y , VIEW_WIDTH, VIEW_HEIGHT); | 221 | incrementIfSet(game, count, x-1, y ); |
| 202 | incrementIfSet(map, count, x-1, y+1, VIEW_WIDTH, VIEW_HEIGHT); | 222 | incrementIfSet(game, count, x-1, y+1); |
| 203 | incrementIfSet(map, count, x , y-1, VIEW_WIDTH, VIEW_HEIGHT); | 223 | incrementIfSet(game, count, x , y-1); |
| 204 | incrementIfSet(map, count, x , y , VIEW_WIDTH, VIEW_HEIGHT); | 224 | incrementIfSet(game, count, x , y ); |
| 205 | incrementIfSet(map, count, x , y+1, VIEW_WIDTH, VIEW_HEIGHT); | 225 | incrementIfSet(game, count, x , y+1); |
| 206 | incrementIfSet(map, count, x+1, y-1, VIEW_WIDTH, VIEW_HEIGHT); | 226 | incrementIfSet(game, count, x+1, y-1); |
| 207 | incrementIfSet(map, count, x+1, y , VIEW_WIDTH, VIEW_HEIGHT); | 227 | incrementIfSet(game, count, x+1, y ); |
| 208 | incrementIfSet(map, count, x+1, y+1, VIEW_WIDTH, VIEW_HEIGHT); | 228 | incrementIfSet(game, count, x+1, y+1); |
| 209 | 229 | ||
| 210 | if (count >= 5) | 230 | if (count >= 5) |
| 211 | { | 231 | { |
| 212 | temp[x+VIEW_WIDTH*y] = Tile::Wall; | 232 | temp.at(x,y).tile = Tile::Wall; |
| 213 | } else { | 233 | } else { |
| 214 | temp[x+VIEW_WIDTH*y] = Tile::Floor; | 234 | temp.at(x,y).tile = Tile::Floor; |
| 215 | } | 235 | } |
| 216 | } | 236 | } |
| 217 | } | 237 | } |
| 218 | 238 | ||
| 219 | map.tiles = temp; | 239 | game.map = std::move(temp); |
| 240 | } | ||
| 241 | |||
| 242 | void tick(Game& game, bool onlyDark = false) | ||
| 243 | { | ||
| 244 | tick( | ||
| 245 | game, | ||
| 246 | game.map.getLeft(), | ||
| 247 | game.map.getTop(), | ||
| 248 | game.map.getRight(), | ||
| 249 | game.map.getBottom(), | ||
| 250 | false, | ||
| 251 | onlyDark); | ||
| 220 | } | 252 | } |
| 221 | 253 | ||
| 222 | void movePlayer(int x, int y, Map& map) | 254 | void movePlayer(Game& game, int x, int y) |
| 223 | { | 255 | { |
| 224 | if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT) && | 256 | if (game.map.inBounds(x, y) && game.map.at(x,y).tile == Tile::Floor) |
| 225 | map.tiles[x+VIEW_WIDTH*y] == Tile::Floor) | ||
| 226 | { | 257 | { |
| 227 | if (map.tiles[player_x+player_y*VIEW_WIDTH] == Tile::Floor) | 258 | if (game.map.at(game.player_x, game.player_y).tile == Tile::Floor) |
| 228 | { | 259 | { |
| 229 | map.tiles[player_x+player_y*VIEW_WIDTH] = Tile::Dust; | 260 | game.map.at(game.player_x, game.player_y).tile = Tile::Dust; |
| 230 | map.numDust++; | 261 | game.numDust++; |
| 231 | } | 262 | } |
| 232 | 263 | ||
| 233 | player_x = x; | 264 | game.player_x = x; |
| 234 | player_y = y; | 265 | game.player_y = y; |
| 235 | 266 | ||
| 236 | map.dirtyLighting = true; | 267 | game.dirtyLighting = true; |
| 237 | } | 268 | } |
| 238 | } | 269 | } |
| 239 | 270 | ||
| 240 | void setIfValid(Map& map, int x, int y, Tile val) | 271 | void recalculateLighting(Game& game, fov_settings_type* fov) |
| 241 | { | 272 | { |
| 242 | if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT)) | 273 | game.lightedSpots = 0; |
| 274 | |||
| 275 | for (MapData& md : game.map.data()) | ||
| 243 | { | 276 | { |
| 244 | map.tiles[x+VIEW_WIDTH*y] = val; | 277 | md.wasLit = md.lit; |
| 278 | md.lit = false; | ||
| 279 | md.visibility = 0.0; | ||
| 245 | } | 280 | } |
| 246 | } | ||
| 247 | |||
| 248 | void recalculateLighting(Map& map, fov_settings_type* fov) | ||
| 249 | { | ||
| 250 | map.oldLighting = map.lighting; | ||
| 251 | map.lighting = std::vector<bool>(VIEW_WIDTH*VIEW_HEIGHT, false); | ||
| 252 | map.lightStrength = std::vector<double>(VIEW_WIDTH*VIEW_HEIGHT, 0.0); | ||
| 253 | map.lightedSpots = 0; | ||
| 254 | 281 | ||
| 255 | fov_settings_set_opacity_test_function( | 282 | fov_settings_set_opacity_test_function( |
| 256 | fov, | 283 | fov, |
| 257 | [] (void* map, int x, int y) { | 284 | [] (void* data, int x, int y) { |
| 258 | return | 285 | Game& game = *static_cast<Game*>(data); |
| 259 | x >= 0 && | 286 | |
| 260 | x < VIEW_WIDTH && | 287 | return game.map.inBounds(x,y) && game.map.at(x,y).tile == Tile::Wall; |
| 261 | y >= 0 && | ||
| 262 | y < VIEW_HEIGHT && | ||
| 263 | static_cast<Map*>(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall; | ||
| 264 | }); | 288 | }); |
| 265 | 289 | ||
| 266 | fov_settings_set_apply_lighting_function( | 290 | fov_settings_set_apply_lighting_function( |
| 267 | fov, | 291 | fov, |
| 268 | [] (void* map, int x, int y, int dx, int dy, void*) { | 292 | [] (void* data, int x, int y, int dx, int dy, void*) { |
| 269 | if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT)) | 293 | Game& game = *static_cast<Game*>(data); |
| 294 | |||
| 295 | if (game.map.inBounds(x, y)) | ||
| 270 | { | 296 | { |
| 271 | Map& m = *static_cast<Map*>(map); | 297 | if (!game.map.at(x,y).lit) |
| 272 | if (!m.lighting[x+VIEW_WIDTH*y]) | ||
| 273 | { | 298 | { |
| 274 | m.lightedSpots++; | 299 | game.lightedSpots++; |
| 275 | } | 300 | } |
| 276 | 301 | ||
| 277 | m.lighting[x+VIEW_WIDTH*y] = true; | 302 | game.map.at(x,y).lit = true; |
| 278 | 303 | ||
| 279 | m.lightStrength[x+VIEW_WIDTH*y] = std::max( | 304 | game.map.at(x,y).visibility = std::max( |
| 280 | m.lightStrength[x+VIEW_WIDTH*y], | 305 | game.map.at(x,y).visibility, |
| 281 | std::pow( | 306 | std::pow( |
| 282 | std::max( | 307 | std::max( |
| 283 | 0.0, | 308 | 0.0, |
| @@ -286,29 +311,29 @@ void recalculateLighting(Map& map, fov_settings_type* fov) | |||
| 286 | } | 311 | } |
| 287 | }); | 312 | }); |
| 288 | 313 | ||
| 289 | for (int y = 0; y < VIEW_HEIGHT; y++) | 314 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) |
| 290 | { | 315 | { |
| 291 | for (int x = 0; x < VIEW_WIDTH; x++) | 316 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) |
| 292 | { | 317 | { |
| 293 | if ((player_x == x && player_y == y && renderPlayer) || | 318 | if ((game.player_x == x && game.player_y == y && game.renderPlayer) || |
| 294 | map.tiles[x+VIEW_WIDTH*y] == Tile::Dust || | 319 | game.map.at(x,y).tile == Tile::Dust || |
| 295 | map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | 320 | game.map.at(x,y).tile == Tile::Lamp) |
| 296 | { | 321 | { |
| 297 | fov_circle(fov, static_cast<void*>(&map), nullptr, x, y, RADIUS); | 322 | fov_circle(fov, static_cast<void*>(&game), nullptr, x, y, RADIUS); |
| 298 | 323 | ||
| 299 | map.lighting[x+VIEW_WIDTH*y] = true; | 324 | game.map.at(x,y).lit = true; |
| 300 | map.lightStrength[x+VIEW_WIDTH*y] = 1.0; | 325 | game.map.at(x,y).visibility = 1.0; |
| 301 | } | 326 | } |
| 302 | } | 327 | } |
| 303 | } | 328 | } |
| 304 | 329 | ||
| 305 | map.dirtyLighting = false; | 330 | game.dirtyLighting = false; |
| 306 | } | 331 | } |
| 307 | 332 | ||
| 308 | void processKeys(Map& map, const Input& keystate) | 333 | void processKeys(Game& game, const Input& keystate) |
| 309 | { | 334 | { |
| 310 | int px = player_x; | 335 | int px = game.player_x; |
| 311 | int py = player_y; | 336 | int py = game.player_y; |
| 312 | 337 | ||
| 313 | if (keystate.up) | 338 | if (keystate.up) |
| 314 | { | 339 | { |
| @@ -330,13 +355,13 @@ void processKeys(Map& map, const Input& keystate) | |||
| 330 | px++; | 355 | px++; |
| 331 | } | 356 | } |
| 332 | 357 | ||
| 333 | if (!(player_x == px && player_y == py)) | 358 | if (!(game.player_x == px && game.player_y == py)) |
| 334 | { | 359 | { |
| 335 | movePlayer(px, py, map); | 360 | movePlayer(game, px, py); |
| 336 | } | 361 | } |
| 337 | } | 362 | } |
| 338 | 363 | ||
| 339 | void kickUpDust(Map& map, int x, int y, size_t chain) | 364 | void kickUpDust(Game& game, int x, int y, size_t chain) |
| 340 | { | 365 | { |
| 341 | Kickup dk; | 366 | Kickup dk; |
| 342 | dk.x = x; | 367 | dk.x = x; |
| @@ -345,71 +370,67 @@ void kickUpDust(Map& map, int x, int y, size_t chain) | |||
| 345 | dk.cur = 0; | 370 | dk.cur = 0; |
| 346 | dk.radius = RADIUS + (chain + 1) * (chain + 1); | 371 | dk.radius = RADIUS + (chain + 1) * (chain + 1); |
| 347 | 372 | ||
| 348 | map.kickups.push_back(dk); | 373 | game.kickups.push_back(dk); |
| 349 | } | 374 | } |
| 350 | 375 | ||
| 351 | void popLamp(Map& map, int x, int y, size_t chain) | 376 | void popLamp(Game& game, int x, int y, size_t chain) |
| 352 | { | 377 | { |
| 353 | if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | 378 | if (game.map.at(x,y).tile == Tile::Lamp) |
| 354 | { | 379 | { |
| 355 | map.numLamps--; | 380 | game.numLamps--; |
| 356 | } | 381 | } |
| 357 | 382 | ||
| 358 | map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; | 383 | game.map.at(x,y).tile = Tile::Dust; |
| 359 | map.numDust++; | 384 | game.numDust++; |
| 360 | map.dirtyLighting = true; | 385 | game.dirtyLighting = true; |
| 361 | 386 | ||
| 362 | kickUpDust(map, x, y, chain); | 387 | kickUpDust(game, x, y, chain); |
| 363 | } | 388 | } |
| 364 | 389 | ||
| 365 | void processKickup(Map& map) | 390 | void processKickup(Game& game) |
| 366 | { | 391 | { |
| 367 | for (Kickup& kickup : map.kickups) | 392 | for (Kickup& kickup : game.kickups) |
| 368 | { | 393 | { |
| 369 | kickup.cur++; | 394 | kickup.cur++; |
| 370 | 395 | ||
| 371 | if (map.tiles[kickup.x+VIEW_WIDTH*kickup.y] == Tile::Floor) | 396 | if (game.map.at(kickup.x, kickup.y).tile == Tile::Floor) |
| 372 | { | 397 | { |
| 373 | map.tiles[kickup.x+VIEW_WIDTH*kickup.y] = Tile::Dust; | 398 | game.map.at(kickup.x, kickup.y).tile = Tile::Dust; |
| 374 | map.numDust++; | 399 | game.numDust++; |
| 375 | } | 400 | } |
| 376 | 401 | ||
| 377 | std::unique_ptr<fov_settings_type> dusty(new fov_settings_type); | 402 | std::unique_ptr<fov_settings_type> dusty(new fov_settings_type); |
| 378 | fov_settings_set_opacity_test_function( | 403 | fov_settings_set_opacity_test_function( |
| 379 | dusty.get(), | 404 | dusty.get(), |
| 380 | [] (void* map, int x, int y) { | 405 | [] (void* data, int x, int y) { |
| 381 | return | 406 | Game& game = *static_cast<Game*>(data); |
| 382 | x >= 0 && | 407 | |
| 383 | x < VIEW_WIDTH && | 408 | return game.map.inBounds(x,y) && game.map.at(x,y).tile == Tile::Wall; |
| 384 | y >= 0 && | ||
| 385 | y < VIEW_HEIGHT && | ||
| 386 | static_cast<Map*>(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall; | ||
| 387 | }); | 409 | }); |
| 388 | 410 | ||
| 389 | fov_settings_set_apply_lighting_function( | 411 | fov_settings_set_apply_lighting_function( |
| 390 | dusty.get(), | 412 | dusty.get(), |
| 391 | [] (void* data, int x, int y, int, int, void* source) { | 413 | [] (void* data, int x, int y, int, int, void* source) { |
| 392 | Map& map = *static_cast<Map*>(data); | 414 | Game& game = *static_cast<Game*>(data); |
| 393 | Kickup& kickup = *static_cast<Kickup*>(source); | 415 | Kickup& kickup = *static_cast<Kickup*>(source); |
| 394 | 416 | ||
| 395 | if ((x >= 0) && (x < VIEW_WIDTH) && | 417 | if (game.map.inBounds(x,y)) |
| 396 | (y >= 0) && (y < VIEW_HEIGHT)) | ||
| 397 | { | 418 | { |
| 398 | if (map.tiles[x+VIEW_WIDTH*y] == Tile::Floor) | 419 | if (game.map.at(x,y).tile == Tile::Floor) |
| 399 | { | 420 | { |
| 400 | map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; | 421 | game.map.at(x,y).tile = Tile::Dust; |
| 401 | map.numDust++; | 422 | game.numDust++; |
| 402 | map.dirtyLighting = true; | 423 | game.dirtyLighting = true; |
| 403 | } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | 424 | } else if (game.map.at(x,y).tile == Tile::Lamp) |
| 404 | { | 425 | { |
| 405 | popLamp(map, x, y, kickup.chain + 1); | 426 | popLamp(game, x, y, kickup.chain + 1); |
| 406 | } | 427 | } |
| 407 | } | 428 | } |
| 408 | }); | 429 | }); |
| 409 | 430 | ||
| 410 | fov_circle( | 431 | fov_circle( |
| 411 | dusty.get(), | 432 | dusty.get(), |
| 412 | static_cast<void*>(&map), | 433 | static_cast<void*>(&game), |
| 413 | static_cast<void*>(&kickup), | 434 | static_cast<void*>(&kickup), |
| 414 | kickup.x, | 435 | kickup.x, |
| 415 | kickup.y, | 436 | kickup.y, |
| @@ -417,7 +438,7 @@ void processKickup(Map& map) | |||
| 417 | } | 438 | } |
| 418 | 439 | ||
| 419 | erase_if( | 440 | erase_if( |
| 420 | map.kickups, | 441 | game.kickups, |
| 421 | [] (const Kickup& kickup) { | 442 | [] (const Kickup& kickup) { |
| 422 | return kickup.cur == kickup.radius; | 443 | return kickup.cur == kickup.radius; |
| 423 | }); | 444 | }); |
| @@ -456,25 +477,22 @@ int main(int, char**) | |||
| 456 | 477 | ||
| 457 | SDL_SetRenderDrawBlendMode(ren.get(), SDL_BLENDMODE_BLEND); | 478 | SDL_SetRenderDrawBlendMode(ren.get(), SDL_BLENDMODE_BLEND); |
| 458 | 479 | ||
| 459 | Map map; | 480 | Game game; |
| 460 | 481 | ||
| 461 | std::unique_ptr<fov_settings_type> fov(new fov_settings_type()); | 482 | std::unique_ptr<fov_settings_type> fov(new fov_settings_type()); |
| 462 | fov_settings_init(fov.get()); | 483 | fov_settings_init(fov.get()); |
| 463 | 484 | ||
| 464 | for (int y = 0; y < VIEW_HEIGHT; y++) | 485 | for (MapData& md : game.map.data()) |
| 465 | { | 486 | { |
| 466 | for (int x = 0; x < VIEW_WIDTH; x++) | 487 | if (std::bernoulli_distribution(0.5)(rng)) |
| 467 | { | 488 | { |
| 468 | if (std::bernoulli_distribution(0.5)(rng)) | 489 | md.tile = Tile::Wall; |
| 469 | { | ||
| 470 | map.tiles[x+y*VIEW_WIDTH] = Tile::Wall; | ||
| 471 | } | ||
| 472 | } | 490 | } |
| 473 | } | 491 | } |
| 474 | 492 | ||
| 475 | tick(map); | 493 | tick(game); |
| 476 | tick(map); | 494 | tick(game); |
| 477 | tick(map); | 495 | tick(game); |
| 478 | 496 | ||
| 479 | bool quit = false; | 497 | bool quit = false; |
| 480 | LoseState losing = LoseState::None; | 498 | LoseState losing = LoseState::None; |
| @@ -531,26 +549,24 @@ int main(int, char**) | |||
| 531 | { | 549 | { |
| 532 | if (losing == LoseState::None) | 550 | if (losing == LoseState::None) |
| 533 | { | 551 | { |
| 534 | if (map.tiles[player_x+VIEW_WIDTH*player_y] == Tile::Floor) | 552 | if (game.map.at(game.player_x, game.player_y).tile == |
| 553 | Tile::Floor) | ||
| 535 | { | 554 | { |
| 536 | map.tiles[player_x+VIEW_WIDTH*player_y] = Tile::Lamp; | 555 | game.map.at(game.player_x, game.player_y).tile = Tile::Lamp; |
| 537 | map.numLamps++; | 556 | game.numLamps++; |
| 538 | map.dirtyLighting = true; | 557 | game.dirtyLighting = true; |
| 539 | kickUpDust(map, player_x, player_y, 0); | 558 | kickUpDust(game, game.player_x, game.player_y, 0); |
| 540 | 559 | ||
| 541 | for (int i = 0; i < 5; i++) | 560 | for (int i = 0; i < 5; i++) |
| 542 | { | 561 | { |
| 543 | processKeys(map, keystate); | 562 | processKeys(game, keystate); |
| 544 | 563 | ||
| 545 | tick( | 564 | tick( |
| 546 | map, | 565 | game, |
| 547 | player_x - (RADIUS - 1), | 566 | game.player_x - (RADIUS - 1), |
| 548 | player_y - (RADIUS - 1), | 567 | game.player_y - (RADIUS - 1), |
| 549 | player_x + RADIUS, | 568 | game.player_x + RADIUS, |
| 550 | player_y + RADIUS); | 569 | game.player_y + RADIUS); |
| 551 | |||
| 552 | //render(ren.get(), map, false); | ||
| 553 | //SDL_Delay(30); | ||
| 554 | } | 570 | } |
| 555 | } | 571 | } |
| 556 | } | 572 | } |
| @@ -572,21 +588,18 @@ int main(int, char**) | |||
| 572 | 588 | ||
| 573 | while (dustAcc >= dustDt) | 589 | while (dustAcc >= dustDt) |
| 574 | { | 590 | { |
| 575 | for (int y = 0; y < VIEW_HEIGHT; y++) | 591 | for (MapData& md : game.map.data()) |
| 576 | { | 592 | { |
| 577 | for (int x = 0; x < VIEW_WIDTH; x++) | 593 | if (md.tile == Tile::Dust) |
| 578 | { | 594 | { |
| 579 | if (map.tiles[x+y*VIEW_WIDTH] == Tile::Dust) | 595 | md.tile = Tile::Floor; |
| 580 | { | 596 | game.dirtyLighting = true; |
| 581 | map.tiles[x+y*VIEW_WIDTH] = Tile::Floor; | ||
| 582 | map.dirtyLighting = true; | ||
| 583 | } | ||
| 584 | } | 597 | } |
| 585 | } | 598 | } |
| 586 | 599 | ||
| 587 | map.numDust = 0; | 600 | game.numDust = 0; |
| 588 | 601 | ||
| 589 | processKickup(map); | 602 | processKickup(game); |
| 590 | 603 | ||
| 591 | dustAcc -= dustDt; | 604 | dustAcc -= dustDt; |
| 592 | } | 605 | } |
| @@ -597,7 +610,7 @@ int main(int, char**) | |||
| 597 | { | 610 | { |
| 598 | while (inputAcc >= inputDt) | 611 | while (inputAcc >= inputDt) |
| 599 | { | 612 | { |
| 600 | processKeys(map, keystate); | 613 | processKeys(game, keystate); |
| 601 | 614 | ||
| 602 | inputAcc -= inputDt; | 615 | inputAcc -= inputDt; |
| 603 | } | 616 | } |
| @@ -607,9 +620,9 @@ int main(int, char**) | |||
| 607 | 620 | ||
| 608 | case LoseState::PoppingLamps: | 621 | case LoseState::PoppingLamps: |
| 609 | { | 622 | { |
| 610 | if (map.numLamps == 0) | 623 | if (game.numLamps == 0) |
| 611 | { | 624 | { |
| 612 | if (map.numDust == 0) | 625 | if (game.numDust == 0) |
| 613 | { | 626 | { |
| 614 | losing = LoseState::PoppingPlayer; | 627 | losing = LoseState::PoppingPlayer; |
| 615 | } | 628 | } |
| @@ -620,11 +633,11 @@ int main(int, char**) | |||
| 620 | { | 633 | { |
| 621 | std::vector<std::tuple<int, int>> lamps; | 634 | std::vector<std::tuple<int, int>> lamps; |
| 622 | 635 | ||
| 623 | for (int y = 0; y < VIEW_HEIGHT; y++) | 636 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) |
| 624 | { | 637 | { |
| 625 | for (int x = 0; x < VIEW_WIDTH; x++) | 638 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) |
| 626 | { | 639 | { |
| 627 | if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | 640 | if (game.map.at(x,y).tile == Tile::Lamp) |
| 628 | { | 641 | { |
| 629 | lamps.emplace_back(x, y); | 642 | lamps.emplace_back(x, y); |
| 630 | } | 643 | } |
| @@ -634,7 +647,7 @@ int main(int, char**) | |||
| 634 | std::uniform_int_distribution<int> lampDist(0, lamps.size() - 1); | 647 | std::uniform_int_distribution<int> lampDist(0, lamps.size() - 1); |
| 635 | std::tuple<int, int> popPos = lamps[lampDist(rng)]; | 648 | std::tuple<int, int> popPos = lamps[lampDist(rng)]; |
| 636 | 649 | ||
| 637 | popLamp(map, std::get<0>(popPos), std::get<1>(popPos), 0); | 650 | popLamp(game, std::get<0>(popPos), std::get<1>(popPos), 0); |
| 638 | 651 | ||
| 639 | losePopLampAcc -= losePopLampDt; | 652 | losePopLampAcc -= losePopLampDt; |
| 640 | } | 653 | } |
| @@ -649,8 +662,8 @@ int main(int, char**) | |||
| 649 | 662 | ||
| 650 | if (losePopPlayerAcc >= losePopPlayerDt) | 663 | if (losePopPlayerAcc >= losePopPlayerDt) |
| 651 | { | 664 | { |
| 652 | popLamp(map, player_x, player_y, 10); | 665 | popLamp(game, game.player_x, game.player_y, 10); |
| 653 | renderPlayer = false; | 666 | game.renderPlayer = false; |
| 654 | 667 | ||
| 655 | losing = LoseState::Outro; | 668 | losing = LoseState::Outro; |
| 656 | } | 669 | } |
| @@ -660,7 +673,7 @@ int main(int, char**) | |||
| 660 | 673 | ||
| 661 | case LoseState::Outro: | 674 | case LoseState::Outro: |
| 662 | { | 675 | { |
| 663 | if (map.numDust == 0) | 676 | if (game.numDust == 0) |
| 664 | { | 677 | { |
| 665 | quit = true; | 678 | quit = true; |
| 666 | } | 679 | } |
| @@ -669,33 +682,32 @@ int main(int, char**) | |||
| 669 | } | 682 | } |
| 670 | } | 683 | } |
| 671 | 684 | ||
| 672 | if (map.dirtyLighting) | 685 | if (game.dirtyLighting) |
| 673 | { | 686 | { |
| 674 | recalculateLighting(map, fov.get()); | 687 | recalculateLighting(game, fov.get()); |
| 675 | 688 | ||
| 676 | for (int y = 0; y < VIEW_HEIGHT; y++) | 689 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) |
| 677 | { | 690 | { |
| 678 | for (int x = 0; x < VIEW_WIDTH; x++) | 691 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) |
| 679 | { | 692 | { |
| 680 | if (!map.lighting[x+y*VIEW_WIDTH] && map.oldLighting[x+y*VIEW_WIDTH]) | 693 | if (!game.map.at(x,y).lit && game.map.at(x,y).wasLit) |
| 681 | { | 694 | { |
| 682 | if (std::bernoulli_distribution(0.5)(rng)) | 695 | if (std::bernoulli_distribution(0.5)(rng)) |
| 683 | { | 696 | { |
| 684 | map.tiles[x+y*VIEW_WIDTH] = Tile::Wall; | 697 | game.map.at(x,y).tile = Tile::Wall; |
| 685 | } else { | 698 | } else { |
| 686 | map.tiles[x+y*VIEW_WIDTH] = Tile::Floor; | 699 | game.map.at(x,y).tile = Tile::Floor; |
| 687 | } | 700 | } |
| 688 | } | 701 | } |
| 689 | } | 702 | } |
| 690 | } | 703 | } |
| 691 | 704 | ||
| 692 | tick(map, 0, 0, VIEW_WIDTH, VIEW_HEIGHT, true); | 705 | tick(game, true); |
| 693 | tick(map, 0, 0, VIEW_WIDTH, VIEW_HEIGHT, true); | 706 | tick(game, true); |
| 694 | tick(map, 0, 0, VIEW_WIDTH, VIEW_HEIGHT, true); | 707 | tick(game, true); |
| 695 | } | 708 | } |
| 696 | 709 | ||
| 697 | render(ren.get(), map, true); | 710 | render(ren.get(), game, true); |
| 698 | //SDL_Delay(50); | ||
| 699 | } | 711 | } |
| 700 | } catch (const sdl_error& ex) | 712 | } catch (const sdl_error& ex) |
| 701 | { | 713 | { |
| diff --git a/src/map.h b/src/map.h new file mode 100644 index 0000000..329553c --- /dev/null +++ b/src/map.h | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | #ifndef MAP_H_3AB00D12 | ||
| 2 | #define MAP_H_3AB00D12 | ||
| 3 | |||
| 4 | #include <vector> | ||
| 5 | #include <algorithm> | ||
| 6 | |||
| 7 | template <typename T> | ||
| 8 | class Map { | ||
| 9 | public: | ||
| 10 | |||
| 11 | Map( | ||
| 12 | int left, | ||
| 13 | int top, | ||
| 14 | int width, | ||
| 15 | int height) : | ||
| 16 | left_(left), | ||
| 17 | top_(top), | ||
| 18 | width_(width), | ||
| 19 | height_(height), | ||
| 20 | data_(width_*height_) | ||
| 21 | { | ||
| 22 | } | ||
| 23 | |||
| 24 | inline int getLeft() const | ||
| 25 | { | ||
| 26 | return left_; | ||
| 27 | } | ||
| 28 | |||
| 29 | inline int getRight() const | ||
| 30 | { | ||
| 31 | return left_ + width_; | ||
| 32 | } | ||
| 33 | |||
| 34 | inline int getTop() const | ||
| 35 | { | ||
| 36 | return top_; | ||
| 37 | } | ||
| 38 | |||
| 39 | inline int getBottom() const | ||
| 40 | { | ||
| 41 | return top_ + height_; | ||
| 42 | } | ||
| 43 | |||
| 44 | inline int getWidth() const | ||
| 45 | { | ||
| 46 | return width_; | ||
| 47 | } | ||
| 48 | |||
| 49 | inline int getHeight() const | ||
| 50 | { | ||
| 51 | return height_; | ||
| 52 | } | ||
| 53 | |||
| 54 | inline int getTrueX(int x) const | ||
| 55 | { | ||
| 56 | return (x - left_); | ||
| 57 | } | ||
| 58 | |||
| 59 | inline int getTrueY(int y) const | ||
| 60 | { | ||
| 61 | return (y - top_); | ||
| 62 | } | ||
| 63 | |||
| 64 | inline bool inBounds(int x, int y) const | ||
| 65 | { | ||
| 66 | return (x >= left_) && | ||
| 67 | (x < left_ + width_) && | ||
| 68 | (y >= top_) && | ||
| 69 | (y < top_ + height_); | ||
| 70 | } | ||
| 71 | |||
| 72 | inline const T& at(int x, int y) const | ||
| 73 | { | ||
| 74 | return data_.at((x - left_) + width_ * (y - top_)); | ||
| 75 | } | ||
| 76 | |||
| 77 | inline T& at(int x, int y) | ||
| 78 | { | ||
| 79 | return const_cast<T&>(static_cast<const Map&>(*this).at(x, y)); | ||
| 80 | } | ||
| 81 | |||
| 82 | inline const std::vector<T>& data() const | ||
| 83 | { | ||
| 84 | return data_; | ||
| 85 | } | ||
| 86 | |||
| 87 | inline std::vector<T>& data() | ||
| 88 | { | ||
| 89 | return data_; | ||
| 90 | } | ||
| 91 | |||
| 92 | void resize(int newLeft, int newTop, int newWidth, int newHeight) | ||
| 93 | { | ||
| 94 | std::vector<T> newData(newWidth * newHeight); | ||
| 95 | |||
| 96 | int winTop = std::max(top_, newTop); | ||
| 97 | int winBottom = std::min(top_ + height_, newTop + newHeight); | ||
| 98 | int winLeft = std::max(left_, newLeft); | ||
| 99 | int winRight = std::min(left_ + width_, newLeft + newWidth); | ||
| 100 | |||
| 101 | for (int y = winTop; y < winBottom; y++) | ||
| 102 | { | ||
| 103 | std::move( | ||
| 104 | std::next(std::begin(data_), (winLeft - left_) + width_ * (y - top_)), | ||
| 105 | std::next(std::begin(data_), (winRight - left_) + width_ * (y - top_)), | ||
| 106 | std::next(std::begin(newData), | ||
| 107 | (winLeft - newLeft) + newWidth * (y - newTop))); | ||
| 108 | } | ||
| 109 | |||
| 110 | left_ = newLeft; | ||
| 111 | top_ = newTop; | ||
| 112 | width_ = newWidth; | ||
| 113 | height_ = newHeight; | ||
| 114 | data_.swap(newData); | ||
| 115 | } | ||
| 116 | |||
| 117 | private: | ||
| 118 | |||
| 119 | int left_; | ||
| 120 | int top_; | ||
| 121 | int width_; | ||
| 122 | int height_; | ||
| 123 | |||
| 124 | std::vector<T> data_; | ||
| 125 | }; | ||
| 126 | |||
| 127 | #endif /* end of include guard: MAP_H_3AB00D12 */ | ||
