Compare commits

..

2 Commits

Author SHA1 Message Date
265714771e Updated readme 2019-10-23 11:14:47 +02:00
d01ea24148 Added readme 2019-10-23 10:45:17 +02:00
7 changed files with 4 additions and 330 deletions

View File

@ -1,28 +1,5 @@
# Spacemania 2000 # Arduboy
This is the shooter game from the book HTML5 Games: Novice to Ninja by Sitepoint. This is a repository for my projects with the Arduboy, a tiny arduino based gaming handheld.
[You can find the book here.](https://www.sitepoint.com/premium/books/html5-games-novice-to-ninja) You can browse different projects by browsing through the branches.
I rewrote the game in C++ because I want to learn a new programming language and this seemed to be a nice way to practice. Screenshots and other info will be hosted on [ARNweb](https://arnweb.nl/projects/arduboy/ "Arduboy projects")
## Getting it yourself
The game is very unfinished at this point, but you can try it anyway. You'll have to compile it yourself.
### Requirements
* Arduboy, Arduboy compatible device or emulator
* Arduino IDE
* Arduboy2 library
* Computer
Start the Arduino IDE and load up arduboyTest.ino and send the game to your device.
### Controls
* A = Start, shoot and restart
* B = Spawn enemy
* D-Pad = Move
* A + B = Reset game
## TODO
* Automatic spawning of enemies
* Pauze menu
* Different stages of difficulty
* Music
* Background image
* Cleaner code

View File

@ -1,303 +0,0 @@
// 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;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 B