Now have a basic sprite system that uses SFML's sprites, but the algorithm for determining how much of a sprite to display is wrong. Need to use the alternate algorithm from LODE's tutorial that draws sprites after rendering.
This commit is contained in:
parent
024d5b30e1
commit
da7075864b
6 changed files with 38 additions and 36 deletions
|
@ -17,7 +17,7 @@ union ColorConv {
|
|||
};
|
||||
|
||||
inline uint32_t dumb_lighting(uint32_t pixel, double distance) {
|
||||
if(distance < 1) return pixel;
|
||||
if(distance < 1.0) return pixel;
|
||||
|
||||
ColorConv conv{.as_int=pixel};
|
||||
conv.as_color.r /= distance;
|
||||
|
@ -84,7 +84,8 @@ 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);
|
||||
// auto& sprite_texture = $textures.get_texture(sprite_rec.texture);
|
||||
sf::Sprite *sf_sprite = sprite_rec.sprite;
|
||||
|
||||
double spriteX = sprite_rec.x - $posX;
|
||||
double spriteY = sprite_rec.y - $posY;
|
||||
|
@ -103,18 +104,10 @@ void Raycaster::sprite_casting() {
|
|||
|
||||
int spriteScreenX = int(($width / 2) * (1 + transformX / transformY));
|
||||
|
||||
int vMoveScreen = int(sprite_rec.elevation * -1 / transformY);
|
||||
|
||||
// calculate the height of the sprite on screen
|
||||
//using "transformY" instead of the real distance prevents fisheye
|
||||
int spriteHeight = abs(int($height / transformY)) / sprite_rec.vDiv;
|
||||
|
||||
//calculate lowest and highest pixel to fill in current stripe
|
||||
int drawStartY = -spriteHeight / 2 + $height / 2 + vMoveScreen;
|
||||
if(drawStartY < 0) drawStartY = 0;
|
||||
int drawEndY = spriteHeight / 2 + $height / 2 + vMoveScreen;
|
||||
if(drawEndY >= $height) drawEndY = $height - 1;
|
||||
|
||||
// calculate width the the sprite
|
||||
// same as height of sprite, given that it's square
|
||||
int spriteWidth = abs(int($height / transformY)) / sprite_rec.uDiv;
|
||||
|
@ -123,29 +116,29 @@ void Raycaster::sprite_casting() {
|
|||
int drawEndX = spriteWidth / 2 + spriteScreenX;
|
||||
if(drawEndX > $width) drawEndX = $width;
|
||||
|
||||
//loop through every vertical stripe of the sprite on screen
|
||||
for(int stripe = drawStartX; stripe < drawEndX; stripe++) {
|
||||
int texX = int(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) * textureWidth / spriteWidth) / 256;
|
||||
// the conditions in the if are:
|
||||
// 1) it's in front of the camera plane so you don't see things behind you
|
||||
// 2) ZBuffer, with perpendicular distance
|
||||
if(transformY > 0 && transformY < ZBuffer[stripe]) {
|
||||
for(int y = drawStartY; y < drawEndY; y++) {
|
||||
//256 and 128 factors to avoid floats
|
||||
int d = (y - vMoveScreen) * 256 - $height * 128 + spriteHeight * 128;
|
||||
int texY = ((d * textureHeight) / spriteHeight) / 256;
|
||||
//get current color from the texture
|
||||
// BUG: this crashes sometimes when the math goes out of bounds
|
||||
int index = textureWidth * texY + texX;
|
||||
if(index < 0 || (size_t)index >= sprite_texture.size()) continue;
|
||||
uint32_t color = sprite_texture[index];
|
||||
// poor person's transparency, get current color from the texture
|
||||
if((color & 0x00FFFFFF) != 0) {
|
||||
RGBA pixel = color;
|
||||
$pixels[pixcoord(stripe, y)] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(drawStartX < drawEndX && transformY > 0 && transformY < ZBuffer[drawStartX]) {
|
||||
int vMoveScreen = int(sprite_rec.elevation * -1 / transformY);
|
||||
//calculate lowest and highest pixel to fill in current stripe
|
||||
int drawStartY = -spriteHeight / 2 + $height / 2 + vMoveScreen;
|
||||
if(drawStartY < 0) drawStartY = 0;
|
||||
int drawEndY = spriteHeight / 2 + $height / 2 + vMoveScreen;
|
||||
if(drawEndY >= $height) drawEndY = $height - 1;
|
||||
|
||||
float x = float(drawStartX + RAY_VIEW_X);
|
||||
float y = float(drawStartY + RAY_VIEW_Y);
|
||||
float sprite_w = float(spriteWidth) / float(textureWidth);
|
||||
float sprite_h = float(spriteHeight) / float(textureHeight);
|
||||
int texX = int(256 * (drawStartX - (-spriteWidth / 2 + spriteScreenX)) * textureWidth / spriteWidth) / 256;
|
||||
int texX_end = int(256 * (drawEndX - (-spriteWidth / 2 + spriteScreenX)) * textureWidth / spriteWidth) / 256;
|
||||
|
||||
int d = (y - vMoveScreen) * 256 - $height * 128 + spriteHeight * 128;
|
||||
int texY = ((d * textureHeight) / spriteHeight) / 256;
|
||||
|
||||
sf_sprite->setScale({sprite_h, sprite_w});
|
||||
sf_sprite->setTextureRect(sf::IntRect({texX, texY}, {texX_end, textureHeight}));
|
||||
sf_sprite->setPosition({x, y});
|
||||
$window.draw(*sf_sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -328,8 +321,8 @@ void Raycaster::draw_ceiling_floor() {
|
|||
void Raycaster::render() {
|
||||
draw_ceiling_floor();
|
||||
cast_rays();
|
||||
sprite_casting();
|
||||
draw_pixel_buffer();
|
||||
sprite_casting();
|
||||
}
|
||||
|
||||
bool Raycaster::empty_space(int new_x, int new_y) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue