Helios Lyons 201239214

Dependencies:   mbed

Brief

My aim for this project was to create a FRDM K64F adapted version of the classic Space Invaders by Tomohiro Nishikado. The game itself has a number of clear features to implement;

  • Left to right movement for the player 'canon'
  • A fixed amount of player lives
  • Firing mechanics for both canon and invaders (hence collision systems)
  • Random firing from remaining invaders
  • Wave based combat

My own addition to these established ideas was Boss waves, featuring a single, larger sprite which fires at a faster interval than previous waves. The addition of a movement system using a basic for loop, as opposed to a velocity based system, will enhance the nostalgic feel of the game.

https://os.mbed.com/media/uploads/helioslyons/screenshot_2020-05-27_at_06.12.00.png

Gameplay

Movement is controlled with the joystick, moving the canon left or right. Fire by pressing A. Invaders spawn at set positions, but randomly fire at a set interval, which is higher for boss waves. Time is taken during each wave, and displayed at wave intervals, and if the play wins.

Controls are shown on the Gamepad below: (attribution: Craig A. Evans, ELEC2645 University of Leeds)

https://os.mbed.com/media/uploads/helioslyons/screenshot_2020-05-27_at_06.20.18.png

Committer:
helioslyons
Date:
Mon May 18 18:14:35 2020 +0000
Revision:
10:19b250c7de5e
Parent:
9:6a245c8ce08e
Child:
11:1fd8fca23375
Helios Lyons 201239214

Who changed what in which revision?

