Retro Invaders a space invaders clone by Chris Favreau. Written for the RetroMbuino development board from outrageouscircuits.com for the game programming contest.

Dependencies:   mbed

This is a space invaders clone written for the Retro Mbuino from outrageous circuits.

Development board: http://www.outrageouscircuits.com/shop/product/15 ).

The game itself is basic space invaders. Shoot them before they get to the bottom of the screen. It has a UFO saucer which you can shoot for extra points. You get 4 shields and each shield can be hit up to 4 times before it is gone. Hmm... as each level increases the speed of the invaders shots goes up. The invaders only speed up when there is less of them. You complete the level when you shoot all the invaders. The game ends when a) you run out of lives (you start with 3) or the invaders get to the bottom.

The LEDs turned out to be a pretty cool addition to the game. I wrote a class that blinks them and turns them on for a specified amount of time. They add a nice extra to the game. I use them on the intro screen and when the UFO is present.

The sound turned out to be really difficult for a few reasons. The biggest was that I had never written a sound engine before. The interrupt service routine working off the timer was the easier part. I also had a lot of trouble because there is no filter to filter out the PWM frequency to the speaker... so I had to run the PWM frequency way up there 30 kHz.

The graphics turned out to be a bit of a bear too. Thanks to Chris Taylor for his really great LCD API. I picked up a couple of frames per second from that. I had modified the DisplayN18 class for blitting a single line buffer to the LCD panel however his is a little faster for some reason? I used a different approach to doing the graphics (as I have very little experience with anything other than double buffered displays). I have a tile map and a list of sprites. Each tile/sprite is 1 bit 8x8. They could be bigger. I ran out of time. That much is not special. What is different from what I can tell is that I use a 1 line buffer that is 160 shorts long. The render function first adds the tile map data into the line buffer first. Then the sprites are added over the existing data. You can have a great deal of different sprites and maps going to the screen and just have to rewrite the LCD memory once per frame. After each line is composited, the line is then drawn to the LCD. Kind of like an Atari 2600. Each sprite/tile has a foreground and background color and can be different from the other tiles/sprites. There is one color reserved for Transparency.

There are 16 colors to choose from. I chose a palette based on the Macintosh OS 4.1 palette I found on WikiPedia. It is a very nice mix of colors.

