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 */ | ||