Skip to content
Permalink
Browse files

Camera movement tweaks. Better sprite scaling

  • Loading branch information...
jhhoward committed May 7, 2019
1 parent 7d860e5 commit ab88af1da17102a65c49aaf097c7de5ca6cb0047
Showing with 311 additions and 8 deletions.
  1. +213 −3 Source/Arduboy3D/Draw.cpp
  2. +1 −0 Source/Arduboy3D/Draw.h
  3. +48 −5 Source/Arduboy3D/Game.cpp
  4. +49 −0 Source/Windows/Arduboy3D/WinMain.cpp
@@ -423,7 +423,28 @@ void DrawCells()
}
}


const uint8_t testSprite[] PROGMEM =
{
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0,
0, 0, 2, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0,
0, 0, 2, 0, 1, 0, 0, 0, 1, 0, 0, 2, 2, 2, 2, 0,
0, 0, 2, 1, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0,
0, 2, 2, 2, 0, 0, 0, 0, 1, 0, 0, 2, 2, 2, 2, 0,
0, 0, 2, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 2, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 2, 2, 2, 2, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0,
};

const uint8_t testSprite2[] PROGMEM =
{
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
@@ -443,12 +464,95 @@ const uint8_t testSprite[] PROGMEM =
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
};

#if 0
void DrawScaled4x(const uint8_t* data, int x, int y, uint8_t halfSize)
{
uint8_t size = 2 * halfSize;

if (size > MAX_SPRITE_SIZE * 4)
{
return;
}

const uint8_t* lut = scaleLUT + ((halfSize / 4) * (halfSize / 4));

uint8_t u0 = 0;
uint8_t u1 = 0;
uint8_t u2;
uint8_t up, px, down;
int outX = x;

for (int i = 0; i < size && outX < DISPLAY_WIDTH; i++)
{
uint8_t v0 = 0;
uint8_t v1 = 0;
uint8_t v2;

u2 = pgm_read_byte(&lut[(i + 1) / 4]);

up = 0;
px = pgm_read_byte(&data[0]);

if (outX >= 0 && wBuffer[outX] < halfSize)
{
int outY = y;

for (int j = 0; j < size && outY < DISPLAY_HEIGHT; j++)
{
v2 = pgm_read_byte(&lut[(j + 1) / 4]);
down = pgm_read_byte(&data[v2 * BASE_SPRITE_SIZE + u1]);

if (outY >= 0 && outY < DISPLAY_HEIGHT)
{
if (px)
{
if (i == 0 || j == 0 || i == size - 1 || j == size - 1)
{
PutPixel(outX, outY, COLOUR_BLACK);
}
else if (px == 2)
{
PutPixel(outX, outY, COLOUR_BLACK);
}
else
{
PutPixel(outX, outY, COLOUR_WHITE);
}
}
else
{
uint8_t left = pgm_read_byte(&data[v1 * BASE_SPRITE_SIZE + u0]);
uint8_t right = pgm_read_byte(&data[v1 * BASE_SPRITE_SIZE + u2]);

if ((up | down | left | right) & 1)
{
PutPixel(outX, outY, COLOUR_BLACK);
}
}
}

v0 = v1;
v1 = v2;

up = px;
px = down;
outY++;
}
}

u0 = u1;
u1 = u2;
outX++;
}
}

void DrawScaled2x(const uint8_t* data, int x, int y, uint8_t halfSize)
{
uint8_t size = 2 * halfSize;

if (size > MAX_SPRITE_SIZE * 2)
{
DrawScaled4x(data, x, y, halfSize);
return;
}

@@ -502,7 +606,7 @@ void DrawScaled2x(const uint8_t* data, int x, int y, uint8_t halfSize)
uint8_t left = pgm_read_byte(&data[v1 * BASE_SPRITE_SIZE + u0]);
uint8_t right = pgm_read_byte(&data[v1 * BASE_SPRITE_SIZE + u2]);

if (up | down | left | right)
if ((up | down | left | right) & 1)
{
PutPixel(outX, outY, COLOUR_BLACK);
}
@@ -587,7 +691,7 @@ void DrawScaled(const uint8_t* data, int x, int y, uint8_t halfSize)
uint8_t left = pgm_read_byte(&data[v1 * BASE_SPRITE_SIZE + u0]);
uint8_t right = pgm_read_byte(&data[v1 * BASE_SPRITE_SIZE + u2]);

if (up | down | left | right)
if ((up | down | left | right) & 1)
{
PutPixel(outX, outY, COLOUR_BLACK);
}
@@ -608,6 +712,112 @@ void DrawScaled(const uint8_t* data, int x, int y, uint8_t halfSize)
}
}

#else

