|
|
|
@ -1,4 +1,5 @@ |
|
|
|
|
#include "amt/raycaster.hpp" |
|
|
|
|
#include "pixel.hpp" |
|
|
|
|
|
|
|
|
|
using namespace fmt; |
|
|
|
|
using std::make_unique; |
|
|
|
@ -7,16 +8,11 @@ using std::make_unique; |
|
|
|
|
#define gray_color(c) rgba_color(c, c, c, 255) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<uint32_t> TexturePack::load_image(const char *filename) { |
|
|
|
|
std::vector<uint32_t> texture(TEXTURE_WIDTH * TEXTURE_HEIGHT); |
|
|
|
|
amt::PixelBuf TexturePack::load_image(const char *filename) { |
|
|
|
|
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; |
|
|
|
|
return amt::PixelBuf(img.getPixelsPtr(), TEXTURE_HEIGHT, TEXTURE_WIDTH); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TexturePack::load_textures() { |
|
|
|
@ -31,7 +27,7 @@ void TexturePack::load_textures() { |
|
|
|
|
images.emplace_back(load_image("assets/portal.png")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<uint32_t>& TexturePack::get(size_t num) { |
|
|
|
|
amt::PixelBuf& TexturePack::get(size_t num) { |
|
|
|
|
return images[num]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -43,6 +39,7 @@ Sprite &TexturePack::get_sprite(size_t sprite_num) { |
|
|
|
|
|
|
|
|
|
Raycaster::Raycaster(sf::RenderWindow& window, Matrix &map, int width, int height) : |
|
|
|
|
$width(width), $height(height), |
|
|
|
|
pixels(static_cast<size_t>(height), static_cast<std::size_t>(width)), |
|
|
|
|
$window(window), |
|
|
|
|
$map(map), |
|
|
|
|
spriteOrder(textures.NUM_SPRITES), |
|
|
|
@ -53,7 +50,6 @@ Raycaster::Raycaster(sf::RenderWindow& window, Matrix &map, int width, int heigh |
|
|
|
|
view_texture.create($width, $height); |
|
|
|
|
view_sprite.setTexture(view_texture); |
|
|
|
|
view_sprite.setPosition(0, 0); |
|
|
|
|
pixels = make_unique<RGBA[]>($width * $height); |
|
|
|
|
textures.load_textures(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -68,13 +64,13 @@ void Raycaster::position_camera(float player_x, float player_y) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Raycaster::draw_pixel_buffer() { |
|
|
|
|
view_texture.update((uint8_t *)pixels.get(), $width, $height, 0, 0); |
|
|
|
|
view_texture.update(pixels.to_raw_buf(), $width, $height, 0, 0); |
|
|
|
|
// BUG: can I do this once and just update it?
|
|
|
|
|
$window.draw(view_sprite); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Raycaster::clear() { |
|
|
|
|
std::fill_n(pixels.get(), $width * $height, 0); |
|
|
|
|
pixels.fill({}); |
|
|
|
|
$window.clear(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -149,16 +145,15 @@ void Raycaster::sprite_casting() { |
|
|
|
|
int texY = ((d * textureHeight) / spriteHeight) / 256; |
|
|
|
|
//get current color from the texture
|
|
|
|
|
// BUG: this crashes sometimes when the math goes out of bounds
|
|
|
|
|
uint32_t color = sprite_texture[textureWidth * texY + texX]; |
|
|
|
|
auto color = sprite_texture[texY][texX]; |
|
|
|
|
// poor person's transparency, get current color from the texture
|
|
|
|
|
if((color & 0x00FFFFFF) != 0) { |
|
|
|
|
RGBA pixel = color; |
|
|
|
|
pixels[pixcoord(stripe, y)] = pixel; |
|
|
|
|
if((color.to_hex() & 0xFFFFFF00) != 0) { |
|
|
|
|
pixels[y][stripe] = color; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Raycaster::cast_rays() { |
|
|
|
@ -217,7 +212,7 @@ void Raycaster::cast_rays() { |
|
|
|
|
side = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if($map[mapX][mapY] > 0) hit = 1; |
|
|
|
|
if($map[mapY][mapX] > 0) hit = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(side == 0) { |
|
|
|
@ -234,7 +229,7 @@ void Raycaster::cast_rays() { |
|
|
|
|
int drawEnd = lineHeight / 2 + $height / 2 + PITCH; |
|
|
|
|
if(drawEnd >= $height) drawEnd = $height - 1; |
|
|
|
|
|
|
|
|
|
auto &texture = textures.get($map[mapX][mapY] - 1); |
|
|
|
|
auto &texture = textures.get($map[mapY][mapX] - 1); |
|
|
|
|
|
|
|
|
|
// calculate value of wallX
|
|
|
|
|
double wallX; // where exactly the wall was hit
|
|
|
|
@ -260,8 +255,7 @@ void Raycaster::cast_rays() { |
|
|
|
|
for(int y = drawStart; y < drawEnd; y++) { |
|
|
|
|
int texY = (int)texPos & (textures.TEXTURE_HEIGHT - 1); |
|
|
|
|
texPos += step; |
|
|
|
|
RGBA pixel = texture[textures.TEXTURE_HEIGHT * texY + texX]; |
|
|
|
|
pixels[pixcoord(x, y)] = pixel; |
|
|
|
|
pixels[y][x] = texture[texY][texX]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// SET THE ZBUFFER FOR THE SPRITE CASTING
|
|
|
|
@ -270,8 +264,8 @@ void Raycaster::cast_rays() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Raycaster::draw_ceiling_floor() { |
|
|
|
|
const int textureWidth = textures.TEXTURE_WIDTH; |
|
|
|
|
const int textureHeight = textures.TEXTURE_HEIGHT; |
|
|
|
|
const size_t textureWidth = textures.TEXTURE_WIDTH; |
|
|
|
|
const size_t textureHeight = textures.TEXTURE_HEIGHT; |
|
|
|
|
|
|
|
|
|
auto& floorTexture = textures.get(textures.floor); |
|
|
|
|
auto& ceilingTexture = textures.get(textures.ceiling); |
|
|
|
@ -322,19 +316,17 @@ void Raycaster::draw_ceiling_floor() { |
|
|
|
|
floorY += floorStepY; |
|
|
|
|
|
|
|
|
|
// now get the pixel from the texture
|
|
|
|
|
uint32_t color; |
|
|
|
|
// this uses the previous ty/tx fractional parts of
|
|
|
|
|
// floorX cellX to find the texture x/y. How?
|
|
|
|
|
|
|
|
|
|
// FLOOR
|
|
|
|
|
color = floorTexture[textureWidth * ty + tx]; |
|
|
|
|
pixels[pixcoord(x, y)] = color; |
|
|
|
|
pixels[y][x] = floorTexture[ty][tx]; |
|
|
|
|
|
|
|
|
|
// CEILING
|
|
|
|
|
color = ceilingTexture[textureWidth * ty + tx]; |
|
|
|
|
pixels[pixcoord(x, $height - y - 1)] = color; |
|
|
|
|
pixels[$height - y - 1][x] = ceilingTexture[ty][tx]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Raycaster::render() { |
|
|
|
@ -350,7 +342,7 @@ bool Raycaster::empty_space(int new_x, int new_y) { |
|
|
|
|
dbc::check((size_t)new_y < $map.rows(), |
|
|
|
|
format("y={} too high={}", new_y, $map.rows())); |
|
|
|
|
|
|
|
|
|
return $map[new_x][new_y] == 0; |
|
|
|
|
return $map[new_y][new_x] == 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|