From f545cf0276e95c9dca33d36d1a0cfe3b4995473a Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Wed, 23 May 2018 21:28:29 -0400 Subject: somethign --- src/main.cpp | 549 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 549 insertions(+) create mode 100644 src/main.cpp (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..2fc610b --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,549 @@ +#include +#include +#include +#include +#include +#include +#include + +class sdl_error : public std::logic_error { +public: + + sdl_error() : std::logic_error(SDL_GetError()) + { + } +}; + +class window_deleter { +public: + + void operator()(SDL_Window* ptr) + { + SDL_DestroyWindow(ptr); + } +}; + +using window_ptr = std::unique_ptr; + +class renderer_deleter { +public: + + void operator()(SDL_Renderer* ptr) + { + SDL_DestroyRenderer(ptr); + } +}; + +using renderer_ptr = std::unique_ptr; + +enum class Tile { + Floor, + Wall, + Dark, + Dust, + Lamp +}; + +const int GAME_WIDTH = 640; +const int GAME_HEIGHT = 480; +const int TILE_WIDTH = 8; +const int TILE_HEIGHT = 8; +const int VIEW_WIDTH = GAME_WIDTH / TILE_WIDTH; +const int VIEW_HEIGHT = GAME_HEIGHT / TILE_HEIGHT; + +class Map { +public: + + Map() : + tiles(VIEW_WIDTH*VIEW_HEIGHT, Tile::Floor), + lighting(VIEW_WIDTH*VIEW_HEIGHT, false) + { + } + + std::vector tiles; + std::vector lighting; + std::deque> playerLocs; +}; + +int player_x = VIEW_WIDTH / 2; +int player_y = VIEW_HEIGHT / 2; + +void render( + SDL_Renderer* ren, + const Map& map, + 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 x = 0; x < VIEW_WIDTH; x++) + { + bool draw = true; + + if (player_x == x && player_y == y) + { + SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); + } else if (!map.lighting.at(x+VIEW_WIDTH*y)) + { + if (drawDark) + { + SDL_SetRenderDrawColor(ren, 40, 40, 40, 255); + } else { + draw = false; + } + } else { + switch (map.tiles.at(x+y*VIEW_WIDTH)) + { + case Tile::Floor: + { + SDL_SetRenderDrawColor(ren, 210, 210, 210, 255); + break; + } + + case Tile::Wall: + case Tile::Dark: + { + SDL_SetRenderDrawColor(ren, 100, 100, 100, 255); + break; + } + + case Tile::Dust: + { + SDL_SetRenderDrawColor(ren, 128, 40, 255, 255); + break; + } + + case Tile::Lamp: + { + SDL_SetRenderDrawColor(ren, 0, 255, 255, 255); + break; + } + } + } + + + if (draw) + { + SDL_Rect rect{x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT}; + SDL_RenderFillRect(ren, &rect); + } + + + } + } + + SDL_RenderPresent(ren); +} + +void incrementIfSet(Map& map, int& count, int x, int y, int w, int h, Tile val = Tile::Dark) +{ + if ((x >= 0) && (x < w) && (y >= 0) && (y < h) && (map.tiles[x+w*y] == val)) + { + count++; + } +} + +void tick(Map& map, int x1 = 0, int y1 = 0, int x2 = VIEW_WIDTH, int y2 = VIEW_HEIGHT) +{ + std::vector temp(map.tiles); + + for (int y = std::max(y1, 0); y < std::min(y2, VIEW_HEIGHT); y++) + { + for (int x = std::max(x1, 0); x < std::min(x2, VIEW_WIDTH); x++) + { + if (map.tiles[x+y*VIEW_WIDTH] == 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); + + if (count >= 5) + { + temp[x+VIEW_WIDTH*y] = Tile::Dark; + } else { + temp[x+VIEW_WIDTH*y] = Tile::Floor; + } + } + } + + map.tiles = temp; +} + +void movePlayer(int x, int y, Map& map) +{ + if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT) && + map.tiles[x+VIEW_WIDTH*y] == Tile::Floor) + { + if (map.tiles[player_x+player_y*VIEW_WIDTH] == Tile::Floor) + { + map.tiles[player_x+player_y*VIEW_WIDTH] = Tile::Dust; + map.playerLocs.emplace_front(player_x, player_y); + + if (map.playerLocs.size() > 5) + { + map.playerLocs.pop_back(); + } + } + + + + + player_x = x; + player_y = y; + } +} + +void setIfValid(Map& map, int x, int y, Tile val) +{ + if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT)) + { + map.tiles[x+VIEW_WIDTH*y] = val; + } +} + +void recalculateLighting(Map& map, fov_settings_type* fov) +{ + map.lighting = std::vector(VIEW_WIDTH*VIEW_HEIGHT, false); + + 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::Dark; + }); + + fov_settings_set_apply_lighting_function( + fov, + [] (void* map, int x, int y, int, int, void*) { + if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT)) + { + static_cast(map)->lighting[x+VIEW_WIDTH*y] = true; + } + }); + + for (int y = 0; y < VIEW_HEIGHT; y++) + { + 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) + { + fov_circle(fov, static_cast(&map), nullptr, x, y, 8); + } + + if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + { + map.lighting[x+VIEW_WIDTH*y] = true; + } + } + } +} + +int main(int, char**) +{ + std::random_device randomEngine; + std::mt19937 rng(randomEngine()); + + if (SDL_Init(SDL_INIT_VIDEO) != 0) + { + throw sdl_error(); + } + + try + { + window_ptr win( + SDL_CreateWindow("Ether", 100, 100, GAME_WIDTH, GAME_HEIGHT, SDL_WINDOW_SHOWN)); + + if (!win) + { + throw sdl_error(); + } + + renderer_ptr ren( + SDL_CreateRenderer( + win.get(), + -1, + SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)); + + if (!ren) + { + throw sdl_error(); + } + + //std::vector tiles(VIEW_WIDTH*VIEW_HEIGHT, Tile::Floor); + //std::vector lighting(VIEW_WIDTH*VIEW_HEIGHT, false); + Map map; + + std::unique_ptr fov(new fov_settings_type()); + fov_settings_init(fov.get()); + + + for (int y = 0; y < VIEW_HEIGHT; y++) + { + for (int x = 0; x < VIEW_WIDTH; x++) + { + if (std::bernoulli_distribution(0.5)(rng)) + { + map.tiles[x+y*VIEW_WIDTH] = Tile::Dark; + } + } + } + + tick(map); + tick(map); + tick(map); + + bool quit = false; + SDL_Event e; + while (!quit) + { + //SDL_PumpEvents(); + bool input = false; + int presses = 0; + while (SDL_PollEvent(&e)) + { + if (e.type == SDL_QUIT) + { + quit = true; + } else if (e.type == SDL_KEYDOWN) + { + presses++; + + switch (e.key.keysym.sym) + { + case SDLK_SPACE: + { + input = true; + + setIfValid(map, player_x-1, player_y , Tile::Floor); + setIfValid(map, player_x+1, player_y , Tile::Floor); + setIfValid(map, player_x , player_y , Tile::Lamp); + setIfValid(map, player_x , player_y-1, Tile::Floor); + setIfValid(map, player_x , player_y+1, Tile::Floor); + + auto locs = map.playerLocs; + while (!locs.empty()) + { + movePlayer(std::get<0>(locs.front()), std::get<1>(locs.front()), map); + locs.pop_front(); + + tick( + map, + player_x - 7, + player_y - 7, + player_x + 8, + player_y + 8); + + render(ren.get(), map, false); + SDL_Delay(30); + } + + break; + } + } + } else if (e.type == SDL_KEYUP) + { + presses++; + } + } + + if (presses > 0) + { + for (int y = 0; y < VIEW_HEIGHT; y++) + { + for (int x = 0; x < VIEW_WIDTH; x++) + { + if (map.tiles[x+y*VIEW_WIDTH] == Tile::Dust) + { + map.tiles[x+y*VIEW_WIDTH] = Tile::Floor; + } + } + } + } + + const Uint8* state = SDL_GetKeyboardState(NULL); + + for (int i = 0; i < presses; i++) + { + //switch (e.key.keysym.sym) + { + //case SDLK_UP: + if (state[SDL_SCANCODE_UP]) + { + movePlayer(player_x, player_y-1, map); + input = true; + //break; + } + + //case SDLK_DOWN: + if (state[SDL_SCANCODE_DOWN]) + { + movePlayer(player_x, player_y+1, map); + input = true; + //break; + } + + //case SDLK_LEFT: + if (state[SDL_SCANCODE_LEFT]) + { + movePlayer(player_x-1, player_y, map); + input = true; + //break; + } + + //case SDLK_RIGHT: + if (state[SDL_SCANCODE_RIGHT]) + { + movePlayer(player_x+1, player_y, map); + input = true; + //break; + } + + + } + + if (input) + { + //render(ren.get(), tiles, false); + //SDL_Delay(1); + } + + //} + } + + bool checkForDust = true; + + while (checkForDust) + { + checkForDust = false; + + for (int y = 0; y < VIEW_HEIGHT; y++) + { + for (int x = 0; x < VIEW_WIDTH; x++) + { + if (map.tiles[x+y*VIEW_WIDTH] == Tile::Lamp) + { + int count = 0; + + incrementIfSet(map, count, x-1, y , VIEW_WIDTH, VIEW_HEIGHT, Tile::Dust); + incrementIfSet(map, count, x+1, y , VIEW_WIDTH, VIEW_HEIGHT, Tile::Dust); + incrementIfSet(map, count, x , y-1, VIEW_WIDTH, VIEW_HEIGHT, Tile::Dust); + incrementIfSet(map, count, x , y+1, VIEW_WIDTH, VIEW_HEIGHT, Tile::Dust); + + if (count > 0) + { + checkForDust = true; + + map.tiles[x+y*VIEW_WIDTH] = Tile::Dust; + + /*for (int i = 0; i < 4; i++) + { + tick( + map, + x - 7, + y - 7, + x + 8, + y + 8); + + for (int l = 0; l < (i*2+1); l++) + { + int px = x - i + l; + int py = y - i + l; + + auto fillInDust = [&] (int sx, int sy) { + if (sx > 0 && sx < VIEW_WIDTH && + sy > 0 && sy < VIEW_HEIGHT && + map.tiles[sx+sy*VIEW_WIDTH] == Tile::Floor && + !(player_y == sy && player_x == sx)) + { + map.tiles[sx+sy*VIEW_WIDTH] = Tile::Dust; + } + }; + + fillInDust(px , y - i); + fillInDust(px , y + i); + fillInDust(x - i, py ); + fillInDust(x + i, py ); + } + + render(ren.get(), map, false); + SDL_Delay(30); + }*/ + + + /* + + for (int py = std::max(0, y - 7); py < std::min(VIEW_HEIGHT, y + 8); py++) + { + for (int px = std::max(0, x - 7); px < std::min(VIEW_WIDTH, x + 8); px++) + { + if ((map.tiles[px+py*VIEW_WIDTH] == Tile::Floor) && + !(player_y == py && player_x == px)) + { + map.tiles[px+py*VIEW_WIDTH] = 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::Dark; + }); + + fov_settings_set_apply_lighting_function( + dusty.get(), + [] (void* map, int x, int y, int, int, void*) { + if ((x >= 0) && (x < VIEW_WIDTH) && + (y >= 0) && (y < VIEW_HEIGHT) && + (static_cast(map)->tiles[x+VIEW_WIDTH*y] == Tile::Floor)) + { + static_cast(map)->tiles[x+VIEW_WIDTH*y] = Tile::Dust; + } + }); + + fov_circle(dusty.get(), static_cast(&map), nullptr, x, y, 8); + + render(ren.get(), map, false); + SDL_Delay(50); + } + } + } + } + } + + + recalculateLighting(map, fov.get()); + render(ren.get(), map, true); + SDL_Delay(10); + } + } catch (const sdl_error&) + { + } + + SDL_Quit(); + + return 0; +} \ No newline at end of file -- cgit 1.4.1