I found a sprite editor called SpriteX ( https://code.google.com/p/spritesx-ed/ )... it works nicely except that the 16x16 sprites are in a weird format. Time limited me to 8x8 sprites. Oh well.

I used nokring to make the music. It makes RTTTL formatted ring tones which my sound api can play. Here is a useful site that has lots of arcade/video game ring tones with a link to nokring in the utilities page. http://arcadetones.emuunlim.com/files.htm

Other than all that stuff I used state machines to do most of the game logic. Please excuse the horrible coding as I tried to comment a lot of it however it is not very nice to look at. Lots of long functions...

Committer:
cfavreau
Date:
Tue Mar 03 04:26:01 2015 +0000
Revision:
0:c79e1f29f029
Retro Invaders by Chris Favreau for the RetroMbuino Platform - outrageouscircuits.com game programming contest.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cfavreau 0:c79e1f29f029 1 #ifndef BURSTSPI_H
cfavreau 0:c79e1f29f029 2 #define BURSTSPI_H
cfavreau 0:c79e1f29f029 3
cfavreau 0:c79e1f29f029 4 #include "mbed.h"
cfavreau 0:c79e1f29f029 5
cfavreau 0:c79e1f29f029 6
cfavreau 0:c79e1f29f029 7 /** An SPI Master, used for communicating with SPI slave devices at very high speeds
cfavreau 0:c79e1f29f029 8 *
cfavreau 0:c79e1f29f029 9 * The default mbed SPI class allows for communication via the SPI bus at high clock frequencies,
cfavreau 0:c79e1f29f029 10 * however at these frequencies there is alot of overhead from the mbed code.
cfavreau 0:c79e1f29f029 11 * While this code makes sure your code is alot more robust, it is also relative slow.
cfavreau 0:c79e1f29f029 12 * This library adds to your default SPI commands some extra commands to transmit data rapidly with
cfavreau 0:c79e1f29f029 13 * very little overhead. Downsides are that currently it is TX only (all RX packets are discarded),
cfavreau 0:c79e1f29f029 14 * and it requires some extra commands.
cfavreau 0:c79e1f29f029 15 *
cfavreau 0:c79e1f29f029 16 * Example:
cfavreau 0:c79e1f29f029 17 * @code
cfavreau 0:c79e1f29f029 18 * //Send 1000 SPI packets as fast as possible
cfavreau 0:c79e1f29f029 19 * spi.setFormat();
cfavreau 0:c79e1f29f029 20 * for (int i = 0; i<1000; i++)
cfavreau 0:c79e1f29f029 21 * spi.fastWrite(data[i]);
cfavreau 0:c79e1f29f029 22 * spi.clearRX();
cfavreau 0:c79e1f29f029 23 * @endcode
cfavreau 0:c79e1f29f029 24 *
cfavreau 0:c79e1f29f029 25 * As an example, writing 76,800 16-bit data packets to an LCD screen at 48MHz requires 111ms with
cfavreau 0:c79e1f29f029 26 * the normal mbed library. With this library it takes 25ms, which is also the theoretical
cfavreau 0:c79e1f29f029 27 * amount of time it should take. If you are running at 1MHz this will do alot less.
cfavreau 0:c79e1f29f029 28 */
cfavreau 0:c79e1f29f029 29 class BurstSPI : public SPI
cfavreau 0:c79e1f29f029 30 {
cfavreau 0:c79e1f29f029 31 public:
cfavreau 0:c79e1f29f029 32 /** Create a SPI master connected to the specified pins
cfavreau 0:c79e1f29f029 33 *
cfavreau 0:c79e1f29f029 34 * Pin Options:
cfavreau 0:c79e1f29f029 35 * (5, 6, 7) or (11, 12, 13)
cfavreau 0:c79e1f29f029 36 *
cfavreau 0:c79e1f29f029 37 * mosi or miso can be specfied as NC if not used
cfavreau 0:c79e1f29f029 38 *
cfavreau 0:c79e1f29f029 39 * @param mosi SPI Master Out, Slave In pin
cfavreau 0:c79e1f29f029 40 * @param miso SPI Master In, Slave Out pin
cfavreau 0:c79e1f29f029 41 * @param sclk SPI Clock pin
cfavreau 0:c79e1f29f029 42 */
cfavreau 0:c79e1f29f029 43 BurstSPI(PinName mosi, PinName miso, PinName sclk) : SPI(mosi, miso, sclk) {};
cfavreau 0:c79e1f29f029 44
cfavreau 0:c79e1f29f029 45 /** Put data packet in the SPI TX FIFO buffer
cfavreau 0:c79e1f29f029 46 *
cfavreau 0:c79e1f29f029 47 * If there is no space in the FIFO buffer it will block until there is space.
cfavreau 0:c79e1f29f029 48 * The FIFO buffer will automatically send the packets. There is no receiving here, only transmitting.
cfavreau 0:c79e1f29f029 49 *
cfavreau 0:c79e1f29f029 50 * @param data Data to be sent to the SPI slave
cfavreau 0:c79e1f29f029 51 */
cfavreau 0:c79e1f29f029 52 void fastWrite(int data);
cfavreau 0:c79e1f29f029 53
cfavreau 0:c79e1f29f029 54 /** Use this function before fastWrite to set the correct settings
cfavreau 0:c79e1f29f029 55 *
cfavreau 0:c79e1f29f029 56 * It is not needed to use this if the last SPI commands were either normal SPI transmissions,
cfavreau 0:c79e1f29f029 57 * or setting different format/frequency for this object. It is required to call this
cfavreau 0:c79e1f29f029 58 * function when several SPI objects use the same peripheral, and your last transmission was
cfavreau 0:c79e1f29f029 59 * from a different object with different settings. Not sure if you should use it?
cfavreau 0:c79e1f29f029 60 * Use it, it takes very little time to execute, so can't hurt.
cfavreau 0:c79e1f29f029 61 */
cfavreau 0:c79e1f29f029 62 void setFormat( void ) {
cfavreau 0:c79e1f29f029 63 format(_bits, _mode);
cfavreau 0:c79e1f29f029 64 frequency(_hz);
cfavreau 0:c79e1f29f029 65 }
cfavreau 0:c79e1f29f029 66
cfavreau 0:c79e1f29f029 67 /** After you are done with fastWrite, call this function
cfavreau 0:c79e1f29f029 68 *
cfavreau 0:c79e1f29f029 69 * FastWrite simply fills the SPI's (SSP's actually) TX FIFO buffer as fast as it can,
cfavreau 0:c79e1f29f029 70 * and that is the only thing it does. It doesn't do anything with received packages (currently, may change),
cfavreau 0:c79e1f29f029 71 * so the the RX buffer is full with unneeded packets. This function waits until transmission is finished,
cfavreau 0:c79e1f29f029 72 * and clears the RX buffer. You always have to call this before you want to receive
cfavreau 0:c79e1f29f029 73 * SPI data after using fastWrite.
cfavreau 0:c79e1f29f029 74 */
cfavreau 0:c79e1f29f029 75 void clearRX( void );
cfavreau 0:c79e1f29f029 76
cfavreau 0:c79e1f29f029 77
cfavreau 0:c79e1f29f029 78 //Just for documentation:
cfavreau 0:c79e1f29f029 79 #if 0
cfavreau 0:c79e1f29f029 80 /** Configure the data transmission format
cfavreau 0:c79e1f29f029 81 *
cfavreau 0:c79e1f29f029 82 * @param bits Number of bits per SPI frame (4 - 16)
cfavreau 0:c79e1f29f029 83 * @param mode Clock polarity and phase mode (0 - 3)
cfavreau 0:c79e1f29f029 84 *
cfavreau 0:c79e1f29f029 85 * @code
cfavreau 0:c79e1f29f029 86 * mode | POL PHA
cfavreau 0:c79e1f29f029 87 * -----+--------
cfavreau 0:c79e1f29f029 88 * 0 | 0 0
cfavreau 0:c79e1f29f029 89 * 1 | 0 1
cfavreau 0:c79e1f29f029 90 * 2 | 1 0
cfavreau 0:c79e1f29f029 91 * 3 | 1 1
cfavreau 0:c79e1f29f029 92 * @endcode
cfavreau 0:c79e1f29f029 93 */
cfavreau 0:c79e1f29f029 94 void format(int bits, int mode = 0);
cfavreau 0:c79e1f29f029 95
cfavreau 0:c79e1f29f029 96 /** Set the spi bus clock frequency
cfavreau 0:c79e1f29f029 97 *
cfavreau 0:c79e1f29f029 98 * @param hz SCLK frequency in hz (default = 1MHz)
cfavreau 0:c79e1f29f029 99 */
cfavreau 0:c79e1f29f029 100 void frequency(int hz = 1000000);
cfavreau 0:c79e1f29f029 101
cfavreau 0:c79e1f29f029 102 /** Write to the SPI Slave and return the response
cfavreau 0:c79e1f29f029 103 *
cfavreau 0:c79e1f29f029 104 * @param value Data to be sent to the SPI slave
cfavreau 0:c79e1f29f029 105 *
cfavreau 0:c79e1f29f029 106 * @returns
cfavreau 0:c79e1f29f029 107 * Response from the SPI slave
cfavreau 0:c79e1f29f029 108 */
cfavreau 0:c79e1f29f029 109 virtual int write(int value);
cfavreau 0:c79e1f29f029 110 #endif
cfavreau 0:c79e1f29f029 111
cfavreau 0:c79e1f29f029 112 };
cfavreau 0:c79e1f29f029 113
cfavreau 0:c79e1f29f029 114 #endif