mirror of
https://github.com/ssloy/tinyraycaster.git
synced 2025-09-01 09:53:50 +02:00
monsters shown on the map
This commit is contained in:
BIN
doc/013.png
Normal file
BIN
doc/013.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
@@ -27,4 +27,3 @@ void FrameBuffer::clear(const uint32_t color) {
|
|||||||
img = std::vector<uint32_t>(w*h, color);
|
img = std::vector<uint32_t>(w*h, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BIN
monsters.png
BIN
monsters.png
Binary file not shown.
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 8.6 KiB |
12
sprite.h
Normal file
12
sprite.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef SPRITE_H
|
||||||
|
#define SPRITE_H
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
struct Sprite {
|
||||||
|
float x, y;
|
||||||
|
size_t tex_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SPRITE_H
|
||||||
|
|
@@ -7,7 +7,7 @@ struct Texture {
|
|||||||
std::vector<uint32_t> img; // textures storage container
|
std::vector<uint32_t> img; // textures storage container
|
||||||
|
|
||||||
Texture(const std::string filename);
|
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 textrue idx
|
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<uint32_t> 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
|
std::vector<uint32_t> 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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -10,22 +10,29 @@
|
|||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "sprite.h"
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "textures.h"
|
#include "textures.h"
|
||||||
|
|
||||||
int wall_x_texcoord(const float x, const float y, Texture &tex_walls) {
|
int wall_x_texcoord(const float hitx, const float hity, Texture &tex_walls) {
|
||||||
float hitx = x - floor(x+.5); // hitx and hity contain (signed) fractional parts of x and y,
|
float x = hitx - floor(hitx+.5); // x and y contain (signed) fractional parts of hitx and hity,
|
||||||
float hity = y - floor(y+.5); // they vary between -0.5 and +0.5, and one of them is supposed to be very close to 0
|
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 = hitx*tex_walls.size;
|
int tex = x*tex_walls.size;
|
||||||
if (std::abs(hity)>std::abs(hitx)) // we need to determine whether we hit a "vertical" or a "horizontal" wall (w.r.t the map)
|
if (std::abs(y)>std::abs(x)) // we need to determine whether we hit a "vertical" or a "horizontal" wall (w.r.t the map)
|
||||||
tex = hity*tex_walls.size;
|
tex = y*tex_walls.size;
|
||||||
if (tex<0) // do not forget x_texcoord can be negative, fix that
|
if (tex<0) // do not forget x_texcoord can be negative, fix that
|
||||||
tex += tex_walls.size;
|
tex += tex_walls.size;
|
||||||
assert(tex>=0 && tex<(int)tex_walls.size);
|
assert(tex>=0 && tex<(int)tex_walls.size);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void render(FrameBuffer &fb, Map &map, Player &player, Texture &tex_walls) {
|
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 render(FrameBuffer &fb, Map &map, Player &player, std::vector<Sprite> &sprites, Texture &tex_walls, Texture &tex_monst) {
|
||||||
fb.clear(pack_color(255, 255, 255)); // clear the screen
|
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_w = fb.w/(map.w*2); // size of one map cell on the screen
|
||||||
@@ -52,7 +59,8 @@ void render(FrameBuffer &fb, Map &map, Player &player, Texture &tex_walls) {
|
|||||||
|
|
||||||
size_t texid = map.get(x, y); // our ray touches a wall, so draw the vertical column to create an illusion of 3D
|
size_t texid = map.get(x, y); // our ray touches a wall, so draw the vertical column to create an illusion of 3D
|
||||||
assert(texid<tex_walls.count);
|
assert(texid<tex_walls.count);
|
||||||
size_t column_height = fb.h/(t*cos(angle-player.a));
|
float dist = t*cos(angle-player.a);
|
||||||
|
size_t column_height = fb.h/dist;
|
||||||
int x_texcoord = wall_x_texcoord(x, y, tex_walls);
|
int x_texcoord = wall_x_texcoord(x, y, tex_walls);
|
||||||
std::vector<uint32_t> column = tex_walls.get_scaled_column(texid, x_texcoord, column_height);
|
std::vector<uint32_t> column = tex_walls.get_scaled_column(texid, x_texcoord, column_height);
|
||||||
int pix_x = i + fb.w/2; // we are drawing at the right half of the screen, thus +fb.w/2
|
int pix_x = i + fb.w/2; // we are drawing at the right half of the screen, thus +fb.w/2
|
||||||
@@ -65,6 +73,10 @@ void render(FrameBuffer &fb, Map &map, Player &player, Texture &tex_walls) {
|
|||||||
break;
|
break;
|
||||||
} // ray marching loop
|
} // ray marching loop
|
||||||
} // field of view ray sweeping
|
} // field of view ray sweeping
|
||||||
|
|
||||||
|
for (size_t i=0; i<sprites.size(); i++) {
|
||||||
|
map_show_sprite(sprites[i], fb, map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@@ -72,19 +84,15 @@ int main() {
|
|||||||
Player player{3.456, 2.345, 1.523, M_PI/3.};
|
Player player{3.456, 2.345, 1.523, M_PI/3.};
|
||||||
Map map;
|
Map map;
|
||||||
Texture tex_walls("../walltext.png");
|
Texture tex_walls("../walltext.png");
|
||||||
if (!tex_walls.count) {
|
Texture tex_monst("../monsters.png");
|
||||||
std::cerr << "Failed to load wall textures" << std::endl;
|
if (!tex_walls.count || !tex_monst.count) {
|
||||||
|
std::cerr << "Failed to load textures" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
std::vector<Sprite> sprites{ {1.834, 8.765, 0}, {5.323, 5.365, 1}, {4.123, 10.265, 1} };
|
||||||
|
|
||||||
for (size_t frame=0; frame<360; frame++) {
|
render(fb, map, player, sprites, tex_walls, tex_monst);
|
||||||
std::stringstream ss;
|
drop_ppm_image("./out.ppm", fb.img, fb.w, fb.h);
|
||||||
ss << std::setfill('0') << std::setw(5) << frame << ".ppm";
|
|
||||||
player.a += 2*M_PI/360;
|
|
||||||
|
|
||||||
render(fb, map, player, tex_walls);
|
|
||||||
drop_ppm_image(ss.str(), fb.img, fb.w, fb.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user