IAN LANG ELECTRONICS

The year is 1978. People have seen video games before, but these were simple and crude affairs based on sports activities, the most famous being Pong (a tennis game with two blocks for bats and a square for a ball controlled by two paddles, one for each player.)

Video games were a novelty enjoyed by a few, and certainly had no place in arcades where the slot machine and the pinball table were dominant. Then, from the Taito company of Japan, came something that changed the face of video gaming forever. That something was Space Invaders, a simple gameplay which by modern standards had very poor graphics and sound, but in 1978 was utterly revolutionary.

The idea was to shoot down waves of alien invaders (who were shooting back) before they landed (i.e got to the bottom of the screen). If they did, the game ended. The game also ended if your cannon was destroyed three times, harking back to the pinball tables where you were given three balls to make your score.

The game was designed by Tomohiro Nishikado and he has been quoted as saying the hardware was the hardest design. He used an Intel 8080 CPU and associated circuitry and a CRT display with a mirrored back as the screen. This meant power hunger and very large cabinets, but it did mean a very large screen to work with.

 

We don't have those luxuries. We've got a 5V Arduino and a small LCD. Obviously we can't reproduce the game exactly- but we can do a reasonable facsimile.

 

We'll need to attach the LCD and two direction buttons and a fire button to the LCD module (or a joystick if you like for those directions). Here's how the bits are wired:

 

 

Go Back

Space Invaders- 5110 Graphic LCD

S1 is the fire button, S2 the right button and S3 the left. They're connected on one side to the 5V supply from the Arduino, and on the other they pull via 2k2 resistors the pins they're attached to low. That stops misreadings on the pins.

You'll notice the LCD module is attached to 3.3V and so is the LED for the backlight. If you attach anything on this module directly to 5V it will not end well, and that's the reason why all the other pins are attached via resistors. In the case of the four purple marked ones it's 10k and the brown one (SCE) is 1k.

 

Spiffing, but now we need a sketch to drive it.  It's a bit of a monster and so you can open it as a text file by clicking on the link below:

invaders invaders

A second or two after you click on it it'll give you the option to open it. If you click on open it'll come up as a text file in wordpad. Copy and paste the sketch to your IDE and upload it to your Arduino Board. If things have gone well, here's what you'll see:

 

Halfway down the screen, there's a row of invaders. Under them, the phrase "Fire to Start" in what would be futuristic lettering if we were in 1974. So, press fire, and the game should start.

You'll see two rows of five invaders and at the bottom your missile base. You can move left and right and fire missiles at the invaders. The invaders move left to right and then back left again, and once they reach the left edge they drop down a row. To the right hand side is the current life you are on and underneath that your score. Once the invaders have dropped down a row, a UFO will zoom across the screen. You get one point per invader, and 10 for a UFO.

If your base gets destroyed three times or the invaders land, then the game is over.

If you clear the screen, the invaders regenerate and begin to move faster. The more times you clear the faster the invaders get. There is also a downbolt shot by the invaders which destroys your base if it hits. As yet there is no sound.

As simple as this is it can get quite engrossing; so be warned if you make it you could waste hours zapping these little sprites. All of which is super, but how does it actually work? The text is full of REM statements telling you what each line does, but it doesn't go into great detail. So that's what were going to do here instead.

The very first thing we do is define the data for the one-and-only complex bitmap in this sketch. Here it is:

 

const unsigned char startflash [ ] = {

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x48, 0x48, 0x48, 0x48, 0xC8, 0xC8, 0x00, 0xC0,

0x40, 0x40, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x40, 0x00,

0x00, 0x80, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x48,

0x80, 0xF0, 0x40, 0x40, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0x40, 0x40, 0x40, 0xF0, 0xF0,

0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00,

0x0F, 0x0F, 0x00, 0x0F, 0x00, 0x00, 0x03, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00,

0x0F, 0x0F, 0x0C, 0x00, 0x00, 0x03, 0x0C, 0x0C, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,

0x0C, 0x0C, 0x0C, 0x0C, 0x03, 0x0F, 0x0C, 0x0C, 0x00, 0x0E, 0x0E, 0x0D, 0x0D, 0x0F, 0x0F, 0x00,

0x00, 0x00, 0x0F, 0x0F, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

};

 

 These will each form a seven by eight piece of the bitmap; when drawn consecutively they will make the futuristic-for-1974 sign "Fire to Start". The drawing comes later, because next we define a table of characters we are going to need. It looks like this:

 

char charactertable [ ][5] =

