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 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; Pokitto::Core p;
Unit zBuffer[SUBSAMPLED_WIDTH];
const unsigned char image[] = const unsigned char image[] =
{ 32, 32 // width, height { 32, 32 // width, height
,0x12,0x12,0x12,0x12,0x12,0x12,0x00,0x09,0x00,0x12,0x12,0x12,0x12,0x12 ,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) inline uint8_t sampleImage(const unsigned char *image, Unit x, Unit y)
{ {
int32_t index = clamp( // TODO: optimize
image[1] * ((image[1] * y) / UNITS_PER_SQUARE) +
(image[0] * x) / UNITS_PER_SQUARE, x = wrap(x,UNITS_PER_SQUARE);
0, image[0] * image[1] - 1); 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]; 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 // TODO: optimize
@ -350,10 +367,21 @@ void drawSprite(const unsigned char *sprite, int16_t x, int16_t y, int16_t size)
uint8_t c; 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); c = sampleImage(sprite,(i * UNITS_PER_SQUARE) / size,(j * UNITS_PER_SQUARE) / size);
if (c != 0xff) if (c != 0xff)
@ -414,6 +442,13 @@ public:
} }
}; };
class Sprite
{
public:
Vector2D mPosition;
Unit mHeight;
};
class Character class Character
{ {
public: public:
@ -433,6 +468,7 @@ public:
Character player; Character player;
Level level; Level level;
Sprite sprites[SPRITES];
Unit heightFunc(int16_t x, int16_t y) 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) inline void pixelFunc(PixelInfo pixel)
{ {
if (pixel.position.y == MIDDLE_ROW)
zBuffer[pixel.position.x] = pixel.depth;
uint8_t c; uint8_t c;
Unit depth = pixel.depth - UNITS_PER_SQUARE; Unit depth = pixel.depth - UNITS_PER_SQUARE;
@ -489,25 +528,32 @@ void draw()
render(player.mCamera,heightFunc,pixelFunc,c); render(player.mCamera,heightFunc,pixelFunc,c);
Vector2D v; for (uint8_t i = 0; i < SPRITES; ++i)
v.x = 5 * UNITS_PER_SQUARE; {
v.y = 7 * UNITS_PER_SQUARE; PixelInfo pos = mapToScreen(sprites[i].mPosition,sprites[i].mHeight,player.mCamera);
PixelInfo pos = mapToScreen(v,UNITS_PER_SQUARE / 4,player.mCamera);
if (pos.depth > 0) if (pos.depth > 0)
drawSprite(sprite,pos.position.x * SUBSAMPLE,pos.position.y,perspectiveScale(32,pos.depth)); drawSprite(sprite,pos.position.x * SUBSAMPLE,pos.position.y,
pos.depth,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);
} }
int main() 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(); p.begin();
for (uint8_t r = 0; r < 8; ++r) for (uint8_t r = 0; r < 8; ++r)
@ -541,26 +587,50 @@ int main()
d.y = d.y > 0 ? step : -step; d.y = d.y > 0 ? step : -step;
} }
bool strafe = p.aBtn();
if (p.upBtn()) if (p.upBtn())
{ {
player.mCamera.position.x += d.x; if (strafe)
player.mCamera.position.y += d.y; player.mCamera.height += step;
else
{
player.mCamera.position.x += d.x;
player.mCamera.position.y += d.y;
}
} }
else if (p.downBtn()) else if (p.downBtn())
{ {
player.mCamera.position.x -= d.x; if (strafe)
player.mCamera.position.y -= d.y; player.mCamera.height -= step;
else
{
player.mCamera.position.x -= d.x;
player.mCamera.position.y -= d.y;
}
} }
if (p.rightBtn()) if (strafe)
player.mCamera.direction += step2; {
else if (p.leftBtn()) d = angleToDirection(player.mCamera.direction + UNITS_PER_SQUARE / 4);
player.mCamera.direction -= step2; d.x = (d.x * step) / UNITS_PER_SQUARE;
d.y = (d.y * step) / UNITS_PER_SQUARE;
}
if (p.aBtn()) int addition = 0;
player.mCamera.height += step;
else if (p.bBtn()) if (p.rightBtn())
player.mCamera.height -= step; 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 = 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); max(heightFunc(player.mCamera.position.x / UNITS_PER_SQUARE,player.mCamera.position.y / UNITS_PER_SQUARE) + UNITS_PER_SQUARE / 2,player.mCamera.height);