304 lines
11 KiB
C++
304 lines
11 KiB
C++
// Arne van Iterson 2019
|
|
|
|
// Include all the stuff
|
|
#include <Arduboy2.h>
|
|
#include <math.h>
|
|
|
|
// Setup instance of arduboy
|
|
Arduboy2 arduboy;
|
|
|
|
// Define all bitmaps
|
|
//// Spacemania 2000 titlescreen
|
|
const unsigned char PROGMEM titlescreen[] =
|
|
{
|
|
// width, height,
|
|
102, 22,
|
|
0x3f, 0x3f, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xf3, 0xf3, 0x00, 0xff, 0xff, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3f, 0x3f, 0x00, 0xff, 0xff, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xff, 0xff, 0x00, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0xff, 0xff, 0x33, 0x33, 0x33, 0x33, 0x03, 0x03, 0x03, 0x03, 0x00, 0xff, 0xff, 0x03, 0x03, 0xff, 0xff, 0x03, 0x03, 0xff, 0xff, 0x00, 0xff, 0xff, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xff, 0xff, 0x00, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xff, 0xff,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x30, 0x33, 0x33, 0x33, 0x33, 0x33, 0xf3, 0xf3, 0x03, 0xf3, 0xf3, 0x30, 0x33, 0x33, 0x33, 0x33, 0x33, 0xf3, 0x03, 0x03, 0xf3, 0xf3, 0x30, 0x33, 0x33, 0x30, 0x30, 0x33, 0xf3, 0x00, 0x00, 0xf3, 0xf3, 0x30, 0x33, 0x33, 0x30, 0x30, 0x30, 0xf0, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x3f, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
//// Gameover screen
|
|
const unsigned char PROGMEM gameover[] =
|
|
{
|
|
// width, height,
|
|
102, 22,
|
|
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00,
|
|
0x00, 0x00, 0xff, 0xff, 0xc0, 0xc0, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0xfc, 0x00, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x30, 0x30, 0xc0, 0xc0, 0x30, 0x30, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x3c, 0xcf, 0xcf, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
//// Player spaceship
|
|
const unsigned char PROGMEM spaceship[] =
|
|
{
|
|
// width, height,
|
|
16, 16,
|
|
0x00, 0xfe, 0xfc, 0xf8, 0xfc, 0xfc, 0xfe, 0xfe, 0x80, 0xfe, 0x80, 0xfc, 0x80, 0xf0, 0x80, 0x00,
|
|
0x00, 0x43, 0x6f, 0x77, 0x7b, 0x3d, 0x5f, 0x6f, 0x77, 0x7b, 0x3d, 0x3f, 0x1f, 0x0f, 0x03, 0x00,
|
|
};
|
|
//// Player bullets
|
|
const unsigned char PROGMEM bullet[] =
|
|
{
|
|
// width, height,
|
|
8, 8,
|
|
0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x3c, 0x00,
|
|
};
|
|
//// Enemy spaceship
|
|
const unsigned char PROGMEM baddie[] =
|
|
{
|
|
// width, height,
|
|
16, 16,
|
|
0xc0, 0xf0, 0xf8, 0xbc, 0xde, 0xce, 0xe7, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfc, 0xfe, 0xf6, 0xc1,
|
|
0x03, 0x0f, 0x19, 0x3f, 0x61, 0x7f, 0xc1, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x7f, 0x6f, 0x83,
|
|
};
|
|
|
|
// Define Variables
|
|
//// System
|
|
const int screen[] = { 128, 64 };
|
|
|
|
//// Timing
|
|
float dt = 0;
|
|
|
|
//// Game Setup
|
|
const int framerate = 60;
|
|
int gamestate = 0;
|
|
bool reset = 0;
|
|
int i;
|
|
|
|
//// Game Variables
|
|
float playerPos[] = { 0, ((screen[1] / 2) - (spaceship[1] / 2)) };
|
|
float playerSpeed = 1;
|
|
float bulletSpeed = 1.5;
|
|
const int bulletAmount = 5;
|
|
float baddieSpeed = 0.8;
|
|
const int baddieAmount = 16;
|
|
|
|
// Setup code
|
|
void setup() {
|
|
// Random number generator
|
|
arduboy.initRandomSeed();
|
|
// Start arduboy
|
|
arduboy.begin();
|
|
// Set framerate
|
|
arduboy.setFrameRate(framerate);
|
|
// Clear screen
|
|
arduboy.clear();
|
|
}
|
|
|
|
// Game loop
|
|
void loop() {
|
|
// Only loop if it is time for the next frame
|
|
if (!arduboy.nextFrame())
|
|
return;
|
|
|
|
// Clear screen
|
|
arduboy.clear();
|
|
// Keep track of buttons
|
|
arduboy.pollButtons();
|
|
|
|
// Switch between gamestates
|
|
switch (gamestate)
|
|
{
|
|
//// Titlescreen
|
|
case 0:
|
|
Sprites::drawOverwrite(((screen[0] - titlescreen[0]) / 2), ((screen[0] - titlescreen[0]) / 2), titlescreen, 0);
|
|
arduboy.setCursor(16, 40);
|
|
arduboy.print("Press A to start");
|
|
arduboy.setCursor(36, 57);
|
|
arduboy.print("McArn 2019");
|
|
if (arduboy.justPressed(A_BUTTON))
|
|
{
|
|
gamestate = 1;
|
|
reset = true;
|
|
}
|
|
break;
|
|
|
|
//// Game
|
|
case 1:
|
|
if ( arduboy.pressed(A_BUTTON) && arduboy.pressed(B_BUTTON) ) {
|
|
gamestate = 0;
|
|
}
|
|
game();
|
|
break;
|
|
|
|
//// Game over
|
|
case 2:
|
|
Sprites::drawOverwrite(((screen[0] - gameover[0]) / 2), ((screen[0] - gameover[0]) / 2), gameover, 0);
|
|
arduboy.setCursor(12, 40);
|
|
arduboy.print("Press A to restart");
|
|
if (arduboy.justPressed(A_BUTTON))
|
|
{
|
|
gamestate = 1;
|
|
reset = true;
|
|
}
|
|
break;
|
|
}
|
|
// Display everything
|
|
arduboy.display();
|
|
}
|
|
|
|
// Bullet class
|
|
class Bullet
|
|
{
|
|
public:
|
|
float pos[2];
|
|
bool dead = true;
|
|
void update() {
|
|
if (pos[0] >= (screen[0] + bullet[0]))
|
|
{
|
|
dead = true;
|
|
pos[0] = 0 - bullet[0];
|
|
} else {
|
|
pos[0] = pos[0] + (1 * bulletSpeed);
|
|
}
|
|
}
|
|
};
|
|
|
|
// Max amount of bullets = 5;
|
|
Bullet bullets[bulletAmount];
|
|
|
|
// Enemy class
|
|
class Baddie
|
|
{
|
|
public:
|
|
float pos[2];
|
|
bool dead = true;
|
|
void update() {
|
|
if (pos[0] <= (0 - baddie[0]))
|
|
{
|
|
dead = true;
|
|
gamestate = 2;
|
|
pos[0] = screen[0] + baddie[0];
|
|
} else {
|
|
pos[0] = pos[0] - (1 * baddieSpeed);
|
|
}
|
|
}
|
|
};
|
|
|
|
Baddie baddies[baddieAmount];
|
|
|
|
void game() {
|
|
// Reset game if coming from title or gameover screen
|
|
if (reset)
|
|
{
|
|
for (i = 0; i < (baddieAmount - 1); i++)
|
|
{
|
|
baddies[i].pos[0] = screen[0] + baddie[0];
|
|
baddies[i].pos[1] = random(screen[1] - baddie[1]);
|
|
baddies[i].dead = true;
|
|
}
|
|
for (i = 0; i < (bulletAmount - 1); i++)
|
|
{
|
|
bullets[i].dead = true;
|
|
}
|
|
playerPos[0] = 0;
|
|
playerPos[1] = (screen[1] / 2) - (spaceship[1] / 2);
|
|
reset = false;
|
|
}
|
|
|
|
// Move Player
|
|
if ( arduboy.pressed(UP_BUTTON) && !(playerPos[1] <= 0) ) {
|
|
playerPos[1] = playerPos[1] - 1 * playerSpeed;
|
|
}
|
|
if ( arduboy.pressed(DOWN_BUTTON) && !(playerPos[1] >= (screen[1] - spaceship[1])) ) {
|
|
playerPos[1] = playerPos[1] + 1 * playerSpeed;
|
|
}
|
|
if ( arduboy.pressed(LEFT_BUTTON) && !(playerPos[0] <= 0) ) {
|
|
playerPos[0] = playerPos[0] - 1 * playerSpeed;
|
|
}
|
|
if ( arduboy.pressed(RIGHT_BUTTON) && !(playerPos[0] >= (screen[0] - spaceship[0])) ) {
|
|
playerPos[0] = playerPos[0] + 1 * playerSpeed;
|
|
}
|
|
|
|
// Spawn Bullet
|
|
if ( arduboy.justPressed(A_BUTTON)) {
|
|
for (i = 0; i < (bulletAmount - 1); i++)
|
|
{
|
|
if (bullets[i].dead)
|
|
{
|
|
bullets[i].pos[0] = playerPos[0];
|
|
bullets[i].pos[1] = playerPos[1] + (spaceship[1] / 2) - (bullet[1] / 2);
|
|
bullets[i].dead = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Spawn baddie for debug
|
|
if ( arduboy.justPressed(B_BUTTON)) {
|
|
for (i = 0; i < (baddieAmount - 1); i++)
|
|
{
|
|
if (baddies[i].dead)
|
|
{
|
|
baddies[i].dead = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update and show non-dead bullets
|
|
for (i = 0; i < (bulletAmount - 1); i++)
|
|
{
|
|
if (!bullets[i].dead)
|
|
{
|
|
bullets[i].update();
|
|
Sprites::drawSelfMasked(round(bullets[i].pos[0]), round(bullets[i].pos[1]), bullet, 0);
|
|
}
|
|
}
|
|
|
|
// Update and show non-dead baddies
|
|
for (i = 0; i < (baddieAmount - 1); i++)
|
|
{
|
|
if (!baddies[i].dead)
|
|
{
|
|
baddies[i].update();
|
|
Sprites::drawSelfMasked(round(baddies[i].pos[0]), round(baddies[i].pos[1]), baddie, 0);
|
|
}
|
|
}
|
|
|
|
// Draw player
|
|
Sprites::drawSelfMasked(round(playerPos[0]), round(playerPos[1]), spaceship, 0);
|
|
checkCollision();
|
|
}
|
|
|
|
// Variables for collision detection
|
|
float distance = 0;
|
|
float difference[2];
|
|
int a;
|
|
|
|
// Check collisions
|
|
void checkCollision() {
|
|
for (i = 0; i < (baddieAmount - 1); i++)
|
|
{
|
|
// Collision baddie x bullet
|
|
for (a = 0; a < (bulletAmount - 1); a++)
|
|
{
|
|
//// Difference x
|
|
difference[0] = (baddies[i].pos[0] + (baddie[0] / 2)) - (bullets[a].pos[0] + (bullet[0] / 2));
|
|
//// Difference y
|
|
difference[1] = (baddies[i].pos[1] + (baddie[1] / 2)) - (bullets[a].pos[1] + (bullet[1] / 2));
|
|
|
|
// Calculate diffence
|
|
distance = sqrt(pow(difference[0], 2) + pow(difference[1], 2));
|
|
if (!baddies[i].dead && !bullets[a].dead && distance <= 11)
|
|
{
|
|
bullets[a].dead = true;
|
|
baddies[i].dead = true;
|
|
baddies[i].pos[0] = screen[0] + baddie[0];
|
|
baddies[i].pos[1] = random(screen[1] - baddie[1]);
|
|
}
|
|
}
|
|
|
|
// Collision baddie x player
|
|
//// Difference x
|
|
difference[0] = (baddies[i].pos[0] + (baddie[0] / 2)) - (playerPos[0] + (spaceship[0] / 2));
|
|
//// Difference y
|
|
difference[1] = (baddies[i].pos[1] + (baddie[1] / 2)) - (playerPos[1] + (spaceship[1] / 2));
|
|
|
|
// Calculate diffence
|
|
distance = sqrt(pow(difference[0], 2) + pow(difference[1], 2));
|
|
if (!baddies[i].dead && distance <= 15)
|
|
{
|
|
gamestate = 2;
|
|
}
|
|
}
|
|
}
|