diff options
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 191 |
1 files changed, 171 insertions, 20 deletions
diff --git a/src/main.cpp b/src/main.cpp index 2840439..c02fdd5 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <SDL.h> | 1 | #include <SDL.h> |
2 | #include <SDL_image.h> | ||
2 | #include <stdexcept> | 3 | #include <stdexcept> |
3 | #include <memory> | 4 | #include <memory> |
4 | #include <vector> | 5 | #include <vector> |
@@ -15,6 +16,14 @@ public: | |||
15 | } | 16 | } |
16 | }; | 17 | }; |
17 | 18 | ||
19 | class img_error : public std::logic_error { | ||
20 | public: | ||
21 | |||
22 | img_error() : std::logic_error(IMG_GetError()) | ||
23 | { | ||
24 | } | ||
25 | }; | ||
26 | |||
18 | class window_deleter { | 27 | class window_deleter { |
19 | public: | 28 | public: |
20 | 29 | ||
@@ -37,6 +46,28 @@ public: | |||
37 | 46 | ||
38 | using renderer_ptr = std::unique_ptr<SDL_Renderer, renderer_deleter>; | 47 | using renderer_ptr = std::unique_ptr<SDL_Renderer, renderer_deleter>; |
39 | 48 | ||
49 | class surface_deleter { | ||
50 | public: | ||
51 | |||
52 | void operator()(SDL_Surface* ptr) | ||
53 | { | ||
54 | SDL_FreeSurface(ptr); | ||
55 | } | ||
56 | }; | ||
57 | |||
58 | using surface_ptr = std::unique_ptr<SDL_Surface, surface_deleter>; | ||
59 | |||
60 | class texture_deleter { | ||
61 | public: | ||
62 | |||
63 | void operator()(SDL_Texture* ptr) | ||
64 | { | ||
65 | SDL_DestroyTexture(ptr); | ||
66 | } | ||
67 | }; | ||
68 | |||
69 | using texture_ptr = std::unique_ptr<SDL_Texture, texture_deleter>; | ||
70 | |||
40 | enum class Tile { | 71 | enum class Tile { |
41 | Floor, | 72 | Floor, |
42 | Wall, | 73 | Wall, |
@@ -44,6 +75,13 @@ enum class Tile { | |||
44 | Lamp | 75 | Lamp |
45 | }; | 76 | }; |
46 | 77 | ||
78 | enum class Source { | ||
79 | None, | ||
80 | Dust, | ||
81 | Lamp, | ||
82 | Player | ||
83 | }; | ||
84 | |||
47 | const int GAME_WIDTH = 640*2; | 85 | const int GAME_WIDTH = 640*2; |
48 | const int GAME_HEIGHT = 480*2; | 86 | const int GAME_HEIGHT = 480*2; |
49 | const int TILE_WIDTH = 8*2; | 87 | const int TILE_WIDTH = 8*2; |
@@ -65,7 +103,8 @@ public: | |||
65 | Map() : | 103 | Map() : |
66 | tiles(VIEW_WIDTH*VIEW_HEIGHT, Tile::Floor), | 104 | tiles(VIEW_WIDTH*VIEW_HEIGHT, Tile::Floor), |
67 | lighting(VIEW_WIDTH*VIEW_HEIGHT, false), | 105 | lighting(VIEW_WIDTH*VIEW_HEIGHT, false), |
68 | lightStrength(VIEW_WIDTH*VIEW_HEIGHT, 0.0) | 106 | lightStrength(VIEW_WIDTH*VIEW_HEIGHT, 0.0), |
107 | lightSource(VIEW_WIDTH*VIEW_HEIGHT, Source::None) | ||
69 | { | 108 | { |
70 | } | 109 | } |
71 | 110 | ||
@@ -73,6 +112,7 @@ public: | |||
73 | std::vector<bool> lighting; | 112 | std::vector<bool> lighting; |
74 | std::vector<bool> oldLighting; | 113 | std::vector<bool> oldLighting; |
75 | std::vector<double> lightStrength; | 114 | std::vector<double> lightStrength; |
115 | std::vector<Source> lightSource; | ||
76 | int lightedSpots = 0; | 116 | int lightedSpots = 0; |
77 | }; | 117 | }; |
78 | 118 | ||
@@ -84,7 +124,53 @@ void render( | |||
84 | const Map& map, | 124 | const Map& map, |
85 | bool drawDark = true) | 125 | bool drawDark = true) |
86 | { | 126 | { |
87 | SDL_SetRenderDrawColor(ren, rand() % 255, rand() % 255, rand() % 255, 255); | 127 | texture_ptr playerFade; |
128 | { | ||
129 | surface_ptr pfs(IMG_Load("../res/lighting.png")); | ||
130 | if (!pfs) | ||
131 | { | ||
132 | throw img_error(); | ||
133 | } | ||
134 | |||
135 | playerFade = texture_ptr(SDL_CreateTextureFromSurface(ren, pfs.get())); | ||
136 | } | ||
137 | |||
138 | texture_ptr lampFade( | ||
139 | SDL_CreateTexture( | ||
140 | ren, | ||
141 | SDL_PIXELFORMAT_RGBA4444, | ||
142 | SDL_TEXTUREACCESS_TARGET, | ||
143 | 144, | ||
144 | 144)); | ||
145 | |||
146 | { | ||
147 | SDL_SetRenderTarget(ren, lampFade.get()); | ||
148 | |||
149 | SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_NONE); | ||
150 | SDL_SetRenderDrawColor(ren, 255, 255, 255, 0); | ||
151 | SDL_RenderFillRect(ren, nullptr); | ||
152 | |||
153 | SDL_RenderCopy(ren, playerFade.get(), nullptr, nullptr); | ||
154 | |||
155 | SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_MOD); | ||
156 | SDL_SetRenderDrawColor(ren, 255, 180, 0, 255); | ||
157 | SDL_RenderFillRect(ren, nullptr); | ||
158 | |||
159 | SDL_SetRenderTarget(ren, nullptr); | ||
160 | } | ||
161 | |||
162 | int darkR = 40; | ||
163 | int darkG = 40; | ||
164 | int darkB = 40; | ||
165 | |||
166 | if (!drawDark) | ||
167 | { | ||
168 | darkR = rand() % 255; | ||
169 | darkG = rand() % 255; | ||
170 | darkB = rand() % 255; | ||
171 | } | ||
172 | |||
173 | SDL_SetRenderDrawColor(ren, darkR, darkG, darkB, 255); | ||
88 | SDL_RenderClear(ren); | 174 | SDL_RenderClear(ren); |
89 | 175 | ||
90 | for (int y = 0; y < VIEW_HEIGHT; y++) | 176 | for (int y = 0; y < VIEW_HEIGHT; y++) |
@@ -98,36 +184,40 @@ void render( | |||
98 | SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); | 184 | SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); |
99 | } else if (!map.lighting.at(x+VIEW_WIDTH*y)) | 185 | } else if (!map.lighting.at(x+VIEW_WIDTH*y)) |
100 | { | 186 | { |
101 | if (drawDark) | 187 | /*if (drawDark) |
102 | { | 188 | { |
103 | SDL_SetRenderDrawColor(ren, 40, 40, 40, 255); | 189 | SDL_SetRenderDrawColor(ren, 40, 40, 40, 255); |
104 | } else { | 190 | } else { |
105 | draw = false; | 191 | draw = false; |
106 | } | 192 | }*/ |
193 | draw = false; | ||
107 | } else { | 194 | } else { |
195 | int alpha = map.lightStrength.at(x+y*VIEW_WIDTH) * 255; | ||
196 | alpha = 255; | ||
197 | |||
108 | switch (map.tiles.at(x+y*VIEW_WIDTH)) | 198 | switch (map.tiles.at(x+y*VIEW_WIDTH)) |
109 | { | 199 | { |
110 | case Tile::Floor: | 200 | case Tile::Floor: |
111 | { | 201 | { |
112 | SDL_SetRenderDrawColor(ren, 210, 210, 210, 255); | 202 | SDL_SetRenderDrawColor(ren, 210, 210, 210, alpha); |
113 | break; | 203 | break; |
114 | } | 204 | } |
115 | 205 | ||
116 | case Tile::Wall: | 206 | case Tile::Wall: |
117 | { | 207 | { |
118 | SDL_SetRenderDrawColor(ren, 100, 100, 100, 255); | 208 | SDL_SetRenderDrawColor(ren, 100, 100, 100, alpha); |
119 | break; | 209 | break; |
120 | } | 210 | } |
121 | 211 | ||
122 | case Tile::Dust: | 212 | case Tile::Dust: |
123 | { | 213 | { |
124 | SDL_SetRenderDrawColor(ren, 128, 40, 255, 255); | 214 | SDL_SetRenderDrawColor(ren, 128, 40, 255, alpha); |
125 | break; | 215 | break; |
126 | } | 216 | } |
127 | 217 | ||
128 | case Tile::Lamp: | 218 | case Tile::Lamp: |
129 | { | 219 | { |
130 | SDL_SetRenderDrawColor(ren, 0, 255, 255, 255); | 220 | SDL_SetRenderDrawColor(ren, 0, 255, 255, alpha); |
131 | break; | 221 | break; |
132 | } | 222 | } |
133 | } | 223 | } |
@@ -136,10 +226,53 @@ void render( | |||
136 | if (draw) | 226 | if (draw) |
137 | { | 227 | { |
138 | SDL_Rect rect{x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT}; | 228 | SDL_Rect rect{x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT}; |
229 | |||
230 | SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); | ||
139 | SDL_RenderFillRect(ren, &rect); | 231 | SDL_RenderFillRect(ren, &rect); |
140 | 232 | ||
141 | int alpha = (1.0 - map.lightStrength.at(x+y*VIEW_WIDTH)) * 255; | 233 | |
142 | SDL_SetRenderDrawColor(ren, 40, 40, 40, alpha); | 234 | } |
235 | } | ||
236 | } | ||
237 | |||
238 | for (int y = 0; y < VIEW_HEIGHT; y++) | ||
239 | { | ||
240 | for (int x = 0; x < VIEW_WIDTH; x++) | ||
241 | { | ||
242 | if (map.lightSource.at(x+VIEW_WIDTH*y) != Source::None) | ||
243 | { | ||
244 | SDL_Rect fadeRect{x*TILE_WIDTH + (TILE_WIDTH/2) - (144/2), y*TILE_HEIGHT + (TILE_HEIGHT/2) - (144/2), 144, 144}; | ||
245 | if (map.lightSource.at(x+VIEW_WIDTH*y) == Source::Lamp) | ||
246 | { | ||
247 | //SDL_SetTextureBlendMode(lampFade.get(), SDL_BLENDMODE_MOD); | ||
248 | SDL_RenderCopy(ren, lampFade.get(), nullptr, &fadeRect); | ||
249 | //SDL_SetRenderDrawColor(ren, 255, 180, 0, 50); | ||
250 | //SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); | ||
251 | //SDL_RenderFillRect(ren, &rect); | ||
252 | } else if (map.lightSource.at(x+VIEW_WIDTH*y) == Source::Player) | ||
253 | { | ||
254 | //SDL_SetTextureBlendMode(playerFade.get(), SDL_BLENDMODE_MOD); | ||
255 | SDL_RenderCopy(ren, playerFade.get(), nullptr, &fadeRect); | ||
256 | } | ||
257 | |||
258 | /*SDL_SetRenderDrawColor(ren, 40, 40, 40, alpha); | ||
259 | SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); | ||
260 | SDL_RenderFillRect(ren, &rect);*/ | ||
261 | } | ||
262 | } | ||
263 | } | ||
264 | |||
265 | SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_NONE); | ||
266 | SDL_SetRenderDrawColor(ren, darkR, darkG, darkB, 255); | ||
267 | |||
268 | for (int y = 0; y < VIEW_HEIGHT; y++) | ||
269 | { | ||
270 | for (int x = 0; x < VIEW_WIDTH; x++) | ||
271 | { | ||
272 | if (!map.lighting.at(x+VIEW_WIDTH*y)) | ||
273 | { | ||
274 | SDL_Rect rect{x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT}; | ||
275 | |||
143 | SDL_RenderFillRect(ren, &rect); | 276 | SDL_RenderFillRect(ren, &rect); |
144 | } | 277 | } |
145 | } | 278 | } |
@@ -227,6 +360,7 @@ void recalculateLighting(Map& map, fov_settings_type* fov) | |||
227 | map.lighting = std::vector<bool>(VIEW_WIDTH*VIEW_HEIGHT, false); | 360 | map.lighting = std::vector<bool>(VIEW_WIDTH*VIEW_HEIGHT, false); |
228 | map.lightStrength = std::vector<double>(VIEW_WIDTH*VIEW_HEIGHT, 0.0); | 361 | map.lightStrength = std::vector<double>(VIEW_WIDTH*VIEW_HEIGHT, 0.0); |
229 | map.lightedSpots = 0; | 362 | map.lightedSpots = 0; |
363 | map.lightSource = std::vector<Source>(VIEW_WIDTH*VIEW_HEIGHT, Source::None); | ||
230 | 364 | ||
231 | fov_settings_set_opacity_test_function( | 365 | fov_settings_set_opacity_test_function( |
232 | fov, | 366 | fov, |
@@ -241,7 +375,7 @@ void recalculateLighting(Map& map, fov_settings_type* fov) | |||
241 | 375 | ||
242 | fov_settings_set_apply_lighting_function( | 376 | fov_settings_set_apply_lighting_function( |
243 | fov, | 377 | fov, |
244 | [] (void* map, int x, int y, int dx, int dy, void*) { | 378 | [] (void* map, int x, int y, int dx, int dy, void* source) { |
245 | if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT)) | 379 | if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT)) |
246 | { | 380 | { |
247 | Map& m = *static_cast<Map*>(map); | 381 | Map& m = *static_cast<Map*>(map); |
@@ -259,6 +393,12 @@ void recalculateLighting(Map& map, fov_settings_type* fov) | |||
259 | 0.0, | 393 | 0.0, |
260 | 1.0 - std::sqrt(dx * dx + dy * dy) / static_cast<double>(RADIUS)), | 394 | 1.0 - std::sqrt(dx * dx + dy * dy) / static_cast<double>(RADIUS)), |
261 | 1.0/3.0)); | 395 | 1.0/3.0)); |
396 | |||
397 | Source ls = *static_cast<Source*>(source); | ||
398 | if (static_cast<size_t>(ls) > static_cast<size_t>(m.lightSource[x+VIEW_WIDTH*y])) | ||
399 | { | ||
400 | //m.lightSource[x+VIEW_WIDTH*y] = ls; | ||
401 | } | ||
262 | } | 402 | } |
263 | }); | 403 | }); |
264 | 404 | ||
@@ -266,22 +406,29 @@ void recalculateLighting(Map& map, fov_settings_type* fov) | |||
266 | { | 406 | { |
267 | for (int x = 0; x < VIEW_WIDTH; x++) | 407 | for (int x = 0; x < VIEW_WIDTH; x++) |
268 | { | 408 | { |
269 | if ((player_x == x && player_y == y) || map.tiles[x+VIEW_WIDTH*y] == Tile::Dust || map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | 409 | Source ls = Source::None; |
410 | |||
411 | if (player_x == x && player_y == y) | ||
412 | { | ||
413 | ls = Source::Player; | ||
414 | } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Dust) | ||
270 | { | 415 | { |
271 | fov_circle(fov, static_cast<void*>(&map), nullptr, x, y, RADIUS); | 416 | ls = Source::Dust; |
417 | } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) | ||
418 | { | ||
419 | ls = Source::Lamp; | ||
272 | } | 420 | } |
273 | 421 | ||
274 | if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp || | 422 | if (ls != Source::None) |
275 | map.tiles[x+VIEW_WIDTH*y] == Tile::Dust) | ||
276 | { | 423 | { |
424 | fov_circle(fov, static_cast<void*>(&map), static_cast<void*>(&ls), x, y, RADIUS); | ||
425 | |||
277 | map.lighting[x+VIEW_WIDTH*y] = true; | 426 | map.lighting[x+VIEW_WIDTH*y] = true; |
278 | map.lightStrength[x+VIEW_WIDTH*y] = 1.0; | 427 | map.lightStrength[x+VIEW_WIDTH*y] = 1.0; |
428 | map.lightSource[x+VIEW_WIDTH*y] = ls; | ||
279 | } | 429 | } |
280 | } | 430 | } |
281 | } | 431 | } |
282 | |||
283 | map.lighting[player_x+VIEW_WIDTH*player_y] = true; | ||
284 | map.lightStrength[player_x+VIEW_WIDTH*player_y] = 1.0; | ||
285 | } | 432 | } |
286 | 433 | ||
287 | void processKeys(Map& map, const Input& keystate) | 434 | void processKeys(Map& map, const Input& keystate) |
@@ -325,6 +472,11 @@ int main(int, char**) | |||
325 | throw sdl_error(); | 472 | throw sdl_error(); |
326 | } | 473 | } |
327 | 474 | ||
475 | if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) | ||
476 | { | ||
477 | throw img_error(); | ||
478 | } | ||
479 | |||
328 | try | 480 | try |
329 | { | 481 | { |
330 | window_ptr win( | 482 | window_ptr win( |
@@ -346,8 +498,6 @@ int main(int, char**) | |||
346 | throw sdl_error(); | 498 | throw sdl_error(); |
347 | } | 499 | } |
348 | 500 | ||
349 | SDL_SetRenderDrawBlendMode(ren.get(), SDL_BLENDMODE_BLEND); | ||
350 | |||
351 | Map map; | 501 | Map map; |
352 | 502 | ||
353 | std::unique_ptr<fov_settings_type> fov(new fov_settings_type()); | 503 | std::unique_ptr<fov_settings_type> fov(new fov_settings_type()); |
@@ -527,6 +677,7 @@ int main(int, char**) | |||
527 | std::cout << "SDL error (" << ex.what() << ")" << std::endl; | 677 | std::cout << "SDL error (" << ex.what() << ")" << std::endl; |
528 | } | 678 | } |
529 | 679 | ||
680 | IMG_Quit(); | ||
530 | SDL_Quit(); | 681 | SDL_Quit(); |
531 | 682 | ||
532 | return 0; | 683 | return 0; |