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