A simple one-level platform game. Developed as part of ELEC2645 at University of Leeds, spring 2015.

Dependencies:   N5110 PinDetect PowerControl mbed

An ARM mbed LPC1768 microcontroller have been used to develop a handheld arcade game in the style of an old-school platformer. This project is entirely my own independent work in all stages of the development; including design, defining project specifications, breadboard prototyping, schematic and PCB layout using CAD, assembly, testing and software development. Due to this being part of the ELEC2645 Embedded Systems Project module at University of Leeds, spring 2015, limitations were given on the available hardware components. Credit is due to the authors of the dependent libraries (N5110, Pin Detect, PowerControl and mbed). I would also like to thank the author of Game Programming Patterns as well as the authors of SFML Game Development for providing me with useful sources for programming design patterns.

/media/uploads/Siriagus/game_assembled.jpg

Project aims

  • Implement simple gameplay:
    • A single, fixed (no scrolling) level.
    • Player can move left to right, jump and shoot.
    • Enemies will drop from the top of the screen.
    • The player gets points for shooting enemies.
    • The player dies when it gets hits by an enemy.
  • Implement a simple menu system.
  • Enable the user to adjust the brightness of the display.
  • Output sound to enhance the user experience.

Software

The program flow is controlled by a finite state machine. The implemented design was inspired by the State design pattern from the books Game Programming Patterns and SFML Game Development. The StateManager class is responsible for updating and rendering the current selected state. It also changes the state based on request from the current state. The framework built for the state machine used in this project makes it easy to add new screens. The different main states (indicated by the background colour) and how the user interaction is shown below: /media/uploads/Siriagus/arcadegameuserinteraction.png

Hardware

Schematic:

/media/uploads/Siriagus/schematic.png

Printed circuit board (PCB):

/media/uploads/Siriagus/pcb.png

Images

A seperate program was written to convert images (png) to text-representation of the maps. Enemies and numbers on the screen are also collected from a sprite-sheet created in the same manner.

/media/uploads/Siriagus/unileeds3.png /media/uploads/Siriagus/newmap2.png

