From 86d2334a52fb4adf7de0489fcce3d18a1bfb5518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Tue, 4 Sep 2018 15:52:12 +0200 Subject: [PATCH] Add z buffer --- game.cpp | 142 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 36 deletions(-) diff --git a/game.cpp b/game.cpp index 658aaa5..17e51ba 100644 --- a/game.cpp +++ b/game.cpp @@ -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,12 +367,23 @@ 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) - { - for (Unit i = 0; i < size; ++i) - { - c = sampleImage(sprite,(i * UNITS_PER_SQUARE) / size,(j * UNITS_PER_SQUARE) / size); + 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 = 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) p.display.drawPixel(x + i,y + j,c); } @@ -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);