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:
Tue Apr 28 12:46:37 2015 +0000
Revision:
1:0cfe2255092a
Parent:
0:1f92de30d43e
Child:
2:0ae5ac8b0cac
Simple Menu test - Uses PinDetect for debouncing.

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 1:0cfe2255092a 11
Siriagus 0:1f92de30d43e 12 #include "Joystick.h"
Siriagus 1:0cfe2255092a 13 #include <string>
Siriagus 1:0cfe2255092a 14
Siriagus 1:0cfe2255092a 15 #include "State.h"
Siriagus 1:0cfe2255092a 16 #include "MainMenu.h"
Siriagus 0:1f92de30d43e 17 #include "map.h"
Siriagus 1:0cfe2255092a 18 #include "images.h"
Siriagus 1:0cfe2255092a 19
Siriagus 0:1f92de30d43e 20 #include <ctime>
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 1:0cfe2255092a 29 #define BUTTON_A p27
Siriagus 1:0cfe2255092a 30 #define BUTTON_B p28
Siriagus 1:0cfe2255092a 31 #define BUTTON_C p29
Siriagus 1:0cfe2255092a 32
Siriagus 1:0cfe2255092a 33 enum MainState {MENU, GAME};
Siriagus 1:0cfe2255092a 34 MainState currentState; // current state
Siriagus 1:0cfe2255092a 35
Siriagus 0:1f92de30d43e 36 // Components
Siriagus 0:1f92de30d43e 37 N5110 *lcd; // VCC, SCE, RST, D/C, MOSI, SCLK and LED
Siriagus 0:1f92de30d43e 38 Joystick *joystick;
Siriagus 0:1f92de30d43e 39
Siriagus 0:1f92de30d43e 40 // Brightness potentiometer
Siriagus 1:0cfe2255092a 41 AnalogIn ledPot(LED_POT);
Siriagus 0:1f92de30d43e 42
Siriagus 1:0cfe2255092a 43 /*
Siriagus 0:1f92de30d43e 44 // Buttons
Siriagus 0:1f92de30d43e 45 DigitalIn btnA(p27);
Siriagus 0:1f92de30d43e 46 DigitalIn btnB(p28);
Siriagus 0:1f92de30d43e 47 DigitalIn btnC(p29);
Siriagus 1:0cfe2255092a 48 */
Siriagus 0:1f92de30d43e 49
Siriagus 0:1f92de30d43e 50 // Debugging
Siriagus 0:1f92de30d43e 51 Serial pc(USBTX, USBRX);
Siriagus 0:1f92de30d43e 52 BusOut leds(LED1, LED2, LED3, LED4);
Siriagus 0:1f92de30d43e 53
Siriagus 1:0cfe2255092a 54
Siriagus 1:0cfe2255092a 55 // @brief Clears the screen and fill it with the image in the argument.
Siriagus 1:0cfe2255092a 56 void clearAndDrawImage(const int img[BANKS][WIDTH])
Siriagus 0:1f92de30d43e 57 {
Siriagus 0:1f92de30d43e 58 for (int i = 0; i < BANKS; ++i)
Siriagus 0:1f92de30d43e 59 {
Siriagus 0:1f92de30d43e 60 for (int j = 0; j < WIDTH; ++j)
Siriagus 0:1f92de30d43e 61 {
Siriagus 1:0cfe2255092a 62 lcd->buffer[j][i] = img[i][j];
Siriagus 0:1f92de30d43e 63 }
Siriagus 0:1f92de30d43e 64 }
Siriagus 0:1f92de30d43e 65 lcd->refresh();
Siriagus 0:1f92de30d43e 66 }
Siriagus 0:1f92de30d43e 67
Siriagus 1:0cfe2255092a 68 State *stateObj; // current state object
Siriagus 1:0cfe2255092a 69 void init()
Siriagus 0:1f92de30d43e 70 {
Siriagus 0:1f92de30d43e 71 // Init LCD
Siriagus 0:1f92de30d43e 72 lcd = new N5110(p7, p8, p9, p10, p11, p13, p26);
Siriagus 0:1f92de30d43e 73 lcd->init();
Siriagus 0:1f92de30d43e 74 lcd->normalMode();
Siriagus 0:1f92de30d43e 75 lcd->setBrightness(1.0 - ledPot); // Update brightness of screen
Siriagus 0:1f92de30d43e 76
Siriagus 0:1f92de30d43e 77 // Init joystick
Siriagus 1:0cfe2255092a 78 joystick = new Joystick(JOY_H, JOY_V, JOY_BTN);
Siriagus 0:1f92de30d43e 79 joystick->calibrate();
Siriagus 0:1f92de30d43e 80
Siriagus 1:0cfe2255092a 81 // Set initial state
Siriagus 1:0cfe2255092a 82 // currentState = MENU;
Siriagus 1:0cfe2255092a 83 // stateObj = new MainMenu(lcd, BUTTON_A, BUTTON_B, BUTTON_C);
Siriagus 1:0cfe2255092a 84 }
Siriagus 1:0cfe2255092a 85
Siriagus 1:0cfe2255092a 86 void cleanUp()
Siriagus 1:0cfe2255092a 87 {
Siriagus 1:0cfe2255092a 88 delete lcd;
Siriagus 1:0cfe2255092a 89 delete joystick;
Siriagus 1:0cfe2255092a 90 delete stateObj;
Siriagus 1:0cfe2255092a 91 }
Siriagus 1:0cfe2255092a 92
Siriagus 1:0cfe2255092a 93 const int NUM_CHOICES = 3;
Siriagus 1:0cfe2255092a 94 std::string choices[NUM_CHOICES] = {"Play", "High Score", "Controls"};
Siriagus 1:0cfe2255092a 95 int selectedChoice = 0;
Siriagus 1:0cfe2255092a 96
Siriagus 1:0cfe2255092a 97 PinDetect btnC(BUTTON_C);
Siriagus 1:0cfe2255092a 98 void nextChoice() { selectedChoice = (selectedChoice + 1) % NUM_CHOICES;}
Siriagus 1:0cfe2255092a 99
Siriagus 1:0cfe2255092a 100 int main()
Siriagus 1:0cfe2255092a 101 {
Siriagus 1:0cfe2255092a 102 init();
Siriagus 1:0cfe2255092a 103
Siriagus 1:0cfe2255092a 104 // button
Siriagus 1:0cfe2255092a 105 btnC.attach_asserted(&nextChoice);
Siriagus 1:0cfe2255092a 106 btnC.setSampleFrequency();
Siriagus 1:0cfe2255092a 107
Siriagus 1:0cfe2255092a 108 // Game loop, fixed-time step, updates game logic with regular intervals, rendering happens as fast as possible
Siriagus 0:1f92de30d43e 109 while(true)
Siriagus 0:1f92de30d43e 110 {
Siriagus 1:0cfe2255092a 111 lcd->clear();
Siriagus 0:1f92de30d43e 112
Siriagus 1:0cfe2255092a 113 //stateObj->run();
Siriagus 1:0cfe2255092a 114
Siriagus 0:1f92de30d43e 115 joystick->update();
Siriagus 0:1f92de30d43e 116 lcd->setBrightness(1.0 - ledPot); // Update brightness of screen
Siriagus 0:1f92de30d43e 117
Siriagus 1:0cfe2255092a 118 for (int i = 0; i < 3; ++i)
Siriagus 1:0cfe2255092a 119 {
Siriagus 1:0cfe2255092a 120 std::string str = (selectedChoice == i) ? ("> " + choices[i]) : choices[i];
Siriagus 1:0cfe2255092a 121 lcd->printString(str.c_str(), 10, i+1);
Siriagus 1:0cfe2255092a 122 }
Siriagus 1:0cfe2255092a 123
Siriagus 1:0cfe2255092a 124 lcd->refresh();
Siriagus 1:0cfe2255092a 125 Sleep(); // Wait for button interrupt
Siriagus 0:1f92de30d43e 126 }
Siriagus 0:1f92de30d43e 127
Siriagus 1:0cfe2255092a 128 cleanUp();
Siriagus 0:1f92de30d43e 129
Siriagus 0:1f92de30d43e 130 return 0;
Siriagus 1:0cfe2255092a 131 }