![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
tao lao
Dependencies: mbed wave_player 4DGL-uLCD-SE MMA8452
main.cpp@2:4947d6a82971, 2020-10-23 (annotated)
- Committer:
- DCchico
- Date:
- Fri Oct 23 16:30:18 2020 -0400
- Revision:
- 2:4947d6a82971
- Parent:
- 1:10330bce85cb
- Child:
- 3:33bf11645fe1
shell
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
DCchico | 2:4947d6a82971 | 1 | //================================================================= |
DCchico | 2:4947d6a82971 | 2 | // The main program file. |
DCchico | 2:4947d6a82971 | 3 | // |
DCchico | 2:4947d6a82971 | 4 | // Copyright 2020 Georgia Tech. All rights reserved. |
DCchico | 2:4947d6a82971 | 5 | // The materials provided by the instructor in this course are for |
DCchico | 2:4947d6a82971 | 6 | // the use of the students currently enrolled in the course. |
DCchico | 2:4947d6a82971 | 7 | // Copyrighted course materials may not be further disseminated. |
DCchico | 2:4947d6a82971 | 8 | // This file must not be made publicly available anywhere. |
DCchico | 2:4947d6a82971 | 9 | //================================================================== |
DCchico | 2:4947d6a82971 | 10 | |
DCchico | 2:4947d6a82971 | 11 | // Project includes |
DCchico | 1:10330bce85cb | 12 | #include "globals.h" |
DCchico | 1:10330bce85cb | 13 | #include "hardware.h" |
DCchico | 1:10330bce85cb | 14 | #include "map.h" |
DCchico | 1:10330bce85cb | 15 | #include "graphics.h" |
DCchico | 1:10330bce85cb | 16 | #include "snake.h" |
DCchico | 1:10330bce85cb | 17 | |
DCchico | 1:10330bce85cb | 18 | #include <math.h> |
DCchico | 1:10330bce85cb | 19 | #include<stdio.h> |
DCchico | 1:10330bce85cb | 20 | |
DCchico | 1:10330bce85cb | 21 | #define CITY_HIT_MARGIN 1 |
DCchico | 1:10330bce85cb | 22 | #define CITY_UPPER_BOUND (SIZE_Y-(LANDSCAPE_HEIGHT+MAX_BUILDING_HEIGHT)) |
DCchico | 2:4947d6a82971 | 23 | |
DCchico | 1:10330bce85cb | 24 | // Helper function declarations |
DCchico | 1:10330bce85cb | 25 | void playSound(char* wav); |
DCchico | 1:10330bce85cb | 26 | |
DCchico | 1:10330bce85cb | 27 | /** |
DCchico | 1:10330bce85cb | 28 | * The main game state. Must include snake locations and previous locations for |
DCchico | 1:10330bce85cb | 29 | * drawing to work properly. Other items can be added as needed. |
DCchico | 1:10330bce85cb | 30 | */ |
DCchico | 1:10330bce85cb | 31 | |
DCchico | 1:10330bce85cb | 32 | /** |
DCchico | 1:10330bce85cb | 33 | * Given the game inputs, determine what kind of update needs to happen. |
DCchico | 1:10330bce85cb | 34 | * Possbile return values are defined below. |
DCchico | 1:10330bce85cb | 35 | */ |
DCchico | 1:10330bce85cb | 36 | Snake snake; |
DCchico | 1:10330bce85cb | 37 | |
DCchico | 1:10330bce85cb | 38 | // Function prototypes |
DCchico | 2:4947d6a82971 | 39 | |
DCchico | 2:4947d6a82971 | 40 | /** |
DCchico | 2:4947d6a82971 | 41 | * Given the game inputs, determine what kind of update needs to happen. |
DCchico | 2:4947d6a82971 | 42 | * Possible return values are defined below. |
DCchico | 2:4947d6a82971 | 43 | */ |
DCchico | 2:4947d6a82971 | 44 | #define NO_RESULT 0 |
DCchico | 2:4947d6a82971 | 45 | #define NO_ACTION 0 |
DCchico | 2:4947d6a82971 | 46 | #define ACTION_BUTTON 1 |
DCchico | 2:4947d6a82971 | 47 | #define MENU_BUTTON 2 |
DCchico | 2:4947d6a82971 | 48 | #define GO_LEFT 3 |
DCchico | 2:4947d6a82971 | 49 | #define GO_RIGHT 4 |
DCchico | 2:4947d6a82971 | 50 | #define GO_UP 5 |
DCchico | 2:4947d6a82971 | 51 | #define GO_DOWN 6 |
DCchico | 2:4947d6a82971 | 52 | #define GAME_OVER 7 |
DCchico | 2:4947d6a82971 | 53 | #define FULL_DRAW 8 |
DCchico | 1:10330bce85cb | 54 | // Get Actions from User (push buttons & accelerometer) |
DCchico | 2:4947d6a82971 | 55 | // Based on push button and accelerometer inputs, determine which action |
DCchico | 2:4947d6a82971 | 56 | // needs to be performed (may be no action). |
DCchico | 1:10330bce85cb | 57 | int get_action(GameInputs inputs) |
DCchico | 1:10330bce85cb | 58 | { |
DCchico | 1:10330bce85cb | 59 | return 0; |
DCchico | 1:10330bce85cb | 60 | } |
DCchico | 1:10330bce85cb | 61 | /** |
DCchico | 1:10330bce85cb | 62 | * Update the game state based on the user action. For example, if the user |
DCchico | 1:10330bce85cb | 63 | * requests GO_UP, then this function should determine if that is possible by |
DCchico | 1:10330bce85cb | 64 | * consulting the map, and update the snake position accordingly. |
DCchico | 1:10330bce85cb | 65 | * |
DCchico | 1:10330bce85cb | 66 | * Return values are defined below. FULL_DRAW indicates that for this frame, |
DCchico | 1:10330bce85cb | 67 | * draw_game should not optimize drawing and should draw every tile, even if |
DCchico | 1:10330bce85cb | 68 | * the snake has not moved. |
DCchico | 1:10330bce85cb | 69 | */ |
DCchico | 1:10330bce85cb | 70 | int update_game(int action) |
DCchico | 1:10330bce85cb | 71 | { |
DCchico | 1:10330bce85cb | 72 | return 0; |
DCchico | 1:10330bce85cb | 73 | } |
DCchico | 1:10330bce85cb | 74 | |
DCchico | 1:10330bce85cb | 75 | /** |
DCchico | 1:10330bce85cb | 76 | * Draw the upper status bar. |
DCchico | 1:10330bce85cb | 77 | */ |
DCchico | 1:10330bce85cb | 78 | void draw_upper_status() |
DCchico | 1:10330bce85cb | 79 | { |
DCchico | 1:10330bce85cb | 80 | uLCD.line(0, 9, 127, 9, GREEN); |
DCchico | 1:10330bce85cb | 81 | } |
DCchico | 1:10330bce85cb | 82 | |
DCchico | 1:10330bce85cb | 83 | /** |
DCchico | 1:10330bce85cb | 84 | * Draw the lower status bar. |
DCchico | 1:10330bce85cb | 85 | */ |
DCchico | 1:10330bce85cb | 86 | void draw_lower_status() |
DCchico | 1:10330bce85cb | 87 | { |
DCchico | 1:10330bce85cb | 88 | uLCD.line(0, 118, 127, 118, GREEN); |
DCchico | 1:10330bce85cb | 89 | } |
DCchico | 1:10330bce85cb | 90 | |
DCchico | 1:10330bce85cb | 91 | /** |
DCchico | 1:10330bce85cb | 92 | * Draw the border for the map. |
DCchico | 1:10330bce85cb | 93 | */ |
DCchico | 1:10330bce85cb | 94 | void draw_border() |
DCchico | 1:10330bce85cb | 95 | { |
DCchico | 1:10330bce85cb | 96 | uLCD.filled_rectangle(0, 9, 127, 14, WHITE); // Top |
DCchico | 1:10330bce85cb | 97 | uLCD.filled_rectangle(0, 13, 2, 114, WHITE); // Left |
DCchico | 1:10330bce85cb | 98 | uLCD.filled_rectangle(0, 114, 127, 117, WHITE); // Bottom |
DCchico | 1:10330bce85cb | 99 | uLCD.filled_rectangle(124, 14, 127, 117, WHITE); // Right |
DCchico | 1:10330bce85cb | 100 | } |
DCchico | 1:10330bce85cb | 101 | |
DCchico | 1:10330bce85cb | 102 | /** |
DCchico | 1:10330bce85cb | 103 | * Entry point for frame drawing. This should be called once per iteration of |
DCchico | 1:10330bce85cb | 104 | * the game loop. This draws all tiles on the screen, followed by the status |
DCchico | 1:10330bce85cb | 105 | * bars. Unless init is nonzero, this function will optimize drawing by only |
DCchico | 1:10330bce85cb | 106 | * drawing tiles that have changed from the previous frame. |
DCchico | 1:10330bce85cb | 107 | */ |
DCchico | 1:10330bce85cb | 108 | void draw_game(int draw_option) |
DCchico | 1:10330bce85cb | 109 | { |
DCchico | 1:10330bce85cb | 110 | // Draw game border first |
DCchico | 1:10330bce85cb | 111 | if(draw_option == FULL_DRAW) |
DCchico | 1:10330bce85cb | 112 | { |
DCchico | 1:10330bce85cb | 113 | draw_border(); |
DCchico | 1:10330bce85cb | 114 | int u = 58; |
DCchico | 1:10330bce85cb | 115 | int v = 56; |
DCchico | 1:10330bce85cb | 116 | draw_snake_head(u, v); |
DCchico | 1:10330bce85cb | 117 | draw_snake_body(u-11, v); |
DCchico | 1:10330bce85cb | 118 | draw_snake_tail(u-22, v); |
DCchico | 1:10330bce85cb | 119 | return; |
DCchico | 1:10330bce85cb | 120 | } |
DCchico | 1:10330bce85cb | 121 | // Iterate over all visible map tiles |
DCchico | 1:10330bce85cb | 122 | for (int i = -5; i <= 5; i++) { // Iterate over columns of tiles |
DCchico | 1:10330bce85cb | 123 | for (int j = -4; j <= 4; j++) { // Iterate over one column of tiles |
DCchico | 1:10330bce85cb | 124 | // Here, we have a given (i,j) |
DCchico | 1:10330bce85cb | 125 | |
DCchico | 1:10330bce85cb | 126 | // Compute the current map (x,y) of this tile |
DCchico | 1:10330bce85cb | 127 | int x = i + snake.head_x; |
DCchico | 1:10330bce85cb | 128 | int y = j + snake.head_y; |
DCchico | 1:10330bce85cb | 129 | |
DCchico | 1:10330bce85cb | 130 | // Compute the previous map (px, py) of this tile |
DCchico | 1:10330bce85cb | 131 | int px = i + snake.head_px; |
DCchico | 1:10330bce85cb | 132 | int py = j + snake.head_py; |
DCchico | 1:10330bce85cb | 133 | |
DCchico | 1:10330bce85cb | 134 | // Compute u,v coordinates for drawing |
DCchico | 1:10330bce85cb | 135 | int u = (i+5)*11 + 3; |
DCchico | 1:10330bce85cb | 136 | int v = (j+4)*11 + 15; |
DCchico | 1:10330bce85cb | 137 | |
DCchico | 1:10330bce85cb | 138 | // Figure out what to draw |
DCchico | 1:10330bce85cb | 139 | DrawFunc draw = NULL; |
DCchico | 1:10330bce85cb | 140 | if (x >= 0 && y >= 0 && x < map_width() && y < map_height()) { // Current (i,j) in the map |
DCchico | 1:10330bce85cb | 141 | MapItem* curr_item = get_here(x, y); |
DCchico | 1:10330bce85cb | 142 | MapItem* prev_item = get_here(px, py); |
DCchico | 1:10330bce85cb | 143 | if (draw_option || curr_item != prev_item) { // Only draw if they're different |
DCchico | 1:10330bce85cb | 144 | if (curr_item) { // There's something here! Draw it |
DCchico | 1:10330bce85cb | 145 | draw = curr_item->draw; |
DCchico | 1:10330bce85cb | 146 | } else { // There used to be something, but now there isn't |
DCchico | 1:10330bce85cb | 147 | draw = draw_nothing; |
DCchico | 1:10330bce85cb | 148 | } |
DCchico | 1:10330bce85cb | 149 | } else if (curr_item && curr_item->type == CLEAR) { |
DCchico | 1:10330bce85cb | 150 | // This is a special case for erasing things like doors. |
DCchico | 1:10330bce85cb | 151 | draw = curr_item->draw; // i.e. draw_nothing |
DCchico | 1:10330bce85cb | 152 | } |
DCchico | 1:10330bce85cb | 153 | } else if (draw_option) { // If doing a full draw, but we're out of bounds, draw the walls. |
DCchico | 1:10330bce85cb | 154 | draw = draw_wall; |
DCchico | 1:10330bce85cb | 155 | } |
DCchico | 1:10330bce85cb | 156 | |
DCchico | 1:10330bce85cb | 157 | // Actually draw the tile |
DCchico | 1:10330bce85cb | 158 | if (draw) draw(u, v); |
DCchico | 1:10330bce85cb | 159 | } |
DCchico | 1:10330bce85cb | 160 | } |
DCchico | 1:10330bce85cb | 161 | |
DCchico | 1:10330bce85cb | 162 | // Draw status bars |
DCchico | 1:10330bce85cb | 163 | draw_upper_status(); |
DCchico | 1:10330bce85cb | 164 | draw_lower_status(); |
DCchico | 1:10330bce85cb | 165 | } |
DCchico | 1:10330bce85cb | 166 | |
DCchico | 1:10330bce85cb | 167 | /** |
DCchico | 1:10330bce85cb | 168 | * Initialize the main world map. Add walls around the edges, interior chambers, |
DCchico | 1:10330bce85cb | 169 | * and plants in the background so you can see motion. |
DCchico | 1:10330bce85cb | 170 | */ |
DCchico | 1:10330bce85cb | 171 | void init_main_map() |
DCchico | 1:10330bce85cb | 172 | { |
DCchico | 1:10330bce85cb | 173 | // "Random" plants |
DCchico | 1:10330bce85cb | 174 | Map* map = set_active_map(0); |
DCchico | 1:10330bce85cb | 175 | for(int i = map_width() + 3; i < map_area(); i += 39) { |
DCchico | 1:10330bce85cb | 176 | add_goodie(i % map_width(), i / map_width()); |
DCchico | 1:10330bce85cb | 177 | } |
DCchico | 1:10330bce85cb | 178 | pc.printf("plants\r\n"); |
DCchico | 1:10330bce85cb | 179 | |
DCchico | 1:10330bce85cb | 180 | pc.printf("Adding walls!\r\n"); |
DCchico | 1:10330bce85cb | 181 | add_wall(0, 0, HORIZONTAL, map_width()); |
DCchico | 1:10330bce85cb | 182 | add_wall(0, map_height()-1, HORIZONTAL, map_width()); |
DCchico | 1:10330bce85cb | 183 | add_wall(0, 0, VERTICAL, map_height()); |
DCchico | 1:10330bce85cb | 184 | add_wall(map_width()-1, 0, VERTICAL, map_height()); |
DCchico | 1:10330bce85cb | 185 | pc.printf("Walls done!\r\n"); |
DCchico | 1:10330bce85cb | 186 | |
DCchico | 1:10330bce85cb | 187 | add_snake_head(snake.locations[0].x, snake.locations[0].y); |
DCchico | 1:10330bce85cb | 188 | add_snake_body(snake.locations[1].x, snake.locations[1].y); |
DCchico | 1:10330bce85cb | 189 | add_snake_tail(snake.locations[2].x, snake.locations[2].y); |
DCchico | 1:10330bce85cb | 190 | |
DCchico | 1:10330bce85cb | 191 | pc.printf("Add extra chamber\r\n"); |
DCchico | 1:10330bce85cb | 192 | add_wall(30, 0, VERTICAL, 10); |
DCchico | 1:10330bce85cb | 193 | add_wall(30, 10, HORIZONTAL, 10); |
DCchico | 1:10330bce85cb | 194 | add_wall(39, 0, VERTICAL, 10); |
DCchico | 1:10330bce85cb | 195 | pc.printf("Added!\r\n"); |
DCchico | 1:10330bce85cb | 196 | |
DCchico | 1:10330bce85cb | 197 | |
DCchico | 1:10330bce85cb | 198 | // Add stairs to chamber (map 1) |
DCchico | 1:10330bce85cb | 199 | //add_stairs(15, 5, 1, 5, 5); |
DCchico | 1:10330bce85cb | 200 | |
DCchico | 1:10330bce85cb | 201 | // profile_hashtable(); |
DCchico | 1:10330bce85cb | 202 | print_map(); |
DCchico | 1:10330bce85cb | 203 | } |
DCchico | 1:10330bce85cb | 204 | |
DCchico | 1:10330bce85cb | 205 | /** |
DCchico | 1:10330bce85cb | 206 | * Program entry point! This is where it all begins. |
DCchico | 1:10330bce85cb | 207 | * This function or all the parts of the game. Most of your |
DCchico | 1:10330bce85cb | 208 | * implementation should be elsewhere - this holds the game loop, and should |
DCchico | 1:10330bce85cb | 209 | * read like a road map for the rest of the code. |
DCchico | 1:10330bce85cb | 210 | */ |
DCchico | 1:10330bce85cb | 211 | int main() |
DCchico | 1:10330bce85cb | 212 | { |
DCchico | 1:10330bce85cb | 213 | // First things first: initialize hardware |
DCchico | 1:10330bce85cb | 214 | ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!"); |
DCchico | 1:10330bce85cb | 215 | |
DCchico | 1:10330bce85cb | 216 | snake_init(&snake); |
DCchico | 2:4947d6a82971 | 217 | // 0. Initialize the maps -- implement this function: |
DCchico | 1:10330bce85cb | 218 | maps_init(); |
DCchico | 1:10330bce85cb | 219 | init_main_map(); |
DCchico | 1:10330bce85cb | 220 | |
DCchico | 1:10330bce85cb | 221 | // Initialize game state |
DCchico | 1:10330bce85cb | 222 | set_active_map(0); |
DCchico | 1:10330bce85cb | 223 | snake.head_x = snake.head_y = 5; |
DCchico | 1:10330bce85cb | 224 | // Initial drawing |
DCchico | 1:10330bce85cb | 225 | draw_game(FULL_DRAW); |
DCchico | 1:10330bce85cb | 226 | // Main game loop |
DCchico | 1:10330bce85cb | 227 | while(1) { |
DCchico | 1:10330bce85cb | 228 | // Timer to measure game update speed |
DCchico | 1:10330bce85cb | 229 | Timer t; |
DCchico | 1:10330bce85cb | 230 | t.start(); |
DCchico | 1:10330bce85cb | 231 | |
DCchico | 2:4947d6a82971 | 232 | // 1. Read inputs -- implement this function: |
DCchico | 2:4947d6a82971 | 233 | GameInputs inputs = read_inputs(); |
DCchico | 2:4947d6a82971 | 234 | |
DCchico | 2:4947d6a82971 | 235 | // 2. Determine action (move, act, menu, etc.) -- implement this function: |
DCchico | 2:4947d6a82971 | 236 | int action = get_action(inputs); |
DCchico | 2:4947d6a82971 | 237 | |
DCchico | 2:4947d6a82971 | 238 | // 3. Update game -- implement this function: |
DCchico | 2:4947d6a82971 | 239 | int result = update_game(action); |
DCchico | 2:4947d6a82971 | 240 | |
DCchico | 2:4947d6a82971 | 241 | // 3b. Check for game over based on result |
DCchico | 2:4947d6a82971 | 242 | // and if so, handle game over -- implement this. |
DCchico | 2:4947d6a82971 | 243 | |
DCchico | 2:4947d6a82971 | 244 | // 4. Draw screen -- provided: |
DCchico | 2:4947d6a82971 | 245 | draw_game(result); |
DCchico | 2:4947d6a82971 | 246 | |
DCchico | 1:10330bce85cb | 247 | // Compute update time |
DCchico | 1:10330bce85cb | 248 | t.stop(); |
DCchico | 1:10330bce85cb | 249 | int dt = t.read_ms(); |
DCchico | 1:10330bce85cb | 250 | |
DCchico | 1:10330bce85cb | 251 | // Display and wait |
DCchico | 1:10330bce85cb | 252 | // NOTE: Text is 8 pixels tall |
DCchico | 1:10330bce85cb | 253 | if (dt < 100) wait_ms(100 - dt); |
DCchico | 1:10330bce85cb | 254 | } |
DCchico | 1:10330bce85cb | 255 | } |
DCchico | 1:10330bce85cb | 256 | |
DCchico | 1:10330bce85cb | 257 | // Plays a wavfile |
DCchico | 1:10330bce85cb | 258 | void playSound(char* wav) |
DCchico | 1:10330bce85cb | 259 | { |
DCchico | 1:10330bce85cb | 260 | |
DCchico | 1:10330bce85cb | 261 | } |