diff options
author | Star Rauchenberger <fefferburbia@gmail.com> | 2022-03-14 14:11:05 -0400 |
---|---|---|
committer | Star Rauchenberger <fefferburbia@gmail.com> | 2022-03-14 14:11:05 -0400 |
commit | 7cd515fcfa1a5aac5605fcc63381033563fbf5d7 (patch) | |
tree | 2a375db2fe6c1476a111c1f3e83e50fd2b68124e | |
parent | 042da1570181dc80ee76860582f6a3c97641c14a (diff) | |
download | ether-7cd515fcfa1a5aac5605fcc63381033563fbf5d7.tar.gz ether-7cd515fcfa1a5aac5605fcc63381033563fbf5d7.tar.bz2 ether-7cd515fcfa1a5aac5605fcc63381033563fbf5d7.zip |
map is now "infinite" using chunks that dynamically load like in diamond&pearl
game is also slow as shit now
-rw-r--r-- | src/consts.h | 4 | ||||
-rw-r--r-- | src/game.cpp | 123 | ||||
-rw-r--r-- | src/game.h | 40 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/map.h | 184 | ||||
-rw-r--r-- | src/renderer.cpp | 83 |
6 files changed, 256 insertions, 180 deletions
diff --git a/src/consts.h b/src/consts.h index 141838b..78312c0 100644 --- a/src/consts.h +++ b/src/consts.h | |||
@@ -5,9 +5,11 @@ constexpr int GAME_WIDTH = 1280;//640*2; | |||
5 | constexpr int GAME_HEIGHT = 720;//480*2; | 5 | constexpr int GAME_HEIGHT = 720;//480*2; |
6 | constexpr int TILE_WIDTH = 8*2; | 6 | constexpr int TILE_WIDTH = 8*2; |
7 | constexpr int TILE_HEIGHT = TILE_WIDTH; | 7 | constexpr int TILE_HEIGHT = TILE_WIDTH; |
8 | constexpr int INIT_ZOOM = 5; | 8 | constexpr int INIT_ZOOM = 2; |
9 | constexpr int ZOOM_X_FACTOR = 16; | 9 | constexpr int ZOOM_X_FACTOR = 16; |
10 | constexpr int ZOOM_Y_FACTOR = 9; | 10 | constexpr int ZOOM_Y_FACTOR = 9; |
11 | constexpr int CHUNK_WIDTH = 80; | ||
12 | constexpr int CHUNK_HEIGHT = 80; | ||
11 | constexpr int RADIUS = 8; | 13 | constexpr int RADIUS = 8; |
12 | constexpr int NUM_TITLES = 1; | 14 | constexpr int NUM_TITLES = 1; |
13 | 15 | ||
diff --git a/src/game.cpp b/src/game.cpp index a7c94db..62e755b 100644 --- a/src/game.cpp +++ b/src/game.cpp | |||
@@ -8,25 +8,11 @@ | |||
8 | 8 | ||
9 | Game::Game(std::mt19937& rng, Muxer& muxer) : | 9 | Game::Game(std::mt19937& rng, Muxer& muxer) : |
10 | rng(rng), | 10 | rng(rng), |
11 | muxer(muxer), | 11 | muxer(muxer) |
12 | map( | ||
13 | -INIT_ZOOM * ZOOM_X_FACTOR / 2, | ||
14 | -INIT_ZOOM * ZOOM_Y_FACTOR / 2, | ||
15 | INIT_ZOOM * ZOOM_X_FACTOR, | ||
16 | INIT_ZOOM * ZOOM_Y_FACTOR) | ||
17 | { | 12 | { |
18 | losePopLampTimer.accumulate(losePopLampTimer.getDt()); | 13 | losePopLampTimer.accumulate(losePopLampTimer.getDt()); |
19 | 14 | ||
20 | for (MapData& md : map.data()) | 15 | loadMap(); |
21 | { | ||
22 | if (std::bernoulli_distribution(0.5)(rng)) | ||
23 | { | ||
24 | md.tile = Tile::Wall; | ||
25 | } | ||
26 | } | ||
27 | |||
28 | tick(); | ||
29 | tick(); | ||
30 | 16 | ||
31 | for (int y = -1; y <= 1; y++) | 17 | for (int y = -1; y <= 1; y++) |
32 | { | 18 | { |
@@ -39,12 +25,12 @@ Game::Game(std::mt19937& rng, Muxer& muxer) : | |||
39 | tick(); | 25 | tick(); |
40 | } | 26 | } |
41 | 27 | ||
42 | inline bool isTileSetOrNotLit(const Map<MapData>& map, int x, int y) | 28 | inline bool isTileSetOrNotLit(const Map& map, int x, int y) |
43 | { | 29 | { |
44 | return (map.inBounds(x, y) && (map.at(x,y).tile == Tile::Wall || !map.at(x,y).lit)); | 30 | return (map.inBounds(x, y) && (map.at(x,y).tile == Tile::Wall || !map.at(x,y).lit)); |
45 | } | 31 | } |
46 | 32 | ||
47 | inline bool isTileSet(const Map<MapData>& map, int x, int y, Tile val = Tile::Wall) | 33 | inline bool isTileSet(const Map& map, int x, int y, Tile val = Tile::Wall) |
48 | { | 34 | { |
49 | return (map.inBounds(x, y) && map.at(x,y).tile == val); | 35 | return (map.inBounds(x, y) && map.at(x,y).tile == val); |
50 | } | 36 | } |
@@ -69,7 +55,7 @@ void Game::tick( | |||
69 | bool invert, | 55 | bool invert, |
70 | bool onlyDark) | 56 | bool onlyDark) |
71 | { | 57 | { |
72 | Map<MapData> temp(map); | 58 | std::vector<MapData> temp(map.data()); |
73 | 59 | ||
74 | for (int y = map.getTop(); y < map.getBottom(); y++) | 60 | for (int y = map.getTop(); y < map.getBottom(); y++) |
75 | { | 61 | { |
@@ -102,21 +88,22 @@ void Game::tick( | |||
102 | incrementIfSet(*this, count, x+1, y ); | 88 | incrementIfSet(*this, count, x+1, y ); |
103 | incrementIfSet(*this, count, x+1, y+1); | 89 | incrementIfSet(*this, count, x+1, y+1); |
104 | 90 | ||
91 | int tempIndex = map.getTrueX(x) + map.getTrueY(y) * map.getWidth(); | ||
105 | if (count >= 5) | 92 | if (count >= 5) |
106 | { | 93 | { |
107 | temp.at(x,y).tile = Tile::Wall; | 94 | temp[tempIndex].tile = Tile::Wall; |
108 | } else { | 95 | } else { |
109 | temp.at(x,y).tile = Tile::Floor; | 96 | temp[tempIndex].tile = Tile::Floor; |
110 | } | 97 | } |
111 | 98 | ||
112 | if (temp.at(x,y).tile != map.at(x,y).tile) { | 99 | if (temp[tempIndex].tile != map.at(x,y).tile) { |
113 | temp.at(x,y).dirtyRender = true; | 100 | temp[tempIndex].dirtyRender = true; |
114 | dirtyRender = true; | 101 | dirtyRender = true; |
115 | } | 102 | } |
116 | } | 103 | } |
117 | } | 104 | } |
118 | 105 | ||
119 | map = std::move(temp); | 106 | map.data() = std::move(temp); |
120 | } | 107 | } |
121 | 108 | ||
122 | void Game::tick(bool onlyDark) | 109 | void Game::tick(bool onlyDark) |
@@ -132,10 +119,10 @@ void Game::tick(bool onlyDark) | |||
132 | 119 | ||
133 | bool Game::movePlayer(int x, int y) | 120 | bool Game::movePlayer(int x, int y) |
134 | { | 121 | { |
135 | if (x >= curBoundX && | 122 | if (/*x >= curBoundX && |
136 | y >= curBoundY && | 123 | y >= curBoundY && |
137 | x < curBoundX + curZoom * ZOOM_X_FACTOR && | 124 | x < curBoundX + curZoom * ZOOM_X_FACTOR && |
138 | y < curBoundY + curZoom * ZOOM_Y_FACTOR && | 125 | y < curBoundY + curZoom * ZOOM_Y_FACTOR &&*/ |
139 | map.at(x,y).tile == Tile::Floor) | 126 | map.at(x,y).tile == Tile::Floor) |
140 | { | 127 | { |
141 | if (map.at(player_x, player_y).tile == Tile::Floor) | 128 | if (map.at(player_x, player_y).tile == Tile::Floor) |
@@ -154,6 +141,13 @@ bool Game::movePlayer(int x, int y) | |||
154 | moveProgress.start(66); | 141 | moveProgress.start(66); |
155 | dirtyLighting = true; | 142 | dirtyLighting = true; |
156 | 143 | ||
144 | int chunkX, chunkY, old_chunkX, old_chunkY; | ||
145 | toChunkPos(player_x, player_y, chunkX, chunkY); | ||
146 | toChunkPos(player_oldx, player_oldy, old_chunkX, old_chunkY); | ||
147 | if ((chunkX != old_chunkX) || (chunkY != old_chunkY)) { | ||
148 | loadMap(); | ||
149 | } | ||
150 | |||
157 | return true; | 151 | return true; |
158 | } else { | 152 | } else { |
159 | if (!alreadyBumped) { | 153 | if (!alreadyBumped) { |
@@ -501,39 +495,25 @@ void Game::processKickup() | |||
501 | }); | 495 | }); |
502 | } | 496 | } |
503 | 497 | ||
504 | void Game::growMap(size_t zoom) | 498 | void Game::loadMap() { |
505 | { | 499 | int newChunksHoriz = std::ceil(static_cast<double>(curZoom) * ZOOM_X_FACTOR / CHUNK_WIDTH) + 4; |
506 | int ol = map.getLeft(); | 500 | int newChunksVert = std::ceil(static_cast<double>(curZoom) * ZOOM_Y_FACTOR / CHUNK_HEIGHT) + 4; |
507 | int ot = map.getTop(); | 501 | int curPlayerChunkX, curPlayerChunkY; |
508 | int ow = map.getWidth(); | 502 | toChunkPos(player_x, player_y, curPlayerChunkX, curPlayerChunkY); |
509 | int oh = map.getHeight(); | ||
510 | 503 | ||
511 | map.resize( | 504 | map.load( |
512 | -zoom * ZOOM_X_FACTOR / 2, | 505 | curPlayerChunkX - newChunksHoriz / 2, |
513 | -zoom * ZOOM_Y_FACTOR / 2, | 506 | curPlayerChunkY - newChunksVert / 2, |
514 | zoom * ZOOM_X_FACTOR, | 507 | newChunksHoriz, |
515 | zoom * ZOOM_Y_FACTOR); | 508 | newChunksVert, |
509 | rng); | ||
516 | 510 | ||
517 | maxZoom = zoom; | 511 | tick(); |
518 | 512 | tick(); | |
519 | for (int y = map.getTop(); y < map.getBottom(); y++) | 513 | tick(); |
520 | { | ||
521 | for (int x = map.getLeft(); x < map.getRight(); x++) | ||
522 | { | ||
523 | if (!(x >= ol && x < (ol + ow) && y >= ot && y < (ot + oh))) | ||
524 | { | ||
525 | if (std::bernoulli_distribution(0.5)(rng)) | ||
526 | { | ||
527 | map.at(x,y).tile = Tile::Wall; | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | } | ||
532 | 514 | ||
533 | for (int i = 0; i < 3; i++) | 515 | dirtyLighting = true; |
534 | { | 516 | dirtyRender = true; |
535 | tick(ol, ot, ol + ow, ot + oh, true); | ||
536 | } | ||
537 | } | 517 | } |
538 | 518 | ||
539 | void Game::setZoom(size_t zoom) | 519 | void Game::setZoom(size_t zoom) |
@@ -543,40 +523,11 @@ void Game::setZoom(size_t zoom) | |||
543 | return; | 523 | return; |
544 | } | 524 | } |
545 | 525 | ||
546 | if (zoom > maxZoom) | ||
547 | { | ||
548 | growMap(zoom); | ||
549 | } | ||
550 | |||
551 | std::tie( | ||
552 | lastZoomLeft, | ||
553 | lastZoomTop, | ||
554 | lastZoomWidth, | ||
555 | lastZoomHeight) = | ||
556 | Renderer::calculateZoomRect(*this); | ||
557 | |||
558 | zoomProgress = 0; | 526 | zoomProgress = 0; |
559 | zoomLength = std::abs(static_cast<long>(zoom - curZoom)) * TILE_WIDTH; | 527 | zoomLength = std::abs(static_cast<long>(zoom - curZoom)) * TILE_WIDTH; |
560 | curZoom = zoom; | 528 | curZoom = zoom; |
561 | zooming = true; | 529 | zooming = true; |
562 | 530 | loadMap(); | |
563 | curBoundX = player_x - zoom * ZOOM_X_FACTOR / 2; | ||
564 | if (curBoundX < map.getLeft()) | ||
565 | { | ||
566 | curBoundX = map.getLeft(); | ||
567 | } else if (curBoundX + zoom * ZOOM_X_FACTOR >= map.getRight()) | ||
568 | { | ||
569 | curBoundX = map.getRight() - zoom * ZOOM_X_FACTOR; | ||
570 | } | ||
571 | |||
572 | curBoundY = player_y - zoom * ZOOM_Y_FACTOR / 2; | ||
573 | if (curBoundY < map.getTop()) | ||
574 | { | ||
575 | curBoundY = map.getTop(); | ||
576 | } else if (curBoundY + zoom * ZOOM_Y_FACTOR >= map.getBottom()) | ||
577 | { | ||
578 | curBoundY = map.getBottom() - zoom * ZOOM_Y_FACTOR; | ||
579 | } | ||
580 | 531 | ||
581 | int zoomLevel = getZoomLevel(*this); | 532 | int zoomLevel = getZoomLevel(*this); |
582 | if (zoomLevel == 0) { | 533 | if (zoomLevel == 0) { |
diff --git a/src/game.h b/src/game.h index 446680a..40ace3d 100644 --- a/src/game.h +++ b/src/game.h | |||
@@ -16,20 +16,6 @@ constexpr int TilesetIndex(int x, int y) { | |||
16 | return x + y * 24; | 16 | return x + y * 24; |
17 | } | 17 | } |
18 | 18 | ||
19 | enum class Tile { | ||
20 | Floor, | ||
21 | Wall, | ||
22 | Dust, | ||
23 | Lamp | ||
24 | }; | ||
25 | |||
26 | enum class Source { | ||
27 | None, | ||
28 | Dust, | ||
29 | Lamp, | ||
30 | Player | ||
31 | }; | ||
32 | |||
33 | enum class LoseState { | 19 | enum class LoseState { |
34 | None, | 20 | None, |
35 | PoppingLamps, | 21 | PoppingLamps, |
@@ -52,8 +38,6 @@ struct Input { | |||
52 | } | 38 | } |
53 | }; | 39 | }; |
54 | 40 | ||
55 | using coord = std::tuple<int, int>; | ||
56 | |||
57 | struct Kickup { | 41 | struct Kickup { |
58 | int x; | 42 | int x; |
59 | int y; | 43 | int y; |
@@ -64,18 +48,6 @@ struct Kickup { | |||
64 | std::set<coord> front; | 48 | std::set<coord> front; |
65 | }; | 49 | }; |
66 | 50 | ||
67 | struct MapData { | ||
68 | Tile tile = Tile::Floor; | ||
69 | bool lit = false; | ||
70 | bool wasLit = false; | ||
71 | size_t dustLife = 0; | ||
72 | Source lightType = Source::None; | ||
73 | int lightRadius = 0; | ||
74 | std::set<coord> litTiles; | ||
75 | int renderId = -1; | ||
76 | bool dirtyRender = true; | ||
77 | }; | ||
78 | |||
79 | class Game { | 51 | class Game { |
80 | public: | 52 | public: |
81 | 53 | ||
@@ -89,7 +61,7 @@ public: | |||
89 | bool quit = false; | 61 | bool quit = false; |
90 | LoseState losing = LoseState::None; | 62 | LoseState losing = LoseState::None; |
91 | 63 | ||
92 | Map<MapData> map; | 64 | Map map; |
93 | std::list<Kickup> kickups; | 65 | std::list<Kickup> kickups; |
94 | int litSpots = 0; | 66 | int litSpots = 0; |
95 | bool dirtyLighting = true; | 67 | bool dirtyLighting = true; |
@@ -105,18 +77,10 @@ public: | |||
105 | Animation playerAnim {"../res/player_anim.txt"}; | 77 | Animation playerAnim {"../res/player_anim.txt"}; |
106 | 78 | ||
107 | int maxZoom = INIT_ZOOM; | 79 | int maxZoom = INIT_ZOOM; |
108 | |||
109 | int curZoom = INIT_ZOOM; | 80 | int curZoom = INIT_ZOOM; |
110 | int curBoundX = map.getLeft(); | ||
111 | int curBoundY = map.getTop(); | ||
112 | |||
113 | bool zooming = false; | 81 | bool zooming = false; |
114 | int zoomProgress = 0; | 82 | int zoomProgress = 0; |
115 | int zoomLength; | 83 | int zoomLength; |
116 | int lastZoomTop; | ||
117 | int lastZoomLeft; | ||
118 | int lastZoomWidth; | ||
119 | int lastZoomHeight; | ||
120 | 84 | ||
121 | Input keystate; | 85 | Input keystate; |
122 | bool firstInput = false; | 86 | bool firstInput = false; |
@@ -159,7 +123,7 @@ private: | |||
159 | 123 | ||
160 | void processKickup(); | 124 | void processKickup(); |
161 | 125 | ||
162 | void growMap(size_t zoom); | 126 | void loadMap(); |
163 | 127 | ||
164 | void setZoom(size_t zoom); | 128 | void setZoom(size_t zoom); |
165 | 129 | ||
diff --git a/src/main.cpp b/src/main.cpp index 4ae11d6..0d14986 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
@@ -23,7 +23,7 @@ int main(int, char**) | |||
23 | 23 | ||
24 | Game game(rng, muxer); | 24 | Game game(rng, muxer); |
25 | 25 | ||
26 | constexpr int titleFadeLen = 3000; | 26 | constexpr int titleFadeLen = 2000; |
27 | bool doneTitles = false; | 27 | bool doneTitles = false; |
28 | int titleNum = 0; | 28 | int titleNum = 0; |
29 | TitleState titleState = TitleState::FadeIn; | 29 | TitleState titleState = TitleState::FadeIn; |
diff --git a/src/map.h b/src/map.h index 329553c..d28b8d4 100644 --- a/src/map.h +++ b/src/map.h | |||
@@ -3,23 +3,62 @@ | |||
3 | 3 | ||
4 | #include <vector> | 4 | #include <vector> |
5 | #include <algorithm> | 5 | #include <algorithm> |
6 | #include <array> | ||
7 | #include <list> | ||
8 | #include <map> | ||
9 | #include <random> | ||
10 | #include "consts.h" | ||
6 | 11 | ||
7 | template <typename T> | 12 | using coord = std::tuple<int, int>; |
8 | class Map { | ||
9 | public: | ||
10 | 13 | ||
11 | Map( | 14 | enum class Tile { |
12 | int left, | 15 | Floor, |
13 | int top, | 16 | Wall, |
14 | int width, | 17 | Dust, |
15 | int height) : | 18 | Lamp |
16 | left_(left), | 19 | }; |
17 | top_(top), | 20 | |
18 | width_(width), | 21 | enum class Source { |
19 | height_(height), | 22 | None, |
20 | data_(width_*height_) | 23 | Dust, |
21 | { | 24 | Lamp, |
25 | Player | ||
26 | }; | ||
27 | |||
28 | struct MapData { | ||
29 | Tile tile = Tile::Floor; | ||
30 | bool lit = false; | ||
31 | bool wasLit = false; | ||
32 | size_t dustLife = 0; | ||
33 | Source lightType = Source::None; | ||
34 | int lightRadius = 0; | ||
35 | std::set<coord> litTiles; | ||
36 | int renderId = -1; | ||
37 | bool dirtyRender = true; | ||
38 | }; | ||
39 | |||
40 | struct Chunk { | ||
41 | std::array<MapData, CHUNK_WIDTH*CHUNK_HEIGHT> data; | ||
42 | int litTiles = 0; | ||
43 | int x; | ||
44 | int y; | ||
45 | }; | ||
46 | |||
47 | inline void toChunkPos(int x, int y, int& cx, int& cy) { | ||
48 | cx = x / CHUNK_WIDTH; | ||
49 | cy = y / CHUNK_HEIGHT; | ||
50 | if (x < 0) { | ||
51 | cx *= -1; | ||
52 | cx--; | ||
53 | } | ||
54 | if (y < 0) { | ||
55 | cy *= -1; | ||
56 | cy--; | ||
22 | } | 57 | } |
58 | } | ||
59 | |||
60 | class Map { | ||
61 | public: | ||
23 | 62 | ||
24 | inline int getLeft() const | 63 | inline int getLeft() const |
25 | { | 64 | { |
@@ -69,27 +108,27 @@ public: | |||
69 | (y < top_ + height_); | 108 | (y < top_ + height_); |
70 | } | 109 | } |
71 | 110 | ||
72 | inline const T& at(int x, int y) const | 111 | inline const MapData& at(int x, int y) const |
73 | { | 112 | { |
74 | return data_.at((x - left_) + width_ * (y - top_)); | 113 | return loaded_.at((x - left_) + width_ * (y - top_)); |
75 | } | 114 | } |
76 | 115 | ||
77 | inline T& at(int x, int y) | 116 | inline MapData& at(int x, int y) |
78 | { | 117 | { |
79 | return const_cast<T&>(static_cast<const Map&>(*this).at(x, y)); | 118 | return const_cast<MapData&>(static_cast<const Map&>(*this).at(x, y)); |
80 | } | 119 | } |
81 | 120 | ||
82 | inline const std::vector<T>& data() const | 121 | inline const std::vector<MapData>& data() const |
83 | { | 122 | { |
84 | return data_; | 123 | return loaded_; |
85 | } | 124 | } |
86 | 125 | ||
87 | inline std::vector<T>& data() | 126 | inline std::vector<MapData>& data() |
88 | { | 127 | { |
89 | return data_; | 128 | return loaded_; |
90 | } | 129 | } |
91 | 130 | ||
92 | void resize(int newLeft, int newTop, int newWidth, int newHeight) | 131 | /*void resize(int newLeft, int newTop, int newWidth, int newHeight) |
93 | { | 132 | { |
94 | std::vector<T> newData(newWidth * newHeight); | 133 | std::vector<T> newData(newWidth * newHeight); |
95 | 134 | ||
@@ -112,6 +151,96 @@ public: | |||
112 | width_ = newWidth; | 151 | width_ = newWidth; |
113 | height_ = newHeight; | 152 | height_ = newHeight; |
114 | data_.swap(newData); | 153 | data_.swap(newData); |
154 | }*/ | ||
155 | |||
156 | void load(int newLeftChunk, int newTopChunk, int newWidthChunks, int newHeightChunks, std::mt19937& rng) { | ||
157 | // Flush the currently loaded data as long as there is any (this isn't the first load). | ||
158 | if (!loaded_.empty()) { | ||
159 | std::vector<size_t> touchedChunks; | ||
160 | |||
161 | for (int chunkY = 0; chunkY < chunksVert_; chunkY++) { | ||
162 | for (int chunkX = 0; chunkX < chunksHoriz_; chunkX++) { | ||
163 | size_t chunkIndex = chunkByPos_.at(leftmostChunk_ + chunkX).at(topmostChunk_ + chunkY); | ||
164 | touchedChunks.push_back(chunkIndex); | ||
165 | |||
166 | Chunk& chunk = chunks_.at(chunkIndex); | ||
167 | chunk.litTiles = 0; | ||
168 | |||
169 | int startX = chunkX * CHUNK_WIDTH; | ||
170 | int startY = chunkY * CHUNK_HEIGHT; | ||
171 | for (int y=0; y<CHUNK_HEIGHT; y++) { | ||
172 | for (int x=0; x<CHUNK_WIDTH; x++) { | ||
173 | chunk.data[x+y*CHUNK_WIDTH] = loaded_[startX+x+(startY+y)*width_]; | ||
174 | if (chunk.data[x+y*CHUNK_WIDTH].lit) { | ||
175 | chunk.litTiles++; | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | // Destroy any completely unlit chunks. | ||
183 | for (size_t chunkIndex : touchedChunks) { | ||
184 | if (chunks_[chunkIndex].litTiles == 0) { | ||
185 | chunkByPos_[chunks_[chunkIndex].x].erase(chunks_[chunkIndex].y); | ||
186 | freeList_.push_back(chunkIndex); | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | |||
191 | leftmostChunk_ = newLeftChunk; | ||
192 | topmostChunk_ = newTopChunk; | ||
193 | chunksHoriz_ = newWidthChunks; | ||
194 | chunksVert_ = newHeightChunks; | ||
195 | left_ = newLeftChunk * CHUNK_WIDTH; | ||
196 | top_ = newTopChunk * CHUNK_HEIGHT; | ||
197 | width_ = chunksHoriz_ * CHUNK_WIDTH; | ||
198 | height_ = chunksVert_ * CHUNK_HEIGHT; | ||
199 | loaded_ = std::vector<MapData>(width_ * height_); | ||
200 | |||
201 | // Load in the requested chunks. | ||
202 | for (int chunkY = 0; chunkY < chunksVert_; chunkY++) { | ||
203 | for (int chunkX = 0; chunkX < chunksHoriz_; chunkX++) { | ||
204 | // Instantiate a new chunk if necessary. | ||
205 | if (!chunkByPos_[leftmostChunk_ + chunkX].count(topmostChunk_ + chunkY)) { | ||
206 | size_t chunkIndex; | ||
207 | if (!freeList_.empty()) { | ||
208 | chunkIndex = freeList_.front(); | ||
209 | freeList_.pop_front(); | ||
210 | } else { | ||
211 | chunkIndex = chunks_.size(); | ||
212 | chunks_.emplace_back(); | ||
213 | } | ||
214 | chunkByPos_[leftmostChunk_ + chunkX][topmostChunk_ + chunkY] = chunkIndex; | ||
215 | |||
216 | Chunk& chunk = chunks_[chunkIndex]; | ||
217 | chunk.x = leftmostChunk_ + chunkX; | ||
218 | chunk.y = topmostChunk_ + chunkY; | ||
219 | |||
220 | for (MapData& md : chunk.data) | ||
221 | { | ||
222 | if (std::bernoulli_distribution(0.5)(rng)) | ||
223 | { | ||
224 | md.tile = Tile::Wall; | ||
225 | } else { | ||
226 | md.tile = Tile::Floor; | ||
227 | } | ||
228 | md.dirtyRender = true; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | size_t chunkIndex = chunkByPos_[leftmostChunk_ + chunkX][topmostChunk_ + chunkY]; | ||
233 | Chunk& chunk = chunks_[chunkIndex]; | ||
234 | |||
235 | for (int y = 0; y < CHUNK_HEIGHT; y++) { | ||
236 | std::copy( | ||
237 | std::next(std::begin(chunk.data), y*CHUNK_WIDTH), | ||
238 | std::next(std::begin(chunk.data), (y+1)*CHUNK_WIDTH), | ||
239 | std::next(std::begin(loaded_), (chunkY*CHUNK_HEIGHT + y)*width_ + chunkX*CHUNK_WIDTH)); | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | |||
115 | } | 244 | } |
116 | 245 | ||
117 | private: | 246 | private: |
@@ -120,8 +249,15 @@ private: | |||
120 | int top_; | 249 | int top_; |
121 | int width_; | 250 | int width_; |
122 | int height_; | 251 | int height_; |
252 | int leftmostChunk_; | ||
253 | int topmostChunk_; | ||
254 | int chunksHoriz_; | ||
255 | int chunksVert_; | ||
256 | std::vector<MapData> loaded_; | ||
123 | 257 | ||
124 | std::vector<T> data_; | 258 | std::vector<Chunk> chunks_; |
259 | std::list<size_t> freeList_; | ||
260 | std::map<int, std::map<int, size_t>> chunkByPos_; // chunkByPos_[X][Y] | ||
125 | }; | 261 | }; |
126 | 262 | ||
127 | #endif /* end of include guard: MAP_H_3AB00D12 */ | 263 | #endif /* end of include guard: MAP_H_3AB00D12 */ |
diff --git a/src/renderer.cpp b/src/renderer.cpp index 9ef8bb9..1f51e0a 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp | |||
@@ -12,7 +12,7 @@ Renderer::Renderer() | |||
12 | GAME_HEIGHT, | 12 | GAME_HEIGHT, |
13 | SDL_WINDOW_SHOWN)); | 13 | SDL_WINDOW_SHOWN)); |
14 | 14 | ||
15 | SDL_SetWindowFullscreen(win_.get(), SDL_WINDOW_FULLSCREEN_DESKTOP); | 15 | //SDL_SetWindowFullscreen(win_.get(), SDL_WINDOW_FULLSCREEN_DESKTOP); |
16 | 16 | ||
17 | if (!win_) | 17 | if (!win_) |
18 | { | 18 | { |
@@ -115,13 +115,16 @@ void Renderer::renderGame( | |||
115 | const Game& game, | 115 | const Game& game, |
116 | bool drawDark) | 116 | bool drawDark) |
117 | { | 117 | { |
118 | int windowTileWidth = game.curZoom * ZOOM_X_FACTOR + 2; | ||
119 | int windowTileHeight = game.curZoom * ZOOM_Y_FACTOR + 2; | ||
120 | |||
118 | texture_ptr canvas( | 121 | texture_ptr canvas( |
119 | SDL_CreateTexture( | 122 | SDL_CreateTexture( |
120 | ren_.get(), | 123 | ren_.get(), |
121 | SDL_PIXELFORMAT_RGBA8888, | 124 | SDL_PIXELFORMAT_RGBA8888, |
122 | SDL_TEXTUREACCESS_TARGET, | 125 | SDL_TEXTUREACCESS_TARGET, |
123 | TILE_WIDTH * game.map.getWidth(), | 126 | windowTileWidth * TILE_WIDTH, |
124 | TILE_HEIGHT * game.map.getHeight())); | 127 | windowTileHeight * TILE_HEIGHT)); |
125 | 128 | ||
126 | if (!canvas) | 129 | if (!canvas) |
127 | { | 130 | { |
@@ -133,15 +136,17 @@ void Renderer::renderGame( | |||
133 | SDL_SetRenderDrawColor(ren_.get(), rand() % 255, rand() % 255, rand() % 255, 255); | 136 | SDL_SetRenderDrawColor(ren_.get(), rand() % 255, rand() % 255, rand() % 255, 255); |
134 | SDL_RenderClear(ren_.get()); | 137 | SDL_RenderClear(ren_.get()); |
135 | 138 | ||
136 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) | 139 | int leftmost = game.player_x - game.curZoom * ZOOM_X_FACTOR / 2 - 1; |
140 | int topmost = game.player_y - game.curZoom * ZOOM_Y_FACTOR / 2 - 1; | ||
141 | for (int y = topmost; y < topmost + windowTileHeight; y++) | ||
137 | { | 142 | { |
138 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) | 143 | for (int x = leftmost; x < leftmost + windowTileWidth; x++) |
139 | { | 144 | { |
140 | bool draw = true; | 145 | bool draw = true; |
141 | bool drawColour = false; | 146 | bool drawColour = false; |
142 | SDL_Rect rect { | 147 | SDL_Rect rect { |
143 | game.map.getTrueX(x) * TILE_WIDTH, | 148 | (x - leftmost) * TILE_WIDTH, |
144 | game.map.getTrueY(y) * TILE_HEIGHT, | 149 | (y - topmost) * TILE_HEIGHT, |
145 | TILE_WIDTH, | 150 | TILE_WIDTH, |
146 | TILE_HEIGHT}; | 151 | TILE_HEIGHT}; |
147 | 152 | ||
@@ -190,14 +195,14 @@ void Renderer::renderGame( | |||
190 | 195 | ||
191 | if (game.renderPlayer) { | 196 | if (game.renderPlayer) { |
192 | SDL_Rect rect { | 197 | SDL_Rect rect { |
193 | game.map.getTrueX(game.player_x) * TILE_WIDTH, | 198 | (game.player_x - leftmost) * TILE_WIDTH, |
194 | game.map.getTrueY(game.player_y) * TILE_HEIGHT, | 199 | (game.player_y - topmost) * TILE_HEIGHT, |
195 | TILE_WIDTH, | 200 | TILE_WIDTH, |
196 | TILE_HEIGHT}; | 201 | TILE_HEIGHT}; |
197 | 202 | ||
198 | if (game.moving) { | 203 | if (game.moving) { |
199 | rect.x = game.moveProgress.getProgress(game.map.getTrueX(game.player_oldx) * TILE_WIDTH, rect.x); | 204 | rect.x = game.moveProgress.getProgress((game.player_oldx - leftmost) * TILE_WIDTH, rect.x); |
200 | rect.y = game.moveProgress.getProgress(game.map.getTrueY(game.player_oldy) * TILE_HEIGHT, rect.y); | 205 | rect.y = game.moveProgress.getProgress((game.player_oldy - topmost) * TILE_HEIGHT, rect.y); |
201 | } | 206 | } |
202 | 207 | ||
203 | SDL_RenderCopy(ren_.get(), playerSheet_.get(), &game.playerAnim.getRenderRect(), &rect); | 208 | SDL_RenderCopy(ren_.get(), playerSheet_.get(), &game.playerAnim.getRenderRect(), &rect); |
@@ -208,8 +213,8 @@ void Renderer::renderGame( | |||
208 | ren_.get(), | 213 | ren_.get(), |
209 | SDL_PIXELFORMAT_RGBA8888, | 214 | SDL_PIXELFORMAT_RGBA8888, |
210 | SDL_TEXTUREACCESS_TARGET, | 215 | SDL_TEXTUREACCESS_TARGET, |
211 | TILE_WIDTH * game.map.getWidth(), | 216 | windowTileWidth * TILE_WIDTH, |
212 | TILE_HEIGHT * game.map.getHeight())); | 217 | windowTileHeight * TILE_HEIGHT)); |
213 | 218 | ||
214 | if (!mask) | 219 | if (!mask) |
215 | { | 220 | { |
@@ -220,9 +225,9 @@ void Renderer::renderGame( | |||
220 | SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); | 225 | SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); |
221 | SDL_RenderClear(ren_.get()); | 226 | SDL_RenderClear(ren_.get()); |
222 | 227 | ||
223 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) | 228 | for (int y = topmost; y < topmost + windowTileHeight; y++) |
224 | { | 229 | { |
225 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) | 230 | for (int x = leftmost; x < leftmost + windowTileWidth; x++) |
226 | { | 231 | { |
227 | if (game.map.at(x,y).lightType != Source::None) | 232 | if (game.map.at(x,y).lightType != Source::None) |
228 | { | 233 | { |
@@ -231,8 +236,8 @@ void Renderer::renderGame( | |||
231 | ren_.get(), | 236 | ren_.get(), |
232 | SDL_PIXELFORMAT_RGBA8888, | 237 | SDL_PIXELFORMAT_RGBA8888, |
233 | SDL_TEXTUREACCESS_TARGET, | 238 | SDL_TEXTUREACCESS_TARGET, |
234 | TILE_WIDTH * game.map.getWidth(), | 239 | windowTileWidth * TILE_WIDTH, |
235 | TILE_HEIGHT * game.map.getHeight())); | 240 | windowTileHeight * TILE_HEIGHT)); |
236 | 241 | ||
237 | if (!sourceMask) | 242 | if (!sourceMask) |
238 | { | 243 | { |
@@ -244,11 +249,11 @@ void Renderer::renderGame( | |||
244 | SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); | 249 | SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); |
245 | SDL_RenderClear(ren_.get()); | 250 | SDL_RenderClear(ren_.get()); |
246 | 251 | ||
247 | int posToUseX = game.map.getTrueX(x); | 252 | int posToUseX = x - leftmost; |
248 | int posToUseY = game.map.getTrueY(y); | 253 | int posToUseY = y - topmost; |
249 | if (game.map.at(x,y).lightType == Source::Player && game.moving) { | 254 | if (game.map.at(x,y).lightType == Source::Player && game.moving) { |
250 | posToUseX = game.moveProgress.getProgress(game.map.getTrueX(game.player_oldx), posToUseX); | 255 | posToUseX = game.moveProgress.getProgress((game.player_oldx) - leftmost, posToUseX); |
251 | posToUseY = game.moveProgress.getProgress(game.map.getTrueY(game.player_oldy), posToUseY); | 256 | posToUseY = game.moveProgress.getProgress((game.player_oldy) - topmost, posToUseY); |
252 | } | 257 | } |
253 | 258 | ||
254 | int fadeX = posToUseX - game.map.at(x,y).lightRadius; | 259 | int fadeX = posToUseX - game.map.at(x,y).lightRadius; |
@@ -283,8 +288,8 @@ void Renderer::renderGame( | |||
283 | if (!game.map.at(x,y).litTiles.count({sx, sy})) | 288 | if (!game.map.at(x,y).litTiles.count({sx, sy})) |
284 | { | 289 | { |
285 | SDL_Rect rect { | 290 | SDL_Rect rect { |
286 | game.map.getTrueX(sx) * TILE_WIDTH, | 291 | (sx - leftmost) * TILE_WIDTH, |
287 | game.map.getTrueY(sy) * TILE_HEIGHT, | 292 | (sy - topmost) * TILE_HEIGHT, |
288 | TILE_WIDTH, | 293 | TILE_WIDTH, |
289 | TILE_HEIGHT}; | 294 | TILE_HEIGHT}; |
290 | 295 | ||
@@ -306,10 +311,28 @@ void Renderer::renderGame( | |||
306 | 311 | ||
307 | SDL_SetRenderTarget(ren_.get(), nullptr); | 312 | SDL_SetRenderTarget(ren_.get(), nullptr); |
308 | 313 | ||
309 | SDL_Rect zoomRect; | 314 | // TODO: this is just moving interp. we also need zoom |
315 | SDL_Rect zoomRect { | ||
316 | TILE_WIDTH, TILE_HEIGHT, (windowTileWidth - 2) * TILE_WIDTH, (windowTileHeight - 2) * TILE_HEIGHT | ||
317 | }; | ||
318 | |||
319 | if (game.moving) { | ||
320 | double interp = | ||
321 | static_cast<double>(game.zoomProgress) / | ||
322 | static_cast<double>(game.zoomLength); | ||
323 | |||
324 | if (game.player_x > game.player_oldx) { | ||
325 | zoomRect.x = game.moveProgress.getProgress(0, TILE_WIDTH); | ||
326 | } else if (game.player_x < game.player_oldx) { | ||
327 | zoomRect.x = game.moveProgress.getProgress(2*TILE_WIDTH, TILE_WIDTH); | ||
328 | } | ||
310 | 329 | ||
311 | std::tie(zoomRect.x, zoomRect.y, zoomRect.w, zoomRect.h) = | 330 | if (game.player_y > game.player_oldy) { |
312 | calculateZoomRect(game); | 331 | zoomRect.y = game.moveProgress.getProgress(0, TILE_HEIGHT); |
332 | } else if (game.player_y < game.player_oldy) { | ||
333 | zoomRect.y = game.moveProgress.getProgress(TILE_HEIGHT*2, TILE_HEIGHT); | ||
334 | } | ||
335 | } | ||
313 | 336 | ||
314 | SDL_RenderCopy(ren_.get(), canvas.get(), &zoomRect, nullptr); | 337 | SDL_RenderCopy(ren_.get(), canvas.get(), &zoomRect, nullptr); |
315 | SDL_RenderPresent(ren_.get()); | 338 | SDL_RenderPresent(ren_.get()); |
@@ -358,12 +381,12 @@ void Renderer::renderTitle(int num, double fade) { | |||
358 | 381 | ||
359 | std::tuple<int, int, int, int> Renderer::calculateZoomRect(const Game& game) | 382 | std::tuple<int, int, int, int> Renderer::calculateZoomRect(const Game& game) |
360 | { | 383 | { |
361 | int x = game.map.getTrueX(game.curBoundX) * TILE_WIDTH; | ||
362 | int y = game.map.getTrueY(game.curBoundY) * TILE_HEIGHT; | ||
363 | int w = game.curZoom * TILE_WIDTH * ZOOM_X_FACTOR; | 384 | int w = game.curZoom * TILE_WIDTH * ZOOM_X_FACTOR; |
364 | int h = game.curZoom * TILE_HEIGHT * ZOOM_Y_FACTOR; | 385 | int h = game.curZoom * TILE_HEIGHT * ZOOM_Y_FACTOR; |
386 | int x = (game.map.getTrueX(game.player_x) * TILE_WIDTH) - (w / 2); | ||
387 | int y = (game.map.getTrueY(game.player_y) * TILE_HEIGHT) - (h / 2); | ||
365 | 388 | ||
366 | if (game.zooming) | 389 | /*if (game.zooming) |
367 | { | 390 | { |
368 | double interp = | 391 | double interp = |
369 | static_cast<double>(game.zoomProgress) / | 392 | static_cast<double>(game.zoomProgress) / |
@@ -373,7 +396,7 @@ std::tuple<int, int, int, int> Renderer::calculateZoomRect(const Game& game) | |||
373 | y = (y - game.lastZoomTop) * interp + game.lastZoomTop; | 396 | y = (y - game.lastZoomTop) * interp + game.lastZoomTop; |
374 | w = (w - game.lastZoomWidth) * interp + game.lastZoomWidth; | 397 | w = (w - game.lastZoomWidth) * interp + game.lastZoomWidth; |
375 | h = (h - game.lastZoomHeight) * interp + game.lastZoomHeight; | 398 | h = (h - game.lastZoomHeight) * interp + game.lastZoomHeight; |
376 | } | 399 | }*/ |
377 | 400 | ||
378 | return {x, y, w, h}; | 401 | return {x, y, w, h}; |
379 | } | 402 | } |