From 72e83df4876d799cc7b7993813533041a112e250 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 29 May 2018 16:32:28 -0400 Subject: dust kickup spreads outward instead of being instantaneous --- src/main.cpp | 194 ++++++++++++++++++++++++++++++++++++------------------- src/untitled.txt | 0 src/util.h | 20 ++++++ 3 files changed, 149 insertions(+), 65 deletions(-) delete mode 100644 src/untitled.txt create mode 100644 src/util.h 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 @@ #include #include #include +#include #include #include -#include #include +#include "util.h" class sdl_error : public std::logic_error { public: @@ -59,6 +60,14 @@ struct Input { bool down = false; }; +struct Kickup { + int x; + int y; + size_t cur; + size_t radius; + size_t chain; +}; + class Map { public: @@ -73,7 +82,9 @@ public: std::vector lighting; std::vector oldLighting; std::vector lightStrength; + std::list kickups; int lightedSpots = 0; + bool dirtyLighting = true; }; int player_x = VIEW_WIDTH / 2; @@ -210,6 +221,8 @@ void movePlayer(int x, int y, Map& map) player_x = x; player_y = y; + + map.dirtyLighting = true; } } @@ -266,22 +279,19 @@ void recalculateLighting(Map& map, fov_settings_type* fov) { for (int x = 0; x < VIEW_WIDTH; x++) { - if ((player_x == x && player_y == y) || map.tiles[x+VIEW_WIDTH*y] == Tile::Dust || map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + if ((player_x == x && player_y == y) || + map.tiles[x+VIEW_WIDTH*y] == Tile::Dust || + map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) { fov_circle(fov, static_cast(&map), nullptr, x, y, RADIUS); - } - if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp || - map.tiles[x+VIEW_WIDTH*y] == Tile::Dust) - { map.lighting[x+VIEW_WIDTH*y] = true; map.lightStrength[x+VIEW_WIDTH*y] = 1.0; } } } - map.lighting[player_x+VIEW_WIDTH*player_y] = true; - map.lightStrength[player_x+VIEW_WIDTH*player_y] = 1.0; + map.dirtyLighting = false; } void processKeys(Map& map, const Input& keystate) @@ -315,6 +325,81 @@ void processKeys(Map& map, const Input& keystate) } } +void kickUpDust(Map& map, int x, int y, size_t chain) +{ + std::cout << "kickup " << x << " " << y << " " << chain << std::endl; + Kickup dk; + dk.x = x; + dk.y = y; + dk.chain = chain; + dk.cur = 0; + dk.radius = RADIUS + (chain + 1) * (chain + 1); + + map.kickups.push_back(dk); +} + +void processKickup(Map& map) +{ + for (Kickup& kickup : map.kickups) + { + kickup.cur++; + + if (map.tiles[kickup.x+VIEW_WIDTH*kickup.y] == Tile::Floor) + { + map.tiles[kickup.x+VIEW_WIDTH*kickup.y] = Tile::Dust; + } + + std::unique_ptr dusty(new fov_settings_type); + fov_settings_set_opacity_test_function( + dusty.get(), + [] (void* map, int x, int y) { + return + x >= 0 && + x < VIEW_WIDTH && + y >= 0 && + y < VIEW_HEIGHT && + static_cast(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall; + }); + + fov_settings_set_apply_lighting_function( + dusty.get(), + [] (void* data, int x, int y, int, int, void* source) { + Map& map = *static_cast(data); + Kickup& kickup = *static_cast(source); + + if ((x >= 0) && (x < VIEW_WIDTH) && + (y >= 0) && (y < VIEW_HEIGHT)) + { + if (map.tiles[x+VIEW_WIDTH*y] == Tile::Floor) + { + map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; + map.dirtyLighting = true; + } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + { + map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; + map.dirtyLighting = true; + + kickUpDust(map, x, y, kickup.chain + 1); + } + } + }); + + fov_circle( + dusty.get(), + static_cast(&map), + static_cast(&kickup), + kickup.x, + kickup.y, + kickup.cur); + } + + erase_if( + map.kickups, + [] (const Kickup& kickup) { + return kickup.cur == kickup.radius; + }); +} + int main(int, char**) { std::random_device randomEngine; @@ -371,8 +456,21 @@ int main(int, char**) bool quit = false; Input keystate; SDL_Event e; + + size_t dustDt = 30; + size_t dustAcc = 0; + + size_t inputDt = 50; + size_t inputAcc = 0; + + size_t lastTime = SDL_GetTicks(); + while (!quit) { + size_t currentTime = SDL_GetTicks(); + size_t frameTime = currentTime - lastTime; + lastTime = currentTime; + //bool input = false; //int presses = 0; bool pressedSpace = false; @@ -396,10 +494,6 @@ int main(int, char**) case SDLK_SPACE: { pressedSpace = true; - //input = true; - - std::deque> lamps; - lamps.emplace_back(player_x, player_y); setIfValid(map, player_x , player_y , Tile::Lamp); @@ -414,56 +508,12 @@ int main(int, char**) player_x + RADIUS, player_y + RADIUS); - render(ren.get(), map, false); - SDL_Delay(30); + //render(ren.get(), map, false); + //SDL_Delay(30); } - int lamped = 0; - while (!lamps.empty()) - { - lamped++; - - int px, py; - std::tie(px, py) = lamps.front(); - lamps.pop_front(); - - std::unique_ptr dusty(new fov_settings_type); - fov_settings_set_opacity_test_function( - dusty.get(), - [] (void* map, int x, int y) { - return - x >= 0 && - x < VIEW_WIDTH && - y >= 0 && - y < VIEW_HEIGHT && - static_cast(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall; - }); - - fov_settings_set_apply_lighting_function( - dusty.get(), - [] (void* map, int x, int y, int, int, void* source) { - Map& m = *static_cast(map); - auto& lamps = *static_cast>*>(source); - - if ((x >= 0) && (x < VIEW_WIDTH) && - (y >= 0) && (y < VIEW_HEIGHT)) - { - if (m.tiles[x+VIEW_WIDTH*y] == Tile::Floor) - { - m.tiles[x+VIEW_WIDTH*y] = Tile::Dust; - } else if (m.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) - { - m.tiles[x+VIEW_WIDTH*y] = Tile::Dust; - lamps.emplace_back(x, y); - } - } - }); - - fov_circle(dusty.get(), static_cast(&map), static_cast(&lamps), px, py, RADIUS+lamped*lamped); - - render(ren.get(), map, false); - SDL_Delay(50); - } + map.dirtyLighting = true; + kickUpDust(map, player_x, player_y, 0); break; } @@ -479,7 +529,10 @@ int main(int, char**) bool input = keystate.left || keystate.right || keystate.up || keystate.down || pressedSpace; - if (input) + dustAcc += frameTime; + inputAcc += frameTime; + + while (dustAcc >= dustDt) { for (int y = 0; y < VIEW_HEIGHT; y++) { @@ -488,16 +541,27 @@ int main(int, char**) if (map.tiles[x+y*VIEW_WIDTH] == Tile::Dust) { map.tiles[x+y*VIEW_WIDTH] = Tile::Floor; + map.dirtyLighting = true; } } } + + processKickup(map); + + dustAcc -= dustDt; } - processKeys(map, keystate); - recalculateLighting(map, fov.get()); + while (inputAcc >= inputDt) + { + processKeys(map, keystate); - if (input) + inputAcc -= inputDt; + } + + if (map.dirtyLighting) { + recalculateLighting(map, fov.get()); + for (int y = 0; y < VIEW_HEIGHT; y++) { for (int x = 0; x < VIEW_WIDTH; x++) @@ -520,7 +584,7 @@ int main(int, char**) } render(ren.get(), map, true); - SDL_Delay(50); + //SDL_Delay(50); } } catch (const sdl_error& ex) { diff --git a/src/untitled.txt b/src/untitled.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..150a6a5 --- /dev/null +++ b/src/util.h @@ -0,0 +1,20 @@ +#ifndef UTIL_H_E9110D4C +#define UTIL_H_E9110D4C + +template +void erase_if(Container& items, const Predicate& predicate) +{ + for (auto it = std::begin(items); it != std::end(items);) + { + if (predicate(*it)) + { + it = items.erase(it); + } + else + { + ++it; + } + } +}; + +#endif /* end of include guard: UTIL_H_E9110D4C */ -- cgit 1.4.1 From 9b1c8e98592cc0e5cec471720498e7bb2a60a449 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 29 May 2018 17:11:12 -0400 Subject: quitting the game causes all of the lamps to pop followed by the player fixed a bug where dashing when dropping a lamp would cause dust kickup to originate from a different tile than the actual lamp. --- src/main.cpp | 189 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 150 insertions(+), 39 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e26a5a8..c39cdb6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,6 +45,13 @@ enum class Tile { Lamp }; +enum class LoseState { + None, + PoppingLamps, + PoppingPlayer, + Outro +}; + const int GAME_WIDTH = 640*2; const int GAME_HEIGHT = 480*2; const int TILE_WIDTH = 8*2; @@ -85,10 +92,13 @@ public: std::list kickups; int lightedSpots = 0; bool dirtyLighting = true; + size_t numLamps = 0; + size_t numDust = 0; }; int player_x = VIEW_WIDTH / 2; int player_y = VIEW_HEIGHT / 2; +bool renderPlayer = true; void render( SDL_Renderer* ren, @@ -104,7 +114,7 @@ void render( { bool draw = true; - if (player_x == x && player_y == y) + if ((player_x == x && player_y == y) && renderPlayer) { SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); } else if (!map.lighting.at(x+VIEW_WIDTH*y)) @@ -217,6 +227,7 @@ void movePlayer(int x, int y, Map& map) if (map.tiles[player_x+player_y*VIEW_WIDTH] == Tile::Floor) { map.tiles[player_x+player_y*VIEW_WIDTH] = Tile::Dust; + map.numDust++; } player_x = x; @@ -279,7 +290,7 @@ void recalculateLighting(Map& map, fov_settings_type* fov) { for (int x = 0; x < VIEW_WIDTH; x++) { - if ((player_x == x && player_y == y) || + if ((player_x == x && player_y == y && renderPlayer) || map.tiles[x+VIEW_WIDTH*y] == Tile::Dust || map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) { @@ -327,7 +338,6 @@ void processKeys(Map& map, const Input& keystate) void kickUpDust(Map& map, int x, int y, size_t chain) { - std::cout << "kickup " << x << " " << y << " " << chain << std::endl; Kickup dk; dk.x = x; dk.y = y; @@ -338,6 +348,20 @@ void kickUpDust(Map& map, int x, int y, size_t chain) map.kickups.push_back(dk); } +void popLamp(Map& map, int x, int y, size_t chain) +{ + if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + { + map.numLamps--; + } + + map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; + map.numDust++; + map.dirtyLighting = true; + + kickUpDust(map, x, y, chain); +} + void processKickup(Map& map) { for (Kickup& kickup : map.kickups) @@ -347,6 +371,7 @@ void processKickup(Map& map) if (map.tiles[kickup.x+VIEW_WIDTH*kickup.y] == Tile::Floor) { map.tiles[kickup.x+VIEW_WIDTH*kickup.y] = Tile::Dust; + map.numDust++; } std::unique_ptr dusty(new fov_settings_type); @@ -373,13 +398,11 @@ void processKickup(Map& map) if (map.tiles[x+VIEW_WIDTH*y] == Tile::Floor) { map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; + map.numDust++; map.dirtyLighting = true; } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) { - map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; - map.dirtyLighting = true; - - kickUpDust(map, x, y, kickup.chain + 1); + popLamp(map, x, y, kickup.chain + 1); } } }); @@ -454,6 +477,7 @@ int main(int, char**) tick(map); bool quit = false; + LoseState losing = LoseState::None; Input keystate; SDL_Event e; @@ -463,6 +487,12 @@ int main(int, char**) size_t inputDt = 50; size_t inputAcc = 0; + size_t losePopLampDt = 1000; + size_t losePopLampAcc = losePopLampDt; + + size_t losePopPlayerDt = 4000; + size_t losePopPlayerAcc = 0; + size_t lastTime = SDL_GetTicks(); while (!quit) @@ -471,50 +501,60 @@ int main(int, char**) size_t frameTime = currentTime - lastTime; lastTime = currentTime; - //bool input = false; - //int presses = 0; - bool pressedSpace = false; while (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) { - quit = true; + if (losing != LoseState::None) + { + quit = true; + } else { + losing = LoseState::PoppingLamps; + } } else if (e.type == SDL_KEYDOWN) { - //presses++; - switch (e.key.keysym.sym) { case SDLK_ESCAPE: { - quit = true; + if (losing != LoseState::None) + { + quit = true; + } else { + losing = LoseState::PoppingLamps; + } + break; } case SDLK_SPACE: { - pressedSpace = true; - - setIfValid(map, player_x , player_y , Tile::Lamp); - - for (int i = 0; i < 5; i++) + if (losing == LoseState::None) { - processKeys(map, keystate); - - tick( - map, - player_x - (RADIUS - 1), - player_y - (RADIUS - 1), - player_x + RADIUS, - player_y + RADIUS); - - //render(ren.get(), map, false); - //SDL_Delay(30); + if (map.tiles[player_x+VIEW_WIDTH*player_y] == Tile::Floor) + { + map.tiles[player_x+VIEW_WIDTH*player_y] = Tile::Lamp; + map.numLamps++; + map.dirtyLighting = true; + kickUpDust(map, player_x, player_y, 0); + + for (int i = 0; i < 5; i++) + { + processKeys(map, keystate); + + tick( + map, + player_x - (RADIUS - 1), + player_y - (RADIUS - 1), + player_x + RADIUS, + player_y + RADIUS); + + //render(ren.get(), map, false); + //SDL_Delay(30); + } + } } - map.dirtyLighting = true; - kickUpDust(map, player_x, player_y, 0); - break; } } @@ -527,8 +567,6 @@ int main(int, char**) keystate.up = state[SDL_SCANCODE_UP]; keystate.down = state[SDL_SCANCODE_DOWN]; - bool input = keystate.left || keystate.right || keystate.up || keystate.down || pressedSpace; - dustAcc += frameTime; inputAcc += frameTime; @@ -546,16 +584,89 @@ int main(int, char**) } } + map.numDust = 0; + processKickup(map); dustAcc -= dustDt; } - while (inputAcc >= inputDt) + switch (losing) { - processKeys(map, keystate); + case LoseState::None: + { + while (inputAcc >= inputDt) + { + processKeys(map, keystate); + + inputAcc -= inputDt; + } - inputAcc -= inputDt; + break; + } + + case LoseState::PoppingLamps: + { + if (map.numLamps == 0) + { + if (map.numDust == 0) + { + losing = LoseState::PoppingPlayer; + } + } else { + losePopLampAcc += frameTime; + + while (losePopLampAcc >= losePopLampDt) + { + std::vector> lamps; + + for (int y = 0; y < VIEW_HEIGHT; y++) + { + for (int x = 0; x < VIEW_WIDTH; x++) + { + if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + { + lamps.emplace_back(x, y); + } + } + } + + std::uniform_int_distribution lampDist(0, lamps.size() - 1); + std::tuple popPos = lamps[lampDist(rng)]; + + popLamp(map, std::get<0>(popPos), std::get<1>(popPos), 0); + + losePopLampAcc -= losePopLampDt; + } + } + + break; + } + + case LoseState::PoppingPlayer: + { + losePopPlayerAcc += frameTime; + + if (losePopPlayerAcc >= losePopPlayerDt) + { + popLamp(map, player_x, player_y, 10); + renderPlayer = false; + + losing = LoseState::Outro; + } + + break; + } + + case LoseState::Outro: + { + if (map.numDust == 0) + { + quit = true; + } + + break; + } } if (map.dirtyLighting) @@ -594,4 +705,4 @@ int main(int, char**) SDL_Quit(); return 0; -} \ No newline at end of file +} -- cgit 1.4.1 From c055e37e57ff365f5ae62d265d4b2140fbdc348a Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 29 May 2018 21:57:33 -0400 Subject: abstracted map data into a class to allow for zooming out --- src/main.cpp | 366 ++++++++++++++++++++++++++++++----------------------------- src/map.h | 127 +++++++++++++++++++++ 2 files changed, 316 insertions(+), 177 deletions(-) create mode 100644 src/map.h diff --git a/src/main.cpp b/src/main.cpp index c39cdb6..9534678 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include #include #include "util.h" +#include "map.h" class sdl_error : public std::logic_error { public: @@ -75,49 +76,51 @@ struct Kickup { size_t chain; }; -class Map { +struct MapData { + Tile tile = Tile::Floor; + bool lit = false; + bool wasLit = false; + double visibility = 0.0; +}; + +class Game { public: - Map() : - tiles(VIEW_WIDTH*VIEW_HEIGHT, Tile::Floor), - lighting(VIEW_WIDTH*VIEW_HEIGHT, false), - lightStrength(VIEW_WIDTH*VIEW_HEIGHT, 0.0) + Game() : + map(-VIEW_WIDTH/2, -VIEW_HEIGHT/2, VIEW_WIDTH, VIEW_HEIGHT) { } - std::vector tiles; - std::vector lighting; - std::vector oldLighting; - std::vector lightStrength; + Map map; std::list kickups; int lightedSpots = 0; bool dirtyLighting = true; size_t numLamps = 0; size_t numDust = 0; -}; -int player_x = VIEW_WIDTH / 2; -int player_y = VIEW_HEIGHT / 2; -bool renderPlayer = true; + int player_x = 0; + int player_y = 0; + bool renderPlayer = true; +}; void render( SDL_Renderer* ren, - const Map& map, + const Game& game, bool drawDark = true) { SDL_SetRenderDrawColor(ren, rand() % 255, rand() % 255, rand() % 255, 255); SDL_RenderClear(ren); - for (int y = 0; y < VIEW_HEIGHT; y++) + for (int y = game.map.getTop(); y < game.map.getBottom(); y++) { - for (int x = 0; x < VIEW_WIDTH; x++) + for (int x = game.map.getLeft(); x < game.map.getRight(); x++) { bool draw = true; - if ((player_x == x && player_y == y) && renderPlayer) + if ((game.player_x == x && game.player_y == y) && game.renderPlayer) { SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); - } else if (!map.lighting.at(x+VIEW_WIDTH*y)) + } else if (!game.map.at(x,y).lit) { if (drawDark) { @@ -126,7 +129,7 @@ void render( draw = false; } } else { - switch (map.tiles.at(x+y*VIEW_WIDTH)) + switch (game.map.at(x,y).tile) { case Tile::Floor: { @@ -156,10 +159,15 @@ void render( if (draw) { - SDL_Rect rect{x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT}; + SDL_Rect rect { + game.map.getTrueX(x) * TILE_WIDTH, + game.map.getTrueY(y) * TILE_HEIGHT, + TILE_WIDTH, + TILE_HEIGHT}; + SDL_RenderFillRect(ren, &rect); - int alpha = (1.0 - map.lightStrength.at(x+y*VIEW_WIDTH)) * 255; + int alpha = (1.0 - game.map.at(x,y).visibility) * 255; SDL_SetRenderDrawColor(ren, 40, 40, 40, alpha); SDL_RenderFillRect(ren, &rect); } @@ -169,115 +177,132 @@ void render( SDL_RenderPresent(ren); } -void incrementIfSet(Map& map, int& count, int x, int y, int w, int h, Tile val = Tile::Wall) +void incrementIfSet(Game& game, int& count, int x, int y, Tile val = Tile::Wall) { - if ((x >= 0) && (x < w) && (y >= 0) && (y < h) && (map.tiles[x+w*y] == val)) + if (game.map.inBounds(x, y) && game.map.at(x,y).tile == val) { count++; } } -void tick(Map& map, int x1 = 0, int y1 = 0, int x2 = VIEW_WIDTH, int y2 = VIEW_HEIGHT, bool onlyDark = false) +void tick( + Game& game, + int x1, + int y1, + int x2, + int y2, + bool invert = false, + bool onlyDark = false) { - std::vector temp(map.tiles); + Map temp(game.map); - for (int y = std::max(y1, 0); y < std::min(y2, VIEW_HEIGHT); y++) + for (int y = game.map.getTop(); y < game.map.getBottom(); y++) { - for (int x = std::max(x1, 0); x < std::min(x2, VIEW_WIDTH); x++) + for (int x = game.map.getLeft(); x < game.map.getRight(); x++) { - if (onlyDark && map.lighting[x+y*VIEW_WIDTH]) + if (invert == (x >= x1 && x < x2 && y >= y1 && y < y2)) + { + continue; + } + + if (onlyDark && game.map.at(x,y).lit) { continue; } - if (map.tiles[x+y*VIEW_WIDTH] == Tile::Lamp) + if (game.map.at(x,y).tile == Tile::Lamp) { continue; } int count = 0; - incrementIfSet(map, count, x-1, y-1, VIEW_WIDTH, VIEW_HEIGHT); - incrementIfSet(map, count, x-1, y , VIEW_WIDTH, VIEW_HEIGHT); - incrementIfSet(map, count, x-1, y+1, VIEW_WIDTH, VIEW_HEIGHT); - incrementIfSet(map, count, x , y-1, VIEW_WIDTH, VIEW_HEIGHT); - incrementIfSet(map, count, x , y , VIEW_WIDTH, VIEW_HEIGHT); - incrementIfSet(map, count, x , y+1, VIEW_WIDTH, VIEW_HEIGHT); - incrementIfSet(map, count, x+1, y-1, VIEW_WIDTH, VIEW_HEIGHT); - incrementIfSet(map, count, x+1, y , VIEW_WIDTH, VIEW_HEIGHT); - incrementIfSet(map, count, x+1, y+1, VIEW_WIDTH, VIEW_HEIGHT); + incrementIfSet(game, count, x-1, y-1); + incrementIfSet(game, count, x-1, y ); + incrementIfSet(game, count, x-1, y+1); + incrementIfSet(game, count, x , y-1); + incrementIfSet(game, count, x , y ); + incrementIfSet(game, count, x , y+1); + incrementIfSet(game, count, x+1, y-1); + incrementIfSet(game, count, x+1, y ); + incrementIfSet(game, count, x+1, y+1); if (count >= 5) { - temp[x+VIEW_WIDTH*y] = Tile::Wall; + temp.at(x,y).tile = Tile::Wall; } else { - temp[x+VIEW_WIDTH*y] = Tile::Floor; + temp.at(x,y).tile = Tile::Floor; } } } - map.tiles = temp; + game.map = std::move(temp); +} + +void tick(Game& game, bool onlyDark = false) +{ + tick( + game, + game.map.getLeft(), + game.map.getTop(), + game.map.getRight(), + game.map.getBottom(), + false, + onlyDark); } -void movePlayer(int x, int y, Map& map) +void movePlayer(Game& game, int x, int y) { - if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT) && - map.tiles[x+VIEW_WIDTH*y] == Tile::Floor) + if (game.map.inBounds(x, y) && game.map.at(x,y).tile == Tile::Floor) { - if (map.tiles[player_x+player_y*VIEW_WIDTH] == Tile::Floor) + if (game.map.at(game.player_x, game.player_y).tile == Tile::Floor) { - map.tiles[player_x+player_y*VIEW_WIDTH] = Tile::Dust; - map.numDust++; + game.map.at(game.player_x, game.player_y).tile = Tile::Dust; + game.numDust++; } - player_x = x; - player_y = y; + game.player_x = x; + game.player_y = y; - map.dirtyLighting = true; + game.dirtyLighting = true; } } -void setIfValid(Map& map, int x, int y, Tile val) +void recalculateLighting(Game& game, fov_settings_type* fov) { - if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT)) + game.lightedSpots = 0; + + for (MapData& md : game.map.data()) { - map.tiles[x+VIEW_WIDTH*y] = val; + md.wasLit = md.lit; + md.lit = false; + md.visibility = 0.0; } -} - -void recalculateLighting(Map& map, fov_settings_type* fov) -{ - map.oldLighting = map.lighting; - map.lighting = std::vector(VIEW_WIDTH*VIEW_HEIGHT, false); - map.lightStrength = std::vector(VIEW_WIDTH*VIEW_HEIGHT, 0.0); - map.lightedSpots = 0; fov_settings_set_opacity_test_function( fov, - [] (void* map, int x, int y) { - return - x >= 0 && - x < VIEW_WIDTH && - y >= 0 && - y < VIEW_HEIGHT && - static_cast(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall; + [] (void* data, int x, int y) { + Game& game = *static_cast(data); + + return game.map.inBounds(x,y) && game.map.at(x,y).tile == Tile::Wall; }); fov_settings_set_apply_lighting_function( fov, - [] (void* map, int x, int y, int dx, int dy, void*) { - if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT)) + [] (void* data, int x, int y, int dx, int dy, void*) { + Game& game = *static_cast(data); + + if (game.map.inBounds(x, y)) { - Map& m = *static_cast(map); - if (!m.lighting[x+VIEW_WIDTH*y]) + if (!game.map.at(x,y).lit) { - m.lightedSpots++; + game.lightedSpots++; } - m.lighting[x+VIEW_WIDTH*y] = true; + game.map.at(x,y).lit = true; - m.lightStrength[x+VIEW_WIDTH*y] = std::max( - m.lightStrength[x+VIEW_WIDTH*y], + game.map.at(x,y).visibility = std::max( + game.map.at(x,y).visibility, std::pow( std::max( 0.0, @@ -286,29 +311,29 @@ void recalculateLighting(Map& map, fov_settings_type* fov) } }); - for (int y = 0; y < VIEW_HEIGHT; y++) + for (int y = game.map.getTop(); y < game.map.getBottom(); y++) { - for (int x = 0; x < VIEW_WIDTH; x++) + for (int x = game.map.getLeft(); x < game.map.getRight(); x++) { - if ((player_x == x && player_y == y && renderPlayer) || - map.tiles[x+VIEW_WIDTH*y] == Tile::Dust || - map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + if ((game.player_x == x && game.player_y == y && game.renderPlayer) || + game.map.at(x,y).tile == Tile::Dust || + game.map.at(x,y).tile == Tile::Lamp) { - fov_circle(fov, static_cast(&map), nullptr, x, y, RADIUS); + fov_circle(fov, static_cast(&game), nullptr, x, y, RADIUS); - map.lighting[x+VIEW_WIDTH*y] = true; - map.lightStrength[x+VIEW_WIDTH*y] = 1.0; + game.map.at(x,y).lit = true; + game.map.at(x,y).visibility = 1.0; } } } - map.dirtyLighting = false; + game.dirtyLighting = false; } -void processKeys(Map& map, const Input& keystate) +void processKeys(Game& game, const Input& keystate) { - int px = player_x; - int py = player_y; + int px = game.player_x; + int py = game.player_y; if (keystate.up) { @@ -330,13 +355,13 @@ void processKeys(Map& map, const Input& keystate) px++; } - if (!(player_x == px && player_y == py)) + if (!(game.player_x == px && game.player_y == py)) { - movePlayer(px, py, map); + movePlayer(game, px, py); } } -void kickUpDust(Map& map, int x, int y, size_t chain) +void kickUpDust(Game& game, int x, int y, size_t chain) { Kickup dk; dk.x = x; @@ -345,71 +370,67 @@ void kickUpDust(Map& map, int x, int y, size_t chain) dk.cur = 0; dk.radius = RADIUS + (chain + 1) * (chain + 1); - map.kickups.push_back(dk); + game.kickups.push_back(dk); } -void popLamp(Map& map, int x, int y, size_t chain) +void popLamp(Game& game, int x, int y, size_t chain) { - if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + if (game.map.at(x,y).tile == Tile::Lamp) { - map.numLamps--; + game.numLamps--; } - map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; - map.numDust++; - map.dirtyLighting = true; + game.map.at(x,y).tile = Tile::Dust; + game.numDust++; + game.dirtyLighting = true; - kickUpDust(map, x, y, chain); + kickUpDust(game, x, y, chain); } -void processKickup(Map& map) +void processKickup(Game& game) { - for (Kickup& kickup : map.kickups) + for (Kickup& kickup : game.kickups) { kickup.cur++; - if (map.tiles[kickup.x+VIEW_WIDTH*kickup.y] == Tile::Floor) + if (game.map.at(kickup.x, kickup.y).tile == Tile::Floor) { - map.tiles[kickup.x+VIEW_WIDTH*kickup.y] = Tile::Dust; - map.numDust++; + game.map.at(kickup.x, kickup.y).tile = Tile::Dust; + game.numDust++; } std::unique_ptr dusty(new fov_settings_type); fov_settings_set_opacity_test_function( dusty.get(), - [] (void* map, int x, int y) { - return - x >= 0 && - x < VIEW_WIDTH && - y >= 0 && - y < VIEW_HEIGHT && - static_cast(map)->tiles.at(x+VIEW_WIDTH*y) == Tile::Wall; + [] (void* data, int x, int y) { + Game& game = *static_cast(data); + + return game.map.inBounds(x,y) && game.map.at(x,y).tile == Tile::Wall; }); fov_settings_set_apply_lighting_function( dusty.get(), [] (void* data, int x, int y, int, int, void* source) { - Map& map = *static_cast(data); + Game& game = *static_cast(data); Kickup& kickup = *static_cast(source); - if ((x >= 0) && (x < VIEW_WIDTH) && - (y >= 0) && (y < VIEW_HEIGHT)) + if (game.map.inBounds(x,y)) { - if (map.tiles[x+VIEW_WIDTH*y] == Tile::Floor) + if (game.map.at(x,y).tile == Tile::Floor) { - map.tiles[x+VIEW_WIDTH*y] = Tile::Dust; - map.numDust++; - map.dirtyLighting = true; - } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + game.map.at(x,y).tile = Tile::Dust; + game.numDust++; + game.dirtyLighting = true; + } else if (game.map.at(x,y).tile == Tile::Lamp) { - popLamp(map, x, y, kickup.chain + 1); + popLamp(game, x, y, kickup.chain + 1); } } }); fov_circle( dusty.get(), - static_cast(&map), + static_cast(&game), static_cast(&kickup), kickup.x, kickup.y, @@ -417,7 +438,7 @@ void processKickup(Map& map) } erase_if( - map.kickups, + game.kickups, [] (const Kickup& kickup) { return kickup.cur == kickup.radius; }); @@ -456,25 +477,22 @@ int main(int, char**) SDL_SetRenderDrawBlendMode(ren.get(), SDL_BLENDMODE_BLEND); - Map map; + Game game; std::unique_ptr fov(new fov_settings_type()); fov_settings_init(fov.get()); - for (int y = 0; y < VIEW_HEIGHT; y++) + for (MapData& md : game.map.data()) { - for (int x = 0; x < VIEW_WIDTH; x++) + if (std::bernoulli_distribution(0.5)(rng)) { - if (std::bernoulli_distribution(0.5)(rng)) - { - map.tiles[x+y*VIEW_WIDTH] = Tile::Wall; - } + md.tile = Tile::Wall; } } - tick(map); - tick(map); - tick(map); + tick(game); + tick(game); + tick(game); bool quit = false; LoseState losing = LoseState::None; @@ -531,26 +549,24 @@ int main(int, char**) { if (losing == LoseState::None) { - if (map.tiles[player_x+VIEW_WIDTH*player_y] == Tile::Floor) + if (game.map.at(game.player_x, game.player_y).tile == + Tile::Floor) { - map.tiles[player_x+VIEW_WIDTH*player_y] = Tile::Lamp; - map.numLamps++; - map.dirtyLighting = true; - kickUpDust(map, player_x, player_y, 0); + game.map.at(game.player_x, game.player_y).tile = Tile::Lamp; + game.numLamps++; + game.dirtyLighting = true; + kickUpDust(game, game.player_x, game.player_y, 0); for (int i = 0; i < 5; i++) { - processKeys(map, keystate); + processKeys(game, keystate); tick( - map, - player_x - (RADIUS - 1), - player_y - (RADIUS - 1), - player_x + RADIUS, - player_y + RADIUS); - - //render(ren.get(), map, false); - //SDL_Delay(30); + game, + game.player_x - (RADIUS - 1), + game.player_y - (RADIUS - 1), + game.player_x + RADIUS, + game.player_y + RADIUS); } } } @@ -572,21 +588,18 @@ int main(int, char**) while (dustAcc >= dustDt) { - for (int y = 0; y < VIEW_HEIGHT; y++) + for (MapData& md : game.map.data()) { - for (int x = 0; x < VIEW_WIDTH; x++) + if (md.tile == Tile::Dust) { - if (map.tiles[x+y*VIEW_WIDTH] == Tile::Dust) - { - map.tiles[x+y*VIEW_WIDTH] = Tile::Floor; - map.dirtyLighting = true; - } + md.tile = Tile::Floor; + game.dirtyLighting = true; } } - map.numDust = 0; + game.numDust = 0; - processKickup(map); + processKickup(game); dustAcc -= dustDt; } @@ -597,7 +610,7 @@ int main(int, char**) { while (inputAcc >= inputDt) { - processKeys(map, keystate); + processKeys(game, keystate); inputAcc -= inputDt; } @@ -607,9 +620,9 @@ int main(int, char**) case LoseState::PoppingLamps: { - if (map.numLamps == 0) + if (game.numLamps == 0) { - if (map.numDust == 0) + if (game.numDust == 0) { losing = LoseState::PoppingPlayer; } @@ -620,11 +633,11 @@ int main(int, char**) { std::vector> lamps; - for (int y = 0; y < VIEW_HEIGHT; y++) + for (int y = game.map.getTop(); y < game.map.getBottom(); y++) { - for (int x = 0; x < VIEW_WIDTH; x++) + for (int x = game.map.getLeft(); x < game.map.getRight(); x++) { - if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + if (game.map.at(x,y).tile == Tile::Lamp) { lamps.emplace_back(x, y); } @@ -634,7 +647,7 @@ int main(int, char**) std::uniform_int_distribution lampDist(0, lamps.size() - 1); std::tuple popPos = lamps[lampDist(rng)]; - popLamp(map, std::get<0>(popPos), std::get<1>(popPos), 0); + popLamp(game, std::get<0>(popPos), std::get<1>(popPos), 0); losePopLampAcc -= losePopLampDt; } @@ -649,8 +662,8 @@ int main(int, char**) if (losePopPlayerAcc >= losePopPlayerDt) { - popLamp(map, player_x, player_y, 10); - renderPlayer = false; + popLamp(game, game.player_x, game.player_y, 10); + game.renderPlayer = false; losing = LoseState::Outro; } @@ -660,7 +673,7 @@ int main(int, char**) case LoseState::Outro: { - if (map.numDust == 0) + if (game.numDust == 0) { quit = true; } @@ -669,33 +682,32 @@ int main(int, char**) } } - if (map.dirtyLighting) + if (game.dirtyLighting) { - recalculateLighting(map, fov.get()); + recalculateLighting(game, fov.get()); - for (int y = 0; y < VIEW_HEIGHT; y++) + for (int y = game.map.getTop(); y < game.map.getBottom(); y++) { - for (int x = 0; x < VIEW_WIDTH; x++) + for (int x = game.map.getLeft(); x < game.map.getRight(); x++) { - if (!map.lighting[x+y*VIEW_WIDTH] && map.oldLighting[x+y*VIEW_WIDTH]) + if (!game.map.at(x,y).lit && game.map.at(x,y).wasLit) { if (std::bernoulli_distribution(0.5)(rng)) { - map.tiles[x+y*VIEW_WIDTH] = Tile::Wall; + game.map.at(x,y).tile = Tile::Wall; } else { - map.tiles[x+y*VIEW_WIDTH] = Tile::Floor; + game.map.at(x,y).tile = Tile::Floor; } } } } - tick(map, 0, 0, VIEW_WIDTH, VIEW_HEIGHT, true); - tick(map, 0, 0, VIEW_WIDTH, VIEW_HEIGHT, true); - tick(map, 0, 0, VIEW_WIDTH, VIEW_HEIGHT, true); + tick(game, true); + tick(game, true); + tick(game, true); } - render(ren.get(), map, true); - //SDL_Delay(50); + render(ren.get(), game, true); } } catch (const sdl_error& ex) { diff --git a/src/map.h b/src/map.h new file mode 100644 index 0000000..329553c --- /dev/null +++ b/src/map.h @@ -0,0 +1,127 @@ +#ifndef MAP_H_3AB00D12 +#define MAP_H_3AB00D12 + +#include +#include + +template +class Map { +public: + + Map( + int left, + int top, + int width, + int height) : + left_(left), + top_(top), + width_(width), + height_(height), + data_(width_*height_) + { + } + + inline int getLeft() const + { + return left_; + } + + inline int getRight() const + { + return left_ + width_; + } + + inline int getTop() const + { + return top_; + } + + inline int getBottom() const + { + return top_ + height_; + } + + inline int getWidth() const + { + return width_; + } + + inline int getHeight() const + { + return height_; + } + + inline int getTrueX(int x) const + { + return (x - left_); + } + + inline int getTrueY(int y) const + { + return (y - top_); + } + + inline bool inBounds(int x, int y) const + { + return (x >= left_) && + (x < left_ + width_) && + (y >= top_) && + (y < top_ + height_); + } + + inline const T& at(int x, int y) const + { + return data_.at((x - left_) + width_ * (y - top_)); + } + + inline T& at(int x, int y) + { + return const_cast(static_cast(*this).at(x, y)); + } + + inline const std::vector& data() const + { + return data_; + } + + inline std::vector& data() + { + return data_; + } + + void resize(int newLeft, int newTop, int newWidth, int newHeight) + { + std::vector newData(newWidth * newHeight); + + int winTop = std::max(top_, newTop); + int winBottom = std::min(top_ + height_, newTop + newHeight); + int winLeft = std::max(left_, newLeft); + int winRight = std::min(left_ + width_, newLeft + newWidth); + + for (int y = winTop; y < winBottom; y++) + { + std::move( + std::next(std::begin(data_), (winLeft - left_) + width_ * (y - top_)), + std::next(std::begin(data_), (winRight - left_) + width_ * (y - top_)), + std::next(std::begin(newData), + (winLeft - newLeft) + newWidth * (y - newTop))); + } + + left_ = newLeft; + top_ = newTop; + width_ = newWidth; + height_ = newHeight; + data_.swap(newData); + } + +private: + + int left_; + int top_; + int width_; + int height_; + + std::vector data_; +}; + +#endif /* end of include guard: MAP_H_3AB00D12 */ -- cgit 1.4.1 From e8420d47578b3ba5ce83238ee8f61c747cdf2521 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Wed, 30 May 2018 22:18:00 -0400 Subject: map zooms in and out based on how lit it is --- src/main.cpp | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 157 insertions(+), 12 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9534678..2d8adf0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,6 +39,17 @@ public: using renderer_ptr = std::unique_ptr; +class texture_deleter { +public: + + void operator()(SDL_Texture* ptr) + { + SDL_DestroyTexture(ptr); + } +}; + +using texture_ptr = std::unique_ptr; + enum class Tile { Floor, Wall, @@ -56,9 +67,10 @@ enum class LoseState { const int GAME_WIDTH = 640*2; const int GAME_HEIGHT = 480*2; const int TILE_WIDTH = 8*2; -const int TILE_HEIGHT = 8*2; -const int VIEW_WIDTH = GAME_WIDTH / TILE_WIDTH; -const int VIEW_HEIGHT = GAME_HEIGHT / TILE_HEIGHT; +const int TILE_HEIGHT = TILE_WIDTH; +const int INIT_ZOOM = 10; +const int ZOOM_X_FACTOR = 8; +const int ZOOM_Y_FACTOR = 6; const int RADIUS = 8; struct Input { @@ -86,14 +98,21 @@ struct MapData { class Game { public: - Game() : - map(-VIEW_WIDTH/2, -VIEW_HEIGHT/2, VIEW_WIDTH, VIEW_HEIGHT) + Game(std::mt19937& rng) : + rng(rng), + map( + -INIT_ZOOM * ZOOM_X_FACTOR / 2, + -INIT_ZOOM * ZOOM_Y_FACTOR / 2, + INIT_ZOOM * ZOOM_X_FACTOR, + INIT_ZOOM * ZOOM_Y_FACTOR) { } + std::mt19937& rng; + Map map; std::list kickups; - int lightedSpots = 0; + int litSpots = 0; bool dirtyLighting = true; size_t numLamps = 0; size_t numDust = 0; @@ -101,6 +120,14 @@ public: int player_x = 0; int player_y = 0; bool renderPlayer = true; + + int curZoom = INIT_ZOOM; + int maxZoom = INIT_ZOOM; + + bool zooming = false; + //size_t oldZoom; + int zoomProgress = 0; + }; void render( @@ -108,6 +135,21 @@ void render( const Game& game, bool drawDark = true) { + texture_ptr canvas( + SDL_CreateTexture( + ren, + SDL_PIXELFORMAT_RGBA8888, + SDL_TEXTUREACCESS_TARGET, + TILE_WIDTH * game.map.getWidth(), + TILE_HEIGHT * game.map.getHeight())); + + if (!canvas) + { + throw sdl_error(); + } + + SDL_SetRenderTarget(ren, canvas.get()); + SDL_SetRenderDrawColor(ren, rand() % 255, rand() % 255, rand() % 255, 255); SDL_RenderClear(ren); @@ -174,6 +216,25 @@ void render( } } + SDL_SetRenderTarget(ren, nullptr); + + if (!game.zooming) + { + SDL_RenderCopy(ren, canvas.get(), nullptr, nullptr); + } else { + // TODO: zooming back in to the player + SDL_Rect zoomRect { + ((game.maxZoom - game.curZoom) * TILE_WIDTH + game.zoomProgress) + * ZOOM_X_FACTOR / 2, + ((game.maxZoom - game.curZoom) * TILE_HEIGHT + game.zoomProgress) + * ZOOM_Y_FACTOR / 2, + (game.curZoom * TILE_WIDTH - game.zoomProgress) * ZOOM_X_FACTOR, + (game.curZoom * TILE_HEIGHT - game.zoomProgress) * ZOOM_Y_FACTOR + }; + + SDL_RenderCopy(ren, canvas.get(), &zoomRect, nullptr); + } + SDL_RenderPresent(ren); } @@ -270,7 +331,7 @@ void movePlayer(Game& game, int x, int y) void recalculateLighting(Game& game, fov_settings_type* fov) { - game.lightedSpots = 0; + game.litSpots = 0; for (MapData& md : game.map.data()) { @@ -296,7 +357,7 @@ void recalculateLighting(Game& game, fov_settings_type* fov) { if (!game.map.at(x,y).lit) { - game.lightedSpots++; + game.litSpots++; } game.map.at(x,y).lit = true; @@ -444,6 +505,61 @@ void processKickup(Game& game) }); } +void growMap(Game& game, size_t zoom) +{ + int ol = game.map.getLeft(); + int ot = game.map.getTop(); + int ow = game.map.getWidth(); + int oh = game.map.getHeight(); + + game.map.resize( + -zoom * ZOOM_X_FACTOR / 2, + -zoom * ZOOM_Y_FACTOR / 2, + zoom * ZOOM_X_FACTOR, + zoom * ZOOM_Y_FACTOR); + + game.maxZoom = zoom; + + // TODO: is this working properly? + for (int y = game.map.getTop(); y < game.map.getBottom(); y++) + { + for (int x = game.map.getLeft(); x < game.map.getRight(); x++) + { + if (!(x >= ol && x < (ol + ow) && y >= ot && y < (ot + oh))) + { + if (std::bernoulli_distribution(0.5)(game.rng)) + { + game.map.at(x,y).tile = Tile::Wall; + } + } + } + } + + for (int i = 0; i < 3; i++) + { + tick(game, ol, ot, ow, oh, true); + } +} + +void setZoom(Game& game, size_t zoom) +{ + if (zoom == game.curZoom) + { + return; + } + + if (zoom > game.maxZoom) + { + growMap(game, zoom); + } + + // TODO: don't think this works well with rapid zoom changes + game.zoomProgress += (zoom - game.curZoom) * TILE_WIDTH; + //game.oldZoom = game.curZoom; + game.curZoom = zoom; + game.zooming = true; +} + int main(int, char**) { std::random_device randomEngine; @@ -477,7 +593,7 @@ int main(int, char**) SDL_SetRenderDrawBlendMode(ren.get(), SDL_BLENDMODE_BLEND); - Game game; + Game game(rng); std::unique_ptr fov(new fov_settings_type()); fov_settings_init(fov.get()); @@ -505,12 +621,15 @@ int main(int, char**) size_t inputDt = 50; size_t inputAcc = 0; - size_t losePopLampDt = 1000; + size_t losePopLampDt = 800; size_t losePopLampAcc = losePopLampDt; - size_t losePopPlayerDt = 4000; + size_t losePopPlayerDt = 3000; size_t losePopPlayerAcc = 0; + size_t zoomDt = 62; + size_t zoomAcc = 0; + size_t lastTime = SDL_GetTicks(); while (!quit) @@ -647,7 +766,7 @@ int main(int, char**) std::uniform_int_distribution lampDist(0, lamps.size() - 1); std::tuple popPos = lamps[lampDist(rng)]; - popLamp(game, std::get<0>(popPos), std::get<1>(popPos), 0); + popLamp(game, std::get<0>(popPos), std::get<1>(popPos), 1); losePopLampAcc -= losePopLampDt; } @@ -705,6 +824,32 @@ int main(int, char**) tick(game, true); tick(game, true); tick(game, true); + + // TODO: better zoom algorithm + setZoom(game, game.litSpots / 1500 * 2 + INIT_ZOOM); + } + + zoomAcc += frameTime; + + while (zoomAcc >= zoomDt) + { + if (game.zooming) + { + if (game.zoomProgress > 0) + { + game.zoomProgress--; + } else if (game.zoomProgress < 0) + { + game.zoomProgress++; + } + + if (game.zoomProgress == 0) + { + game.zooming = false; + } + } + + zoomAcc -= zoomDt; } render(ren.get(), game, true); -- cgit 1.4.1 From 06d1fb3ba346d6712206e35a022afcb340b434fd Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 31 May 2018 15:49:58 -0400 Subject: player won't start in the middle of a wall --- src/main.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 2d8adf0..77c4510 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -608,6 +608,15 @@ int main(int, char**) tick(game); tick(game); + + for (int y = -1; y <= 1; y++) + { + for (int x = -1; x <= 1; x++) + { + game.map.at(x,y).tile = Tile::Floor; + } + } + tick(game); bool quit = false; -- cgit 1.4.1 From 91dd78d4c963dbcc596e44bf6991c40bb2df90cb Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sat, 2 Jun 2018 12:09:04 -0400 Subject: dust now ripples outward --- src/main.cpp | 96 +++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 77c4510..67be361 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "util.h" #include "map.h" @@ -80,12 +82,16 @@ struct Input { bool down = false; }; +using coord = std::tuple; + struct Kickup { int x; int y; size_t cur; size_t radius; size_t chain; + std::set done; + std::set front; }; struct MapData { @@ -93,6 +99,7 @@ struct MapData { bool lit = false; bool wasLit = false; double visibility = 0.0; + size_t dustLife = 0; }; class Game { @@ -319,6 +326,7 @@ void movePlayer(Game& game, int x, int y) if (game.map.at(game.player_x, game.player_y).tile == Tile::Floor) { game.map.at(game.player_x, game.player_y).tile = Tile::Dust; + game.map.at(game.player_x, game.player_y).dustLife = 1; game.numDust++; } @@ -430,6 +438,8 @@ void kickUpDust(Game& game, int x, int y, size_t chain) dk.chain = chain; dk.cur = 0; dk.radius = RADIUS + (chain + 1) * (chain + 1); + dk.front.emplace(x, y); + dk.done.emplace(x, y); game.kickups.push_back(dk); } @@ -442,6 +452,7 @@ void popLamp(Game& game, int x, int y, size_t chain) } game.map.at(x,y).tile = Tile::Dust; + game.map.at(x,y).dustLife = 2; game.numDust++; game.dirtyLighting = true; @@ -454,32 +465,24 @@ void processKickup(Game& game) { kickup.cur++; - if (game.map.at(kickup.x, kickup.y).tile == Tile::Floor) + std::set newFront; + for (const coord& xy : kickup.front) { - game.map.at(kickup.x, kickup.y).tile = Tile::Dust; - game.numDust++; - } - - std::unique_ptr dusty(new fov_settings_type); - fov_settings_set_opacity_test_function( - dusty.get(), - [] (void* data, int x, int y) { - Game& game = *static_cast(data); + auto processDir = [&] (int x, int y) { + coord c {x,y}; - return game.map.inBounds(x,y) && game.map.at(x,y).tile == Tile::Wall; - }); - - fov_settings_set_apply_lighting_function( - dusty.get(), - [] (void* data, int x, int y, int, int, void* source) { - Game& game = *static_cast(data); - Kickup& kickup = *static_cast(source); - - if (game.map.inBounds(x,y)) + if (game.map.inBounds(x,y) && + (game.map.at(x,y).tile == Tile::Floor || + game.map.at(x,y).tile == Tile::Lamp) && + !kickup.done.count(c)) { + newFront.insert(c); + kickup.done.insert(c); + if (game.map.at(x,y).tile == Tile::Floor) { game.map.at(x,y).tile = Tile::Dust; + game.map.at(x,y).dustLife = 2; game.numDust++; game.dirtyLighting = true; } else if (game.map.at(x,y).tile == Tile::Lamp) @@ -487,15 +490,35 @@ void processKickup(Game& game) popLamp(game, x, y, kickup.chain + 1); } } - }); - - fov_circle( - dusty.get(), - static_cast(&game), - static_cast(&kickup), - kickup.x, - kickup.y, - kickup.cur); + }; + + processDir(std::get<0>(xy) - 1, std::get<1>(xy) ); + processDir(std::get<0>(xy) + 1, std::get<1>(xy) ); + processDir(std::get<0>(xy) , std::get<1>(xy) - 1); + processDir(std::get<0>(xy) , std::get<1>(xy) + 1); + + if (std::bernoulli_distribution(0.5)(game.rng)) + { + processDir(std::get<0>(xy) - 1, std::get<1>(xy) - 1); + } + + if (std::bernoulli_distribution(0.5)(game.rng)) + { + processDir(std::get<0>(xy) - 1, std::get<1>(xy) + 1); + } + + if (std::bernoulli_distribution(0.5)(game.rng)) + { + processDir(std::get<0>(xy) + 1, std::get<1>(xy) - 1); + } + + if (std::bernoulli_distribution(0.5)(game.rng)) + { + processDir(std::get<0>(xy) + 1, std::get<1>(xy) + 1); + } + } + + kickup.front.swap(newFront); } erase_if( @@ -716,17 +739,24 @@ int main(int, char**) while (dustAcc >= dustDt) { + game.numDust = 0; + for (MapData& md : game.map.data()) { if (md.tile == Tile::Dust) { - md.tile = Tile::Floor; - game.dirtyLighting = true; + md.dustLife--; + + if (md.dustLife <= 0) + { + md.tile = Tile::Floor; + game.dirtyLighting = true; + } else { + game.numDust++; + } } } - game.numDust = 0; - processKickup(game); dustAcc -= dustDt; -- cgit 1.4.1 From 9ee8022798235c640f13271d4dfad067dbd6542e Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sat, 2 Jun 2018 12:58:15 -0400 Subject: map expansion looks more normal now --- src/main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 67be361..24f3829 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -543,7 +543,6 @@ void growMap(Game& game, size_t zoom) game.maxZoom = zoom; - // TODO: is this working properly? for (int y = game.map.getTop(); y < game.map.getBottom(); y++) { for (int x = game.map.getLeft(); x < game.map.getRight(); x++) @@ -560,7 +559,7 @@ void growMap(Game& game, size_t zoom) for (int i = 0; i < 3; i++) { - tick(game, ol, ot, ow, oh, true); + tick(game, ol, ot, ol + ow, ot + oh, true); } } -- cgit 1.4.1 From 47c584d8a583bab3a71333e9993b72cf481bca2f Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sun, 3 Jun 2018 11:54:16 -0400 Subject: decreased dust light radius this makes it less likely that dropping a lamp will cause cave-ins. also slowed down the propagation of dust slightly. --- src/main.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 24f3829..2daf153 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -358,11 +358,13 @@ void recalculateLighting(Game& game, fov_settings_type* fov) fov_settings_set_apply_lighting_function( fov, - [] (void* data, int x, int y, int dx, int dy, void*) { + [] (void* data, int x, int y, int dx, int dy, void* source) { Game& game = *static_cast(data); if (game.map.inBounds(x, y)) { + double lightRadius = static_cast(*static_cast(source)); + if (!game.map.at(x,y).lit) { game.litSpots++; @@ -375,7 +377,7 @@ void recalculateLighting(Game& game, fov_settings_type* fov) std::pow( std::max( 0.0, - 1.0 - std::sqrt(dx * dx + dy * dy) / static_cast(RADIUS)), + 1.0 - std::sqrt(dx * dx + dy * dy) / lightRadius), 1.0/3.0)); } }); @@ -388,7 +390,24 @@ void recalculateLighting(Game& game, fov_settings_type* fov) game.map.at(x,y).tile == Tile::Dust || game.map.at(x,y).tile == Tile::Lamp) { - fov_circle(fov, static_cast(&game), nullptr, x, y, RADIUS); + int lightRadius; + + if ((game.player_x == x && game.player_y == y && game.renderPlayer) || + game.map.at(x,y).tile == Tile::Lamp) + { + lightRadius = RADIUS; + } else if (game.map.at(x,y).tile == Tile::Dust) + { + lightRadius = 2; + } + + fov_circle( + fov, + static_cast(&game), + static_cast(&lightRadius), + x, + y, + lightRadius); game.map.at(x,y).lit = true; game.map.at(x,y).visibility = 1.0; @@ -646,7 +665,7 @@ int main(int, char**) Input keystate; SDL_Event e; - size_t dustDt = 30; + size_t dustDt = 40; size_t dustAcc = 0; size_t inputDt = 50; -- cgit 1.4.1