template<int scaleMultiplier>
inline void DrawScaledTx(const uint8_t* data, int8_t x, int8_t y, uint8_t halfSize)
{
uint8_t size = 2 * halfSize;
const uint8_t* lut = scaleLUT + ((halfSize / scaleMultiplier) * (halfSize / scaleMultiplier));

uint8_t u0 = 0;
uint8_t u1 = 0;
uint8_t u2;
uint8_t up, px, down;
int8_t outX = x;

for (uint8_t i = 0; i < size && outX < DISPLAY_WIDTH; i++)
{
uint8_t v0 = 0;
uint8_t v1 = 0;
uint8_t v2;

u2 = pgm_read_byte(&lut[(i + 1) / scaleMultiplier]);

up = 0;
px = pgm_read_byte(&data[0]);

if (outX >= 0 && wBuffer[outX] < halfSize)
{
int8_t outY = y;

for (uint8_t j = 0; j < size && outY < DISPLAY_HEIGHT; j++)
{
v2 = pgm_read_byte(&lut[(j + 1) / scaleMultiplier]);
down = pgm_read_byte(&data[v2 * BASE_SPRITE_SIZE + u1]);

if (outY >= 0)
{
if (px)
{
if (i == 0 || j == 0 || i == size - 1 || j == size - 1)
{
PutPixel(outX, outY, COLOUR_BLACK);
}
else if (px == 2)
{
PutPixel(outX, outY, COLOUR_BLACK);
}
else
{
PutPixel(outX, outY, COLOUR_WHITE);
}
}
else
{
uint8_t left = pgm_read_byte(&data[v1 * BASE_SPRITE_SIZE + u0]);
uint8_t right = pgm_read_byte(&data[v1 * BASE_SPRITE_SIZE + u2]);

if ((up | down | left | right) & 1)
{
PutPixel(outX, outY, COLOUR_BLACK);
}
}
}

v0 = v1;
v1 = v2;

up = px;
px = down;
outY++;
}
}

u0 = u1;
u1 = u2;
outX++;
}
}

void DrawScaled(const uint8_t* data, int8_t x, int8_t y, uint8_t halfSize)
{
uint8_t size = 2 * halfSize;

if (size > MAX_SPRITE_SIZE * 8)
{
return;
}
else if (size > MAX_SPRITE_SIZE * 4)
{
DrawScaledTx<8>(data, x, y, halfSize);
}
else if (size > MAX_SPRITE_SIZE * 2)
{
DrawScaledTx<4>(data, x, y, halfSize);
}
else if (size > MAX_SPRITE_SIZE)
{
DrawScaledTx<2>(data, x, y, halfSize);
}
else if(halfSize >= 2)
{
DrawScaledTx<1>(data, x, y, halfSize);
}
}

#endif

inline int8_t GetHorizon(int16_t x)
{
if (x < 0)
@@ -670,7 +880,7 @@ void Render()
{
wallIdBuffer[n] = 0;
wBuffer[n] = 0;
horizonBuffer[n] = HORIZON + (((DISPLAY_WIDTH / 2 - n) * camera.tilt) >> 8);
horizonBuffer[n] = HORIZON + (((DISPLAY_WIDTH / 2 - n) * camera.tilt) >> 8) + camera.bob;
}

camera.cellX = camera.x / CELL_SIZE;
@@ -9,6 +9,7 @@ struct Camera
int16_t clipCos, clipSin;
uint8_t cellX, cellY;
int8_t tilt;
int8_t bob;
};

extern uint8_t wBuffer[];
@@ -4,6 +4,10 @@
#include "Draw.h"
#include "Map.h"

#define USE_ROTATE_BOB 0
#define STRAFE_TILT 14
#define ROTATE_TILT 2

int16_t cameraVelocityX;
int16_t cameraVelocityY;

@@ -110,6 +114,8 @@ void TickGame()
int8_t targetTilt = 0;
int8_t moveDelta = 0;
int8_t strafeDelta = 0;
static uint8_t shakeTime = 0;
static uint8_t reloadTime = 0;

if(input & INPUT_A)
{
@@ -134,6 +140,18 @@ void TickGame()
}
}

if (reloadTime > 0)
{
reloadTime--;
}
else if (input & INPUT_B)
{
reloadTime = 13;
shakeTime = 8;
if(!moveDelta)
moveDelta -= 5;
}

if (cameraAngularVelocity < turnDelta)
{
cameraAngularVelocity++;
@@ -156,7 +174,7 @@ void TickGame()

static int tiltTimer = 0;
tiltTimer++;
if (moveDelta)
if (moveDelta && USE_ROTATE_BOB)
{
targetTilt = (int8_t)(FixedSin(tiltTimer * 10) / 32);
}
@@ -165,8 +183,16 @@ void TickGame()
targetTilt = 0;
}

targetTilt += cameraAngularVelocity * 3;
targetTilt += strafeDelta * 14;
targetTilt += cameraAngularVelocity * ROTATE_TILT;
targetTilt += strafeDelta * STRAFE_TILT;
int8_t targetBob = moveDelta || strafeDelta ? FixedSin(tiltTimer * 10) / 128 : 0;

if (shakeTime > 0)
{
shakeTime--;
targetBob += (Random() & 3) - 1;
targetTilt += (Random() & 31) - 16;
}

constexpr int tiltRate = 6;

@@ -186,7 +212,25 @@ void TickGame()
camera.tilt = targetTilt;
}
}


constexpr int bobRate = 3;

if (camera.bob < targetBob)
{
camera.bob += bobRate;
if (camera.bob > targetBob)
{
camera.bob = targetBob;
}
}
else if (camera.bob > targetBob)
{
camera.bob -= bobRate;
if (camera.bob < targetBob)
{
camera.bob = targetBob;
}
}

int16_t cosAngle = FixedCos(camera.angle);
int16_t sinAngle = FixedSin(camera.angle);
@@ -206,6 +250,5 @@ void TickGame()

MoveCamera(&camera, cameraVelocityX / 4, cameraVelocityY / 4);


Render();
}

0 comments on commit ab88af1

Please sign in to comment.
You can’t perform that action at this time.