diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2019-03-10 12:07:40 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2019-03-10 12:07:40 -0400 |
commit | 57fe8f3c4124819b95164547333a33f4c45eac8d (patch) | |
tree | 99dd89a0c1cf0a8ceaa2ff941549d631950efd11 /src/editor.cpp | |
parent | bf34f891c5c09e6c8a42797085860fa80ab53814 (diff) | |
download | dispatcher-57fe8f3c4124819b95164547333a33f4c45eac8d.tar.gz dispatcher-57fe8f3c4124819b95164547333a33f4c45eac8d.tar.bz2 dispatcher-57fe8f3c4124819b95164547333a33f4c45eac8d.zip |
Editor now allows tile placement
You can scroll through the three layers (map, track, object) with Z/X. You can swap between focusing on the map and the tileset with TAB. You can place tiles with enter or space. Pretty rudimentary, but it's a start.
Diffstat (limited to 'src/editor.cpp')
-rw-r--r-- | src/editor.cpp | 246 |
1 files changed, 235 insertions, 11 deletions
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 | } |