/** General definitions for Pokitto raycasting demos. author: Miloslav "drummyfish" Ciz license: CC0 1.0 */ #ifndef RAYCAST_DEMO_GENERAL_HPP #define RAYCAST_DEMO_GENERAL_HPP #include "stdio.h" // for debugging raycastlibg #define VERTICAL_FOV UNITS_PER_SQUARE // redefine camera vertical FOV #include "raycastlib.h" #include "Pokitto.h" Pokitto::Core pokitto; #define SCREEN_WIDTH 110 #define SCREEN_HEIGHT 88 #define MIDDLE_ROW (SCREEN_HEIGHT / 2) #define MIDDLE_COLUMN (SCREEN_WIDTH / 2) #ifndef SUBSAMPLE #define SUBSAMPLE 2 #endif #define SUBSAMPLED_WIDTH (SCREEN_WIDTH / SUBSAMPLE) #define TRANSPARENT_COLOR 0b00000111 Unit zBuffer[SUBSAMPLED_WIDTH]; ///< 1D z-buffer for visibility determination. /** Gets (the index of) color by specified RGB components. @param r red, 3 bits (0 to 7) @param g green, 3 bits (0 to 7) @param b blue, 2 bits (0 to 3) @return palette index of the color */ inline uint8_t rgbToIndex(uint8_t r, uint8_t g, uint8_t b) { return (r & 0b00000111) | ((g & 0b00000111) << 3) | ((b & 0b00000011) << 6); } /** Adds given intensity to a color. @param color input color @param intensity intensity to add, 3 bit (0 to 7) @return new color */ inline uint8_t addIntensity(uint8_t color, int intensity) { uint8_t r = color & 0b00000111; uint8_t g = (color & 0b00111000) >> 3; uint8_t b = (color & 0b11000000) >> 6; if (intensity >= 0) { r += intensity; r = r > 7 ? 7 : r; g += intensity; g = g > 7 ? 7 : g; b += intensity / 2; b = b > 3 ? 3 : b; } else { intensity *= -1; r = (intensity > r) ? 0 : r - intensity; g = (intensity > g) ? 0 : g - intensity; intensity /= 2; b = intensity > b ? 0 : b - intensity; } return rgbToIndex(r,g,b); } /** Samples an image by normalized coordinates - each coordinate is in range 0 to UNITS_PER_SQUARE (from raycastlib). */ inline uint8_t sampleImage(const unsigned char *image, Unit x, Unit y) { // TODO: optimize x = wrap(x,UNITS_PER_SQUARE); y = wrap(y,UNITS_PER_SQUARE); int32_t index = image[1] * ((image[1] * x) / UNITS_PER_SQUARE) + (image[0] * y) / UNITS_PER_SQUARE; return image[2 + index]; } void inline drawSprite(const unsigned char *sprite, int16_t x, int16_t y, Unit depth, int16_t size) { // TODO: optimize x -= size / 2; y -= size / 2; Unit step = UNITS_PER_SQUARE / size; uint8_t c; int16_t jTo = size - max(0,y + size - 88); int16_t iTo = size - max(0,x + size - 110); for (Unit i = max(-1 * x,0); i < iTo; ++i) { int16_t xPos = x + i; if (zBuffer[xPos / SUBSAMPLE] <= depth) continue; for (Unit j = max(-1 * y,0); j < jTo; ++j) { c = sampleImage(sprite,(i * UNITS_PER_SQUARE) / size,(j * UNITS_PER_SQUARE) / size); if (c != TRANSPARENT_COLOR) pokitto.display.drawPixel(xPos,y + j,c); } } } #endif