diff options
-rw-r--r-- | src/main.cpp | 194 | ||||
-rw-r--r-- | src/untitled.txt | 0 | ||||
-rw-r--r-- | src/util.h | 20 |
3 files changed, 149 insertions, 65 deletions
diff --git a/src/main.cpp b/src/main.cpp index 2840439..e26a5a8 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
@@ -2,10 +2,11 @@ | |||
2 | #include <stdexcept> | 2 | #include <stdexcept> |
3 | #include <memory> | 3 | #include <memory> |
4 | #include <vector> | 4 | #include <vector> |
5 | #include <list> | ||
5 | #include <random> | 6 | #include <random> |
6 | #include <fov.h> | 7 | #include <fov.h> |
7 | #include <deque> | ||
8 | #include <iostream> | 8 | #include <iostream> |
9 | #include "util.h" | ||
9 | 10 | ||
10 | class sdl_error : public std::logic_error { | 11 | class sdl_error : public std::logic_error { |
11 | public: | 12 | public: |
@@ -59,6 +60,14 @@ struct Input { | |||
59 | bool down = false; | 60 | bool down = false; |
60 | }; | 61 | }; |
61 | 62 | ||
63 | struct Kickup { | ||
64 | int x; | ||
65 | int y; | ||
66 | size_t cur; | ||
67 | size_t radius; | ||
68 | size_t chain; | ||
69 | }; | ||
70 | |||
62 | class Map { | 71 | class Map { |
63 | public: | 72 | public: |
64 | 73 | ||
@@ -73,7 +82,9 @@ public: | |||
73 | std::vector<bool> lighting; | 82 | std::vector<bool> lighting; |
74 | std::vector<bool> oldLighting; | 83 | std::vector<bool> oldLighting; |
75 | std::vector<double> lightStrength; | 84 | std::vector<double> lightStrength; |
85 | std::list<Kickup> kickups; | ||
76 | int lightedSpots = 0; | 86 | int lightedSpots = 0; |
87 | bool dirtyLighting = true; | ||
77 | }; | 88 | }; |
78 | 89 | ||
79 | int player_x = VIEW_WIDTH / 2; | 90 | int player_x = VIEW_WIDTH / 2; |
@@ -210,6 +221,8 @@ void movePlayer(int x, int y, Map& map) | |||
210 | 221 | ||
211 | player_x = x; | 222 | player_x = x; |
212 | player_y = y; | 223 | player_y = y; |
224 | |||
225 | map.dirtyLighting = true; | ||
213 | } | 226 | } |
214 | } | 227 | } |
215 | 228 | ||
@@ -266,22 +279,19 @@ void recalculateLighting(Map& map, fov_settings_type* fov) | |||
266 | { | 279 | { |
267 | for (int x = 0; x < VIEW_WIDTH; x++) | 280 | for (int x = 0; x < VIEW_WIDTH; x++) |
268 | { | 281 | { |
269 | if ((player_x == x && player_y == y) || map.tiles[x+VIEW_WIDTH*y] == Tile::Dust || map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | 282 | if ((player_x == x && player_y == y) || |
283 | map.tiles[x+VIEW_WIDTH*y] == Tile::Dust || | ||
284 | map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | ||
270 | { | 285 | { |
271 | fov_circle(fov, static_cast<void*>(&map), nullptr, x, y, RADIUS); | 286 | fov_circle(fov, static_cast<void*>(&map), nullptr, x, y, RADIUS); |
272 | } | ||
273 | 287 | ||
274 | if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp || | ||
275 | map.tiles[x+VIEW_WIDTH*y] == Tile::Dust) | ||
276 | { | ||
277 | map.lighting[x+VIEW_WIDTH*y] = true; | 288 | map.lighting[x+VIEW_WIDTH*y] = true; |
278 | map.lightStrength[x+VIEW_WIDTH*y] = 1.0; | 289 | map.lightStrength[x+VIEW_WIDTH*y] = 1.0; |
279 | } | 290 | } |
280 | } | 291 | } |
281 | } | 292 | } |
282 | 293 | ||
283 | map.lighting[player_x+VIEW_WIDTH*player_y] = true; | 294 | map.dirtyLighting = false; |
284 | map.lightStrength[player_x+VIEW_WIDTH*player_y] = 1.0; | ||
285 | } | 295 | } |
286 | 296 | ||
287 | void processKeys(Map& map, const Input& keystate) | 297 | void processKeys(Map& map, const Input& keystate) |
@@ -315,6 +325,81 @@ void processKeys(Map& map, const Input& keystate) | |||
315 | } | 325 | } |
316 | } | 326 | } |
317 | 327 | ||
328 | void kickUpDust(Map& map, int x, int y, size_t chain) | ||
329 | { | ||
330 | std::cout << "kickup " << x << " " << y << " " << chain << std::endl; | ||
331 | Kickup dk; | ||
332 | dk.x = x; | ||
333 | dk.y = y; | ||
334 | dk.chain = chain; | ||
335 | dk.cur = 0; | ||
336 | dk.radius = RADIUS + (chain + 1) * (chain + 1); | ||
337 | |||
338 | map.kickups.push_back(dk); | ||
339 | } | ||
340 | |||
341 | void processKickup(Map& map) | ||
342 | { | ||
343 | for (Kickup& kickup : map.kickups) | ||
344 | { | ||
345 | kickup.cur++; | ||
346 | |||
347 | if (map.tiles[kickup.x+VIEW_WIDTH*kickup.y] == Tile::Floor) | ||
348 | { | ||
349 | map.tiles[kickup.x+VIEW_WIDTH*kickup.y] = Tile::Dust; | ||
350 | } | ||
351 | |||
352 | std::unique_ptr<fov_settings_type> dusty(new fov_settings_type); | ||
353 | fov_settings_set_opacity_test_function( | ||
354 | dusty.get(), | ||
355 | [] (void* map, int x, int y) { | ||
356 | return | ||
357 | x >= 0 && | ||
358 | x < VIEW_WIDTH && | ||
359 | y >= 0 && | ||
360 | y < VIEW_HEIGHT && | ||
361 | static_cast<Map*>(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall; | ||
362 | }); | ||
363 | |||
364 | fov_settings_set_apply_lighting_function( | ||
365 | dusty.get(), | ||
366 | [] (void* data, int x, int y, int, int, void* source) { | ||
367 | Map& map = *static_cast<Map*>(data); | ||
368 | Kickup& kickup = *static_cast<Kickup*>(source); | ||
369 | |||
370 | if ((x >= 0) && (x < VIEW_WIDTH) && | ||
371 | (y >= 0) && (y < VIEW_HEIGHT)) | ||
372 | { | ||
373 | if (map.tiles[x+VIEW_WIDTH*y] == Tile::Floor) | ||
374 | { | ||
375 | map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; | ||
376 | map.dirtyLighting = true; | ||
377 | } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | ||
378 | { | ||
379 | map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; | ||
380 | map.dirtyLighting = true; | ||
381 | |||
382 | kickUpDust(map, x, y, kickup.chain + 1); | ||
383 | } | ||
384 | } | ||
385 | }); | ||
386 | |||
387 | fov_circle( | ||
388 | dusty.get(), | ||
389 | static_cast<void*>(&map), | ||
390 | static_cast<void*>(&kickup), | ||
391 | kickup.x, | ||
392 | kickup.y, | ||
393 | kickup.cur); | ||
394 | } | ||
395 | |||
396 | erase_if( | ||
397 | map.kickups, | ||
398 | [] (const Kickup& kickup) { | ||
399 | return kickup.cur == kickup.radius; | ||
400 | }); | ||
401 | } | ||
402 | |||
318 | int main(int, char**) | 403 | int main(int, char**) |
319 | { | 404 | { |
320 | std::random_device randomEngine; | 405 | std::random_device randomEngine; |
@@ -371,8 +456,21 @@ int main(int, char**) | |||
371 | bool quit = false; | 456 | bool quit = false; |
372 | Input keystate; | 457 | Input keystate; |
373 | SDL_Event e; | 458 | SDL_Event e; |
459 | |||
460 | size_t dustDt = 30; | ||
461 | size_t dustAcc = 0; | ||
462 | |||
463 | size_t inputDt = 50; | ||
464 | size_t inputAcc = 0; | ||
465 | |||
466 | size_t lastTime = SDL_GetTicks(); | ||
467 | |||
374 | while (!quit) | 468 | while (!quit) |
375 | { | 469 | { |
470 | size_t currentTime = SDL_GetTicks(); | ||
471 | size_t frameTime = currentTime - lastTime; | ||
472 | lastTime = currentTime; | ||
473 | |||
376 | //bool input = false; | 474 | //bool input = false; |
377 | //int presses = 0; | 475 | //int presses = 0; |
378 | bool pressedSpace = false; | 476 | bool pressedSpace = false; |
@@ -396,10 +494,6 @@ int main(int, char**) | |||
396 | case SDLK_SPACE: | 494 | case SDLK_SPACE: |
397 | { | 495 | { |
398 | pressedSpace = true; | 496 | pressedSpace = true; |
399 | //input = true; | ||
400 | |||
401 | std::deque<std::tuple<int, int>> lamps; | ||
402 | lamps.emplace_back(player_x, player_y); | ||
403 | 497 | ||
404 | setIfValid(map, player_x , player_y , Tile::Lamp); | 498 | setIfValid(map, player_x , player_y , Tile::Lamp); |
405 | 499 | ||
@@ -414,56 +508,12 @@ int main(int, char**) | |||
414 | player_x + RADIUS, | 508 | player_x + RADIUS, |
415 | player_y + RADIUS); | 509 | player_y + RADIUS); |
416 | 510 | ||
417 | render(ren.get(), map, false); | 511 | //render(ren.get(), map, false); |
418 | SDL_Delay(30); | 512 | //SDL_Delay(30); |
419 | } | 513 | } |
420 | 514 | ||
421 | int lamped = 0; | 515 | map.dirtyLighting = true; |
422 | while (!lamps.empty()) | 516 | kickUpDust(map, player_x, player_y, 0); |
423 | { | ||
424 | lamped++; | ||
425 | |||
426 | int px, py; | ||
427 | std::tie(px, py) = lamps.front(); | ||
428 | lamps.pop_front(); | ||
429 | |||
430 | std::unique_ptr<fov_settings_type> dusty(new fov_settings_type); | ||
431 | fov_settings_set_opacity_test_function( | ||
432 | dusty.get(), | ||
433 | [] (void* map, int x, int y) { | ||
434 | return | ||
435 | x >= 0 && | ||
436 | x < VIEW_WIDTH && | ||
437 | y >= 0 && | ||
438 | y < VIEW_HEIGHT && | ||
439 | static_cast<Map*>(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall; | ||
440 | }); | ||
441 | |||
442 | fov_settings_set_apply_lighting_function( | ||
443 | dusty.get(), | ||
444 | [] (void* map, int x, int y, int, int, void* source) { | ||
445 | Map& m = *static_cast<Map*>(map); | ||
446 | auto& lamps = *static_cast<std::deque<std::pair<int, int>>*>(source); | ||
447 | |||
448 | if ((x >= 0) && (x < VIEW_WIDTH) && | ||
449 | (y >= 0) && (y < VIEW_HEIGHT)) | ||
450 | { | ||
451 | if (m.tiles[x+VIEW_WIDTH*y] == Tile::Floor) | ||
452 | { | ||
453 | m.tiles[x+VIEW_WIDTH*y] = Tile::Dust; | ||
454 | } else if (m.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | ||
455 | { | ||
456 | m.tiles[x+VIEW_WIDTH*y] = Tile::Dust; | ||
457 | lamps.emplace_back(x, y); | ||
458 | } | ||
459 | } | ||
460 | }); | ||
461 | |||
462 | fov_circle(dusty.get(), static_cast<void*>(&map), static_cast<void*>(&lamps), px, py, RADIUS+lamped*lamped); | ||
463 | |||
464 | render(ren.get(), map, false); | ||
465 | SDL_Delay(50); | ||
466 | } | ||
467 | 517 | ||
468 | break; | 518 | break; |
469 | } | 519 | } |
@@ -479,7 +529,10 @@ int main(int, char**) | |||
479 | 529 | ||
480 | bool input = keystate.left || keystate.right || keystate.up || keystate.down || pressedSpace; | 530 | bool input = keystate.left || keystate.right || keystate.up || keystate.down || pressedSpace; |
481 | 531 | ||
482 | if (input) | 532 | dustAcc += frameTime; |
533 | inputAcc += frameTime; | ||
534 | |||
535 | while (dustAcc >= dustDt) | ||
483 | { | 536 | { |
484 | for (int y = 0; y < VIEW_HEIGHT; y++) | 537 | for (int y = 0; y < VIEW_HEIGHT; y++) |
485 | { | 538 | { |
@@ -488,16 +541,27 @@ int main(int, char**) | |||
488 | if (map.tiles[x+y*VIEW_WIDTH] == Tile::Dust) | 541 | if (map.tiles[x+y*VIEW_WIDTH] == Tile::Dust) |
489 | { | 542 | { |
490 | map.tiles[x+y*VIEW_WIDTH] = Tile::Floor; | 543 | map.tiles[x+y*VIEW_WIDTH] = Tile::Floor; |
544 | map.dirtyLighting = true; | ||
491 | } | 545 | } |
492 | } | 546 | } |
493 | } | 547 | } |
548 | |||
549 | processKickup(map); | ||
550 | |||
551 | dustAcc -= dustDt; | ||
494 | } | 552 | } |
495 | 553 | ||
496 | processKeys(map, keystate); | 554 | while (inputAcc >= inputDt) |
497 | recalculateLighting(map, fov.get()); | 555 | { |
556 | processKeys(map, keystate); | ||
498 | 557 | ||
499 | if (input) | 558 | inputAcc -= inputDt; |
559 | } | ||
560 | |||
561 | if (map.dirtyLighting) | ||
500 | { | 562 | { |
563 | recalculateLighting(map, fov.get()); | ||
564 | |||
501 | for (int y = 0; y < VIEW_HEIGHT; y++) | 565 | for (int y = 0; y < VIEW_HEIGHT; y++) |
502 | { | 566 | { |
503 | for (int x = 0; x < VIEW_WIDTH; x++) | 567 | for (int x = 0; x < VIEW_WIDTH; x++) |
@@ -520,7 +584,7 @@ int main(int, char**) | |||
520 | } | 584 | } |
521 | 585 | ||
522 | render(ren.get(), map, true); | 586 | render(ren.get(), map, true); |
523 | SDL_Delay(50); | 587 | //SDL_Delay(50); |
524 | } | 588 | } |
525 | } catch (const sdl_error& ex) | 589 | } catch (const sdl_error& ex) |
526 | { | 590 | { |
diff --git a/src/untitled.txt b/src/untitled.txt deleted file mode 100644 index e69de29..0000000 --- a/src/untitled.txt +++ /dev/null | |||
diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..150a6a5 --- /dev/null +++ b/src/util.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #ifndef UTIL_H_E9110D4C | ||
2 | #define UTIL_H_E9110D4C | ||
3 | |||
4 | template <typename Container, typename Predicate> | ||
5 | void erase_if(Container& items, const Predicate& predicate) | ||
6 | { | ||
7 | for (auto it = std::begin(items); it != std::end(items);) | ||
8 | { | ||
9 | if (predicate(*it)) | ||
10 | { | ||
11 | it = items.erase(it); | ||
12 | } | ||
13 | else | ||
14 | { | ||
15 | ++it; | ||
16 | } | ||
17 | } | ||
18 | }; | ||
19 | |||
20 | #endif /* end of include guard: UTIL_H_E9110D4C */ | ||