UserRevisionLine numberNew contents of line
helioslyons 4:c644522ff9d9 1 #include "Army.h"
helioslyons 5:72f59786b695 2 #include "Invader.h"
helioslyons 8:ec4199484adf 3 #include "mbed.h"
helioslyons 8:ec4199484adf 4 #include "N5110.h"
helioslyons 8:ec4199484adf 5 #include "Gamepad.h"
helioslyons 9:6a245c8ce08e 6
helioslyons 9:6a245c8ce08e 7 #include <cstdlib>
helioslyons 4:c644522ff9d9 8 #include <vector>
helioslyons 4:c644522ff9d9 9
helioslyons 4:c644522ff9d9 10 Army::Army()
helioslyons 4:c644522ff9d9 11 {
helioslyons 6:e3a1bfbb1627 12
helioslyons 4:c644522ff9d9 13 }
helioslyons 6:e3a1bfbb1627 14
helioslyons 4:c644522ff9d9 15 Army::~Army()
helioslyons 4:c644522ff9d9 16 {
helioslyons 6:e3a1bfbb1627 17
helioslyons 4:c644522ff9d9 18 }
helioslyons 6:e3a1bfbb1627 19
helioslyons 10:19b250c7de5e 20 void Army::create_army(int invaders)
helioslyons 4:c644522ff9d9 21 {
helioslyons 8:ec4199484adf 22 Invader army[3][3];
helioslyons 5:72f59786b695 23
helioslyons 6:e3a1bfbb1627 24 int i, n;
helioslyons 5:72f59786b695 25 for(i=0; i < 4; i++) {
helioslyons 9:6a245c8ce08e 26 //army[i].setX(i);
helioslyons 6:e3a1bfbb1627 27
helioslyons 6:e3a1bfbb1627 28 for(n=0; n < 4; n++) {
helioslyons 5:72f59786b695 29 army[i][n].init(i+1, 1);
helioslyons 5:72f59786b695 30 }
helioslyons 6:e3a1bfbb1627 31 }
helioslyons 6:e3a1bfbb1627 32 }
helioslyons 6:e3a1bfbb1627 33
helioslyons 6:e3a1bfbb1627 34 void Army::create_boss()
helioslyons 6:e3a1bfbb1627 35 {
helioslyons 6:e3a1bfbb1627 36 Invader boss;
helioslyons 6:e3a1bfbb1627 37 boss.init(4, 4);
helioslyons 6:e3a1bfbb1627 38 }
helioslyons 6:e3a1bfbb1627 39
helioslyons 6:e3a1bfbb1627 40 void Army::start_pos(int rowX, int rowY)
helioslyons 6:e3a1bfbb1627 41 {
helioslyons 6:e3a1bfbb1627 42 int tempX = rowX;
helioslyons 7:5fe9ac6522c5 43 _move_left = true;
helioslyons 6:e3a1bfbb1627 44
helioslyons 6:e3a1bfbb1627 45 for (int i = 0; i < 4; i++){ // Loop through each row and assign start_pos
helioslyons 6:e3a1bfbb1627 46 army[i][0].set_pos(rowX, rowY); // Based on X and Y inputs
helioslyons 6:e3a1bfbb1627 47 rowX += 13; // 2 above standard Invader width of 11
helioslyons 6:e3a1bfbb1627 48 }
helioslyons 7:5fe9ac6522c5 49 rowX = tempX;
helioslyons 6:e3a1bfbb1627 50 rowY += 10;
helioslyons 6:e3a1bfbb1627 51 for (int i = 0; i < 4; i++){
helioslyons 6:e3a1bfbb1627 52 army[i][1].set_pos(rowX, rowY);
helioslyons 6:e3a1bfbb1627 53 rowX +=13;
helioslyons 6:e3a1bfbb1627 54 }
helioslyons 7:5fe9ac6522c5 55 rowX = tempX;
helioslyons 6:e3a1bfbb1627 56 rowY += 10;
helioslyons 6:e3a1bfbb1627 57 for (int i = 0; i < 4; i++){
helioslyons 6:e3a1bfbb1627 58 army[i][2].set_pos(rowX, rowY);
helioslyons 6:e3a1bfbb1627 59 rowX +=13;
helioslyons 6:e3a1bfbb1627 60 }
helioslyons 6:e3a1bfbb1627 61 }
helioslyons 6:e3a1bfbb1627 62
helioslyons 7:5fe9ac6522c5 63 void Army::move_army(int x_distance, int y_distance) // REPLACE WITH FSM AFTER BASIC FUNCTIONALITY TEST
helioslyons 6:e3a1bfbb1627 64 {
helioslyons 7:5fe9ac6522c5 65 _x_distance = x_distance;
helioslyons 7:5fe9ac6522c5 66 _y_distance = y_distance;
helioslyons 7:5fe9ac6522c5 67
helioslyons 7:5fe9ac6522c5 68 int left_X = 0;
helioslyons 7:5fe9ac6522c5 69 int right_X = 80;
helioslyons 7:5fe9ac6522c5 70 int bot_Y = 0;
helioslyons 7:5fe9ac6522c5 71 int top_Y = 80;
helioslyons 7:5fe9ac6522c5 72
helioslyons 7:5fe9ac6522c5 73 // find leftmost, rightmost, top and bottom invaders
helioslyons 7:5fe9ac6522c5 74 // less invaders means more room to cover (also speed up)
helioslyons 7:5fe9ac6522c5 75
helioslyons 7:5fe9ac6522c5 76 for (int i = 3; i < 0; i--) {
helioslyons 7:5fe9ac6522c5 77 for (int n = 3; n < 0; n--) {
helioslyons 7:5fe9ac6522c5 78 int tempX = army[n][i].get_x_pos();
helioslyons 7:5fe9ac6522c5 79 int tempY = army[n][i].get_y_pos();
helioslyons 7:5fe9ac6522c5 80
helioslyons 7:5fe9ac6522c5 81 if (tempX < left_X) {
helioslyons 7:5fe9ac6522c5 82 left_X = tempX;
helioslyons 7:5fe9ac6522c5 83 }
helioslyons 7:5fe9ac6522c5 84 else if (tempX > right_X) {
helioslyons 7:5fe9ac6522c5 85 right_X = tempX;
helioslyons 7:5fe9ac6522c5 86 }
helioslyons 7:5fe9ac6522c5 87
helioslyons 7:5fe9ac6522c5 88 if (tempY < top_Y) {
helioslyons 7:5fe9ac6522c5 89 top_Y = tempY;
helioslyons 7:5fe9ac6522c5 90 }
helioslyons 7:5fe9ac6522c5 91 else if (tempY > bot_Y) {
helioslyons 7:5fe9ac6522c5 92 bot_Y = tempY;
helioslyons 7:5fe9ac6522c5 93 }
helioslyons 7:5fe9ac6522c5 94 }
helioslyons 7:5fe9ac6522c5 95 }
helioslyons 7:5fe9ac6522c5 96
helioslyons 7:5fe9ac6522c5 97
helioslyons 7:5fe9ac6522c5 98 if (_move_left == true) { // if moving left
helioslyons 7:5fe9ac6522c5 99 if (left_X < 12) { // check if edge will be reached, if so change direction
helioslyons 7:5fe9ac6522c5 100 _move_left = false;
helioslyons 7:5fe9ac6522c5 101 if(bot_Y > 50) {
helioslyons 7:5fe9ac6522c5 102 // if lowest Y point is below 50, move up
helioslyons 7:5fe9ac6522c5 103 for (int i = 3; i < 0; i--) {
helioslyons 7:5fe9ac6522c5 104 for (int n = 3; n < 0; n--) {
helioslyons 7:5fe9ac6522c5 105 army[i][n].set_pos(army[i][n].get_x_pos(), army[i][n].get_y_pos() - _y_distance);
helioslyons 7:5fe9ac6522c5 106 }
helioslyons 7:5fe9ac6522c5 107 }
helioslyons 7:5fe9ac6522c5 108 }
helioslyons 7:5fe9ac6522c5 109 else { // else move down
helioslyons 7:5fe9ac6522c5 110 for (int i = 3; i < 0; i--) {
helioslyons 7:5fe9ac6522c5 111 for (int n = 3; n < 0; n--) {
helioslyons 7:5fe9ac6522c5 112 army[i][n].set_pos(army[i][n].get_x_pos(), army[i][n].get_y_pos() + _y_distance);
helioslyons 7:5fe9ac6522c5 113 }
helioslyons 7:5fe9ac6522c5 114 }
helioslyons 7:5fe9ac6522c5 115 }
helioslyons 7:5fe9ac6522c5 116 }
helioslyons 7:5fe9ac6522c5 117 else { // if edge is not near to being reached, move left
helioslyons 7:5fe9ac6522c5 118 for (int i = 3; i < 0; i--) {
helioslyons 7:5fe9ac6522c5 119 for (int n = 3; n < 0; n--) {
helioslyons 7:5fe9ac6522c5 120 army[i][n].set_pos(army[i][n].get_x_pos() - _x_distance, army[i][n].get_y_pos());
helioslyons 7:5fe9ac6522c5 121 }
helioslyons 7:5fe9ac6522c5 122 }
helioslyons 7:5fe9ac6522c5 123 }
helioslyons 7:5fe9ac6522c5 124 }
helioslyons 7:5fe9ac6522c5 125
helioslyons 7:5fe9ac6522c5 126 else {
helioslyons 9:6a245c8ce08e 127 if (right_X > 80) { // if rightmost invader is further than X = 65, change direction
helioslyons 7:5fe9ac6522c5 128 _move_left = true;
helioslyons 7:5fe9ac6522c5 129
helioslyons 7:5fe9ac6522c5 130 if (bot_Y > 50) { // if lowest invader is below Y = 50, go up
helioslyons 7:5fe9ac6522c5 131 for (int i = 3; i < 0; i--) {
helioslyons 7:5fe9ac6522c5 132 for (int n = 3; n < 0; n--) {
helioslyons 7:5fe9ac6522c5 133 army[i][n].set_pos(army[i][n].get_x_pos(), army[i][n].get_y_pos() - _y_distance);
helioslyons 7:5fe9ac6522c5 134 }
helioslyons 7:5fe9ac6522c5 135 }
helioslyons 7:5fe9ac6522c5 136 }
helioslyons 7:5fe9ac6522c5 137 else { // otherwise go down
helioslyons 7:5fe9ac6522c5 138 for (int i = 3; i < 0; i--) {
helioslyons 7:5fe9ac6522c5 139 for (int n = 3; n < 0; n--) {
helioslyons 7:5fe9ac6522c5 140 army[i][n].set_pos(army[i][n].get_x_pos(), army[i][n].get_y_pos() + _y_distance);
helioslyons 7:5fe9ac6522c5 141 }
helioslyons 7:5fe9ac6522c5 142 }
helioslyons 7:5fe9ac6522c5 143 }
helioslyons 7:5fe9ac6522c5 144 }
helioslyons 7:5fe9ac6522c5 145 else { // if edge is not near to being reached, move right
helioslyons 7:5fe9ac6522c5 146 for (int i = 3; i < 0; i--) {
helioslyons 7:5fe9ac6522c5 147 for (int n = 3; n < 0; n--) {
helioslyons 7:5fe9ac6522c5 148 army[i][n].set_pos(army[i][n].get_x_pos() + _x_distance, army[i][n].get_y_pos() + _y_distance);
helioslyons 7:5fe9ac6522c5 149 }
helioslyons 7:5fe9ac6522c5 150 }
helioslyons 7:5fe9ac6522c5 151 }
helioslyons 7:5fe9ac6522c5 152 }
helioslyons 6:e3a1bfbb1627 153 }
helioslyons 8:ec4199484adf 154
helioslyons 10:19b250c7de5e 155 void Army::draw(N5110 &lcd)
helioslyons 8:ec4199484adf 156 {
helioslyons 8:ec4199484adf 157 int i, n;
helioslyons 8:ec4199484adf 158 for(i=0; i < 4; i++) {
helioslyons 8:ec4199484adf 159
helioslyons 8:ec4199484adf 160 for(n=0; n < 4; n++) {
helioslyons 10:19b250c7de5e 161 army[i][n].draw(lcd);
helioslyons 8:ec4199484adf 162 }
helioslyons 8:ec4199484adf 163 }
helioslyons 8:ec4199484adf 164 }
helioslyons 9:6a245c8ce08e 165
helioslyons 9:6a245c8ce08e 166 void Army::rand_invader()
helioslyons 9:6a245c8ce08e 167 {
helioslyons 9:6a245c8ce08e 168 // get random coordinates for an invader
helioslyons 9:6a245c8ce08e 169 int rem = rand() % 5; // random column number
helioslyons 9:6a245c8ce08e 170 int rem2 = rand()% 4; // random row number
helioslyons 9:6a245c8ce08e 171 _fire_x = army[rem2][rem].get_x_pos(); // get position for random choices
helioslyons 9:6a245c8ce08e 172 _fire_y = army[rem2][rem].get_y_pos(); // used to set bullet start location
helioslyons 9:6a245c8ce08e 173 }
helioslyons 10:19b250c7de5e 174
helioslyons 10:19b250c7de5e 175 void Army::check_col(int x, int y)
helioslyons 10:19b250c7de5e 176 {
helioslyons 10:19b250c7de5e 177
helioslyons 10:19b250c7de5e 178 for (int i = 0; i < 4; i++) { // take 2 positions
helioslyons 10:19b250c7de5e 179 for (int n = 0; n < 4; n++) { // return match after iterating through army
helioslyons 10:19b250c7de5e 180 int tempX = army[n][i].get_x_pos();
helioslyons 10:19b250c7de5e 181 int tempY = army[n][i].get_y_pos();
helioslyons 10:19b250c7de5e 182
helioslyons 10:19b250c7de5e 183 if (x == tempX && y == tempY) {
helioslyons 10:19b250c7de5e 184 _x_col = true;
helioslyons 10:19b250c7de5e 185 _y_col = true;
helioslyons 10:19b250c7de5e 186
helioslyons 10:19b250c7de5e 187 army[n][i].hit();
helioslyons 10:19b250c7de5e 188 _sprite_pass = army[n][i].get_sprite();
helioslyons 10:19b250c7de5e 189 }
helioslyons 10:19b250c7de5e 190 }
helioslyons 10:19b250c7de5e 191 }
helioslyons 10:19b250c7de5e 192 }