Add z buffer

This commit is contained in:
Miloslav Číž 2018-09-04 15:52:12 +02:00
parent d24bf31d6e
commit 86d2334a52

136
game.cpp
View file

@ -15,8 +15,21 @@
#define SUBSAMPLE 2
#define SCREEN_WIDTH 110
#define SCREEN_HEIGHT 88
#define SUBSAMPLED_WIDTH (SCREEN_WIDTH / SUBSAMPLE)
#define SUBSAMPLED_HEIGHT (SCREEN_HEIGHT / SUBSAMPLE)
#define MIDDLE_ROW (SCREEN_HEIGHT / 2)
#define MIDDLE_COLUMN (SCREEN_WIDTH / 2)
#define SPRITES 6
Pokitto::Core p;
Unit zBuffer[SUBSAMPLED_WIDTH];
const unsigned char image[] =
{ 32, 32 // width, height
,0x12,0x12,0x12,0x12,0x12,0x12,0x00,0x09,0x00,0x12,0x12,0x12,0x12,0x12
@ -331,15 +344,19 @@ const unsigned char sprite[] =
inline uint8_t sampleImage(const unsigned char *image, Unit x, Unit y)
{
int32_t index = clamp(
image[1] * ((image[1] * y) / UNITS_PER_SQUARE) +
(image[0] * x) / UNITS_PER_SQUARE,
0, image[0] * image[1] - 1);
// TODO: optimize
x = wrap(x,UNITS_PER_SQUARE);
y = wrap(y,UNITS_PER_SQUARE);
int32_t index =
image[1] * ((image[1] * y) / UNITS_PER_SQUARE) + (image[0] * x) /
UNITS_PER_SQUARE;
return image[2 + index];
}
void drawSprite(const unsigned char *sprite, int16_t x, int16_t y, int16_t size)
void drawSprite(const unsigned char *sprite, int16_t x, int16_t y, Unit depth, int16_t size)
{
// TODO: optimize
@ -350,10 +367,21 @@ void drawSprite(const unsigned char *sprite, int16_t x, int16_t y, int16_t size)
uint8_t c;
for (Unit j = 0; j < size; ++j)
int16_t jTo = size - max(0,y + size - 88);
int16_t iTo = size - max(0,x + size - 110);
bool mask[SUBSAMPLED_WIDTH];
for (int i = 0; i < SUBSAMPLED_WIDTH; ++i)
mask[i] = zBuffer[i] > depth;
for (Unit j = max(-1 * y,0); j < jTo; ++j)
{
for (Unit i = 0; i < size; ++i)
for (Unit i = max(-1 * x,0); i < iTo; ++i)
{
if (!mask[i])
continue;
c = sampleImage(sprite,(i * UNITS_PER_SQUARE) / size,(j * UNITS_PER_SQUARE) / size);
if (c != 0xff)
@ -414,6 +442,13 @@ public:
}
};
class Sprite
{
public:
Vector2D mPosition;
Unit mHeight;
};
class Character
{
public:
@ -433,6 +468,7 @@ public:
Character player;
Level level;
Sprite sprites[SPRITES];
Unit heightFunc(int16_t x, int16_t y)
{
@ -441,6 +477,9 @@ Unit heightFunc(int16_t x, int16_t y)
inline void pixelFunc(PixelInfo pixel)
{
if (pixel.position.y == MIDDLE_ROW)
zBuffer[pixel.position.x] = pixel.depth;
uint8_t c;
Unit depth = pixel.depth - UNITS_PER_SQUARE;
@ -489,25 +528,32 @@ void draw()
render(player.mCamera,heightFunc,pixelFunc,c);
Vector2D v;
v.x = 5 * UNITS_PER_SQUARE;
v.y = 7 * UNITS_PER_SQUARE;
PixelInfo pos = mapToScreen(v,UNITS_PER_SQUARE / 4,player.mCamera);
for (uint8_t i = 0; i < SPRITES; ++i)
{
PixelInfo pos = mapToScreen(sprites[i].mPosition,sprites[i].mHeight,player.mCamera);
if (pos.depth > 0)
drawSprite(sprite,pos.position.x * SUBSAMPLE,pos.position.y,perspectiveScale(32,pos.depth));
p.display.setColor(rgbToIndex(7,7,3));
p.display.setCursor(1,1);
p.display.print(player.mCamera.position.x);
p.display.print(" ");
p.display.print(player.mCamera.position.y);
p.display.print(" ");
p.display.print(player.mCamera.direction);
if (pos.depth > 0)
drawSprite(sprite,pos.position.x * SUBSAMPLE,pos.position.y,
pos.depth,perspectiveScale(32,pos.depth));
}
}
int main()
{
#define placeSprite(I,X,Y,Z)\
sprites[I].mPosition.x = X * UNITS_PER_SQUARE + UNITS_PER_SQUARE / 2;\
sprites[I].mPosition.y = Y * UNITS_PER_SQUARE + UNITS_PER_SQUARE / 2;\
sprites[I].mHeight = Z * UNITS_PER_SQUARE + UNITS_PER_SQUARE / 2;
placeSprite(0,5,7,0)
placeSprite(1,6,7,0)
placeSprite(2,5,8,0)
placeSprite(3,6,8,0)
placeSprite(4,-1,-2,1)
placeSprite(5,1,11,1)
#undef placeSprite
p.begin();
for (uint8_t r = 0; r < 8; ++r)
@ -541,26 +587,50 @@ int main()
d.y = d.y > 0 ? step : -step;
}
bool strafe = p.aBtn();
if (p.upBtn())
{
player.mCamera.position.x += d.x;
player.mCamera.position.y += d.y;
if (strafe)
player.mCamera.height += step;
else
{
player.mCamera.position.x += d.x;
player.mCamera.position.y += d.y;
}
}
else if (p.downBtn())
{
player.mCamera.position.x -= d.x;
player.mCamera.position.y -= d.y;
if (strafe)
player.mCamera.height -= step;
else
{
player.mCamera.position.x -= d.x;
player.mCamera.position.y -= d.y;
}
}
if (p.rightBtn())
player.mCamera.direction += step2;
else if (p.leftBtn())
player.mCamera.direction -= step2;
if (strafe)
{
d = angleToDirection(player.mCamera.direction + UNITS_PER_SQUARE / 4);
d.x = (d.x * step) / UNITS_PER_SQUARE;
d.y = (d.y * step) / UNITS_PER_SQUARE;
}
if (p.aBtn())
player.mCamera.height += step;
else if (p.bBtn())
player.mCamera.height -= step;
int addition = 0;
if (p.rightBtn())
addition = 1;
else if (p.leftBtn())
addition = -1;
if (strafe)
{
player.mCamera.position.x += addition * d.x;
player.mCamera.position.y += addition * d.y;
}
else
player.mCamera.direction += addition * step2;
player.mCamera.height =
max(heightFunc(player.mCamera.position.x / UNITS_PER_SQUARE,player.mCamera.position.y / UNITS_PER_SQUARE) + UNITS_PER_SQUARE / 2,player.mCamera.height);