diff --git a/.gitignore b/.gitignore index e257658..d866181 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ *.out *.app +.vscode/* + diff --git a/arduboyTest.ino b/arduboyTest.ino new file mode 100644 index 0000000..9cf0147 --- /dev/null +++ b/arduboyTest.ino @@ -0,0 +1,303 @@ +// Arne van Iterson 2019 + +// Include all the stuff +#include +#include + +// 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; + } + } +} diff --git a/data/baddie.png b/data/baddie.png new file mode 100644 index 0000000..9e81441 Binary files /dev/null and b/data/baddie.png differ diff --git a/data/bullet.png b/data/bullet.png new file mode 100644 index 0000000..98e5e1f Binary files /dev/null and b/data/bullet.png differ diff --git a/data/gameover.png b/data/gameover.png new file mode 100644 index 0000000..167d98a Binary files /dev/null and b/data/gameover.png differ diff --git a/data/spaceship.png b/data/spaceship.png new file mode 100644 index 0000000..27fd994 Binary files /dev/null and b/data/spaceship.png differ diff --git a/data/titlescreen.png b/data/titlescreen.png new file mode 100644 index 0000000..1ba0dc1 Binary files /dev/null and b/data/titlescreen.png differ