diff options
Diffstat (limited to 'src/game.cpp')
-rw-r--r-- | src/game.cpp | 195 |
1 files changed, 105 insertions, 90 deletions
diff --git a/src/game.cpp b/src/game.cpp index 088ab4d..9d557e3 100644 --- a/src/game.cpp +++ b/src/game.cpp | |||
@@ -20,7 +20,7 @@ Game::Game(std::mt19937& rng, Muxer& muxer, Renderer& renderer) : | |||
20 | { | 20 | { |
21 | for (int x = -1; x <= 1; x++) | 21 | for (int x = -1; x <= 1; x++) |
22 | { | 22 | { |
23 | map.at(x,y).tile = Tile::Floor; | 23 | map.tile(x,y) = Tile::Floor; |
24 | } | 24 | } |
25 | } | 25 | } |
26 | 26 | ||
@@ -35,12 +35,12 @@ Game::Game(std::mt19937& rng, Muxer& muxer, Renderer& renderer) : | |||
35 | 35 | ||
36 | inline bool isTileSetOrNotLit(const Map& map, int x, int y) | 36 | inline bool isTileSetOrNotLit(const Map& map, int x, int y) |
37 | { | 37 | { |
38 | return (map.inBounds(x, y) && (map.at(x,y).tile == Tile::Wall || !map.at(x,y).lit)); | 38 | return (map.inBounds(x, y) && (map.tile(x,y) == Tile::Wall || !map.at(x,y).lit)); |
39 | } | 39 | } |
40 | 40 | ||
41 | inline bool isTileSet(const Map& map, int x, int y, Tile val = Tile::Wall) | 41 | inline bool isTileSet(const Map& map, int x, int y, Tile val = Tile::Wall) |
42 | { | 42 | { |
43 | return (map.inBounds(x, y) && map.at(x,y).tile == val); | 43 | return (map.inBounds(x, y) && map.tile(x,y) == val); |
44 | } | 44 | } |
45 | 45 | ||
46 | inline void incrementIfSet(const Game& game, int& count, int x, int y, Tile val = Tile::Wall) | 46 | inline void incrementIfSet(const Game& game, int& count, int x, int y, Tile val = Tile::Wall) |
@@ -55,6 +55,56 @@ inline int getZoomLevel(const Game& game) { | |||
55 | return game.curZoom - INIT_ZOOM; | 55 | return game.curZoom - INIT_ZOOM; |
56 | } | 56 | } |
57 | 57 | ||
58 | inline void tickIndividual(Game& game, std::vector<Tile>& mapDoubleBuffer, int x, int y, bool onlyDark) { | ||
59 | if (onlyDark && game.map.at(x,y).lit) | ||
60 | { | ||
61 | return; | ||
62 | } | ||
63 | |||
64 | if (game.map.tile(x,y) == Tile::Lamp) | ||
65 | { | ||
66 | return; | ||
67 | } | ||
68 | |||
69 | int count = 0; | ||
70 | |||
71 | incrementIfSet(game, count, x-1, y-1); | ||
72 | incrementIfSet(game, count, x-1, y ); | ||
73 | incrementIfSet(game, count, x-1, y+1); | ||
74 | incrementIfSet(game, count, x , y-1); | ||
75 | incrementIfSet(game, count, x , y ); | ||
76 | incrementIfSet(game, count, x , y+1); | ||
77 | incrementIfSet(game, count, x+1, y-1); | ||
78 | incrementIfSet(game, count, x+1, y ); | ||
79 | incrementIfSet(game, count, x+1, y+1); | ||
80 | |||
81 | int tempIndex = game.map.getTrueX(x) + game.map.getTrueY(y) * game.map.getWidth(); | ||
82 | if (count >= 5) | ||
83 | { | ||
84 | mapDoubleBuffer[tempIndex] = Tile::Wall; | ||
85 | } else { | ||
86 | mapDoubleBuffer[tempIndex] = Tile::Floor; | ||
87 | } | ||
88 | |||
89 | if (mapDoubleBuffer[tempIndex] != game.map.tile(x,y)) { | ||
90 | game.map.at(x,y).dirtyRender = true; | ||
91 | game.dirtyRender = true; | ||
92 | game.map.markDirtyAround(x,y); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | void Game::tickDirty(bool onlyDark) { | ||
97 | mapDoubleBuffer = map.tiles(); | ||
98 | std::vector<coord> dirty = map.getDirty(); | ||
99 | map.resetDirty(); | ||
100 | |||
101 | for (auto [x,y] : dirty) { | ||
102 | tickIndividual(*this, mapDoubleBuffer, x, y, onlyDark); | ||
103 | } | ||
104 | |||
105 | std::swap(map.tiles(), mapDoubleBuffer); | ||
106 | } | ||
107 | |||
58 | void Game::tick( | 108 | void Game::tick( |
59 | int x1, | 109 | int x1, |
60 | int y1, | 110 | int y1, |
@@ -63,7 +113,8 @@ void Game::tick( | |||
63 | bool invert, | 113 | bool invert, |
64 | bool onlyDark) | 114 | bool onlyDark) |
65 | { | 115 | { |
66 | mapDoubleBuffer = map.data(); | 116 | mapDoubleBuffer = map.tiles(); |
117 | map.resetDirty(); | ||
67 | 118 | ||
68 | for (int y = map.getTop(); y < map.getBottom(); y++) | 119 | for (int y = map.getTop(); y < map.getBottom(); y++) |
69 | { | 120 | { |
@@ -74,44 +125,11 @@ void Game::tick( | |||
74 | continue; | 125 | continue; |
75 | } | 126 | } |
76 | 127 | ||
77 | if (onlyDark && map.at(x,y).lit) | 128 | tickIndividual(*this, mapDoubleBuffer, x, y, onlyDark); |
78 | { | ||
79 | continue; | ||
80 | } | ||
81 | |||
82 | if (map.at(x,y).tile == Tile::Lamp) | ||
83 | { | ||
84 | continue; | ||
85 | } | ||
86 | |||
87 | int count = 0; | ||
88 | |||
89 | incrementIfSet(*this, count, x-1, y-1); | ||
90 | incrementIfSet(*this, count, x-1, y ); | ||
91 | incrementIfSet(*this, count, x-1, y+1); | ||
92 | incrementIfSet(*this, count, x , y-1); | ||
93 | incrementIfSet(*this, count, x , y ); | ||
94 | incrementIfSet(*this, count, x , y+1); | ||
95 | incrementIfSet(*this, count, x+1, y-1); | ||
96 | incrementIfSet(*this, count, x+1, y ); | ||
97 | incrementIfSet(*this, count, x+1, y+1); | ||
98 | |||
99 | int tempIndex = map.getTrueX(x) + map.getTrueY(y) * map.getWidth(); | ||
100 | if (count >= 5) | ||
101 | { | ||
102 | mapDoubleBuffer[tempIndex].tile = Tile::Wall; | ||
103 | } else { | ||
104 | mapDoubleBuffer[tempIndex].tile = Tile::Floor; | ||
105 | } | ||
106 | |||
107 | if (mapDoubleBuffer[tempIndex].tile != map.at(x,y).tile) { | ||
108 | mapDoubleBuffer[tempIndex].dirtyRender = true; | ||
109 | dirtyRender = true; | ||
110 | } | ||
111 | } | 129 | } |
112 | } | 130 | } |
113 | 131 | ||
114 | std::swap(map.data(), mapDoubleBuffer); | 132 | std::swap(map.tiles(), mapDoubleBuffer); |
115 | } | 133 | } |
116 | 134 | ||
117 | void Game::tick(bool onlyDark) | 135 | void Game::tick(bool onlyDark) |
@@ -127,11 +145,11 @@ void Game::tick(bool onlyDark) | |||
127 | 145 | ||
128 | bool Game::movePlayer(int x, int y) | 146 | bool Game::movePlayer(int x, int y) |
129 | { | 147 | { |
130 | if (map.at(x,y).tile == Tile::Floor && !map.at(x,y).sign) | 148 | if (map.tile(x,y) == Tile::Floor && !map.at(x,y).sign) |
131 | { | 149 | { |
132 | if (map.at(player_x, player_y).tile == Tile::Floor) | 150 | if (map.tile(player_x, player_y) == Tile::Floor) |
133 | { | 151 | { |
134 | map.at(player_x, player_y).tile = Tile::Dust; | 152 | map.tile(player_x, player_y) = Tile::Dust; |
135 | map.at(player_x, player_y).dustLife = 1; | 153 | map.at(player_x, player_y).dustLife = 1; |
136 | numDust++; | 154 | numDust++; |
137 | } | 155 | } |
@@ -169,14 +187,15 @@ void Game::recalculateLighting() | |||
169 | litSpots = 0; | 187 | litSpots = 0; |
170 | dirtyRender = true; | 188 | dirtyRender = true; |
171 | 189 | ||
172 | for (MapData& md : map.data()) | 190 | for (int y=map.getTop(); y<map.getBottom(); y++) { |
173 | { | 191 | for (int x=map.getLeft(); x<map.getRight(); x++) { |
174 | md.wasLit = md.lit; | 192 | map.at(x,y).wasLit = map.at(x,y).lit; |
175 | md.lit = false; | 193 | map.at(x,y).lit = false; |
176 | md.litTiles.clear(); | 194 | map.at(x,y).litTiles.clear(); |
177 | 195 | ||
178 | if (md.tile == Tile::Wall) { | 196 | if (map.tile(x,y) == Tile::Wall) { |
179 | md.dirtyRender = true; | 197 | map.at(x,y).dirtyRender = true; |
198 | } | ||
180 | } | 199 | } |
181 | } | 200 | } |
182 | 201 | ||
@@ -188,7 +207,7 @@ void Game::recalculateLighting() | |||
188 | [] (void* data, int x, int y) { | 207 | [] (void* data, int x, int y) { |
189 | Game& game = *static_cast<Game*>(data); | 208 | Game& game = *static_cast<Game*>(data); |
190 | 209 | ||
191 | return game.map.inBounds(x,y) && game.map.at(x,y).tile == Tile::Wall; | 210 | return game.map.inBounds(x,y) && game.map.tile(x,y) == Tile::Wall; |
192 | }); | 211 | }); |
193 | 212 | ||
194 | fov_settings_set_apply_lighting_function( | 213 | fov_settings_set_apply_lighting_function( |
@@ -223,11 +242,11 @@ void Game::recalculateLighting() | |||
223 | { | 242 | { |
224 | ls = Source::Player; | 243 | ls = Source::Player; |
225 | lightRadius = RADIUS; | 244 | lightRadius = RADIUS; |
226 | } else if (map.at(x,y).tile == Tile::Dust) | 245 | } else if (map.tile(x,y) == Tile::Dust) |
227 | { | 246 | { |
228 | ls = Source::Dust; | 247 | ls = Source::Dust; |
229 | lightRadius = 2; | 248 | lightRadius = 2; |
230 | } else if (map.at(x,y).tile == Tile::Lamp) | 249 | } else if (map.tile(x,y) == Tile::Lamp) |
231 | { | 250 | { |
232 | ls = Source::Lamp; | 251 | ls = Source::Lamp; |
233 | lightRadius = RADIUS; | 252 | lightRadius = RADIUS; |
@@ -265,7 +284,7 @@ void Game::recalculateRender() { | |||
265 | if (map.at(x,y).dirtyRender) { | 284 | if (map.at(x,y).dirtyRender) { |
266 | map.at(x,y).dirtyRender = false; | 285 | map.at(x,y).dirtyRender = false; |
267 | 286 | ||
268 | if (map.at(x,y).tile == Tile::Floor) { | 287 | if (map.tile(x,y) == Tile::Floor) { |
269 | int renderDesc = 0; | 288 | int renderDesc = 0; |
270 | if (isTileSetOrNotLit(map, x-1, y-1)) renderDesc |= (1 << 7); | 289 | if (isTileSetOrNotLit(map, x-1, y-1)) renderDesc |= (1 << 7); |
271 | if (isTileSetOrNotLit(map, x , y-1)) renderDesc |= (1 << 6); | 290 | if (isTileSetOrNotLit(map, x , y-1)) renderDesc |= (1 << 6); |
@@ -297,7 +316,7 @@ void Game::recalculateRender() { | |||
297 | map.at(x,y).renderId = -1; | 316 | map.at(x,y).renderId = -1; |
298 | map.at(x,y).sign = false; | 317 | map.at(x,y).sign = false; |
299 | } | 318 | } |
300 | } else if (map.at(x,y).tile == Tile::Wall) { | 319 | } else if (map.tile(x,y) == Tile::Wall) { |
301 | static bool initWalls = false; | 320 | static bool initWalls = false; |
302 | static std::vector<int> wallRenders(256, TilesetIndex(0, 0)); | 321 | static std::vector<int> wallRenders(256, TilesetIndex(0, 0)); |
303 | if (!initWalls) { | 322 | if (!initWalls) { |
@@ -439,12 +458,12 @@ void Game::popLamp(int x, int y, size_t chain) | |||
439 | { | 458 | { |
440 | muxer.playSoundAtPosition("pop", x, y); | 459 | muxer.playSoundAtPosition("pop", x, y); |
441 | 460 | ||
442 | if (map.at(x,y).tile == Tile::Lamp) | 461 | if (map.tile(x,y) == Tile::Lamp) |
443 | { | 462 | { |
444 | numLamps--; | 463 | numLamps--; |
445 | } | 464 | } |
446 | 465 | ||
447 | map.at(x,y).tile = Tile::Dust; | 466 | map.tile(x,y) = Tile::Dust; |
448 | map.at(x,y).dustLife = 2; | 467 | map.at(x,y).dustLife = 2; |
449 | numDust++; | 468 | numDust++; |
450 | dirtyLighting = true; | 469 | dirtyLighting = true; |
@@ -465,19 +484,19 @@ void Game::processKickup() | |||
465 | coord c {x,y}; | 484 | coord c {x,y}; |
466 | 485 | ||
467 | if (map.inBounds(x,y) && | 486 | if (map.inBounds(x,y) && |
468 | (map.at(x,y).tile == Tile::Floor || map.at(x,y).tile == Tile::Lamp) && | 487 | (map.tile(x,y) == Tile::Floor || map.tile(x,y) == Tile::Lamp) && |
469 | !kickup.done.count(c)) | 488 | !kickup.done.count(c)) |
470 | { | 489 | { |
471 | newFront.insert(c); | 490 | newFront.insert(c); |
472 | kickup.done.insert(c); | 491 | kickup.done.insert(c); |
473 | 492 | ||
474 | if (map.at(x,y).tile == Tile::Floor) | 493 | if (map.tile(x,y) == Tile::Floor) |
475 | { | 494 | { |
476 | map.at(x,y).tile = Tile::Dust; | 495 | map.tile(x,y) = Tile::Dust; |
477 | map.at(x,y).dustLife = 2; | 496 | map.at(x,y).dustLife = 2; |
478 | numDust++; | 497 | numDust++; |
479 | dirtyLighting = true; | 498 | dirtyLighting = true; |
480 | } else if (map.at(x,y).tile == Tile::Lamp) | 499 | } else if (map.tile(x,y) == Tile::Lamp) |
481 | { | 500 | { |
482 | popLamp(x, y, kickup.chain + 1); | 501 | popLamp(x, y, kickup.chain + 1); |
483 | } | 502 | } |
@@ -571,11 +590,11 @@ void Game::setZoom(size_t zoom) | |||
571 | } | 590 | } |
572 | 591 | ||
573 | void Game::performDash() { | 592 | void Game::performDash() { |
574 | if (map.at(player_x, player_y).tile == Tile::Floor) { | 593 | if (map.tile(player_x, player_y) == Tile::Floor) { |
575 | std::vector<coord> freeSpaces; | 594 | std::vector<coord> freeSpaces; |
576 | 595 | ||
577 | auto addIfFree = [&] (int x, int y) { | 596 | auto addIfFree = [&] (int x, int y) { |
578 | if (map.inBounds(x,y) && map.at(x,y).tile == Tile::Floor) | 597 | if (map.inBounds(x,y) && map.tile(x,y) == Tile::Floor) |
579 | { | 598 | { |
580 | freeSpaces.emplace_back(x, y); | 599 | freeSpaces.emplace_back(x, y); |
581 | } | 600 | } |
@@ -592,7 +611,7 @@ void Game::performDash() { | |||
592 | 611 | ||
593 | if (!freeSpaces.empty()) | 612 | if (!freeSpaces.empty()) |
594 | { | 613 | { |
595 | map.at(player_x, player_y).tile = Tile::Lamp; | 614 | map.tile(player_x, player_y) = Tile::Lamp; |
596 | numLamps++; | 615 | numLamps++; |
597 | dirtyLighting = true; | 616 | dirtyLighting = true; |
598 | kickUpDust(player_x, player_y, 0); | 617 | kickUpDust(player_x, player_y, 0); |
@@ -725,18 +744,19 @@ void Game::updatePlaying(size_t frameTime) { | |||
725 | { | 744 | { |
726 | numDust = 0; | 745 | numDust = 0; |
727 | 746 | ||
728 | for (MapData& md : map.data()) | 747 | for (int y=map.getTop(); y<map.getBottom(); y++) { |
729 | { | 748 | for (int x=map.getLeft(); x<map.getRight(); x++) { |
730 | if (md.tile == Tile::Dust) | 749 | if (map.tile(x,y) == Tile::Dust) |
731 | { | ||
732 | md.dustLife--; | ||
733 | |||
734 | if (md.dustLife <= 0) | ||
735 | { | 750 | { |
736 | md.tile = Tile::Floor; | 751 | map.at(x,y).dustLife--; |
737 | dirtyLighting = true; | 752 | |
738 | } else { | 753 | if (map.at(x,y).dustLife <= 0) |
739 | numDust++; | 754 | { |
755 | map.tile(x,y) = Tile::Floor; | ||
756 | dirtyLighting = true; | ||
757 | } else { | ||
758 | numDust++; | ||
759 | } | ||
740 | } | 760 | } |
741 | } | 761 | } |
742 | } | 762 | } |
@@ -784,7 +804,7 @@ void Game::updatePlaying(size_t frameTime) { | |||
784 | { | 804 | { |
785 | for (int x = map.getLeft(); x < map.getRight(); x++) | 805 | for (int x = map.getLeft(); x < map.getRight(); x++) |
786 | { | 806 | { |
787 | if (map.at(x,y).tile == Tile::Lamp) | 807 | if (map.tile(x,y) == Tile::Lamp) |
788 | { | 808 | { |
789 | lamps.emplace_back(x, y); | 809 | lamps.emplace_back(x, y); |
790 | } | 810 | } |
@@ -874,29 +894,24 @@ void Game::updatePlaying(size_t frameTime) { | |||
874 | { | 894 | { |
875 | if (!map.at(x,y).lit && map.at(x,y).wasLit) | 895 | if (!map.at(x,y).lit && map.at(x,y).wasLit) |
876 | { | 896 | { |
897 | Tile oldTile = map.tile(x,y); | ||
877 | if (std::bernoulli_distribution(0.5)(rng)) | 898 | if (std::bernoulli_distribution(0.5)(rng)) |
878 | { | 899 | { |
879 | map.at(x,y).tile = Tile::Wall; | 900 | map.tile(x,y) = Tile::Wall; |
880 | } else { | 901 | } else { |
881 | map.at(x,y).tile = Tile::Floor; | 902 | map.tile(x,y) = Tile::Floor; |
903 | } | ||
904 | if (map.tile(x,y) != oldTile) { | ||
905 | map.at(x,y).dirtyRender = true; | ||
906 | map.markDirtyAround(x,y); | ||
882 | } | 907 | } |
883 | map.at(x,y).dirtyRender = true; | ||
884 | } | 908 | } |
885 | } | 909 | } |
886 | } | 910 | } |
887 | 911 | ||
888 | /*int x1 = player_x - curZoom * ZOOM_X_FACTOR / 2 - 1; | 912 | tickDirty(true); |
889 | int y1 = player_y - curZoom * ZOOM_Y_FACTOR / 2 - 1; | 913 | tickDirty(true); |
890 | int x2 = player_x + curZoom * ZOOM_X_FACTOR / 2 + 2; | 914 | tickDirty(true); |
891 | int y2 = player_y + curZoom * ZOOM_Y_FACTOR / 2 + 2;*/ | ||
892 | int x1 = player_x - CHUNK_WIDTH / 2 - 1; | ||
893 | int y1 = player_y - CHUNK_HEIGHT / 2 - 1; | ||
894 | int x2 = player_x + CHUNK_WIDTH / 2 + 2; | ||
895 | int y2 = player_y + CHUNK_HEIGHT / 2 + 2; | ||
896 | |||
897 | tick(x1, y1, x2, y2, false, true); | ||
898 | tick(x1, y1, x2, y2, false, true); | ||
899 | tick(x1, y1, x2, y2, false, true); | ||
900 | 915 | ||
901 | // TODO: better zoom algorithm | 916 | // TODO: better zoom algorithm |
902 | setZoom(litSpots / 1500 + INIT_ZOOM); | 917 | setZoom(litSpots / 1500 + INIT_ZOOM); |