{

{0x00, 0x00, 0x00, 0x00, 0x00} // 00//blank

,{0x1c, 0x76, 0x3f, 0x76, 0x1c} // 01/ invader

,{0x55, 0x00, 0x41, 0x00, 0x55} // 02//blip

,{0x60, 0x78, 0x7e, 0x78, 0x60} // 03 // missile base

,{0x00, 0x00, 0xff, 0x00, 0x00} // 04  upbolt

,{0x0c, 0x1e, 0x3b, 0x1e, 0x0c} // 05  UFO

,{0x00, 0x10, 0xa8, 0x40, 0x00} // 06 downbolt

,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 07 M

,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 08 A

,{0x3e, 0x41, 0x41, 0x41, 0x22} // 09 C

,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 10 D

,{0x7f, 0x49, 0x49, 0x49, 0x41} // 11 E

,{0x00, 0x41, 0x7f, 0x41, 0x00} // 12 I

,{0x7f, 0x40, 0x40, 0x40, 0x40} // 13 L

,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 14 N

,{0x7f, 0x09, 0x09, 0x09, 0x06} // 15 P

,{0x7f, 0x09, 0x19, 0x29, 0x46} // 16 R

,{0x46, 0x49, 0x49, 0x49, 0x31} // 17 S

,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 18 V

,{0x07, 0x08, 0x70, 0x08, 0x07} // 19 Y

,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 20 0

,{0x00, 0x42, 0x7f, 0x40, 0x00} // 21 1

,{0x42, 0x61, 0x51, 0x49, 0x46} // 22 2

,{0x21, 0x41, 0x45, 0x4b, 0x31} // 23 3

,{0x18, 0x14, 0x12, 0x7f, 0x10} // 24 4

,{0x27, 0x45, 0x45, 0x45, 0x39} // 25 5

,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 26 6

,{0x01, 0x71, 0x09, 0x05, 0x03} // 27 7

,{0x36, 0x49, 0x49, 0x49, 0x36} // 28 8

,{0x06, 0x49, 0x49, 0x29, 0x1e} // 29 9

,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 30 G

};

 

This array is double dimensioned. It has a positional indicator and five positions within that indicator.

For example  charactertable [ 7][3] = 0x0c and charactertable [1 ][5] =0x00.

 

These are the letters, digits and glyphs we need to display on the screen to mark the invaders, missile base, ufo, bolts, score and lives left as well as writing "GAME 0VER at the end. They need to be arranged this way to make small bitmaps as the screen won't handle alphanumerics directly (at least not without a library). The pixel banks are seven wide and the observant amongst you will notice that there are only five pieces of data. We don't use the columns either side or the eighth row as if we do the edge of the character runs into the next one, which we don't want.

 

Most of this sketch is line driven, that is the code is contained in a single loop and is processed on each cycle of the loop and the reason for this is that calling too many functions can increase RAM usage on your Arduino to the point where it runs out of stack memory and then everything goes belly-up. We're using quite a lot of that RAM for the bitmap and character table and we'll be using more for some global variables, and so it's a good idea to keep everything in one loop and use conditionals to switch on and off rather than call functions from functions and risk running out of stack- there's not terribly much RAM available on the Arduino as it's a microcontroller designed for physical computing  rather than a computer per se and we're running a bit outside design parameters here. Having said that, there are two functions external to the loop:

 

 

 

void LcdCharacter(char character){

LcdWrite(1, 0x00);  for (int index = 0; index < 5; index++)

{    LcdWrite(1, charactertable[character][index]);  }  LcdWrite(1, 0x00);}

 

void LcdWrite(byte dc, byte data)

{  digitalWrite(5, dc);

digitalWrite(7, LOW);

shiftOut(4,3, MSBFIRST, data);

digitalWrite(7, HIGH);}

 

These are the two functions that display our text and graphics and since they're always being used it's better to sacrifice some RAM than risk running out of program memory by repeating these several times.

 

The final step before the setup function is to define global variables. These variables monitor and/or position our text, graphics and other considerations. They are:

 

unsigned long timethen=0;int rowcount=0;int dly=500;boolean gameover=false;boolean leftmove=false;int basepos=25;int softmove=0;int score=0;

int upbolt[2]={99,99};int downbolt[2]={99,99};int softup=0;int kill=0;int upboltrate=15;int downboltrate=100;int softdown=0;int lives=3;

int uforate=50;boolean ufoon=false;int ufopos=-1;boolean start=true;

int invarray[]={

1,0,1,8,0,1,16,0,1,24,0,1,32,0,1,1,1,1,8,1,1,16,1,1,24,1,1,32,1,1,};

 

There's rather a lot of them and so over the page we look at what they all do.

 

 

More>