PART 2:
Constants.h:
#pragma once
const char tileArraySize = 31;
LevelMap.cpp:
#include "Tile.cpp"
#include "Bitmaps.h"
class LevelMap {
public:
Tile tiles[2] = {Tile(nullTile),Tile(floorTile)};
const unsigned char tileMap[2][8][16] = {
{ // Level 0:
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
},
{ // Level 1:
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
}
};
LevelMap(int a) {
}
Draw() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 16; j++) {
if (tileMap[0][i][j] > 0)
tiles[1].Draw(j * 8 * 256, i * 8 * 256);
}
}
}
};
Player.cpp:
#include "Sprite.cpp"
//#include "Solid.cpp"
#include "Constants.h"
#include "Tile.cpp"
class Player {
public:
Sprite sprite;
int screenPosX = 64; // -32768 to 32767 (screen 128 pixels wide).
int screenPosY = 0; // -128 to 127 (screen only 64 pixels high).
int posX = screenPosX * 256; // 16-bit value.
int posY = screenPosY * 256;
int state = 0; // 0 = idleRight
// 1 = idleLeft
// 2 = runRight
// 3 = runLeft
// 4 = fallRight
// 5 = fallLeft
int velocityX = 0;
int velocityY = 0;
char velocityStep = 16;
char gravity = 32;
int velocityXMax = 256;
int velocityYMax = 256;
char directionX = 1;
void Update() {
char stateOld = state;
if (velocityY == 0) {
sprite.frameRate = 60;
sprite.animationLength = 6;
if (velocityX > 0)
state = 2;
else if (velocityX < 0)
state = 3;
else {
sprite.frameRate = 15;
sprite.animationLength = 4;
if (directionX > 0)
state = 0;
if (directionX < 0)
state = 1;
}
}
else {
sprite.frameRate = 45;
sprite.animationLength = 2;
if (directionX > 0)
state = 4;
if (directionX < 0)
state = 5;
}
sprite.Update(stateOld == state);
if (velocityY < (4 * 256))
velocityY += gravity;
if (velocityX >= 12)
velocityX -= 12;
else if (velocityX <= -12)
velocityX += 12;
else
velocityX = 0;
int tempX = posX + velocityX;
int tempY = posY + velocityY;
/*
for (int i = 0; i < tileArraySize; i++) {
// Bottom collision.
if ((tempY >> 8) + sprite.height >= (tiles[i].posY >> 8)
and (tempY >> 8) < (tiles[i].posY >> 8) + 8
and (tempX >> 8) + 11 > tiles[i].posX >> 8
and (tempX >> 8) + 5 < (tiles[i].posX >> 8) + 8) {
posY += (tiles[i].posY - (sprite.height * 256)) - posY;
velocityY = 0;
}
else {
// Right collision.
if ((tempX >> 8) + 11 >= (tiles[i].posX >> 8)
and (tempX >> 8) + 5 < (tiles[i].posX >> 8) + 8
and (tempY >> 8) + sprite.height > tiles[i].posY >> 8
and (tempY >> 8) < (tiles[i].posY >> 8) + 8
and directionX > 0) {
posX += tiles[i].posX - (posX + (11 * 256));
velocityX = 0;
}
// Left collision.
if ((tempX >> 8) + 5 <= (tiles[i].posX >> 8) + 8
and (tempX >> 8) + 5 > tiles[i].posX
and (tempY >> 8) + sprite.height > tiles[i].posY >> 8
and (tempY >> 8) < (tiles[i].posY >> 8) + 8
and directionX < 0) {
posX -= (posX + (5 * 256)) - (tiles[i].posX + (8 * 256));
velocityX = 0;
}
}
}
*/
posX += velocityX;
posY += velocityY;
if (posY > (66 * 256))
Reset();
}
void Draw() {
switch (state) {
case 0: // Idle Right
sprite.Draw(posX, posY, playerIdleRight);
break;
case 1: // Idle Left
sprite.Draw(posX, posY, playerIdleLeft);
break;
case 2: // Run Right
sprite.Draw(posX, posY, playerRunRight);
break;
case 3: // Run Left
sprite.Draw(posX, posY, playerRunLeft);
break;
case 4: // Fall Right
sprite.Draw(posX, posY, playerFallRight);
break;
case 5: // Fall Left
sprite.Draw(posX, posY, playerFallLeft);
break;
}
}
void Reset() {
posX = 16384;
posY = 0;
velocityX = 0;
velocityY = 0;
directionX = 1;
}
};
// Fixed Point 8.8
// ---------------
// 8 bits in a byte.
// In 8 bits (1 byte) you can store 0 - 255 (enough for a coordinate
// on the small screen.
// In 16 bits (2 bytes) you can store 0 - 65536. Use 1st byte for integer
// and 2nd byte for fraction.
// Increment the bottom 8 bits until it wraps around 256, and the upper
// 8 bits will increment by 1.
// Acts like a decimal: 0.0 to 255.255
// Use whole 16 bits to calculate velocities but only use the upper 8
// bits to render the object to the screen, discarding the lower 8 with
// the >> operator.
// 256 is 1 pixel per frame. 128 is 0.5 pixels per frame.
Sprite.cpp:
#include<Arduboy2.h>
#pragma once
class Sprite {
public:
Sprites sprites;
// Sprite animation variables.
unsigned int framesSinceAnimUpdate = 0; // Number of updates since last animation frame advance.
unsigned int currentFrame = 0; // Displayed frame.
unsigned int animationLength = 6; // Number of frames.
unsigned int frameRate = 60; // Sprite frame rate.
unsigned int framesBetweenUpdates; // Number of frames between sprite animation updates.
unsigned int height = 16;
unsigned int width = 16;
bool active = true;
Sprite() {
// Calculate number of frames between animation updates.
framesBetweenUpdates = round((1.0 / frameRate) * 100);
}
void Update(bool sameState) {
if (active) {
framesBetweenUpdates = round((1.0 / frameRate) * 100);
// Advance the sprite animation frame.
framesSinceAnimUpdate++;
if (framesSinceAnimUpdate > framesBetweenUpdates){
currentFrame = (currentFrame + 1) % animationLength;
framesSinceAnimUpdate = 0;
}
if (!sameState)
currentFrame = 0;
}
}
void Draw(int posX, int posY, const unsigned char bitmap[]) {
sprites.drawSelfMasked(posX >> 8, posY >> 8, bitmap, currentFrame);
}
};
Tile.cpp:
#pragma once
#include "Sprite.cpp"
#include "Bitmaps.h"
class Tile {
public:
Sprite sprite;
unsigned char tileTexture[10];
Tile(const unsigned char texture[]) {
memcpy(tileTexture, texture, sizeof(texture));
}
void Update() {
sprite.active = false;
sprite.Update(true);
}
void Draw(int posX, int posY) {
sprite.Draw(posX, posY, tileTexture);
}
};