diff --git a/gui.cpp b/gui.cpp index 4f9a384..a4c8dc5 100644 --- a/gui.cpp +++ b/gui.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "SDL.h" #include "map.h" @@ -12,15 +13,18 @@ int main() { FrameBuffer fb{1024, 512, std::vector(1024*512, pack_color(255, 255, 255))}; - Player player{3.456, 2.345, 1.523, M_PI/3., 0, 0}; - Map map; - Texture tex_walls("../walltext.png"); - Texture tex_monst("../monsters.png"); - if (!tex_walls.count || !tex_monst.count) { + GameState gs{ Map(), // game map + {3.456, 2.345, 1.523, M_PI/3., 0, 0}, // player + { {3.523, 3.812, 2, 0}, // monsters lists + {1.834, 8.765, 0, 0}, + {5.323, 5.365, 1, 0}, + {4.123, 10.76, 1, 0} }, + Texture("../walltext.png"), // textures for the walls + Texture("../monsters.png") }; // textures for the monsters + if (!gs.tex_walls.count || !gs.tex_monst.count) { std::cerr << "Failed to load textures" << std::endl; return -1; } - std::vector sprites{ {3.523, 3.812, 2, 0}, {1.834, 8.765, 0, 0}, {5.323, 5.365, 1, 0}, {4.123, 10.765, 1, 0} }; SDL_Window *window = nullptr; SDL_Renderer *renderer = nullptr; @@ -42,27 +46,31 @@ int main() { if (SDL_PollEvent(&event)) { if (SDL_QUIT==event.type || (SDL_KEYDOWN==event.type && SDLK_ESCAPE==event.key.keysym.sym)) break; if (SDL_KEYUP==event.type) { - if ('a'==event.key.keysym.sym || 'd'==event.key.keysym.sym) player.turn = 0; - if ('w'==event.key.keysym.sym || 's'==event.key.keysym.sym) player.walk = 0; + if ('a'==event.key.keysym.sym || 'd'==event.key.keysym.sym) gs.player.turn = 0; + if ('w'==event.key.keysym.sym || 's'==event.key.keysym.sym) gs.player.walk = 0; } if (SDL_KEYDOWN==event.type) { - if ('a'==event.key.keysym.sym) player.turn = -1; - if ('d'==event.key.keysym.sym) player.turn = 1; - if ('w'==event.key.keysym.sym) player.walk = 1; - if ('s'==event.key.keysym.sym) player.walk = -1; + if ('a'==event.key.keysym.sym) gs.player.turn = -1; + if ('d'==event.key.keysym.sym) gs.player.turn = 1; + if ('w'==event.key.keysym.sym) gs.player.walk = 1; + if ('s'==event.key.keysym.sym) gs.player.walk = -1; } } - player.a += float(player.turn)*.05; - float nx = player.x + player.walk*cos(player.a)*.1; - float ny = player.y + player.walk*sin(player.a)*.1; + gs.player.a += float(gs.player.turn)*.05; + float nx = gs.player.x + gs.player.walk*cos(gs.player.a)*.1; + float ny = gs.player.y + gs.player.walk*sin(gs.player.a)*.1; - if (int(nx)>=0 && int(nx)=0 && int(ny)=0 && int(nx)=0 && int(ny)(fb.img.data()), fb.w*4); SDL_RenderClear(renderer); diff --git a/map.cpp b/map.cpp index 4d71a98..6a762c0 100644 --- a/map.cpp +++ b/map.cpp @@ -24,12 +24,12 @@ Map::Map() : w(16), h(16) { assert(sizeof(map) == w*h+1); // +1 for the null terminated string } -int Map::get(const size_t i, const size_t j) { +int Map::get(const size_t i, const size_t j) const { assert(i Texture::get_scaled_column(const size_t texture_id, const size_t tex_coord, const size_t column_height) { +std::vector Texture::get_scaled_column(const size_t texture_id, const size_t tex_coord, const size_t column_height) const { assert(tex_coord column(column_height); for (size_t y=0; y img; // textures storage container Texture(const std::string filename); - uint32_t &get(const size_t i, const size_t j, const size_t idx); // get the pixel (i,j) from the texture idx - std::vector get_scaled_column(const size_t texture_id, const size_t tex_coord, const size_t column_height); // retrieve one column (tex_coord) from the texture texture_id and scale it to the destination size + uint32_t get(const size_t i, const size_t j, const size_t idx) const; // get the pixel (i,j) from the texture idx + std::vector get_scaled_column(const size_t texture_id, const size_t tex_coord, const size_t column_height) const; // retrieve one column (tex_coord) from the texture texture_id and scale it to the destination size }; #endif // TEXTURES_H diff --git a/tinyraycaster.cpp b/tinyraycaster.cpp index 7023620..7522ffd 100644 --- a/tinyraycaster.cpp +++ b/tinyraycaster.cpp @@ -1,7 +1,6 @@ #define _USE_MATH_DEFINES #include #include -#include #include #include #include @@ -14,8 +13,9 @@ #include "sprite.h" #include "framebuffer.h" #include "textures.h" +#include "tinyraycaster.h" -int wall_x_texcoord(const float hitx, const float hity, Texture &tex_walls) { +int wall_x_texcoord(const float hitx, const float hity, const Texture &tex_walls) { float x = hitx - floor(hitx+.5); // x and y contain (signed) fractional parts of hitx and hity, float y = hity - floor(hity+.5); // they vary between -0.5 and +0.5, and one of them is supposed to be very close to 0 int tex = x*tex_walls.size; @@ -27,13 +27,23 @@ int wall_x_texcoord(const float hitx, const float hity, Texture &tex_walls) { return tex; } -void map_show_sprite(Sprite &sprite, FrameBuffer &fb, Map &map) { - const size_t rect_w = fb.w/(map.w*2); // size of one map cell on the screen - const size_t rect_h = fb.h/map.h; - fb.draw_rectangle(sprite.x*rect_w-3, sprite.y*rect_h-3, 6, 6, pack_color(255, 0, 0)); +void draw_map(FrameBuffer &fb, const std::vector &sprites, const Texture &tex_walls, const Map &map, const size_t cell_w, const size_t cell_h) { + for (size_t j=0; j &depth_buffer, FrameBuffer &fb, Player &player, Texture &tex_sprites) { +void draw_sprite(FrameBuffer &fb, const Sprite &sprite, const std::vector &depth_buffer, const Player &player, const Texture &tex_sprites) { // absolute direction from the player to the sprite (in radians) float sprite_dir = atan2(sprite.y - player.y, sprite.x - player.x); while (sprite_dir - player.a > M_PI) sprite_dir -= 2*M_PI; // remove unncesessary periods from the relative direction @@ -57,35 +67,31 @@ void draw_sprite(Sprite &sprite, std::vector &depth_buffer, FrameBuffer & } } -void render(FrameBuffer &fb, Map &map, Player &player, std::vector &sprites, Texture &tex_walls, Texture &tex_monst) { +void render(FrameBuffer &fb, const GameState &gs) { + const Map &map = gs.map; + const Player &player = gs.player; + const std::vector &sprites = gs.monsters; + const Texture &tex_walls = gs.tex_walls; + const Texture &tex_monst = gs.tex_monst; + fb.clear(pack_color(255, 255, 255)); // clear the screen - const size_t rect_w = fb.w/(map.w*2); // size of one map cell on the screen - const size_t rect_h = fb.h/map.h; - for (size_t j=0; j depth_buffer(fb.w/2, 1e3); + for (size_t i=0; i &spri } // ray marching loop } // field of view ray sweeping - for (size_t i=0; i &sprites, Texture &tex_walls, Texture &tex_monst); +struct GameState { + Map map; + Player player; + std::vector monsters; + Texture tex_walls; + Texture tex_monst; +}; + +void render(FrameBuffer &fb, const GameState &gs); #endif // TINYRAYCASTER_H