There is no need to introduce a legendary “Space Invaders” game. The most interesting feature of this project is that it uses text display for graphical output. It is achieved by implementing 8 custom characters.
You may download the complete Arduino sketch here.
The screen does not allow to control separate pixels and provides just two lines of text which is not enough for game. But it allows to implement up to 8 custom characters. The trick is to process each 5x8 pixels character as two 5x4 pixels game cells. That is to say, we’ll have 16x4 game field, which makes sense. 8 characters is just enough to implement sprites for player's spaceship, bullets and animated aliens. Since the sprites are 5x4 and the characters are 5x8, we’ll need some characters with two sprites like “a spaceship and a bullet” sprite, “an alien and a bullet sprite” etc. All the custom characters are shown on the picture.
Typically, all the buttons on an LCD shield are connected to the same analogue pin. There are different versions of LCD shield, so you’ll probably need to tune integer literals in my button processing code.
// Processing buttons state
byte buttonPressed()
{
int adc_key_in = analogRead(0); // read analogue value
//Please adjust these values for your version of LCD shield
if (adc_key_in <= 60) return btnRIGHT;
if (adc_key_in <= 200) return btnUP;
if (adc_key_in <= 400) return btnDOWN;
if (adc_key_in <= 600) return btnLEFT;
if (adc_key_in <= 800) return btnSELECT;
return btnNONE;
}
Classes HierarchyI have implemented a base class GameObject which has coordinates and speed fields and processes collisions. Classes Ship, Alien and Bullet are inherited from it.
Updating the ScreenRendering logic may look somewhat complicated because we have to transform 16x4 game logic into 16x2 display. It is implemented in UpdateScreen() function. Please read the comments in the code for further reference. To avoid flickering, I used a two dimensional char array as a text buffer. It allows to use a couple (one for each line) of print operations to update the screen.
void updateScreen(){
bool shipDisplayed = false; //shows whether ship have been displayed with SHIP_BULLET sprite
//Clearing the buffer
for (byte i = 0; i < HEIGHT/2; i++){
for (byte j = 0; j < WIDTH; j++)
screenBuffer[i][j] = ' ';
screenBuffer[i][WIDTH] = '\0';
}
//Drawing ship's bullet
if (shipBullet.active()){
if ((ship.x()==shipBullet.x()) && (shipBullet.y()==2)){
screenBuffer[shipBullet.y()/2][shipBullet.x()] = SHIP_BULLET;
shipDisplayed = true;
}
else
screenBuffer[shipBullet.y()/2][shipBullet.x()] = shipBullet.y()%2 ? BULLET_DOWN : BULLET_UP;
}
//Drawing aliens
for (byte i = 0; i<ALIENS_NUM; i++){
if(aliens[i].alive()){
screenBuffer[aliens[i].y()/2][aliens[i].x()] = aliens[i].state() ? ALIEN1 : ALIEN2;
}
}
//Drawing aliens and bullets
bool bulletDisplayed = false;
for (byte i = 0; i < ALIENS_NUM; i++){
if(alienBullets[i].active()){
bulletDisplayed = false;
for (int j = 0; j < ALIENS_NUM; j++){
if ((aliens[j].x()==alienBullets[i].x()) && (alienBullets[i].y()==1) && (aliens[i].alive())){
screenBuffer[alienBullets[i].y()/2][alienBullets[i].x()] = aliens[i].state() ? ALIEN1BULLET : ALIEN2BULLET;
bulletDisplayed = true;
}
}
if (!bulletDisplayed){
if ((ship.x()==alienBullets[i].x()) && (alienBullets[i].y()==2)){
screenBuffer[alienBullets[i].y()/2][alienBullets[i].x()] = SHIP_BULLET;
shipDisplayed = true;
}
else
screenBuffer[alienBullets[i].y()/2][alienBullets[i].x()] = alienBullets[i].y()%2 ? BULLET_DOWN : BULLET_UP;
}
}
}
//Sending the buffer to the screen
for (byte i = 0; i < HEIGHT/2; i++){
lcd.setCursor(0,i);
lcd.print(screenBuffer[i]);
}
//After all, displaying the ship
if (!shipDisplayed){
lcd.setCursor(ship.x(), ship.y()/2);
lcd.write(byte(SHIP));
}
}
Game Logicloop() function is the heart of the game. The main loop changes coordinates of all the objects, checks all sorts of collisions and button press events. The speed of aliens and their shooting probability increases from level to level. But the score reward increases as well.
An Easter EggThere is no level after level 42. Seriously. It’s the Ultimate Level of Life, The Universe, and Everything. :)
if (level>42)//Easter egg: 42 is the ultimate level :)
level = 42;
Playing
Comments