135 lines
2.8 KiB
C++
135 lines
2.8 KiB
C++
|
/**
|
||
|
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
|