diff --git a/assets/config.json b/assets/config.json new file mode 100644 index 0000000..1ab6e95 --- /dev/null +++ b/assets/config.json @@ -0,0 +1,15 @@ +{ + "textures": [ + "assets/tile01.png", + "assets/tile16.png", + "assets/tile02.png", + "assets/tile03.png", + "assets/tile05.png", + "assets/tile17.png" + ], + "sprites": [ + "assets/portal.png" + ], + "floor": "assets/tile32.png", + "ceiling": "assets/tile10.png" +} diff --git a/config.cpp b/config.cpp new file mode 100644 index 0000000..b15c336 --- /dev/null +++ b/config.cpp @@ -0,0 +1,32 @@ +#include "config.hpp" +#include "dbc.hpp" +#include + +using nlohmann::json; +using fmt::format; + +Config::Config(const std::string src_path) : $src_path(src_path) { + std::ifstream infile($src_path); + $config = json::parse(infile); +} + +json &Config::operator[](const std::string &key) { + dbc::check($config.contains(key), format("ERROR in config, key {} doesn't exist.", key)); + return $config[key]; +} + +std::wstring Config::wstring(const std::string key) { + dbc::check($config.contains(key), format("ERROR wstring in config, key {} doesn't exist.", key)); + std::wstring_convert> $converter; + const std::string& str_val = $config[key]; + return $converter.from_bytes(str_val); +} + +std::wstring Config::wstring(const std::string main_key, const std::string sub_key) { + dbc::check($config.contains(main_key), format("ERROR wstring main/key in config, main_key {} doesn't exist.", main_key)); + dbc::check($config[main_key].contains(sub_key), format("ERROR wstring in config, main_key/key {}/{} doesn't exist.", main_key, sub_key)); + + const std::string& str_val = $config[main_key][sub_key]; + std::wstring_convert> $converter; + return $converter.from_bytes(str_val); +} diff --git a/config.hpp b/config.hpp new file mode 100644 index 0000000..2c2e295 --- /dev/null +++ b/config.hpp @@ -0,0 +1,19 @@ +#pragma once +#include +#include +#include + +struct Config { + nlohmann::json $config; + std::string $src_path; + + Config(const std::string src_path); + + Config(nlohmann::json config, std::string src_path) + : $config(config), $src_path(src_path) {} + + nlohmann::json &operator[](const std::string &key); + nlohmann::json &json() { return $config; }; + std::wstring wstring(const std::string main_key); + std::wstring wstring(const std::string main_key, const std::string sub_key); +}; diff --git a/main.cpp b/main.cpp index 6b952ed..24a60be 100644 --- a/main.cpp +++ b/main.cpp @@ -9,15 +9,15 @@ static const int SCREEN_HEIGHT=720; static const int SCREEN_WIDTH=1280; Matrix MAP{ - {8,8,8,8,8,8,8,8,8}, - {8,0,2,0,0,0,0,0,8}, - {8,0,7,0,0,5,6,0,8}, - {8,0,0,0,0,0,0,0,8}, - {8,8,0,0,0,0,0,8,8}, - {8,0,0,1,3,4,0,0,8}, - {8,0,0,0,0,0,8,8,8}, - {8,0,0,0,0,0,0,0,8}, - {8,8,8,8,8,8,8,8,8} + {1,1,1,1,1,1,1,1,1}, + {1,0,2,0,0,0,0,0,1}, + {1,0,4,0,0,5,2,0,1}, + {1,0,0,0,0,0,0,0,1}, + {1,1,0,0,0,0,0,1,1}, + {1,0,0,1,3,4,0,0,1}, + {1,0,0,0,0,0,1,1,1}, + {1,0,0,0,0,0,0,0,1}, + {1,1,1,1,1,1,1,1,1} }; int main() { diff --git a/meson.build b/meson.build index 7000c4f..c0e0dae 100644 --- a/meson.build +++ b/meson.build @@ -24,6 +24,8 @@ executable('sfmlcaster', [ executable('zedcaster', [ 'dbc.cpp', 'matrix.cpp', + 'config.cpp', + 'texture.cpp', 'raycaster.cpp', 'main.cpp' ], diff --git a/raycaster.cpp b/raycaster.cpp index 64dfddc..b79b283 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -1,46 +1,9 @@ #include "raycaster.hpp" +#include "texture.hpp" using namespace fmt; using std::make_unique; -#define rgba_color(r,g,b,a) (r<<(0*8))|(g<<(1*8))|(b<<(2*8))|(a<<(3*8)) -#define gray_color(c) rgba_color(c, c, c, 255) - - -std::vector TexturePack::load_image(const char *filename) { - std::vector texture(TEXTURE_WIDTH * TEXTURE_HEIGHT); - sf::Image img; - bool good = img.loadFromFile(filename); - dbc::check(good, format("failed to load {}", filename)); - - uint32_t *pixbuf = (uint32_t *)img.getPixelsPtr(); - std::copy_n(pixbuf, texture.size(), texture.begin()); - - return texture; -} - -void TexturePack::load_textures() { - images.emplace_back(load_image("assets/tile16.png")); - images.emplace_back(load_image("assets/tile02.png")); - images.emplace_back(load_image("assets/tile03.png")); - images.emplace_back(load_image("assets/tile32.png")); - images.emplace_back(load_image("assets/tile05.png")); - images.emplace_back(load_image("assets/tile17.png")); - images.emplace_back(load_image("assets/tile10.png")); - images.emplace_back(load_image("assets/tile01.png")); - images.emplace_back(load_image("assets/portal.png")); -} - -std::vector& TexturePack::get(size_t num) { - return images[num]; -} - -Sprite &TexturePack::get_sprite(size_t sprite_num) { - return SPRITE[sprite_num]; -} - - - Raycaster::Raycaster(sf::RenderWindow& window, Matrix &map, int width, int height) : $width(width), $height(height), $window(window), @@ -84,12 +47,13 @@ void Raycaster::sprite_casting() { // sort sprites from far to close for(int i = 0; i < textures.NUM_SPRITES; i++) { + auto& sprite = textures.get_sprite(i); spriteOrder[i] = i; // this is just the distance calculation - spriteDistance[i] = ((posX - textures.SPRITE[i].x) * - (posX - textures.SPRITE[i].x) + - (posY - textures.SPRITE[i].y) * - (posY - textures.SPRITE[i].y)); + spriteDistance[i] = ((posX - sprite.x) * + (posX - sprite.x) + + (posY - sprite.y) * + (posY - sprite.y)); } sort_sprites(spriteOrder, spriteDistance, textures.NUM_SPRITES); @@ -98,9 +62,10 @@ void Raycaster::sprite_casting() { for(int i = 0; i < textures.NUM_SPRITES; i++) { int sprite_index = spriteOrder[i]; Sprite& sprite_rec = textures.get_sprite(sprite_index); + auto& sprite_texture = textures.get_texture(sprite_rec.texture); + double spriteX = sprite_rec.x - posX; double spriteY = sprite_rec.y - posY; - auto& sprite_texture = textures.get(sprite_rec.texture); //transform sprite with the inverse camera matrix // [ planeX dirX ] -1 [ dirY -dirX ] @@ -234,7 +199,7 @@ void Raycaster::cast_rays() { int drawEnd = lineHeight / 2 + $height / 2 + PITCH; if(drawEnd >= $height) drawEnd = $height - 1; - auto &texture = textures.get($map[mapY][mapX] - 1); + auto &texture = textures.get_texture($map[mapY][mapX] - 1); // calculate value of wallX double wallX; // where exactly the wall was hit @@ -273,9 +238,6 @@ void Raycaster::draw_ceiling_floor() { const int textureWidth = textures.TEXTURE_WIDTH; const int textureHeight = textures.TEXTURE_HEIGHT; - auto& floorTexture = textures.get(textures.floor); - auto& ceilingTexture = textures.get(textures.ceiling); - for(int y = $height / 2 + 1; y < $height; ++y) { // rayDir for leftmost ray (x=0) and rightmost (x = w) float rayDirX0 = dirX - planeX; @@ -327,11 +289,11 @@ void Raycaster::draw_ceiling_floor() { // floorX cellX to find the texture x/y. How? // FLOOR - color = floorTexture[textureWidth * ty + tx]; + color = textures.floor[textureWidth * ty + tx]; pixels[pixcoord(x, y)] = color; // CEILING - color = ceilingTexture[textureWidth * ty + tx]; + color = textures.ceiling[textureWidth * ty + tx]; pixels[pixcoord(x, $height - y - 1)] = color; } } diff --git a/raycaster.hpp b/raycaster.hpp index 45a8742..6f9c68f 100644 --- a/raycaster.hpp +++ b/raycaster.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -11,38 +10,11 @@ #include #include "dbc.hpp" #include +#include "texture.hpp" using matrix::Matrix; - -struct Sprite { - double x; - double y; - int texture; - // ZED: this should be a separate transform parameter - double elevation=0; - int uDiv=1; - int vDiv=1; -}; - using RGBA = uint32_t; -struct TexturePack { - int NUM_SPRITES=1; - int NUM_TEXTURES=11; - int TEXTURE_WIDTH=256; // must be power of two - int TEXTURE_HEIGHT=256; // must be power of two - - std::vector> images; - std::vector SPRITE{{4.0, 3.55, 8}}; - const int floor = 3; - const int ceiling = 6; - - void load_textures(); - std::vector load_image(const char *filename); - Sprite &get_sprite(size_t sprite_num); - std::vector& get(size_t num); -}; - struct Raycaster { int PITCH=0; diff --git a/texture.cpp b/texture.cpp new file mode 100644 index 0000000..7d8edc2 --- /dev/null +++ b/texture.cpp @@ -0,0 +1,41 @@ +#include "texture.hpp" +#include +#include "dbc.hpp" +#include +#include "config.hpp" + +using namespace fmt; + +Image TexturePack::load_image(std::string filename) { + Image texture(TEXTURE_WIDTH * TEXTURE_HEIGHT); + sf::Image img; + bool good = img.loadFromFile(filename); + dbc::check(good, format("failed to load {}", filename)); + + uint32_t *pixbuf = (uint32_t *)img.getPixelsPtr(); + std::copy_n(pixbuf, texture.size(), texture.begin()); + + return texture; +} + +void TexturePack::load_textures() { + Config assets("assets/config.json"); + for(string tile_path : assets["textures"]) { + images.emplace_back(load_image(tile_path)); + } + + for(string tile_path : assets["sprites"]) { + images.emplace_back(load_image(tile_path)); + } + + floor = load_image(assets["floor"]); + ceiling = load_image(assets["ceiling"]); +} + +Image& TexturePack::get_texture(size_t num) { + return images[num]; +} + +Sprite &TexturePack::get_sprite(size_t sprite_num) { + return sprites[sprite_num]; +} diff --git a/texture.hpp b/texture.hpp new file mode 100644 index 0000000..6795d8a --- /dev/null +++ b/texture.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +struct Sprite { + double x; + double y; + int texture; + // ZED: this should be a separate transform parameter + double elevation=0; + int uDiv=1; + int vDiv=1; +}; + +using Image = std::vector; + +struct TexturePack { + int NUM_SPRITES=1; + static const int TEXTURE_WIDTH=256; // must be power of two + static const int TEXTURE_HEIGHT=256; // must be power of two + + std::vector images; + std::vector sprites{{4.0, 3.55, 6}}; + Image floor; + Image ceiling; + + void load_textures(); + std::vector load_image(std::string filename); + Sprite &get_sprite(size_t sprite_num); + Image& get_texture(size_t num); +};