diff options
| -rw-r--r-- | res/map.png | bin | 0 -> 124 bytes | |||
| -rw-r--r-- | res/object.png | bin | 0 -> 125 bytes | |||
| -rw-r--r-- | res/track.png | bin | 0 -> 775 bytes | |||
| -rw-r--r-- | src/consts.h | 6 | ||||
| -rw-r--r-- | src/editor.cpp | 246 | ||||
| -rw-r--r-- | src/editor.h | 30 | ||||
| -rw-r--r-- | src/input.h | 39 | ||||
| -rw-r--r-- | src/input_lag.h | 66 | ||||
| -rw-r--r-- | src/level.cpp | 41 | ||||
| -rw-r--r-- | src/level.h | 64 | ||||
| -rw-r--r-- | src/main.cpp | 20 | ||||
| -rw-r--r-- | src/simulation.cpp | 2 | ||||
| -rw-r--r-- | src/tileset.h | 38 |
13 files changed, 496 insertions, 56 deletions
| diff --git a/res/map.png b/res/map.png new file mode 100644 index 0000000..e41bd05 --- /dev/null +++ b/res/map.png | |||
| Binary files differ | |||
| diff --git a/res/object.png b/res/object.png new file mode 100644 index 0000000..fe84b88 --- /dev/null +++ b/res/object.png | |||
| Binary files differ | |||
| diff --git a/res/track.png b/res/track.png new file mode 100644 index 0000000..d3a9a93 --- /dev/null +++ b/res/track.png | |||
| Binary files differ | |||
| diff --git a/src/consts.h b/src/consts.h index f3a073c..a6b5094 100644 --- a/src/consts.h +++ b/src/consts.h | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | #include "vector.h" | 4 | #include "vector.h" |
| 5 | 5 | ||
| 6 | constexpr vec2s TILE_SIZE { 32, 32 }; | 6 | constexpr vec2s TILE_SIZE { 32, 32 }; |
| 7 | constexpr vec2s LEVEL_SIZE { 16, 16 }; | 7 | constexpr vec2s MAP_SIZE { 16, 16 }; |
| 8 | constexpr vec2s WINDOW_SIZE = TILE_SIZE * LEVEL_SIZE; | 8 | constexpr vec2s LEVEL_SIZE = TILE_SIZE * MAP_SIZE; |
| 9 | constexpr vec2s BORDER_SIZE = TILE_SIZE; | ||
| 10 | constexpr vec2s WINDOW_SIZE = LEVEL_SIZE * vec2s { 2, 1 } + BORDER_SIZE * 2; | ||
| 9 | 11 | ||
| 10 | #endif /* end of include guard: CONSTS_H_8019F1B3 */ | 12 | #endif /* end of include guard: CONSTS_H_8019F1B3 */ |
| diff --git a/src/editor.cpp b/src/editor.cpp index 92c6b67..30dde45 100644 --- a/src/editor.cpp +++ b/src/editor.cpp | |||
| @@ -5,27 +5,150 @@ void Editor::tick( | |||
| 5 | double dt, | 5 | double dt, |
| 6 | const Uint8* keystate) | 6 | const Uint8* keystate) |
| 7 | { | 7 | { |
| 8 | if (keystate[SDL_SCANCODE_LEFT] || | ||
| 9 | keystate[SDL_SCANCODE_UP] || | ||
| 10 | keystate[SDL_SCANCODE_RIGHT] || | ||
| 11 | keystate[SDL_SCANCODE_DOWN]) | ||
| 12 | { | ||
| 13 | // If the player is holding down a directional key, accumulate the time | ||
| 14 | // since the last tick, and then apply the directional key as many times as | ||
| 15 | // needed. The input lag class automatically handles the delays necessary | ||
| 16 | // for key repeat. | ||
| 17 | inputLag_.accumulate(dt); | ||
| 8 | 18 | ||
| 9 | } | 19 | while (inputLag_.step()) |
| 20 | { | ||
| 21 | if (mapFocus_) | ||
| 22 | { | ||
| 23 | // If we are focused on the map, move the map cursor. | ||
| 24 | if (keystate[SDL_SCANCODE_LEFT] && cursor_.x() > 0) | ||
| 25 | { | ||
| 26 | cursor_.x()--; | ||
| 27 | } | ||
| 10 | 28 | ||
| 11 | void Editor::render(SDL_Renderer* ren) | 29 | if (keystate[SDL_SCANCODE_UP] && cursor_.y() > 0) |
| 12 | { | 30 | { |
| 13 | if (!background_) | 31 | cursor_.y()--; |
| 32 | } | ||
| 33 | |||
| 34 | if (keystate[SDL_SCANCODE_RIGHT] && | ||
| 35 | cursor_.x() < level_.getSize().w() - 1) | ||
| 36 | { | ||
| 37 | cursor_.x()++; | ||
| 38 | } | ||
| 39 | |||
| 40 | if (keystate[SDL_SCANCODE_DOWN] && | ||
| 41 | cursor_.y() < level_.getSize().h() - 1) | ||
| 42 | { | ||
| 43 | cursor_.y()++; | ||
| 44 | } | ||
| 45 | } else { | ||
| 46 | // If we are focused on the tileset, rotate through the selection of | ||
| 47 | // tiles. | ||
| 48 | if (keystate[SDL_SCANCODE_UP]) | ||
| 49 | { | ||
| 50 | selectedTile_--; | ||
| 51 | } else if (keystate[SDL_SCANCODE_DOWN]) | ||
| 52 | { | ||
| 53 | selectedTile_++; | ||
| 54 | } | ||
| 55 | |||
| 56 | selectedTile_ %= level_.getTileset(layer_).getNumTiles(); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | } else if (inputLag_.isActive()) | ||
| 14 | { | 60 | { |
| 15 | surface_ptr bgSurf(IMG_Load("../res/editor_bg.png")); | 61 | // If the player is not holding down a directional key, reset the input lag. |
| 62 | inputLag_.reset(); | ||
| 63 | } | ||
| 64 | |||
| 65 | // Check for keypress changes since the last tick. | ||
| 66 | input_.tick(keystate); | ||
| 16 | 67 | ||
| 17 | if (!bgSurf) | 68 | if (input_.wasPressed(SDL_SCANCODE_Z)) |
| 69 | { | ||
| 70 | switch (layer_) | ||
| 18 | { | 71 | { |
| 19 | throw img_error(); | 72 | case Layer::map: |
| 73 | { | ||
| 74 | layer_ = Layer::object; | ||
| 75 | |||
| 76 | break; | ||
| 77 | } | ||
| 78 | |||
| 79 | case Layer::track: | ||
| 80 | { | ||
| 81 | layer_ = Layer::map; | ||
| 82 | |||
| 83 | break; | ||
| 84 | } | ||
| 85 | |||
| 86 | case Layer::object: | ||
| 87 | { | ||
| 88 | layer_ = Layer::track; | ||
| 89 | |||
| 90 | break; | ||
| 91 | } | ||
| 20 | } | 92 | } |
| 21 | 93 | ||
| 22 | background_.reset(SDL_CreateTextureFromSurface(ren, bgSurf.get())); | 94 | selectedTile_ = 0; |
| 23 | bgSize_ = { bgSurf->w, bgSurf->h }; | 95 | |
| 96 | // Reset the cached map so that it gets redrawn with the focused layer. | ||
| 97 | renderedMap_.reset(); | ||
| 98 | } else if (input_.wasPressed(SDL_SCANCODE_X)) | ||
| 99 | { | ||
| 100 | switch (layer_) | ||
| 101 | { | ||
| 102 | case Layer::map: | ||
| 103 | { | ||
| 104 | layer_ = Layer::track; | ||
| 105 | |||
| 106 | break; | ||
| 107 | } | ||
| 108 | |||
| 109 | case Layer::track: | ||
| 110 | { | ||
| 111 | layer_ = Layer::object; | ||
| 112 | |||
| 113 | break; | ||
| 114 | } | ||
| 115 | |||
| 116 | case Layer::object: | ||
| 117 | { | ||
| 118 | layer_ = Layer::map; | ||
| 119 | |||
| 120 | break; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | selectedTile_ = 0; | ||
| 125 | |||
| 126 | // Reset the cached map so that it gets redrawn with the focused layer. | ||
| 127 | renderedMap_.reset(); | ||
| 128 | } else if (input_.wasPressed(SDL_SCANCODE_TAB)) | ||
| 129 | { | ||
| 130 | mapFocus_ = !mapFocus_; | ||
| 24 | } | 131 | } |
| 25 | 132 | ||
| 26 | for (int y = 0; y < WINDOW_SIZE.h() / bgSize_.h(); y++) | 133 | if (mapFocus_) |
| 27 | { | 134 | { |
| 28 | for (int x = 0; x < WINDOW_SIZE.w() / bgSize_.w(); x++) | 135 | if (keystate[SDL_SCANCODE_RETURN] || |
| 136 | keystate[SDL_SCANCODE_SPACE]) | ||
| 137 | { | ||
| 138 | level_.at(cursor_.x(), cursor_.y(), layer_) = selectedTile_; | ||
| 139 | |||
| 140 | // Reset the cached map so that it gets redrawn with the new tile. | ||
| 141 | renderedMap_.reset(); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | void Editor::render(SDL_Renderer* ren) | ||
| 147 | { | ||
| 148 | // Tile the background art. | ||
| 149 | for (int y = 0; y <= WINDOW_SIZE.h() / bgSize_.h(); y++) | ||
| 150 | { | ||
| 151 | for (int x = 0; x <= WINDOW_SIZE.w() / bgSize_.w(); x++) | ||
| 29 | { | 152 | { |
| 30 | SDL_Rect rect { | 153 | SDL_Rect rect { |
| 31 | x * bgSize_.w(), | 154 | x * bgSize_.w(), |
| @@ -37,4 +160,105 @@ void Editor::render(SDL_Renderer* ren) | |||
| 37 | SDL_RenderCopy(ren, background_.get(), nullptr, &rect); | 160 | SDL_RenderCopy(ren, background_.get(), nullptr, &rect); |
| 38 | } | 161 | } |
| 39 | } | 162 | } |
| 163 | |||
| 164 | // Render and cache the map if the cache is currently empty. | ||
| 165 | if (!renderedMap_) | ||
| 166 | { | ||
| 167 | renderedMap_.reset( | ||
| 168 | SDL_CreateTexture( | ||
| 169 | ren, | ||
| 170 | SDL_PIXELFORMAT_RGBA8888, | ||
| 171 | SDL_TEXTUREACCESS_TARGET, | ||
| 172 | LEVEL_SIZE.w(), | ||
| 173 | LEVEL_SIZE.h())); | ||
| 174 | |||
| 175 | // Render each layer separately, then compose them atop each other. Layers | ||
| 176 | // above the currently selected one are drawn semi-transparently. | ||
| 177 | texture_ptr mapRender = level_.render(ren, Layer::map); | ||
| 178 | texture_ptr trackRender = level_.render(ren, Layer::track); | ||
| 179 | texture_ptr objectRender = level_.render(ren, Layer::object); | ||
| 180 | |||
| 181 | if (layer_ < Layer::track) | ||
| 182 | { | ||
| 183 | SDL_SetTextureBlendMode(trackRender.get(), SDL_BLENDMODE_BLEND); | ||
| 184 | SDL_SetTextureAlphaMod(trackRender.get(), 127); | ||
| 185 | } | ||
| 186 | |||
| 187 | if (layer_ < Layer::object) | ||
| 188 | { | ||
| 189 | SDL_SetTextureBlendMode(objectRender.get(), SDL_BLENDMODE_BLEND); | ||
| 190 | SDL_SetTextureAlphaMod(objectRender.get(), 127); | ||
| 191 | } | ||
| 192 | |||
| 193 | SDL_SetRenderTarget(ren, renderedMap_.get()); | ||
| 194 | SDL_RenderCopy(ren, mapRender.get(), nullptr, nullptr); | ||
| 195 | SDL_RenderCopy(ren, trackRender.get(), nullptr, nullptr); | ||
| 196 | SDL_RenderCopy(ren, objectRender.get(), nullptr, nullptr); | ||
| 197 | SDL_SetRenderTarget(ren, nullptr); | ||
| 198 | } | ||
| 199 | |||
| 200 | // Copy the rendered map onto the editor. | ||
| 201 | SDL_Rect mapLoc { | ||
| 202 | static_cast<int>(BORDER_SIZE.w()), | ||
| 203 | static_cast<int>(BORDER_SIZE.h()), | ||
| 204 | static_cast<int>(LEVEL_SIZE.w()), | ||
| 205 | static_cast<int>(LEVEL_SIZE.h()) | ||
| 206 | }; | ||
| 207 | |||
| 208 | SDL_RenderCopy(ren, renderedMap_.get(), nullptr, &mapLoc); | ||
| 209 | |||
| 210 | // If the map is focused, draw an outline around it. | ||
| 211 | if (mapFocus_) | ||
| 212 | { | ||
| 213 | SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); | ||
| 214 | SDL_RenderDrawRect(ren, &mapLoc); | ||
| 215 | } | ||
| 216 | |||
| 217 | // Draw a box indicating the position of the map cursor. | ||
| 218 | vec2s cursorLoc = BORDER_SIZE + TILE_SIZE * cursor_; | ||
| 219 | |||
| 220 | SDL_Rect cursorRect { | ||
| 221 | static_cast<int>(cursorLoc.x()), | ||
| 222 | static_cast<int>(cursorLoc.y()), | ||
| 223 | static_cast<int>(TILE_SIZE.w()), | ||
| 224 | static_cast<int>(TILE_SIZE.h()) | ||
| 225 | }; | ||
| 226 | |||
| 227 | SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); | ||
| 228 | SDL_RenderDrawRect(ren, &cursorRect); | ||
| 229 | |||
| 230 | // Draw the tileset for the currently selected layer. | ||
| 231 | SDL_Rect tilesetLoc { | ||
| 232 | static_cast<int>(BORDER_SIZE.w() * 2 + LEVEL_SIZE.w()), | ||
| 233 | static_cast<int>(BORDER_SIZE.h()), | ||
| 234 | static_cast<int>(TILE_SIZE.w()), | ||
| 235 | level_.getTileset(layer_).getSize().h() | ||
| 236 | }; | ||
| 237 | |||
| 238 | SDL_SetRenderDrawColor(ren, 255, 255, 255, 255); | ||
| 239 | SDL_RenderFillRect(ren, &tilesetLoc); | ||
| 240 | |||
| 241 | SDL_RenderCopy( | ||
| 242 | ren, | ||
| 243 | level_.getTileset(layer_).getImage().get(), | ||
| 244 | nullptr, | ||
| 245 | &tilesetLoc); | ||
| 246 | |||
| 247 | // If the tileset is focused, draw an outline around it. | ||
| 248 | if (!mapFocus_) | ||
| 249 | { | ||
| 250 | SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); | ||
| 251 | SDL_RenderDrawRect(ren, &tilesetLoc); | ||
| 252 | } | ||
| 253 | |||
| 254 | // Draw a box indicating which tile is currently selected. | ||
| 255 | SDL_Rect tileCursorRect { | ||
| 256 | tilesetLoc.x, | ||
| 257 | static_cast<int>((1 + selectedTile_) * TILE_SIZE.h()), | ||
| 258 | static_cast<int>(TILE_SIZE.w()), | ||
| 259 | static_cast<int>(TILE_SIZE.h()) | ||
| 260 | }; | ||
| 261 | |||
| 262 | SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); | ||
| 263 | SDL_RenderDrawRect(ren, &tileCursorRect); | ||
| 40 | } | 264 | } |
| diff --git a/src/editor.h b/src/editor.h index dc908b9..dbf50c0 100644 --- a/src/editor.h +++ b/src/editor.h | |||
| @@ -3,10 +3,26 @@ | |||
| 3 | 3 | ||
| 4 | #include "state.h" | 4 | #include "state.h" |
| 5 | #include "vector.h" | 5 | #include "vector.h" |
| 6 | #include "level.h" | ||
| 7 | #include "input.h" | ||
| 8 | #include "input_lag.h" | ||
| 6 | 9 | ||
| 7 | class Editor : public State { | 10 | class Editor : public State { |
| 8 | public: | 11 | public: |
| 9 | 12 | ||
| 13 | Editor(SDL_Renderer* ren) : level_(ren) | ||
| 14 | { | ||
| 15 | surface_ptr bgSurf(IMG_Load("../res/editor_bg.png")); | ||
| 16 | |||
| 17 | if (!bgSurf) | ||
| 18 | { | ||
| 19 | throw img_error(); | ||
| 20 | } | ||
| 21 | |||
| 22 | background_.reset(SDL_CreateTextureFromSurface(ren, bgSurf.get())); | ||
| 23 | bgSize_ = { bgSurf->w, bgSurf->h }; | ||
| 24 | } | ||
| 25 | |||
| 10 | void tick( | 26 | void tick( |
| 11 | double dt, | 27 | double dt, |
| 12 | const Uint8* keystate) override; | 28 | const Uint8* keystate) override; |
| @@ -15,9 +31,23 @@ public: | |||
| 15 | 31 | ||
| 16 | private: | 32 | private: |
| 17 | 33 | ||
| 34 | Level level_; | ||
| 35 | |||
| 18 | texture_ptr background_; | 36 | texture_ptr background_; |
| 19 | vec2i bgSize_; | 37 | vec2i bgSize_; |
| 20 | 38 | ||
| 39 | texture_ptr renderedMap_; | ||
| 40 | |||
| 41 | bool mapFocus_ = true; | ||
| 42 | vec2s cursor_; | ||
| 43 | |||
| 44 | size_t selectedTile_ = 0; | ||
| 45 | |||
| 46 | Input input_; | ||
| 47 | InputLag inputLag_; | ||
| 48 | |||
| 49 | Layer layer_ = Layer::map; | ||
| 50 | |||
| 21 | }; | 51 | }; |
| 22 | 52 | ||
| 23 | #endif /* end of include guard: EDITOR_H_8BB54FE3 */ | 53 | #endif /* end of include guard: EDITOR_H_8BB54FE3 */ |
| diff --git a/src/input.h b/src/input.h new file mode 100644 index 0000000..ad8b761 --- /dev/null +++ b/src/input.h | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #ifndef INPUT_H_0FB34C42 | ||
| 2 | #define INPUT_H_0FB34C42 | ||
| 3 | |||
| 4 | #include <SDL.h> | ||
| 5 | #include <vector> | ||
| 6 | |||
| 7 | /** | ||
| 8 | * Helper class that detects when a key is newly pressed. | ||
| 9 | */ | ||
| 10 | class Input { | ||
| 11 | public: | ||
| 12 | |||
| 13 | Input() | ||
| 14 | { | ||
| 15 | const Uint8* s = SDL_GetKeyboardState(&length_); | ||
| 16 | |||
| 17 | curstate_.assign(s, s + length_); | ||
| 18 | prevstate_ = curstate_; | ||
| 19 | } | ||
| 20 | |||
| 21 | void tick(const Uint8* keystate) | ||
| 22 | { | ||
| 23 | prevstate_ = std::move(curstate_); | ||
| 24 | curstate_.assign(keystate, keystate + length_); | ||
| 25 | } | ||
| 26 | |||
| 27 | bool wasPressed(int scancode) const | ||
| 28 | { | ||
| 29 | return curstate_.at(scancode) && !prevstate_.at(scancode); | ||
| 30 | } | ||
| 31 | |||
| 32 | private: | ||
| 33 | |||
| 34 | int length_; | ||
| 35 | std::vector<Uint8> curstate_; | ||
| 36 | std::vector<Uint8> prevstate_; | ||
| 37 | }; | ||
| 38 | |||
| 39 | #endif /* end of include guard: INPUT_H_0FB34C42 */ | ||
| diff --git a/src/input_lag.h b/src/input_lag.h new file mode 100644 index 0000000..40bc4a1 --- /dev/null +++ b/src/input_lag.h | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | #ifndef INPUT_LAG_H_DF16F381 | ||
| 2 | #define INPUT_LAG_H_DF16F381 | ||
| 3 | |||
| 4 | /** | ||
| 5 | * Helper class that handles key repeat. | ||
| 6 | */ | ||
| 7 | class InputLag { | ||
| 8 | public: | ||
| 9 | |||
| 10 | bool isActive() const | ||
| 11 | { | ||
| 12 | return active_; | ||
| 13 | } | ||
| 14 | |||
| 15 | void reset() | ||
| 16 | { | ||
| 17 | accum_ = 0.0; | ||
| 18 | active_ = false; | ||
| 19 | repeat_ = false; | ||
| 20 | } | ||
| 21 | |||
| 22 | void accumulate(double dt) | ||
| 23 | { | ||
| 24 | accum_ += dt; | ||
| 25 | } | ||
| 26 | |||
| 27 | bool step() | ||
| 28 | { | ||
| 29 | if (!active_) | ||
| 30 | { | ||
| 31 | active_ = true; | ||
| 32 | |||
| 33 | return true; | ||
| 34 | } else if (!repeat_) | ||
| 35 | { | ||
| 36 | if (accum_ > delay_) | ||
| 37 | { | ||
| 38 | accum_ -= delay_; | ||
| 39 | repeat_ = true; | ||
| 40 | |||
| 41 | return true; | ||
| 42 | } | ||
| 43 | } else { | ||
| 44 | if (accum_ > tick_) | ||
| 45 | { | ||
| 46 | accum_ -= tick_; | ||
| 47 | |||
| 48 | return true; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | return false; | ||
| 53 | } | ||
| 54 | |||
| 55 | private: | ||
| 56 | |||
| 57 | double tick_ = 1.0 / 15.0; | ||
| 58 | double delay_ = tick_ * 3.0; | ||
| 59 | |||
| 60 | double accum_ = 0.0; | ||
| 61 | bool active_ = false; | ||
| 62 | bool repeat_ = false; | ||
| 63 | |||
| 64 | }; | ||
| 65 | |||
| 66 | #endif /* end of include guard: INPUT_LAG_H_DF16F381 */ | ||
| diff --git a/src/level.cpp b/src/level.cpp index b97eb70..e22a43f 100644 --- a/src/level.cpp +++ b/src/level.cpp | |||
| @@ -7,30 +7,37 @@ texture_ptr Level::render(SDL_Renderer* ren, Layer layer) const | |||
| 7 | ren, | 7 | ren, |
| 8 | SDL_PIXELFORMAT_RGBA8888, | 8 | SDL_PIXELFORMAT_RGBA8888, |
| 9 | SDL_TEXTUREACCESS_TARGET, | 9 | SDL_TEXTUREACCESS_TARGET, |
| 10 | WINDOW_SIZE.w(), | 10 | LEVEL_SIZE.w(), |
| 11 | WINDOW_SIZE.h())); | 11 | LEVEL_SIZE.h())); |
| 12 | 12 | ||
| 13 | SDL_SetRenderTarget(ren, canvas.get()); | 13 | SDL_SetRenderTarget(ren, canvas.get()); |
| 14 | SDL_SetTextureBlendMode(canvas.get(), SDL_BLENDMODE_BLEND); | ||
| 15 | SDL_SetRenderDrawColor(ren, 0, 0, 0, 0); | ||
| 16 | SDL_RenderFillRect(ren, nullptr); | ||
| 14 | 17 | ||
| 15 | for (size_t y = 0; y < size_.h(); y++) | 18 | for (size_t y = 0; y < size_.h(); y++) |
| 16 | { | 19 | { |
| 17 | for (size_t x = 0; x < size_.w(); x++) | 20 | for (size_t x = 0; x < size_.w(); x++) |
| 18 | { | 21 | { |
| 19 | if (layer == Layer::map) | 22 | SDL_Rect src { |
| 20 | { | 23 | 0, |
| 21 | int val = 255 - at(x, y) * 10; | 24 | static_cast<int>(at(x, y, layer) * TILE_SIZE.h()), |
| 22 | 25 | TILE_SIZE.w(), | |
| 23 | SDL_SetRenderDrawColor(ren, val, val, val, 255); | 26 | TILE_SIZE.h() |
| 24 | 27 | }; | |
| 25 | SDL_Rect rect { | 28 | |
| 26 | static_cast<int>(x * TILE_SIZE.w()), | 29 | SDL_Rect dest { |
| 27 | static_cast<int>(y * TILE_SIZE.h()), | 30 | static_cast<int>(x * TILE_SIZE.w()), |
| 28 | TILE_SIZE.w(), | 31 | static_cast<int>(y * TILE_SIZE.h()), |
| 29 | TILE_SIZE.h() | 32 | TILE_SIZE.w(), |
| 30 | }; | 33 | TILE_SIZE.h() |
| 31 | 34 | }; | |
| 32 | SDL_RenderFillRect(ren, &rect); | 35 | |
| 33 | } | 36 | SDL_RenderCopy( |
| 37 | ren, | ||
| 38 | getTileset(layer).getImage().get(), | ||
| 39 | &src, | ||
| 40 | &dest); | ||
| 34 | } | 41 | } |
| 35 | } | 42 | } |
| 36 | 43 | ||
| diff --git a/src/level.h b/src/level.h index bc05837..9b01f64 100644 --- a/src/level.h +++ b/src/level.h | |||
| @@ -6,15 +6,22 @@ | |||
| 6 | #include "vector.h" | 6 | #include "vector.h" |
| 7 | #include "consts.h" | 7 | #include "consts.h" |
| 8 | #include "tileset.h" | 8 | #include "tileset.h" |
| 9 | #include "enums.h" | ||
| 9 | 10 | ||
| 10 | class Level { | 11 | class Level { |
| 11 | public: | 12 | public: |
| 12 | 13 | ||
| 13 | Level() | 14 | Level( |
| 15 | SDL_Renderer* ren) : | ||
| 16 | mapTileset_(ren, "map.png"), | ||
| 17 | trackTileset_(ren, "track.png"), | ||
| 18 | objectTileset_(ren, "object.png") | ||
| 14 | { | 19 | { |
| 15 | size_ = LEVEL_SIZE; | 20 | size_ = MAP_SIZE; |
| 16 | 21 | ||
| 17 | tiles_.resize(size_.w() * size_.h()); | 22 | mapTiles_.resize(size_.w() * size_.h()); |
| 23 | trackTiles_.resize(size_.w() * size_.h()); | ||
| 24 | objectTiles_.resize(size_.w() * size_.h()); | ||
| 18 | } | 25 | } |
| 19 | 26 | ||
| 20 | const vec2s& getSize() const | 27 | const vec2s& getSize() const |
| @@ -22,19 +29,48 @@ public: | |||
| 22 | return size_; | 29 | return size_; |
| 23 | } | 30 | } |
| 24 | 31 | ||
| 25 | size_t at(vec2s pos) const | 32 | size_t at(vec2s pos, Layer layer = Layer::map) const |
| 26 | { | 33 | { |
| 27 | return at(pos.x(), pos.y()); | 34 | return at(pos.x(), pos.y(), layer); |
| 28 | } | 35 | } |
| 29 | 36 | ||
| 30 | size_t at(size_t x, size_t y) const | 37 | size_t& at(vec2s pos, Layer layer = Layer::map) |
| 31 | { | 38 | { |
| 32 | return tiles_.at(x + size_.w() * y); | 39 | return at(pos.x(), pos.y(), layer); |
| 33 | } | 40 | } |
| 34 | 41 | ||
| 35 | const Tileset& getTileset() const | 42 | size_t at(size_t x, size_t y, Layer layer = Layer::map) const |
| 36 | { | 43 | { |
| 37 | return tileset_; | 44 | size_t index = x + size_.w() * y; |
| 45 | |||
| 46 | switch (layer) | ||
| 47 | { | ||
| 48 | case Layer::map: return mapTiles_.at(index); | ||
| 49 | case Layer::track: return trackTiles_.at(index); | ||
| 50 | case Layer::object: return objectTiles_.at(index); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | size_t& at(size_t x, size_t y, Layer layer = Layer::map) | ||
| 55 | { | ||
| 56 | size_t index = x + size_.w() * y; | ||
| 57 | |||
| 58 | switch (layer) | ||
| 59 | { | ||
| 60 | case Layer::map: return mapTiles_.at(index); | ||
| 61 | case Layer::track: return trackTiles_.at(index); | ||
| 62 | case Layer::object: return objectTiles_.at(index); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | const Tileset& getTileset(Layer layer) const | ||
| 67 | { | ||
| 68 | switch (layer) | ||
| 69 | { | ||
| 70 | case Layer::map: return mapTileset_; | ||
| 71 | case Layer::track: return trackTileset_; | ||
| 72 | case Layer::object: return objectTileset_; | ||
| 73 | } | ||
| 38 | } | 74 | } |
| 39 | 75 | ||
| 40 | texture_ptr render(SDL_Renderer* ren, Layer layer) const; | 76 | texture_ptr render(SDL_Renderer* ren, Layer layer) const; |
| @@ -42,8 +78,14 @@ public: | |||
| 42 | private: | 78 | private: |
| 43 | 79 | ||
| 44 | vec2s size_; | 80 | vec2s size_; |
| 45 | std::vector<size_t> tiles_; | 81 | |
| 46 | Tileset tileset_; | 82 | std::vector<size_t> mapTiles_; |
| 83 | std::vector<size_t> trackTiles_; | ||
| 84 | std::vector<size_t> objectTiles_; | ||
| 85 | |||
| 86 | Tileset mapTileset_; | ||
| 87 | Tileset trackTileset_; | ||
| 88 | Tileset objectTileset_; | ||
| 47 | }; | 89 | }; |
| 48 | 90 | ||
| 49 | #endif /* end of include guard: LEVEL_H_678CFCCF */ | 91 | #endif /* end of include guard: LEVEL_H_678CFCCF */ |
| diff --git a/src/main.cpp b/src/main.cpp index cbac5bb..cd8ee3e 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -39,13 +39,13 @@ int main(int argc, char** argv) | |||
| 39 | throw sdl_error(); | 39 | throw sdl_error(); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | Level level; | 42 | Level level(ren.get()); |
| 43 | 43 | ||
| 44 | std::unique_ptr<State> state; | 44 | std::unique_ptr<State> state; |
| 45 | 45 | ||
| 46 | if (argc == 2 && !strcmp(argv[1], "--editor")) | 46 | if (argc == 2 && !strcmp(argv[1], "--editor")) |
| 47 | { | 47 | { |
| 48 | state.reset(new Editor()); | 48 | state.reset(new Editor(ren.get())); |
| 49 | } else { | 49 | } else { |
| 50 | state.reset(new Simulation(level)); | 50 | state.reset(new Simulation(level)); |
| 51 | } | 51 | } |
| @@ -63,20 +63,12 @@ int main(int argc, char** argv) | |||
| 63 | 63 | ||
| 64 | while (SDL_PollEvent(&e)) | 64 | while (SDL_PollEvent(&e)) |
| 65 | { | 65 | { |
| 66 | if (e.type == SDL_QUIT) | 66 | if (e.type == SDL_QUIT || |
| 67 | (e.type == SDL_KEYDOWN && | ||
| 68 | e.key.keysym.sym == SDLK_ESCAPE)) | ||
| 67 | { | 69 | { |
| 68 | quit = true; | 70 | quit = true; |
| 69 | } else if (e.type == SDL_KEYDOWN) | 71 | break; |
| 70 | { | ||
| 71 | switch (e.key.keysym.sym) | ||
| 72 | { | ||
| 73 | case SDLK_ESCAPE: | ||
| 74 | { | ||
| 75 | quit = true; | ||
| 76 | |||
| 77 | break; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | 72 | } |
| 81 | } | 73 | } |
| 82 | 74 | ||
| diff --git a/src/simulation.cpp b/src/simulation.cpp index 4d8ec02..62026a6 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp | |||
| @@ -342,7 +342,7 @@ bool Simulation::moveEntityOnGrid( | |||
| 342 | } | 342 | } |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | if (!level_.getTileset().canEntityMoveTo( | 345 | if (!level_.getTileset(Layer::map).canEntityMoveTo( |
| 346 | entity.colliderType, | 346 | entity.colliderType, |
| 347 | level_.at(shouldMoveTo))) | 347 | level_.at(shouldMoveTo))) |
| 348 | { | 348 | { |
| diff --git a/src/tileset.h b/src/tileset.h index 8a565bc..745ea1d 100644 --- a/src/tileset.h +++ b/src/tileset.h | |||
| @@ -1,15 +1,53 @@ | |||
| 1 | #ifndef TILESET_H_B89AE7A1 | 1 | #ifndef TILESET_H_B89AE7A1 |
| 2 | #define TILESET_H_B89AE7A1 | 2 | #define TILESET_H_B89AE7A1 |
| 3 | 3 | ||
| 4 | #include <string> | ||
| 5 | #include "renderer.h" | ||
| 4 | #include "enums.h" | 6 | #include "enums.h" |
| 7 | #include "consts.h" | ||
| 5 | 8 | ||
| 6 | class Tileset { | 9 | class Tileset { |
| 7 | public: | 10 | public: |
| 8 | 11 | ||
| 12 | Tileset(SDL_Renderer* ren, std::string filename) | ||
| 13 | { | ||
| 14 | surface_ptr surf(IMG_Load(("../res/" + filename).c_str())); | ||
| 15 | |||
| 16 | if (!surf) | ||
| 17 | { | ||
| 18 | throw img_error(); | ||
| 19 | } | ||
| 20 | |||
| 21 | image_.reset(SDL_CreateTextureFromSurface(ren, surf.get())); | ||
| 22 | size_ = { surf->w, surf->h }; | ||
| 23 | numTiles_ = size_.h() / TILE_SIZE.h(); | ||
| 24 | } | ||
| 25 | |||
| 9 | bool canEntityMoveTo(ColliderType collider, size_t tile) const | 26 | bool canEntityMoveTo(ColliderType collider, size_t tile) const |
| 10 | { | 27 | { |
| 11 | return true; | 28 | return true; |
| 12 | } | 29 | } |
| 30 | |||
| 31 | const texture_ptr& getImage() const | ||
| 32 | { | ||
| 33 | return image_; | ||
| 34 | } | ||
| 35 | |||
| 36 | const vec2i& getSize() const | ||
| 37 | { | ||
| 38 | return size_; | ||
| 39 | } | ||
| 40 | |||
| 41 | size_t getNumTiles() const | ||
| 42 | { | ||
| 43 | return numTiles_; | ||
| 44 | } | ||
| 45 | |||
| 46 | private: | ||
| 47 | |||
| 48 | texture_ptr image_; | ||
| 49 | vec2i size_; | ||
| 50 | size_t numTiles_; | ||
| 13 | }; | 51 | }; |
| 14 | 52 | ||
| 15 | #endif /* end of include guard: TILESET_H_B89AE7A1 */ | 53 | #endif /* end of include guard: TILESET_H_B89AE7A1 */ |
