summary refs log tree commit diff stats
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp194
1 files changed, 129 insertions, 65 deletions
diff --git a/src/main.cpp b/src/main.cpp index 2840439..e26a5a8 100644 --- a/src/main.cpp +++ b/src/main.cpp
@@ -2,10 +2,11 @@
2#include <stdexcept> 2#include <stdexcept>
3#include <memory> 3#include <memory>
4#include <vector> 4#include <vector>
5#include <list>
5#include <random> 6#include <random>
6#include <fov.h> 7#include <fov.h>
7#include <deque>
8#include <iostream> 8#include <iostream>
9#include "util.h"
9 10
10class sdl_error : public std::logic_error { 11class sdl_error : public std::logic_error {
11public: 12public:
@@ -59,6 +60,14 @@ struct Input {
59 bool down = false; 60 bool down = false;
60}; 61};
61 62
63struct Kickup {
64 int x;
65 int y;
66 size_t cur;
67 size_t radius;
68 size_t chain;
69};
70
62class Map { 71class Map {
63public: 72public:
64 73
@@ -73,7 +82,9 @@ public:
73 std::vector<bool> lighting; 82 std::vector<bool> lighting;
74 std::vector<bool> oldLighting; 83 std::vector<bool> oldLighting;
75 std::vector<double> lightStrength; 84 std::vector<double> lightStrength;
85 std::list<Kickup> kickups;
76 int lightedSpots = 0; 86 int lightedSpots = 0;
87 bool dirtyLighting = true;
77}; 88};
78 89
79int player_x = VIEW_WIDTH / 2; 90int player_x = VIEW_WIDTH / 2;
@@ -210,6 +221,8 @@ void movePlayer(int x, int y, Map& map)
210 221
211 player_x = x; 222 player_x = x;
212 player_y = y; 223 player_y = y;
224
225 map.dirtyLighting = true;
213 } 226 }
214} 227}
215 228
@@ -266,22 +279,19 @@ void recalculateLighting(Map& map, fov_settings_type* fov)
266 { 279 {
267 for (int x = 0; x < VIEW_WIDTH; x++) 280 for (int x = 0; x < VIEW_WIDTH; x++)
268 { 281 {
269 if ((player_x == x && player_y == y) || map.tiles[x+VIEW_WIDTH*y] == Tile::Dust || map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) 282 if ((player_x == x && player_y == y) ||
283 map.tiles[x+VIEW_WIDTH*y] == Tile::Dust ||
284 map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp)
270 { 285 {
271 fov_circle(fov, static_cast<void*>(&map), nullptr, x, y, RADIUS); 286 fov_circle(fov, static_cast<void*>(&map), nullptr, x, y, RADIUS);
272 }
273 287
274 if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp ||
275 map.tiles[x+VIEW_WIDTH*y] == Tile::Dust)
276 {
277 map.lighting[x+VIEW_WIDTH*y] = true; 288 map.lighting[x+VIEW_WIDTH*y] = true;
278 map.lightStrength[x+VIEW_WIDTH*y] = 1.0; 289 map.lightStrength[x+VIEW_WIDTH*y] = 1.0;
279 } 290 }
280 } 291 }
281 } 292 }
282 293
283 map.lighting[player_x+VIEW_WIDTH*player_y] = true; 294 map.dirtyLighting = false;
284 map.lightStrength[player_x+VIEW_WIDTH*player_y] = 1.0;
285} 295}
286 296
287void processKeys(Map& map, const Input& keystate) 297void processKeys(Map& map, const Input& keystate)
@@ -315,6 +325,81 @@ void processKeys(Map& map, const Input& keystate)
315 } 325 }
316} 326}
317 327
328void kickUpDust(Map& map, int x, int y, size_t chain)
329{
330 std::cout << "kickup " << x << " " << y << " " << chain << std::endl;
331 Kickup dk;
332 dk.x = x;
333 dk.y = y;
334 dk.chain = chain;
335 dk.cur = 0;
336 dk.radius = RADIUS + (chain + 1) * (chain + 1);
337
338 map.kickups.push_back(dk);
339}
340
341void processKickup(Map& map)
342{
343 for (Kickup& kickup : map.kickups)
344 {
345 kickup.cur++;
346
347 if (map.tiles[kickup.x+VIEW_WIDTH*kickup.y] == Tile::Floor)
348 {
349 map.tiles[kickup.x+VIEW_WIDTH*kickup.y] = Tile::Dust;
350 }
351
352 std::unique_ptr<fov_settings_type> dusty(new fov_settings_type);
353 fov_settings_set_opacity_test_function(
354 dusty.get(),
355 [] (void* map, int x, int y) {
356 return
357 x >= 0 &&
358 x < VIEW_WIDTH &&
359 y >= 0 &&
360 y < VIEW_HEIGHT &&
361 static_cast<Map*>(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall;
362 });
363
364 fov_settings_set_apply_lighting_function(
365 dusty.get(),
366 [] (void* data, int x, int y, int, int, void* source) {
367 Map& map = *static_cast<Map*>(data);
368 Kickup& kickup = *static_cast<Kickup*>(source);
369
370 if ((x >= 0) && (x < VIEW_WIDTH) &&
371 (y >= 0) && (y < VIEW_HEIGHT))
372 {
373 if (map.tiles[x+VIEW_WIDTH*y] == Tile::Floor)
374 {
375 map.tiles[x+VIEW_WIDTH*y] = Tile::Dust;
376 map.dirtyLighting = true;
377 } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp)
378 {
379 map.tiles[x+VIEW_WIDTH*y] = Tile::Dust;
380 map.dirtyLighting = true;
381
382 kickUpDust(map, x, y, kickup.chain + 1);
383 }
384 }
385 });
386
387 fov_circle(
388 dusty.get(),
389 static_cast<void*>(&map),
390 static_cast<void*>(&kickup),
391 kickup.x,
392 kickup.y,
393 kickup.cur);
394 }
395
396 erase_if(
397 map.kickups,
398 [] (const Kickup& kickup) {
399 return kickup.cur == kickup.radius;
400 });
401}
402
318int main(int, char**) 403int main(int, char**)
319{ 404{
320 std::random_device randomEngine; 405 std::random_device randomEngine;
@@ -371,8 +456,21 @@ int main(int, char**)
371 bool quit = false; 456 bool quit = false;
372 Input keystate; 457 Input keystate;
373 SDL_Event e; 458 SDL_Event e;
459
460 size_t dustDt = 30;
461 size_t dustAcc = 0;
462
463 size_t inputDt = 50;
464 size_t inputAcc = 0;
465
466 size_t lastTime = SDL_GetTicks();
467
374 while (!quit) 468 while (!quit)
375 { 469 {
470 size_t currentTime = SDL_GetTicks();
471 size_t frameTime = currentTime - lastTime;
472 lastTime = currentTime;
473
376 //bool input = false; 474 //bool input = false;
377 //int presses = 0; 475 //int presses = 0;
378 bool pressedSpace = false; 476 bool pressedSpace = false;
@@ -396,10 +494,6 @@ int main(int, char**)
396 case SDLK_SPACE: 494 case SDLK_SPACE:
397 { 495 {
398 pressedSpace = true; 496 pressedSpace = true;
399 //input = true;
400
401 std::deque<std::tuple<int, int>> lamps;
402 lamps.emplace_back(player_x, player_y);
403 497
404 setIfValid(map, player_x , player_y , Tile::Lamp); 498 setIfValid(map, player_x , player_y , Tile::Lamp);
405 499
@@ -414,56 +508,12 @@ int main(int, char**)
414 player_x + RADIUS, 508 player_x + RADIUS,
415 player_y + RADIUS); 509 player_y + RADIUS);
416 510
417 render(ren.get(), map, false); 511 //render(ren.get(), map, false);
418 SDL_Delay(30); 512 //SDL_Delay(30);
419 } 513 }
420 514
421 int lamped = 0; 515 map.dirtyLighting = true;
422 while (!lamps.empty()) 516 kickUpDust(map, player_x, player_y, 0);
423 {
424 lamped++;
425
426 int px, py;
427 std::tie(px, py) = lamps.front();
428 lamps.pop_front();
429
430 std::unique_ptr<fov_settings_type> dusty(new fov_settings_type);
431 fov_settings_set_opacity_test_function(
432 dusty.get(),
433 [] (void* map, int x, int y) {
434 return
435 x >= 0 &&
436 x < VIEW_WIDTH &&
437 y >= 0 &&
438 y < VIEW_HEIGHT &&
439 static_cast<Map*>(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall;
440 });
441
442 fov_settings_set_apply_lighting_function(
443 dusty.get(),
444 [] (void* map, int x, int y, int, int, void* source) {
445 Map& m = *static_cast<Map*>(map);
446 auto& lamps = *static_cast<std::deque<std::pair<int, int>>*>(source);
447
448 if ((x >= 0) && (x < VIEW_WIDTH) &&
449 (y >= 0) && (y < VIEW_HEIGHT))
450 {
451 if (m.tiles[x+VIEW_WIDTH*y] == Tile::Floor)
452 {
453 m.tiles[x+VIEW_WIDTH*y] = Tile::Dust;
454 } else if (m.tiles[x+VIEW_WIDTH*y] == Tile::Lamp)
455 {
456 m.tiles[x+VIEW_WIDTH*y] = Tile::Dust;
457 lamps.emplace_back(x, y);
458 }
459 }
460 });
461
462 fov_circle(dusty.get(), static_cast<void*>(&map), static_cast<void*>(&lamps), px, py, RADIUS+lamped*lamped);
463
464 render(ren.get(), map, false);
465 SDL_Delay(50);
466 }
467 517
468 break; 518 break;
469 } 519 }
@@ -479,7 +529,10 @@ int main(int, char**)
479 529
480 bool input = keystate.left || keystate.right || keystate.up || keystate.down || pressedSpace; 530 bool input = keystate.left || keystate.right || keystate.up || keystate.down || pressedSpace;
481 531
482 if (input) 532 dustAcc += frameTime;
533 inputAcc += frameTime;
534
535 while (dustAcc >= dustDt)
483 { 536 {
484 for (int y = 0; y < VIEW_HEIGHT; y++) 537 for (int y = 0; y < VIEW_HEIGHT; y++)
485 { 538 {
@@ -488,16 +541,27 @@ int main(int, char**)
488 if (map.tiles[x+y*VIEW_WIDTH] == Tile::Dust) 541 if (map.tiles[x+y*VIEW_WIDTH] == Tile::Dust)
489 { 542 {
490 map.tiles[x+y*VIEW_WIDTH] = Tile::Floor; 543 map.tiles[x+y*VIEW_WIDTH] = Tile::Floor;
544 map.dirtyLighting = true;
491 } 545 }
492 } 546 }
493 } 547 }
548
549 processKickup(map);
550
551 dustAcc -= dustDt;
494 } 552 }
495 553
496 processKeys(map, keystate); 554 while (inputAcc >= inputDt)
497 recalculateLighting(map, fov.get()); 555 {
556 processKeys(map, keystate);
498 557
499 if (input) 558 inputAcc -= inputDt;
559 }
560
561 if (map.dirtyLighting)
500 { 562 {
563 recalculateLighting(map, fov.get());
564
501 for (int y = 0; y < VIEW_HEIGHT; y++) 565 for (int y = 0; y < VIEW_HEIGHT; y++)
502 { 566 {
503 for (int x = 0; x < VIEW_WIDTH; x++) 567 for (int x = 0; x < VIEW_WIDTH; x++)
@@ -520,7 +584,7 @@ int main(int, char**)
520 } 584 }
521 585
522 render(ren.get(), map, true); 586 render(ren.get(), map, true);
523 SDL_Delay(50); 587 //SDL_Delay(50);
524 } 588 }
525 } catch (const sdl_error& ex) 589 } catch (const sdl_error& ex)
526 { 590 {