Game For ECE 2035

Dependencies:   mbed wave_player 4DGL-uLCD-SE MMA8452

Committer:
nasiromar
Date:
Sat Nov 20 03:57:56 2021 +0000
Revision:
8:fcc333a8f9e1
Parent:
7:862062ffca62
Child:
9:cbb9cfb1f6c5
Base Game

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rconnorlawson 0:35660d7952f7 1 // Project includes
rconnorlawson 0:35660d7952f7 2 #include "globals.h"
rconnorlawson 0:35660d7952f7 3 #include "hardware.h"
rconnorlawson 0:35660d7952f7 4 #include "map.h"
rconnorlawson 0:35660d7952f7 5 #include "graphics.h"
rconnorlawson 0:35660d7952f7 6 #include "speech.h"
nasiromar 6:c9695079521d 7 #include "spells.h"
nasiromar 6:c9695079521d 8 #include "actions.h"
rconnorlawson 0:35660d7952f7 9
rconnorlawson 0:35660d7952f7 10 // Functions in this file
rconnorlawson 0:35660d7952f7 11 int get_action (GameInputs inputs);
rconnorlawson 0:35660d7952f7 12 int update_game (int action);
rconnorlawson 0:35660d7952f7 13 void draw_game (int init);
rconnorlawson 0:35660d7952f7 14 void init_main_map ();
rconnorlawson 0:35660d7952f7 15 int main ();
rconnorlawson 0:35660d7952f7 16
rconnorlawson 0:35660d7952f7 17 /**
rconnorlawson 0:35660d7952f7 18 * The main game state. Must include Player locations and previous locations for
rconnorlawson 0:35660d7952f7 19 * drawing to work properly. Other items can be added as needed.
rconnorlawson 0:35660d7952f7 20 */
rconnorlawson 0:35660d7952f7 21 struct {
rconnorlawson 0:35660d7952f7 22 int x,y; // Current locations
rconnorlawson 0:35660d7952f7 23 int px, py; // Previous locations
rconnorlawson 0:35660d7952f7 24 int has_key;
nasiromar 6:c9695079521d 25 int spell;
nasiromar 6:c9695079521d 26 int god;
nasiromar 8:fcc333a8f9e1 27 int won;
rashidi1saeed 2:1ca97843a334 28 // You can add other properties for the player here
rconnorlawson 0:35660d7952f7 29 } Player;
rconnorlawson 0:35660d7952f7 30
rconnorlawson 0:35660d7952f7 31 /**
rconnorlawson 0:35660d7952f7 32 * Given the game inputs, determine what kind of update needs to happen.
rconnorlawson 0:35660d7952f7 33 * Possbile return values are defined below.
rconnorlawson 0:35660d7952f7 34 */
rconnorlawson 0:35660d7952f7 35 #define NO_ACTION 0
rconnorlawson 0:35660d7952f7 36 #define ACTION_BUTTON 1
rconnorlawson 0:35660d7952f7 37 #define MENU_BUTTON 2
rconnorlawson 0:35660d7952f7 38 #define GO_LEFT 3
rconnorlawson 0:35660d7952f7 39 #define GO_RIGHT 4
rconnorlawson 0:35660d7952f7 40 #define GO_UP 5
rconnorlawson 0:35660d7952f7 41 #define GO_DOWN 6
nasiromar 6:c9695079521d 42 #define GOD_MODE 7
nasiromar 6:c9695079521d 43
nasiromar 6:c9695079521d 44 #define TILT .25
rconnorlawson 0:35660d7952f7 45 int get_action(GameInputs inputs)
rconnorlawson 0:35660d7952f7 46 {
nasiromar 6:c9695079521d 47
nasiromar 6:c9695079521d 48 if(inputs.ay > TILT) { //Go in north direction if it is not blocked
nasiromar 6:c9695079521d 49 return GO_UP;
nasiromar 6:c9695079521d 50 }
nasiromar 6:c9695079521d 51 if(inputs.ay < TILT *-1) { //Go in south direction if it is not blocked
nasiromar 6:c9695079521d 52 return GO_DOWN;
nasiromar 6:c9695079521d 53 }
nasiromar 6:c9695079521d 54 if(inputs.ax > TILT) { //Go in north direction if it is not blocked
nasiromar 6:c9695079521d 55 return GO_RIGHT;
nasiromar 6:c9695079521d 56 }
nasiromar 6:c9695079521d 57 if(inputs.ax < TILT *-1) { //Go in north direction if it is not blocked
nasiromar 6:c9695079521d 58 return GO_LEFT;
nasiromar 6:c9695079521d 59 }
nasiromar 6:c9695079521d 60 if(!inputs.b1) {
nasiromar 6:c9695079521d 61 wait(.5);
nasiromar 6:c9695079521d 62 return ACTION_BUTTON;
nasiromar 6:c9695079521d 63 }
nasiromar 6:c9695079521d 64 if(!inputs.b2) {
nasiromar 6:c9695079521d 65 wait(.5);
nasiromar 6:c9695079521d 66 return MENU_BUTTON;
nasiromar 6:c9695079521d 67 }
nasiromar 6:c9695079521d 68 if (!inputs.b3) {
nasiromar 6:c9695079521d 69 wait(.5);
nasiromar 6:c9695079521d 70 return GOD_MODE;
nasiromar 6:c9695079521d 71 } else {
nasiromar 6:c9695079521d 72 return NO_ACTION;
nasiromar 6:c9695079521d 73 }
rconnorlawson 0:35660d7952f7 74 }
rconnorlawson 0:35660d7952f7 75
nasiromar 6:c9695079521d 76
rconnorlawson 0:35660d7952f7 77 /**
rconnorlawson 0:35660d7952f7 78 * Update the game state based on the user action. For example, if the user
rconnorlawson 0:35660d7952f7 79 * requests GO_UP, then this function should determine if that is possible by
rconnorlawson 0:35660d7952f7 80 * consulting the map, and update the Player position accordingly.
nasiromar 6:c9695079521d 81 *
rconnorlawson 0:35660d7952f7 82 * Return values are defined below. FULL_DRAW indicates that for this frame,
rconnorlawson 0:35660d7952f7 83 * draw_game should not optimize drawing and should draw every tile, even if
rconnorlawson 0:35660d7952f7 84 * the player has not moved.
rconnorlawson 0:35660d7952f7 85 */
nasiromar 6:c9695079521d 86 // Gmae Life and Magic Points
nasiromar 6:c9695079521d 87 #define HP 100
nasiromar 6:c9695079521d 88 #define MP 100
nasiromar 6:c9695079521d 89
nasiromar 6:c9695079521d 90
nasiromar 6:c9695079521d 91
rconnorlawson 0:35660d7952f7 92 #define NO_RESULT 0
rconnorlawson 0:35660d7952f7 93 #define GAME_OVER 1
rconnorlawson 0:35660d7952f7 94 #define FULL_DRAW 2
rconnorlawson 0:35660d7952f7 95 int update_game(int action)
rconnorlawson 0:35660d7952f7 96 {
rconnorlawson 0:35660d7952f7 97 // Save player previous location before updating
rconnorlawson 0:35660d7952f7 98 Player.px = Player.x;
rconnorlawson 0:35660d7952f7 99 Player.py = Player.y;
nasiromar 6:c9695079521d 100
nasiromar 6:c9695079521d 101
nasiromar 6:c9695079521d 102
rconnorlawson 0:35660d7952f7 103 // Do different things based on the each action.
rconnorlawson 0:35660d7952f7 104 // You can define functions like "go_up()" that get called for each case.
nasiromar 6:c9695079521d 105
nasiromar 6:c9695079521d 106 // Need to check if Claue has changed as well if whats in front of me is able to be walked into
nasiromar 6:c9695079521d 107 switch(action) {
nasiromar 6:c9695079521d 108 case GO_UP: {
nasiromar 6:c9695079521d 109 MapItem* north = get_north(Player.x,Player.y);
nasiromar 6:c9695079521d 110 if (north->walkable && north == NULL || north->type == (PORTAL || PLANT) && Player.y != 0 || Player.god ) {
nasiromar 6:c9695079521d 111 Player.y--;
nasiromar 6:c9695079521d 112 }
nasiromar 6:c9695079521d 113 break;
nasiromar 6:c9695079521d 114 }
nasiromar 6:c9695079521d 115 case GO_RIGHT: {
nasiromar 6:c9695079521d 116 MapItem* east = get_east(Player.x,Player.y);
nasiromar 6:c9695079521d 117 if (east->walkable && east == NULL || east->type == (PORTAL || PLANT) && Player.x != 0 || Player.god ) {
nasiromar 6:c9695079521d 118 Player.x++;
nasiromar 6:c9695079521d 119 }
nasiromar 6:c9695079521d 120 break;
nasiromar 6:c9695079521d 121 }
nasiromar 6:c9695079521d 122 case GO_DOWN: {
nasiromar 6:c9695079521d 123 MapItem* south = get_south(Player.x,Player.y);
nasiromar 6:c9695079521d 124 if (south->walkable && south == NULL || south->type ==(PORTAL || PLANT) && Player.y != 0 || Player.god ) {
nasiromar 6:c9695079521d 125 Player.y++;
nasiromar 6:c9695079521d 126 }
nasiromar 6:c9695079521d 127 break;
nasiromar 6:c9695079521d 128 }
nasiromar 6:c9695079521d 129 case GO_LEFT: {
nasiromar 6:c9695079521d 130 MapItem* west = get_west(Player.x,Player.y);
nasiromar 6:c9695079521d 131 if (west->walkable && west == NULL || west->type == (PORTAL || PLANT) && Player.x != 0 || Player.god ) {
nasiromar 6:c9695079521d 132 Player.x--;
nasiromar 6:c9695079521d 133 }
nasiromar 6:c9695079521d 134 break;
nasiromar 6:c9695079521d 135 }
nasiromar 6:c9695079521d 136 case ACTION_BUTTON: {
nasiromar 6:c9695079521d 137 MapItem* west = get_west(Player.x,Player.y);
nasiromar 6:c9695079521d 138 MapItem* south = get_south(Player.x,Player.y);
nasiromar 6:c9695079521d 139 MapItem* north = get_north(Player.x,Player.y);
nasiromar 6:c9695079521d 140 MapItem* east = get_east(Player.x,Player.y);
nasiromar 6:c9695079521d 141 MapItem* curr = get_here(Player.x,Player.y);
nasiromar 6:c9695079521d 142
nasiromar 7:862062ffca62 143 if((east->type == NPC||west->type == NPC||north->type == NPC||south->type == NPC)&& Player.has_key == 1){
nasiromar 7:862062ffca62 144 npc_speech2();
nasiromar 7:862062ffca62 145 }
nasiromar 7:862062ffca62 146
nasiromar 8:fcc333a8f9e1 147 if(east->type == NPC||west->type == NPC||north->type == NPC||south->type == NPC && Player.has_key == 0 ){
nasiromar 6:c9695079521d 148 npc_speech1();
nasiromar 6:c9695079521d 149 }
nasiromar 6:c9695079521d 150
nasiromar 7:862062ffca62 151 if(north->type == PORTAL||south->type == PORTAL||east->type == PORTAL||west->type == PORTAL){
nasiromar 7:862062ffca62 152 init_dung();
nasiromar 7:862062ffca62 153 Player.x = Player.y = 7;
nasiromar 7:862062ffca62 154 }
nasiromar 7:862062ffca62 155
nasiromar 7:862062ffca62 156 if((north->type == DRAGON||south->type == DRAGON||east->type == DRAGON||west->type == DRAGON )&& Player.spell == WATER){
nasiromar 7:862062ffca62 157 slay_dragon();
nasiromar 7:862062ffca62 158 Player.has_key = 1;
nasiromar 7:862062ffca62 159 }
nasiromar 7:862062ffca62 160
nasiromar 7:862062ffca62 161 if(north->type == PORTAl||south->type == PORTAl||east->type == PORTAl||west->type == PORTAl){
nasiromar 7:862062ffca62 162 init_main_map();
nasiromar 7:862062ffca62 163 }
nasiromar 7:862062ffca62 164
nasiromar 8:fcc333a8f9e1 165 if((north->type == DOOR||south->type == DOOR||east->type == DOOR||west->type == DOOR)&&Player.has_key == 1){
nasiromar 8:fcc333a8f9e1 166 Player.won = door_open();
nasiromar 8:fcc333a8f9e1 167 }
nasiromar 8:fcc333a8f9e1 168
nasiromar 6:c9695079521d 169 }
nasiromar 6:c9695079521d 170 break;
nasiromar 6:c9695079521d 171 case MENU_BUTTON: {
nasiromar 6:c9695079521d 172 init_spells();
nasiromar 6:c9695079521d 173 Player.spell = spell();
nasiromar 6:c9695079521d 174 }
nasiromar 6:c9695079521d 175 break;
nasiromar 6:c9695079521d 176 case GOD_MODE: {
nasiromar 6:c9695079521d 177
nasiromar 6:c9695079521d 178 Player.god = !Player.god;
nasiromar 6:c9695079521d 179 }
nasiromar 6:c9695079521d 180 break;
nasiromar 6:c9695079521d 181
nasiromar 6:c9695079521d 182 default:
nasiromar 6:c9695079521d 183
nasiromar 6:c9695079521d 184 break;
rconnorlawson 0:35660d7952f7 185 }
rconnorlawson 0:35660d7952f7 186 return NO_RESULT;
rconnorlawson 0:35660d7952f7 187 }
rconnorlawson 0:35660d7952f7 188
rconnorlawson 0:35660d7952f7 189 /**
rconnorlawson 0:35660d7952f7 190 * Entry point for frame drawing. This should be called once per iteration of
nasiromar 6:c9695079521d 191 * the game loop. This draws all tiles on the screen, followed by the status
nasiromar 6:c9695079521d 192 * bars. Unless init is nonzero, this function will optimize drawing by only
rconnorlawson 0:35660d7952f7 193 * drawing tiles that have changed from the previous frame.
rconnorlawson 0:35660d7952f7 194 */
rconnorlawson 0:35660d7952f7 195 void draw_game(int init)
rconnorlawson 0:35660d7952f7 196 {
rconnorlawson 0:35660d7952f7 197 // Draw game border first
rconnorlawson 0:35660d7952f7 198 if(init) draw_border();
nasiromar 6:c9695079521d 199
rconnorlawson 0:35660d7952f7 200 // Iterate over all visible map tiles
nasiromar 6:c9695079521d 201 for (int i = -5; i <= 5; i++) { // Iterate over columns of tiles
nasiromar 6:c9695079521d 202 for (int j = -4; j <= 4; j++) { // Iterate over one column of tiles
rconnorlawson 0:35660d7952f7 203 // Here, we have a given (i,j)
nasiromar 6:c9695079521d 204
rconnorlawson 0:35660d7952f7 205 // Compute the current map (x,y) of this tile
rconnorlawson 0:35660d7952f7 206 int x = i + Player.x;
rconnorlawson 0:35660d7952f7 207 int y = j + Player.y;
nasiromar 6:c9695079521d 208
rconnorlawson 0:35660d7952f7 209 // Compute the previous map (px, py) of this tile
rconnorlawson 0:35660d7952f7 210 int px = i + Player.px;
rconnorlawson 0:35660d7952f7 211 int py = j + Player.py;
nasiromar 6:c9695079521d 212
rconnorlawson 0:35660d7952f7 213 // Compute u,v coordinates for drawing
rconnorlawson 0:35660d7952f7 214 int u = (i+5)*11 + 3;
rconnorlawson 0:35660d7952f7 215 int v = (j+4)*11 + 15;
nasiromar 6:c9695079521d 216
rconnorlawson 0:35660d7952f7 217 // Figure out what to draw
rconnorlawson 0:35660d7952f7 218 DrawFunc draw = NULL;
nasiromar 6:c9695079521d 219 if (init && i == 0 && j == 0) { // Only draw the player on init
rconnorlawson 0:35660d7952f7 220 draw_player(u, v, Player.has_key);
rconnorlawson 0:35660d7952f7 221 continue;
nasiromar 6:c9695079521d 222 } else if (x >= 0 && y >= 0 && x < map_width() && y < map_height()) { // Current (i,j) in the map
rconnorlawson 0:35660d7952f7 223 MapItem* curr_item = get_here(x, y);
rconnorlawson 0:35660d7952f7 224 MapItem* prev_item = get_here(px, py);
nasiromar 6:c9695079521d 225 if (init || curr_item != prev_item) { // Only draw if they're different
nasiromar 6:c9695079521d 226 if (curr_item) { // There's something here! Draw it
rconnorlawson 0:35660d7952f7 227 draw = curr_item->draw;
nasiromar 6:c9695079521d 228 } else { // There used to be something, but now there isn't
rconnorlawson 0:35660d7952f7 229 draw = draw_nothing;
rconnorlawson 0:35660d7952f7 230 }
rconnorlawson 0:35660d7952f7 231 }
nasiromar 6:c9695079521d 232 } else if (init) { // If doing a full draw, but we're out of bounds, draw the walls.
rconnorlawson 0:35660d7952f7 233 draw = draw_wall;
rconnorlawson 0:35660d7952f7 234 }
rconnorlawson 0:35660d7952f7 235
rconnorlawson 0:35660d7952f7 236 // Actually draw the tile
rconnorlawson 0:35660d7952f7 237 if (draw) draw(u, v);
rconnorlawson 0:35660d7952f7 238 }
rconnorlawson 0:35660d7952f7 239 }
rconnorlawson 0:35660d7952f7 240
nasiromar 6:c9695079521d 241 // Draw status bars
nasiromar 6:c9695079521d 242 draw_upper_status(Player.x,Player.y);
nasiromar 6:c9695079521d 243 draw_lower_status(HP,MP);
rconnorlawson 0:35660d7952f7 244 }
rconnorlawson 0:35660d7952f7 245
rconnorlawson 0:35660d7952f7 246
rconnorlawson 0:35660d7952f7 247 /**
rconnorlawson 0:35660d7952f7 248 * Initialize the main world map. Add walls around the edges, interior chambers,
rashidi1saeed 2:1ca97843a334 249 * and plants in the background so you can see motion. Note: using the similar
rashidi1saeed 3:e4690ad5a4d2 250 * procedure you can init the secondary map(s).
rconnorlawson 0:35660d7952f7 251 */
rconnorlawson 0:35660d7952f7 252 void init_main_map()
rconnorlawson 0:35660d7952f7 253 {
rconnorlawson 0:35660d7952f7 254 // "Random" plants
rconnorlawson 0:35660d7952f7 255 Map* map = set_active_map(0);
nasiromar 6:c9695079521d 256 for(int i = map_width() + 3; i < map_area(); i += 39) {
rconnorlawson 0:35660d7952f7 257 add_plant(i % map_width(), i / map_width());
rconnorlawson 0:35660d7952f7 258 }
rconnorlawson 0:35660d7952f7 259 pc.printf("plants\r\n");
nasiromar 6:c9695079521d 260
rconnorlawson 0:35660d7952f7 261 pc.printf("Adding walls!\r\n");
rconnorlawson 0:35660d7952f7 262 add_wall(0, 0, HORIZONTAL, map_width());
rconnorlawson 0:35660d7952f7 263 add_wall(0, map_height()-1, HORIZONTAL, map_width());
rconnorlawson 0:35660d7952f7 264 add_wall(0, 0, VERTICAL, map_height());
rconnorlawson 0:35660d7952f7 265 add_wall(map_width()-1, 0, VERTICAL, map_height());
rconnorlawson 0:35660d7952f7 266 pc.printf("Walls done!\r\n");
nasiromar 7:862062ffca62 267
nasiromar 7:862062ffca62 268
nasiromar 7:862062ffca62 269
nasiromar 7:862062ffca62 270 for(int i = 7; i < 13;i++)
nasiromar 7:862062ffca62 271 {
nasiromar 7:862062ffca62 272 for (int j = 23; j <31;j++)
nasiromar 7:862062ffca62 273 {
nasiromar 7:862062ffca62 274 add_kindom(j,i);
nasiromar 7:862062ffca62 275 }
nasiromar 7:862062ffca62 276 }
nasiromar 7:862062ffca62 277
nasiromar 6:c9695079521d 278 add_npc(9,9);
nasiromar 6:c9695079521d 279
nasiromar 7:862062ffca62 280 //add_chest(10,10);
nasiromar 6:c9695079521d 281
nasiromar 7:862062ffca62 282 add_door(26,12);
nasiromar 7:862062ffca62 283
nasiromar 7:862062ffca62 284 add_portal(20,35);
nasiromar 6:c9695079521d 285
rconnorlawson 0:35660d7952f7 286 print_map();
rconnorlawson 0:35660d7952f7 287 }
rconnorlawson 0:35660d7952f7 288
nasiromar 6:c9695079521d 289
rconnorlawson 0:35660d7952f7 290 /**
rconnorlawson 0:35660d7952f7 291 * Program entry point! This is where it all begins.
rconnorlawson 0:35660d7952f7 292 * This function orchestrates all the parts of the game. Most of your
rconnorlawson 0:35660d7952f7 293 * implementation should be elsewhere - this holds the game loop, and should
rconnorlawson 0:35660d7952f7 294 * read like a road map for the rest of the code.
rconnorlawson 0:35660d7952f7 295 */
rconnorlawson 0:35660d7952f7 296 int main()
rconnorlawson 0:35660d7952f7 297 {
nasiromar 7:862062ffca62 298
nasiromar 7:862062ffca62 299
nasiromar 7:862062ffca62 300 // MapItem* north = get_north(Player.x,Player.y);
nasiromar 7:862062ffca62 301
nasiromar 7:862062ffca62 302
rconnorlawson 0:35660d7952f7 303 // First things first: initialize hardware
rconnorlawson 0:35660d7952f7 304 ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!");
nasiromar 6:c9695079521d 305
rconnorlawson 0:35660d7952f7 306 // Initialize the maps
rconnorlawson 0:35660d7952f7 307 maps_init();
rconnorlawson 0:35660d7952f7 308 init_main_map();
nasiromar 6:c9695079521d 309
rconnorlawson 0:35660d7952f7 310 // Initialize game state
rconnorlawson 0:35660d7952f7 311 set_active_map(0);
rconnorlawson 0:35660d7952f7 312 Player.x = Player.y = 5;
rconnorlawson 0:35660d7952f7 313
rconnorlawson 0:35660d7952f7 314 // Initial drawing
rconnorlawson 0:35660d7952f7 315 draw_game(true);
rconnorlawson 0:35660d7952f7 316 // Main game loop
nasiromar 6:c9695079521d 317 while(1) {
rconnorlawson 0:35660d7952f7 318 // Timer to measure game update speed
nasiromar 6:c9695079521d 319 Timer t;
nasiromar 6:c9695079521d 320 t.start();
nasiromar 6:c9695079521d 321
lballard9 5:2f34484325bc 322 // Actually do the game update:
nasiromar 6:c9695079521d 323 // 1. Read inputs
nasiromar 6:c9695079521d 324 GameInputs input = read_inputs();
nasiromar 6:c9695079521d 325 // 2. Determine action (get_action)
nasiromar 6:c9695079521d 326 int action = get_action(input);
rconnorlawson 0:35660d7952f7 327 // 3. Update game (update_game)
nasiromar 6:c9695079521d 328 update_game(action);
rconnorlawson 0:35660d7952f7 329 // 3b. Check for game over
nasiromar 8:fcc333a8f9e1 330 if(Player.won == 1){
nasiromar 8:fcc333a8f9e1 331 draw_gameover();
nasiromar 8:fcc333a8f9e1 332 break;
nasiromar 8:fcc333a8f9e1 333 }
rconnorlawson 0:35660d7952f7 334 // 4. Draw frame (draw_game)
lballard9 5:2f34484325bc 335 draw_game(true);
nasiromar 6:c9695079521d 336
rconnorlawson 0:35660d7952f7 337 // 5. Frame delay
rconnorlawson 0:35660d7952f7 338 t.stop();
rconnorlawson 0:35660d7952f7 339 int dt = t.read_ms();
rconnorlawson 0:35660d7952f7 340 if (dt < 100) wait_ms(100 - dt);
rconnorlawson 0:35660d7952f7 341 }
nasiromar 6:c9695079521d 342 //
nasiromar 7:862062ffca62 343
nasiromar 6:c9695079521d 344
rconnorlawson 0:35660d7952f7 345 }