From 8c9d046123f0978ea3f770838a2321d85ffda977 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 29 May 2018 15:28:52 -0400 Subject: started implementing color tinting on lighting --- CMakeLists.txt | 3 + cmake/FindSDL2_Image.cmake | 98 +++++++++++++++++++++++ res/lighting.png | Bin 0 -> 10226 bytes src/main.cpp | 191 ++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 272 insertions(+), 20 deletions(-) create mode 100644 cmake/FindSDL2_Image.cmake create mode 100644 res/lighting.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 6eb5830..e3b88fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,13 +7,16 @@ set(CMAKE_BUILD_TYPE Debug) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${Ether_SOURCE_DIR}/cmake") find_package(SDL2 REQUIRED) +find_package(SDL2_Image REQUIRED) set(ALL_LIBS ${SDL2_LIBRARY} + ${SDL2_IMAGE_LIBRARIES} ) include_directories( ${SDL2_INCLUDE_DIR} + ${SDL2_IMAGE_INCLUDE_DIRS} src vendor ) diff --git a/cmake/FindSDL2_Image.cmake b/cmake/FindSDL2_Image.cmake new file mode 100644 index 0000000..de842ca --- /dev/null +++ b/cmake/FindSDL2_Image.cmake @@ -0,0 +1,98 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindSDL2_image +# ------------- +# +# Locate SDL2_image library +# +# This module defines: +# +# :: +# +# SDL2_IMAGE_LIBRARIES, the name of the library to link against +# SDL2_IMAGE_INCLUDE_DIRS, where to find the headers +# SDL2_IMAGE_FOUND, if false, do not try to link against +# SDL2_IMAGE_VERSION_STRING - human-readable string containing the +# version of SDL_image +# +# +# +# For backward compatibility the following variables are also set: +# +# :: +# +# SDL2IMAGE_LIBRARY (same value as SDL_IMAGE_LIBRARIES) +# SDL2IMAGE_INCLUDE_DIR (same value as SDL_IMAGE_INCLUDE_DIRS) +# SDL2IMAGE_FOUND (same value as SDL_IMAGE_FOUND) +# +# +# +# $SDL2DIR is an environment variable that would correspond to the +# ./configure --prefix=$SDL2DIR used in building SDL. +# +# Created by Eric Wing. This was influenced by the FindSDL.cmake +# module, but with modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). + +if(NOT SDL2_IMAGE_INCLUDE_DIR AND SDL2IMAGE_INCLUDE_DIR) + set(SDL2_IMAGE_INCLUDE_DIR ${SDL2IMAGE_INCLUDE_DIR} CACHE PATH "directory cache entry initialized from old variable name") +endif() +find_path(SDL2_IMAGE_INCLUDE_DIR SDL_image.h + HINTS + ENV SDL2IMAGEDIR + ENV SDL2DIR + ${SDL2_DIR} + PATH_SUFFIXES SDL2 + # path suffixes to search inside ENV{SDL2DIR} + include/SDL2 include +) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(VC_LIB_PATH_SUFFIX lib/x64) +else() + set(VC_LIB_PATH_SUFFIX lib/x86) +endif() + +if(NOT SDL2_IMAGE_LIBRARY AND SDL2IMAGE_LIBRARY) + set(SDL2_IMAGE_LIBRARY ${SDL2IMAGE_LIBRARY} CACHE FILEPATH "file cache entry initialized from old variable name") +endif() +find_library(SDL2_IMAGE_LIBRARY + NAMES SDL2_image + HINTS + ENV SDL2IMAGEDIR + ENV SDL2DIR + ${SDL2_DIR} + PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX} +) + +if(SDL2_IMAGE_INCLUDE_DIR AND EXISTS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h") + file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MAJOR "${SDL_IMAGE_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MINOR "${SDL_IMAGE_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_PATCH "${SDL_IMAGE_VERSION_PATCH_LINE}") + set(SDL2_IMAGE_VERSION_STRING ${SDL2_IMAGE_VERSION_MAJOR}.${SDL2_IMAGE_VERSION_MINOR}.${SDL2_IMAGE_VERSION_PATCH}) + unset(SDL2_IMAGE_VERSION_MAJOR_LINE) + unset(SDL2_IMAGE_VERSION_MINOR_LINE) + unset(SDL2_IMAGE_VERSION_PATCH_LINE) + unset(SDL2_IMAGE_VERSION_MAJOR) + unset(SDL2_IMAGE_VERSION_MINOR) + unset(SDL2_IMAGE_VERSION_PATCH) +endif() + +set(SDL2_IMAGE_LIBRARIES ${SDL2_IMAGE_LIBRARY}) +set(SDL2_IMAGE_INCLUDE_DIRS ${SDL2_IMAGE_INCLUDE_DIR}) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_image + REQUIRED_VARS SDL2_IMAGE_LIBRARIES SDL2_IMAGE_INCLUDE_DIRS + VERSION_VAR SDL2_IMAGE_VERSION_STRING) + +# for backward compatibility +set(SDL2IMAGE_LIBRARY ${SDL2_IMAGE_LIBRARIES}) +set(SDL2IMAGE_INCLUDE_DIR ${SDL2_IMAGE_INCLUDE_DIRS}) +set(SDL2IMAGE_FOUND ${SDL2_IMAGE_FOUND}) + +mark_as_advanced(SDL2_IMAGE_LIBRARY SDL2_IMAGE_INCLUDE_DIR) \ No newline at end of file diff --git a/res/lighting.png b/res/lighting.png new file mode 100644 index 0000000..b69fc55 Binary files /dev/null and b/res/lighting.png differ 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 @@ #include +#include #include #include #include @@ -15,6 +16,14 @@ public: } }; +class img_error : public std::logic_error { +public: + + img_error() : std::logic_error(IMG_GetError()) + { + } +}; + class window_deleter { public: @@ -37,6 +46,28 @@ public: using renderer_ptr = std::unique_ptr; +class surface_deleter { +public: + + void operator()(SDL_Surface* ptr) + { + SDL_FreeSurface(ptr); + } +}; + +using surface_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, @@ -44,6 +75,13 @@ enum class Tile { Lamp }; +enum class Source { + None, + Dust, + Lamp, + Player +}; + const int GAME_WIDTH = 640*2; const int GAME_HEIGHT = 480*2; const int TILE_WIDTH = 8*2; @@ -65,7 +103,8 @@ public: Map() : tiles(VIEW_WIDTH*VIEW_HEIGHT, Tile::Floor), lighting(VIEW_WIDTH*VIEW_HEIGHT, false), - lightStrength(VIEW_WIDTH*VIEW_HEIGHT, 0.0) + lightStrength(VIEW_WIDTH*VIEW_HEIGHT, 0.0), + lightSource(VIEW_WIDTH*VIEW_HEIGHT, Source::None) { } @@ -73,6 +112,7 @@ public: std::vector lighting; std::vector oldLighting; std::vector lightStrength; + std::vector lightSource; int lightedSpots = 0; }; @@ -84,7 +124,53 @@ void render( const Map& map, bool drawDark = true) { - SDL_SetRenderDrawColor(ren, rand() % 255, rand() % 255, rand() % 255, 255); + texture_ptr playerFade; + { + surface_ptr pfs(IMG_Load("../res/lighting.png")); + if (!pfs) + { + throw img_error(); + } + + playerFade = texture_ptr(SDL_CreateTextureFromSurface(ren, pfs.get())); + } + + texture_ptr lampFade( + SDL_CreateTexture( + ren, + SDL_PIXELFORMAT_RGBA4444, + SDL_TEXTUREACCESS_TARGET, + 144, + 144)); + + { + SDL_SetRenderTarget(ren, lampFade.get()); + + SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_NONE); + SDL_SetRenderDrawColor(ren, 255, 255, 255, 0); + SDL_RenderFillRect(ren, nullptr); + + SDL_RenderCopy(ren, playerFade.get(), nullptr, nullptr); + + SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_MOD); + SDL_SetRenderDrawColor(ren, 255, 180, 0, 255); + SDL_RenderFillRect(ren, nullptr); + + SDL_SetRenderTarget(ren, nullptr); + } + + int darkR = 40; + int darkG = 40; + int darkB = 40; + + if (!drawDark) + { + darkR = rand() % 255; + darkG = rand() % 255; + darkB = rand() % 255; + } + + SDL_SetRenderDrawColor(ren, darkR, darkG, darkB, 255); SDL_RenderClear(ren); for (int y = 0; y < VIEW_HEIGHT; y++) @@ -98,36 +184,40 @@ void render( SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); } else if (!map.lighting.at(x+VIEW_WIDTH*y)) { - if (drawDark) + /*if (drawDark) { SDL_SetRenderDrawColor(ren, 40, 40, 40, 255); } else { draw = false; - } + }*/ + draw = false; } else { + int alpha = map.lightStrength.at(x+y*VIEW_WIDTH) * 255; + alpha = 255; + switch (map.tiles.at(x+y*VIEW_WIDTH)) { case Tile::Floor: { - SDL_SetRenderDrawColor(ren, 210, 210, 210, 255); + SDL_SetRenderDrawColor(ren, 210, 210, 210, alpha); break; } case Tile::Wall: { - SDL_SetRenderDrawColor(ren, 100, 100, 100, 255); + SDL_SetRenderDrawColor(ren, 100, 100, 100, alpha); break; } case Tile::Dust: { - SDL_SetRenderDrawColor(ren, 128, 40, 255, 255); + SDL_SetRenderDrawColor(ren, 128, 40, 255, alpha); break; } case Tile::Lamp: { - SDL_SetRenderDrawColor(ren, 0, 255, 255, 255); + SDL_SetRenderDrawColor(ren, 0, 255, 255, alpha); break; } } @@ -136,10 +226,53 @@ void render( if (draw) { SDL_Rect rect{x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT}; + + SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); SDL_RenderFillRect(ren, &rect); - int alpha = (1.0 - map.lightStrength.at(x+y*VIEW_WIDTH)) * 255; - SDL_SetRenderDrawColor(ren, 40, 40, 40, alpha); + + } + } + } + + for (int y = 0; y < VIEW_HEIGHT; y++) + { + for (int x = 0; x < VIEW_WIDTH; x++) + { + if (map.lightSource.at(x+VIEW_WIDTH*y) != Source::None) + { + SDL_Rect fadeRect{x*TILE_WIDTH + (TILE_WIDTH/2) - (144/2), y*TILE_HEIGHT + (TILE_HEIGHT/2) - (144/2), 144, 144}; + if (map.lightSource.at(x+VIEW_WIDTH*y) == Source::Lamp) + { + //SDL_SetTextureBlendMode(lampFade.get(), SDL_BLENDMODE_MOD); + SDL_RenderCopy(ren, lampFade.get(), nullptr, &fadeRect); + //SDL_SetRenderDrawColor(ren, 255, 180, 0, 50); + //SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); + //SDL_RenderFillRect(ren, &rect); + } else if (map.lightSource.at(x+VIEW_WIDTH*y) == Source::Player) + { + //SDL_SetTextureBlendMode(playerFade.get(), SDL_BLENDMODE_MOD); + SDL_RenderCopy(ren, playerFade.get(), nullptr, &fadeRect); + } + + /*SDL_SetRenderDrawColor(ren, 40, 40, 40, alpha); + SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); + SDL_RenderFillRect(ren, &rect);*/ + } + } + } + + SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_NONE); + SDL_SetRenderDrawColor(ren, darkR, darkG, darkB, 255); + + for (int y = 0; y < VIEW_HEIGHT; y++) + { + for (int x = 0; x < VIEW_WIDTH; x++) + { + if (!map.lighting.at(x+VIEW_WIDTH*y)) + { + SDL_Rect rect{x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT}; + SDL_RenderFillRect(ren, &rect); } } @@ -227,6 +360,7 @@ void recalculateLighting(Map& map, fov_settings_type* fov) map.lighting = std::vector(VIEW_WIDTH*VIEW_HEIGHT, false); map.lightStrength = std::vector(VIEW_WIDTH*VIEW_HEIGHT, 0.0); map.lightedSpots = 0; + map.lightSource = std::vector(VIEW_WIDTH*VIEW_HEIGHT, Source::None); fov_settings_set_opacity_test_function( fov, @@ -241,7 +375,7 @@ void recalculateLighting(Map& map, fov_settings_type* fov) fov_settings_set_apply_lighting_function( fov, - [] (void* map, int x, int y, int dx, int dy, void*) { + [] (void* map, int x, int y, int dx, int dy, void* source) { if ((x >= 0) && (x < VIEW_WIDTH) && (y >= 0) && (y < VIEW_HEIGHT)) { Map& m = *static_cast(map); @@ -259,6 +393,12 @@ void recalculateLighting(Map& map, fov_settings_type* fov) 0.0, 1.0 - std::sqrt(dx * dx + dy * dy) / static_cast(RADIUS)), 1.0/3.0)); + + Source ls = *static_cast(source); + if (static_cast(ls) > static_cast(m.lightSource[x+VIEW_WIDTH*y])) + { + //m.lightSource[x+VIEW_WIDTH*y] = ls; + } } }); @@ -266,22 +406,29 @@ 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) + Source ls = Source::None; + + if (player_x == x && player_y == y) + { + ls = Source::Player; + } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Dust) { - fov_circle(fov, static_cast(&map), nullptr, x, y, RADIUS); + ls = Source::Dust; + } else if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp) + { + ls = Source::Lamp; } - if (map.tiles[x+VIEW_WIDTH*y] == Tile::Lamp || - map.tiles[x+VIEW_WIDTH*y] == Tile::Dust) + if (ls != Source::None) { + fov_circle(fov, static_cast(&map), static_cast(&ls), x, y, RADIUS); + map.lighting[x+VIEW_WIDTH*y] = true; map.lightStrength[x+VIEW_WIDTH*y] = 1.0; + map.lightSource[x+VIEW_WIDTH*y] = ls; } } } - - map.lighting[player_x+VIEW_WIDTH*player_y] = true; - map.lightStrength[player_x+VIEW_WIDTH*player_y] = 1.0; } void processKeys(Map& map, const Input& keystate) @@ -325,6 +472,11 @@ int main(int, char**) throw sdl_error(); } + if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) + { + throw img_error(); + } + try { window_ptr win( @@ -346,8 +498,6 @@ int main(int, char**) throw sdl_error(); } - SDL_SetRenderDrawBlendMode(ren.get(), SDL_BLENDMODE_BLEND); - Map map; std::unique_ptr fov(new fov_settings_type()); @@ -527,6 +677,7 @@ int main(int, char**) std::cout << "SDL error (" << ex.what() << ")" << std::endl; } + IMG_Quit(); SDL_Quit(); return 0; -- cgit 1.4.1