diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.cpp | 269 |
1 files changed, 243 insertions, 26 deletions
| diff --git a/src/main.cpp b/src/main.cpp index 2daf153..dacc646 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> |
| @@ -19,6 +20,14 @@ public: | |||
| 19 | } | 20 | } |
| 20 | }; | 21 | }; |
| 21 | 22 | ||
| 23 | class img_error : public std::logic_error { | ||
| 24 | public: | ||
| 25 | |||
| 26 | img_error() : std::logic_error(IMG_GetError()) | ||
| 27 | { | ||
| 28 | } | ||
| 29 | }; | ||
| 30 | |||
| 22 | class window_deleter { | 31 | class window_deleter { |
| 23 | public: | 32 | public: |
| 24 | 33 | ||
| @@ -41,6 +50,17 @@ public: | |||
| 41 | 50 | ||
| 42 | using renderer_ptr = std::unique_ptr<SDL_Renderer, renderer_deleter>; | 51 | using renderer_ptr = std::unique_ptr<SDL_Renderer, renderer_deleter>; |
| 43 | 52 | ||
| 53 | class surface_deleter { | ||
| 54 | public: | ||
| 55 | |||
| 56 | void operator()(SDL_Surface* ptr) | ||
| 57 | { | ||
| 58 | SDL_FreeSurface(ptr); | ||
| 59 | } | ||
| 60 | }; | ||
| 61 | |||
| 62 | using surface_ptr = std::unique_ptr<SDL_Surface, surface_deleter>; | ||
| 63 | |||
| 44 | class texture_deleter { | 64 | class texture_deleter { |
| 45 | public: | 65 | public: |
| 46 | 66 | ||
| @@ -59,6 +79,13 @@ enum class Tile { | |||
| 59 | Lamp | 79 | Lamp |
| 60 | }; | 80 | }; |
| 61 | 81 | ||
| 82 | enum class Source { | ||
| 83 | None, | ||
| 84 | Dust, | ||
| 85 | Lamp, | ||
| 86 | Player | ||
| 87 | }; | ||
| 88 | |||
| 62 | enum class LoseState { | 89 | enum class LoseState { |
| 63 | None, | 90 | None, |
| 64 | PoppingLamps, | 91 | PoppingLamps, |
| @@ -100,6 +127,9 @@ struct MapData { | |||
| 100 | bool wasLit = false; | 127 | bool wasLit = false; |
| 101 | double visibility = 0.0; | 128 | double visibility = 0.0; |
| 102 | size_t dustLife = 0; | 129 | size_t dustLife = 0; |
| 130 | Source lightType = Source::None; | ||
| 131 | int lightRadius = 0; | ||
| 132 | std::set<coord> litTiles; | ||
| 103 | }; | 133 | }; |
| 104 | 134 | ||
| 105 | class Game { | 135 | class Game { |
| @@ -142,6 +172,83 @@ void render( | |||
| 142 | const Game& game, | 172 | const Game& game, |
| 143 | bool drawDark = true) | 173 | bool drawDark = true) |
| 144 | { | 174 | { |
| 175 | texture_ptr origFade; | ||
| 176 | { | ||
| 177 | surface_ptr pfs(IMG_Load("../res/lighting.png")); | ||
| 178 | if (!pfs) | ||
| 179 | { | ||
| 180 | throw img_error(); | ||
| 181 | } | ||
| 182 | |||
| 183 | origFade = texture_ptr(SDL_CreateTextureFromSurface(ren, pfs.get())); | ||
| 184 | } | ||
| 185 | |||
| 186 | SDL_SetTextureBlendMode(origFade.get(), SDL_BLENDMODE_BLEND); | ||
| 187 | |||
| 188 | texture_ptr playerFade( | ||
| 189 | SDL_CreateTexture( | ||
| 190 | ren, | ||
| 191 | SDL_PIXELFORMAT_RGBA4444, | ||
| 192 | SDL_TEXTUREACCESS_TARGET, | ||
| 193 | 144, | ||
| 194 | 144)); | ||
| 195 | |||
| 196 | if (!playerFade) | ||
| 197 | { | ||
| 198 | throw sdl_error(); | ||
| 199 | } | ||
| 200 | |||
| 201 | SDL_SetRenderTarget(ren, playerFade.get()); | ||
| 202 | SDL_SetRenderDrawColor(ren, 0, 0, 0, 255); | ||
| 203 | SDL_RenderClear(ren); | ||
| 204 | SDL_RenderCopy(ren, origFade.get(), nullptr, nullptr); | ||
| 205 | |||
| 206 | texture_ptr lampFade( | ||
| 207 | SDL_CreateTexture( | ||
| 208 | ren, | ||
| 209 | SDL_PIXELFORMAT_RGBA4444, | ||
| 210 | SDL_TEXTUREACCESS_TARGET, | ||
| 211 | 144, | ||
| 212 | 144)); | ||
| 213 | |||
| 214 | if (!lampFade) | ||
| 215 | { | ||
| 216 | throw sdl_error(); | ||
| 217 | } | ||
| 218 | |||
| 219 | SDL_SetRenderTarget(ren, lampFade.get()); | ||
| 220 | |||
| 221 | SDL_SetRenderDrawColor(ren, 0, 0, 0, 255); | ||
| 222 | SDL_RenderClear(ren); | ||
| 223 | SDL_RenderCopy(ren, origFade.get(), nullptr, nullptr); | ||
| 224 | |||
| 225 | SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_MOD); | ||
| 226 | SDL_SetRenderDrawColor(ren, 255, 204, 58, 255); | ||
| 227 | SDL_RenderFillRect(ren, nullptr); | ||
| 228 | |||
| 229 | texture_ptr dustFade( | ||
| 230 | SDL_CreateTexture( | ||
| 231 | ren, | ||
| 232 | SDL_PIXELFORMAT_RGBA4444, | ||
| 233 | SDL_TEXTUREACCESS_TARGET, | ||
| 234 | 144, | ||
| 235 | 144)); | ||
| 236 | |||
| 237 | if (!dustFade) | ||
| 238 | { | ||
| 239 | throw sdl_error(); | ||
| 240 | } | ||
| 241 | |||
| 242 | SDL_SetRenderTarget(ren, dustFade.get()); | ||
| 243 | |||
| 244 | SDL_SetRenderDrawColor(ren, 0, 0, 0, 255); | ||
| 245 | SDL_RenderClear(ren); | ||
| 246 | SDL_RenderCopy(ren, origFade.get(), nullptr, nullptr); | ||
| 247 | |||
| 248 | SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_MOD); | ||
| 249 | SDL_SetRenderDrawColor(ren, 255, 150, 255, 255); | ||
| 250 | SDL_RenderFillRect(ren, nullptr); | ||
| 251 | |||
| 145 | texture_ptr canvas( | 252 | texture_ptr canvas( |
| 146 | SDL_CreateTexture( | 253 | SDL_CreateTexture( |
| 147 | ren, | 254 | ren, |
| @@ -156,7 +263,7 @@ void render( | |||
| 156 | } | 263 | } |
| 157 | 264 | ||
| 158 | SDL_SetRenderTarget(ren, canvas.get()); | 265 | SDL_SetRenderTarget(ren, canvas.get()); |
| 159 | 266 | SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_NONE); | |
| 160 | SDL_SetRenderDrawColor(ren, rand() % 255, rand() % 255, rand() % 255, 255); | 267 | SDL_SetRenderDrawColor(ren, rand() % 255, rand() % 255, rand() % 255, 255); |
| 161 | SDL_RenderClear(ren); | 268 | SDL_RenderClear(ren); |
| 162 | 269 | ||
| @@ -169,38 +276,40 @@ void render( | |||
| 169 | if ((game.player_x == x && game.player_y == y) && game.renderPlayer) | 276 | if ((game.player_x == x && game.player_y == y) && game.renderPlayer) |
| 170 | { | 277 | { |
| 171 | SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); | 278 | SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); |
| 172 | } else if (!game.map.at(x,y).lit) | 279 | /*} else if (!game.map.at(x,y).lit) |
| 173 | { | 280 | { |
| 174 | if (drawDark) | 281 | if (drawDark) |
| 175 | { | 282 | { |
| 176 | SDL_SetRenderDrawColor(ren, 40, 40, 40, 255); | 283 | SDL_SetRenderDrawColor(ren, 40, 40, 40, 255); |
| 177 | } else { | 284 | } else { |
| 178 | draw = false; | 285 | draw = false; |
| 179 | } | 286 | }*/ |
| 180 | } else { | 287 | } else { |
| 288 | int alpha = 255; | ||
| 289 | |||
| 181 | switch (game.map.at(x,y).tile) | 290 | switch (game.map.at(x,y).tile) |
| 182 | { | 291 | { |
| 183 | case Tile::Floor: | 292 | case Tile::Floor: |
| 184 | { | 293 | { |
| 185 | SDL_SetRenderDrawColor(ren, 210, 210, 210, 255); | 294 | SDL_SetRenderDrawColor(ren, 210, 210, 210, alpha); |
| 186 | break; | 295 | break; |
| 187 | } | 296 | } |
| 188 | 297 | ||
| 189 | case Tile::Wall: | 298 | case Tile::Wall: |
| 190 | { | 299 | { |
| 191 | SDL_SetRenderDrawColor(ren, 100, 100, 100, 255); | 300 | SDL_SetRenderDrawColor(ren, 100, 100, 100, alpha); |
| 192 | break; | 301 | break; |
| 193 | } | 302 | } |
| 194 | 303 | ||
| 195 | case Tile::Dust: | 304 | case Tile::Dust: |
| 196 | { | 305 | { |
| 197 | SDL_SetRenderDrawColor(ren, 128, 40, 255, 255); | 306 | SDL_SetRenderDrawColor(ren, 128, 40, 255, alpha); |
| 198 | break; | 307 | break; |
| 199 | } | 308 | } |
| 200 | 309 | ||
| 201 | case Tile::Lamp: | 310 | case Tile::Lamp: |
| 202 | { | 311 | { |
| 203 | SDL_SetRenderDrawColor(ren, 0, 255, 255, 255); | 312 | SDL_SetRenderDrawColor(ren, 0, 255, 255, alpha); |
| 204 | break; | 313 | break; |
| 205 | } | 314 | } |
| 206 | } | 315 | } |
| @@ -214,15 +323,97 @@ void render( | |||
| 214 | TILE_WIDTH, | 323 | TILE_WIDTH, |
| 215 | TILE_HEIGHT}; | 324 | TILE_HEIGHT}; |
| 216 | 325 | ||
| 217 | SDL_RenderFillRect(ren, &rect); | 326 | //SDL_RenderFillRect(ren, &rect); |
| 218 | 327 | ||
| 219 | int alpha = (1.0 - game.map.at(x,y).visibility) * 255; | 328 | //int alpha = (1.0 - game.map.at(x,y).visibility) * 255; |
| 220 | SDL_SetRenderDrawColor(ren, 40, 40, 40, alpha); | 329 | //SDL_SetRenderDrawColor(ren, 40, 40, 40, 255); |
| 221 | SDL_RenderFillRect(ren, &rect); | 330 | SDL_RenderFillRect(ren, &rect); |
| 222 | } | 331 | } |
| 223 | } | 332 | } |
| 224 | } | 333 | } |
| 225 | 334 | ||
| 335 | texture_ptr mask( | ||
| 336 | SDL_CreateTexture( | ||
| 337 | ren, | ||
| 338 | SDL_PIXELFORMAT_RGBA8888, | ||
| 339 | SDL_TEXTUREACCESS_TARGET, | ||
| 340 | TILE_WIDTH * game.map.getWidth(), | ||
| 341 | TILE_HEIGHT * game.map.getHeight())); | ||
| 342 | |||
| 343 | if (!mask) | ||
| 344 | { | ||
| 345 | throw sdl_error(); | ||
| 346 | } | ||
| 347 | |||
| 348 | SDL_SetRenderTarget(ren, mask.get()); | ||
| 349 | SDL_SetRenderDrawColor(ren, 0, 0, 0, 255); | ||
| 350 | SDL_RenderClear(ren); | ||
| 351 | |||
| 352 | for (int y = game.map.getTop(); y < game.map.getBottom(); y++) | ||
| 353 | { | ||
| 354 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) | ||
| 355 | { | ||
| 356 | if (game.map.at(x,y).lightType != Source::None) | ||
| 357 | { | ||
| 358 | texture_ptr sourceMask( | ||
| 359 | SDL_CreateTexture( | ||
| 360 | ren, | ||
| 361 | SDL_PIXELFORMAT_RGBA8888, | ||
| 362 | SDL_TEXTUREACCESS_TARGET, | ||
| 363 | TILE_WIDTH * game.map.getWidth(), | ||
| 364 | TILE_HEIGHT * game.map.getHeight())); | ||
| 365 | |||
| 366 | if (!sourceMask) | ||
| 367 | { | ||
| 368 | throw sdl_error(); | ||
| 369 | } | ||
| 370 | |||
| 371 | SDL_SetRenderTarget(ren, sourceMask.get()); | ||
| 372 | SDL_SetRenderDrawColor(ren, 0, 0, 0, 255); | ||
| 373 | SDL_RenderClear(ren); | ||
| 374 | |||
| 375 | SDL_SetRenderDrawColor(ren, 255, 255, 255, 255); | ||
| 376 | |||
| 377 | for (const coord& xy : game.map.at(x,y).litTiles) | ||
| 378 | { | ||
| 379 | SDL_Rect rect { | ||
| 380 | game.map.getTrueX(std::get<0>(xy)) * TILE_WIDTH, | ||
| 381 | game.map.getTrueY(std::get<1>(xy)) * TILE_HEIGHT, | ||
| 382 | TILE_WIDTH, | ||
| 383 | TILE_HEIGHT}; | ||
| 384 | |||
| 385 | SDL_RenderFillRect(ren, &rect); | ||
| 386 | } | ||
| 387 | |||
| 388 | SDL_Rect fadeRect { | ||
| 389 | (game.map.getTrueX(x) - game.map.at(x,y).lightRadius) * TILE_WIDTH, | ||
| 390 | (game.map.getTrueY(y) - game.map.at(x,y).lightRadius) * TILE_HEIGHT, | ||
| 391 | (game.map.at(x,y).lightRadius * 2 + 1) * TILE_WIDTH, | ||
| 392 | (game.map.at(x,y).lightRadius * 2 + 1) * TILE_HEIGHT}; | ||
| 393 | |||
| 394 | if (game.map.at(x,y).lightType == Source::Lamp) | ||
| 395 | { | ||
| 396 | SDL_SetTextureBlendMode(lampFade.get(), SDL_BLENDMODE_MOD); | ||
| 397 | SDL_RenderCopy(ren, lampFade.get(), nullptr, &fadeRect); | ||
| 398 | } else if (game.map.at(x,y).lightType == Source::Player) { | ||
| 399 | SDL_SetTextureBlendMode(playerFade.get(), SDL_BLENDMODE_MOD); | ||
| 400 | SDL_RenderCopy(ren, playerFade.get(), nullptr, &fadeRect); | ||
| 401 | } else if (game.map.at(x,y).lightType == Source::Dust) { | ||
| 402 | SDL_SetTextureBlendMode(dustFade.get(), SDL_BLENDMODE_MOD); | ||
| 403 | SDL_RenderCopy(ren, dustFade.get(), nullptr, &fadeRect); | ||
| 404 | } | ||
| 405 | |||
| 406 | SDL_SetRenderTarget(ren, mask.get()); | ||
| 407 | SDL_SetTextureBlendMode(sourceMask.get(), SDL_BLENDMODE_ADD); | ||
| 408 | SDL_RenderCopy(ren, sourceMask.get(), nullptr, nullptr); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | SDL_SetRenderTarget(ren, canvas.get()); | ||
| 414 | SDL_SetTextureBlendMode(mask.get(), SDL_BLENDMODE_MOD); | ||
| 415 | SDL_RenderCopy(ren, mask.get(), nullptr, nullptr); | ||
| 416 | |||
| 226 | SDL_SetRenderTarget(ren, nullptr); | 417 | SDL_SetRenderTarget(ren, nullptr); |
| 227 | 418 | ||
| 228 | if (!game.zooming) | 419 | if (!game.zooming) |
| @@ -346,6 +537,7 @@ void recalculateLighting(Game& game, fov_settings_type* fov) | |||
| 346 | md.wasLit = md.lit; | 537 | md.wasLit = md.lit; |
| 347 | md.lit = false; | 538 | md.lit = false; |
| 348 | md.visibility = 0.0; | 539 | md.visibility = 0.0; |
| 540 | md.litTiles.clear(); | ||
| 349 | } | 541 | } |
| 350 | 542 | ||
| 351 | fov_settings_set_opacity_test_function( | 543 | fov_settings_set_opacity_test_function( |
| @@ -363,7 +555,8 @@ void recalculateLighting(Game& game, fov_settings_type* fov) | |||
| 363 | 555 | ||
| 364 | if (game.map.inBounds(x, y)) | 556 | if (game.map.inBounds(x, y)) |
| 365 | { | 557 | { |
| 366 | double lightRadius = static_cast<double>(*static_cast<int*>(source)); | 558 | MapData& sourceData = *static_cast<MapData*>(source); |
| 559 | double lightRadius = static_cast<double>(sourceData.lightRadius); | ||
| 367 | 560 | ||
| 368 | if (!game.map.at(x,y).lit) | 561 | if (!game.map.at(x,y).lit) |
| 369 | { | 562 | { |
| @@ -372,13 +565,21 @@ void recalculateLighting(Game& game, fov_settings_type* fov) | |||
| 372 | 565 | ||
| 373 | game.map.at(x,y).lit = true; | 566 | game.map.at(x,y).lit = true; |
| 374 | 567 | ||
| 375 | game.map.at(x,y).visibility = std::max( | 568 | /*game.map.at(x,y).visibility = std::max( |
| 376 | game.map.at(x,y).visibility, | 569 | game.map.at(x,y).visibility, |
| 377 | std::pow( | 570 | std::pow( |
| 378 | std::max( | 571 | std::max( |
| 379 | 0.0, | 572 | 0.0, |
| 380 | 1.0 - std::sqrt(dx * dx + dy * dy) / lightRadius), | 573 | 1.0 - std::sqrt(dx * dx + dy * dy) / lightRadius), |
| 381 | 1.0/3.0)); | 574 | 1.0/3.0));*/ |
| 575 | |||
| 576 | sourceData.litTiles.emplace(x,y); | ||
| 577 | |||
| 578 | //Source ls = *static_cast<Source*>(source); | ||
| 579 | //if (static_cast<size_t>(ls) > static_cast<size_t>(m.lightSource[x+VIEW_WIDTH*y])) | ||
| 580 | { | ||
| 581 | //m.lightSource[x+VIEW_WIDTH*y] = ls; | ||
| 582 | } | ||
| 382 | } | 583 | } |
| 383 | }); | 584 | }); |
| 384 | 585 | ||
| @@ -386,25 +587,35 @@ void recalculateLighting(Game& game, fov_settings_type* fov) | |||
| 386 | { | 587 | { |
| 387 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) | 588 | for (int x = game.map.getLeft(); x < game.map.getRight(); x++) |
| 388 | { | 589 | { |
| 389 | if ((game.player_x == x && game.player_y == y && game.renderPlayer) || | 590 | Source ls = Source::None; |
| 390 | game.map.at(x,y).tile == Tile::Dust || | 591 | int lightRadius; |
| 391 | game.map.at(x,y).tile == Tile::Lamp) | 592 | |
| 593 | if (game.renderPlayer && game.player_x == x && game.player_y == y) | ||
| 594 | { | ||
| 595 | ls = Source::Player; | ||
| 596 | lightRadius = RADIUS; | ||
| 597 | } else if (game.map.at(x,y).tile == Tile::Dust) | ||
| 392 | { | 598 | { |
| 393 | int lightRadius; | 599 | ls = Source::Dust; |
| 600 | lightRadius = 2; | ||
| 601 | } else if (game.map.at(x,y).tile == Tile::Lamp) | ||
| 602 | { | ||
| 603 | ls = Source::Lamp; | ||
| 604 | lightRadius = RADIUS; | ||
| 605 | } | ||
| 394 | 606 | ||
| 395 | if ((game.player_x == x && game.player_y == y && game.renderPlayer) || | 607 | game.map.at(x,y).lightType = ls; |
| 396 | game.map.at(x,y).tile == Tile::Lamp) | 608 | //game.map.at(x,y).litTiles.clear(); |
| 397 | { | 609 | |
| 398 | lightRadius = RADIUS; | 610 | if (ls != Source::None) |
| 399 | } else if (game.map.at(x,y).tile == Tile::Dust) | 611 | { |
| 400 | { | 612 | game.map.at(x,y).lightRadius = lightRadius; |
| 401 | lightRadius = 2; | 613 | game.map.at(x,y).litTiles.emplace(x,y); |
| 402 | } | ||
| 403 | 614 | ||
| 404 | fov_circle( | 615 | fov_circle( |
| 405 | fov, | 616 | fov, |
| 406 | static_cast<void*>(&game), | 617 | static_cast<void*>(&game), |
| 407 | static_cast<void*>(&lightRadius), | 618 | static_cast<void*>(&game.map.at(x,y)), |
| 408 | x, | 619 | x, |
| 409 | y, | 620 | y, |
| 410 | lightRadius); | 621 | lightRadius); |
| @@ -611,6 +822,11 @@ int main(int, char**) | |||
| 611 | throw sdl_error(); | 822 | throw sdl_error(); |
| 612 | } | 823 | } |
| 613 | 824 | ||
| 825 | if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) | ||
| 826 | { | ||
| 827 | throw img_error(); | ||
| 828 | } | ||
| 829 | |||
| 614 | try | 830 | try |
| 615 | { | 831 | { |
| 616 | window_ptr win( | 832 | window_ptr win( |
| @@ -916,6 +1132,7 @@ int main(int, char**) | |||
| 916 | std::cout << "SDL error (" << ex.what() << ")" << std::endl; | 1132 | std::cout << "SDL error (" << ex.what() << ")" << std::endl; |
| 917 | } | 1133 | } |
| 918 | 1134 | ||
| 1135 | IMG_Quit(); | ||
| 919 | SDL_Quit(); | 1136 | SDL_Quit(); |
| 920 | 1137 | ||
| 921 | return 0; | 1138 | return 0; |