Committer:
Siriagus
Date:
Fri May 01 00:38:59 2015 +0000
Revision:
4:d6661b976359
Parent:
3:4e3f342a135c
Child:
5:100d960fc6d5
Started rewriting the main finite state machine - design in progress

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Siriagus 0:1f92de30d43e 1 /**
Siriagus 0:1f92de30d43e 2 @brief Simple platform game developed for ELEC2645 Embedded Systems Project at University of Leeds
Siriagus 0:1f92de30d43e 3
Siriagus 0:1f92de30d43e 4 @author Andreas Garmannslund
Siriagus 0:1f92de30d43e 5 **/
Siriagus 0:1f92de30d43e 6
Siriagus 0:1f92de30d43e 7 #include "mbed.h"
Siriagus 0:1f92de30d43e 8 #include "N5110.h"
Siriagus 1:0cfe2255092a 9 #include "PowerControl.h"
Siriagus 1:0cfe2255092a 10 #include "PinDetect.h"
Siriagus 4:d6661b976359 11 #include <string>
Siriagus 4:d6661b976359 12 #include <ctime>
Siriagus 1:0cfe2255092a 13
Siriagus 0:1f92de30d43e 14 #include "Joystick.h"
Siriagus 1:0cfe2255092a 15
Siriagus 1:0cfe2255092a 16 #include "State.h"
Siriagus 1:0cfe2255092a 17 #include "images.h"
Siriagus 4:d6661b976359 18 #include "InputManager.h"
Siriagus 1:0cfe2255092a 19
Siriagus 4:d6661b976359 20
Siriagus 0:1f92de30d43e 21
Siriagus 1:0cfe2255092a 22 // Redefine pin names for simple access.
Siriagus 1:0cfe2255092a 23 #define JOY_H p17
Siriagus 1:0cfe2255092a 24 #define JOY_V p16
Siriagus 1:0cfe2255092a 25 #define JOY_BTN p15
Siriagus 1:0cfe2255092a 26
Siriagus 1:0cfe2255092a 27 #define LED_POT p20
Siriagus 1:0cfe2255092a 28
Siriagus 2:0ae5ac8b0cac 29 #define BUTTON_A p28
Siriagus 2:0ae5ac8b0cac 30 #define BUTTON_B p27
Siriagus 1:0cfe2255092a 31 #define BUTTON_C p29
Siriagus 1:0cfe2255092a 32
Siriagus 4:d6661b976359 33 // Input and Output
Siriagus 0:1f92de30d43e 34 N5110 *lcd; // VCC, SCE, RST, D/C, MOSI, SCLK and LED
Siriagus 4:d6661b976359 35
Siriagus 4:d6661b976359 36 InputManager *input;
Siriagus 4:d6661b976359 37
Siriagus 4:d6661b976359 38 // Replaced by InputManager
Siriagus 4:d6661b976359 39 /*Joystick *joystick;
Siriagus 4:d6661b976359 40 PinDetect *btnA;
Siriagus 4:d6661b976359 41 PinDetect *btnB;
Siriagus 4:d6661b976359 42 PinDetect *btnC;*/
Siriagus 0:1f92de30d43e 43
Siriagus 0:1f92de30d43e 44 // Brightness potentiometer
Siriagus 1:0cfe2255092a 45 AnalogIn ledPot(LED_POT);
Siriagus 0:1f92de30d43e 46
Siriagus 0:1f92de30d43e 47 // Debugging
Siriagus 0:1f92de30d43e 48 Serial pc(USBTX, USBRX);
Siriagus 0:1f92de30d43e 49 BusOut leds(LED1, LED2, LED3, LED4);
Siriagus 0:1f92de30d43e 50
Siriagus 1:0cfe2255092a 51 // @brief Clears the screen and fill it with the image in the argument.
Siriagus 1:0cfe2255092a 52 void clearAndDrawImage(const int img[BANKS][WIDTH])
Siriagus 0:1f92de30d43e 53 {
Siriagus 0:1f92de30d43e 54 for (int i = 0; i < BANKS; ++i)
Siriagus 0:1f92de30d43e 55 {
Siriagus 0:1f92de30d43e 56 for (int j = 0; j < WIDTH; ++j)
Siriagus 0:1f92de30d43e 57 {
Siriagus 1:0cfe2255092a 58 lcd->buffer[j][i] = img[i][j];
Siriagus 0:1f92de30d43e 59 }
Siriagus 0:1f92de30d43e 60 }
Siriagus 0:1f92de30d43e 61 lcd->refresh();
Siriagus 0:1f92de30d43e 62 }
Siriagus 0:1f92de30d43e 63
Siriagus 2:0ae5ac8b0cac 64 // States
Siriagus 2:0ae5ac8b0cac 65
Siriagus 3:4e3f342a135c 66
Siriagus 1:0cfe2255092a 67
Siriagus 2:0ae5ac8b0cac 68
Siriagus 3:4e3f342a135c 69 void init();
Siriagus 3:4e3f342a135c 70 void cleanUp();
Siriagus 1:0cfe2255092a 71
Siriagus 1:0cfe2255092a 72 int main()
Siriagus 1:0cfe2255092a 73 {
Siriagus 1:0cfe2255092a 74 init();
Siriagus 1:0cfe2255092a 75
Siriagus 4:d6661b976359 76 time_t dt = time(NULL);
Siriagus 4:d6661b976359 77
Siriagus 0:1f92de30d43e 78 while(true)
Siriagus 0:1f92de30d43e 79 {
Siriagus 1:0cfe2255092a 80 lcd->clear();
Siriagus 1:0cfe2255092a 81
Siriagus 4:d6661b976359 82 input->joystick->update();
Siriagus 0:1f92de30d43e 83 lcd->setBrightness(1.0 - ledPot); // Update brightness of screen
Siriagus 0:1f92de30d43e 84
Siriagus 4:d6661b976359 85 // update
Siriagus 4:d6661b976359 86
Siriagus 4:d6661b976359 87 // render
Siriagus 4:d6661b976359 88
Siriagus 1:0cfe2255092a 89
Siriagus 1:0cfe2255092a 90 lcd->refresh();
Siriagus 2:0ae5ac8b0cac 91 Sleep();
Siriagus 0:1f92de30d43e 92 }
Siriagus 0:1f92de30d43e 93
Siriagus 1:0cfe2255092a 94 cleanUp();
Siriagus 0:1f92de30d43e 95
Siriagus 0:1f92de30d43e 96 return 0;
Siriagus 3:4e3f342a135c 97 }
Siriagus 3:4e3f342a135c 98
Siriagus 4:d6661b976359 99 void ledToggle()
Siriagus 4:d6661b976359 100 {
Siriagus 4:d6661b976359 101 leds[0] = !leds[0];
Siriagus 4:d6661b976359 102 }
Siriagus 4:d6661b976359 103
Siriagus 4:d6661b976359 104 int ctr = 0;
Siriagus 4:d6661b976359 105 void ledToggle4() {leds[3] = !leds[3];}
Siriagus 4:d6661b976359 106 void ledToggle2()
Siriagus 4:d6661b976359 107 {
Siriagus 4:d6661b976359 108 leds[1] = !leds[1];
Siriagus 4:d6661b976359 109
Siriagus 4:d6661b976359 110 if (++ctr > 4)
Siriagus 4:d6661b976359 111 input->addBtnPressInterrupt(input->btnB, ledToggle4);
Siriagus 4:d6661b976359 112
Siriagus 4:d6661b976359 113 }
Siriagus 4:d6661b976359 114
Siriagus 4:d6661b976359 115
Siriagus 4:d6661b976359 116 void ledToggle3() {leds[2] = !leds[2];}
Siriagus 4:d6661b976359 117
Siriagus 3:4e3f342a135c 118 void init()
Siriagus 3:4e3f342a135c 119 {
Siriagus 3:4e3f342a135c 120 // Init LCD
Siriagus 3:4e3f342a135c 121 lcd = new N5110(p7, p8, p9, p10, p11, p13, p26);
Siriagus 3:4e3f342a135c 122 lcd->init();
Siriagus 3:4e3f342a135c 123 lcd->normalMode();
Siriagus 3:4e3f342a135c 124 lcd->setBrightness(1.0 - ledPot); // Update brightness of screen
Siriagus 3:4e3f342a135c 125
Siriagus 4:d6661b976359 126 // Input
Siriagus 4:d6661b976359 127 input = new InputManager(BUTTON_A, BUTTON_B, BUTTON_C, JOY_V, JOY_H, JOY_BTN);
Siriagus 4:d6661b976359 128 input->addBtnPressInterrupt(input->btnA, ledToggle);
Siriagus 4:d6661b976359 129 input->addBtnPressInterrupt(input->btnB, ledToggle2);
Siriagus 4:d6661b976359 130 input->addBtnPressInterrupt(input->btnC, ledToggle3);
Siriagus 3:4e3f342a135c 131
Siriagus 3:4e3f342a135c 132
Siriagus 3:4e3f342a135c 133
Siriagus 3:4e3f342a135c 134 }
Siriagus 3:4e3f342a135c 135
Siriagus 3:4e3f342a135c 136 void cleanUp()
Siriagus 3:4e3f342a135c 137 {
Siriagus 3:4e3f342a135c 138 delete lcd;
Siriagus 4:d6661b976359 139 delete input;
Siriagus 1:0cfe2255092a 140 }