Jay Balar / Mbed 2 deprecated 4180_Project_3

Dependencies:   4DGL-uLCD-SE Physac-MBED PinDetect SDFileSystem mbed-rtos mbed

Committer:
jsanchez307
Date:
Wed Dec 07 23:12:12 2022 +0000
Revision:
23:214c0c828d98
Parent:
20:73e4f12277bd
Child:
26:163d7ca8c42d
Tetris and Hockey updated for Nav_Switch myNav

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jstephens78 9:4e6fae5f9b23 1 #include "hockey.h"
jstephens78 12:5d913b57da7c 2 #include "globals.h"
jstephens78 9:4e6fae5f9b23 3
jstephens78 20:73e4f12277bd 4 // Custom memory allocation methods
jstephens78 9:4e6fae5f9b23 5 #define PHYSAC_NO_THREADS
jstephens78 9:4e6fae5f9b23 6 #define PHYSAC_STANDALONE
jstephens78 9:4e6fae5f9b23 7 #define PHYSAC_IMPLEMENTATION
jstephens78 9:4e6fae5f9b23 8 #define _STDBOOL_H
jstephens78 9:4e6fae5f9b23 9 #include "physac.h"
jstephens78 9:4e6fae5f9b23 10
jstephens78 12:5d913b57da7c 11 // Controls size of gamepieces in the hockey arena. This influences both
jstephens78 12:5d913b57da7c 12 // rendering and collision, so be careful adjusting dimensions too small
jstephens78 12:5d913b57da7c 13 #define HOCKEY_PUCK_RADIUS 4
jstephens78 12:5d913b57da7c 14 #define HOCKEY_PADDLE_W 8
jstephens78 12:5d913b57da7c 15 #define HOCKEY_PADDLE_H 24
jstephens78 9:4e6fae5f9b23 16
jstephens78 20:73e4f12277bd 17 // Physics sim properties
jstephens78 17:3517251daf96 18 // HOCKEY_PHYSICS_STEPS number of physics ticks between frames
jstephens78 17:3517251daf96 19 // HOCKEY_PHYSICS_DELTA how many ms the physics engine believes pass per
jstephens78 17:3517251daf96 20 // update. This is arbitrary. Pick what behaves well.
jstephens78 17:3517251daf96 21 // HOCKEY_PUCK_VELOCITY how fact the puck moves in one physics tick
jstephens78 17:3517251daf96 22 #define HOCKEY_PHYSICS_STEPS 4
jstephens78 17:3517251daf96 23 #define HOCKEY_PHYSICS_DELTA 1.66
jstephens78 17:3517251daf96 24 #define HOCKEY_PUCK_VELOCITY (5.0f / HOCKEY_PHYSICS_STEPS)
jstephens78 17:3517251daf96 25
jstephens78 20:73e4f12277bd 26 // Screen-space constants:
jstephens78 20:73e4f12277bd 27 #define SCREEN_WIDTH 128
jstephens78 20:73e4f12277bd 28 #define SCREEN_HEIGHT 128
jstephens78 20:73e4f12277bd 29
jstephens78 12:5d913b57da7c 30 // Controls the dimensions of the arena. You can adjust the screen margin above
jstephens78 12:5d913b57da7c 31 // and below the court, and the width of the goal.
jstephens78 12:5d913b57da7c 32 #define HOCKEY_ARENA_TOP 16
jstephens78 12:5d913b57da7c 33 #define HOCKEY_ARENA_BOT 127
jstephens78 12:5d913b57da7c 34 #define HOCKEY_GOAL_HEIGHT 32
jstephens78 12:5d913b57da7c 35
jstephens78 12:5d913b57da7c 36 // Properties derived from other macros
jstephens78 12:5d913b57da7c 37 #define _HOCKEY_ARENA_H (HOCKEY_ARENA_BOT - HOCKEY_ARENA_TOP)
jstephens78 17:3517251daf96 38 #define _HOCKEY_ARENA_MID ((HOCKEY_ARENA_BOT + HOCKEY_ARENA_TOP)/2)
jstephens78 12:5d913b57da7c 39 #define _HOCKEY_GOAL_TOP ((_HOCKEY_ARENA_H - HOCKEY_GOAL_HEIGHT)/2 + HOCKEY_ARENA_TOP)
jstephens78 12:5d913b57da7c 40 #define _HOCKEY_GOAL_BOT (_HOCKEY_GOAL_TOP + HOCKEY_GOAL_HEIGHT)
jstephens78 9:4e6fae5f9b23 41
jstephens78 17:3517251daf96 42
jstephens78 12:5d913b57da7c 43 PhysicsBody puck;
jstephens78 12:5d913b57da7c 44 PhysicsBody paddle_a;
jstephens78 12:5d913b57da7c 45 PhysicsBody paddle_b;
jstephens78 12:5d913b57da7c 46
jstephens78 17:3517251daf96 47 int blue_score;
jstephens78 17:3517251daf96 48 int red_score;
jstephens78 17:3517251daf96 49 bool serve_direction; // 0 means toward blue, 1 means red
jstephens78 17:3517251daf96 50 float input_sensitivity = 4.00f;
jstephens78 9:4e6fae5f9b23 51
jstephens78 17:3517251daf96 52 // Helper functions
jstephens78 17:3517251daf96 53 // @{
jstephens78 12:5d913b57da7c 54 int maxOf(int a, int b)
jstephens78 12:5d913b57da7c 55 {
jstephens78 12:5d913b57da7c 56 return (a > b) ? a : b;
jstephens78 12:5d913b57da7c 57 }
jstephens78 12:5d913b57da7c 58 int minOf(int a, int b)
jstephens78 12:5d913b57da7c 59 {
jstephens78 12:5d913b57da7c 60 return (a < b) ? a : b;
jstephens78 12:5d913b57da7c 61 }
jstephens78 17:3517251daf96 62 int clamp(int a, int low, int upp)
jstephens78 17:3517251daf96 63 {
jstephens78 17:3517251daf96 64 return minOf(upp, maxOf(a, low));
jstephens78 17:3517251daf96 65 }
jstephens78 17:3517251daf96 66 // @}
jstephens78 12:5d913b57da7c 67
jstephens78 17:3517251daf96 68 /**
jstephens78 17:3517251daf96 69 * Sets up physics elements within the Physac library
jstephens78 17:3517251daf96 70 */
jstephens78 12:5d913b57da7c 71 void initPhysicsObjects()
jstephens78 12:5d913b57da7c 72 {
jstephens78 17:3517251daf96 73 SetPhysicsTimeStep(HOCKEY_PHYSICS_DELTA);
jstephens78 17:3517251daf96 74
jstephens78 12:5d913b57da7c 75 puck = CreatePhysicsBodyCircle((Vector2) {
jstephens78 12:5d913b57da7c 76 SCREEN_WIDTH/2, SCREEN_HEIGHT/2
jstephens78 12:5d913b57da7c 77 }, HOCKEY_PUCK_RADIUS, 1);
jstephens78 9:4e6fae5f9b23 78 puck->enabled = true;
jstephens78 9:4e6fae5f9b23 79 puck->useGravity = false;
jstephens78 9:4e6fae5f9b23 80 puck->restitution = 1.0;
jstephens78 17:3517251daf96 81 puck->dynamicFriction = 0;
jstephens78 9:4e6fae5f9b23 82 puck->velocity = (Vector2) {
jstephens78 17:3517251daf96 83 HOCKEY_PUCK_VELOCITY, 0
jstephens78 9:4e6fae5f9b23 84 };
jstephens78 9:4e6fae5f9b23 85
jstephens78 12:5d913b57da7c 86 paddle_a = CreatePhysicsBodyRectangle((Vector2) {
jstephens78 17:3517251daf96 87 32, _HOCKEY_ARENA_MID
jstephens78 12:5d913b57da7c 88 }, HOCKEY_PADDLE_W, HOCKEY_PADDLE_H, 100);
jstephens78 9:4e6fae5f9b23 89 paddle_a->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions)
jstephens78 9:4e6fae5f9b23 90 paddle_a->useGravity = false;
jstephens78 9:4e6fae5f9b23 91 paddle_a->restitution = 1.0;
jstephens78 9:4e6fae5f9b23 92 SetPhysicsBodyRotation(paddle_a, 3.14159 / 6);
jstephens78 9:4e6fae5f9b23 93
jstephens78 12:5d913b57da7c 94 paddle_b = CreatePhysicsBodyRectangle((Vector2) {
jstephens78 17:3517251daf96 95 96, _HOCKEY_ARENA_MID
jstephens78 12:5d913b57da7c 96 }, HOCKEY_PADDLE_W, HOCKEY_PADDLE_H, 100);
jstephens78 9:4e6fae5f9b23 97 paddle_b->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions)
jstephens78 9:4e6fae5f9b23 98 paddle_b->useGravity = false;
jstephens78 9:4e6fae5f9b23 99 paddle_b->restitution = 1.0;
jstephens78 9:4e6fae5f9b23 100 SetPhysicsBodyRotation(paddle_b, 3.14159 / 6);
jstephens78 12:5d913b57da7c 101 }
jstephens78 9:4e6fae5f9b23 102
jstephens78 12:5d913b57da7c 103 /**
jstephens78 12:5d913b57da7c 104 * Draws the fixed graphics of the game. This is the border of the arena
jstephens78 17:3517251daf96 105 *
jstephens78 17:3517251daf96 106 * note: locks `uLCD_mutex`
jstephens78 12:5d913b57da7c 107 */
jstephens78 12:5d913b57da7c 108 void drawStaticEnvironment()
jstephens78 12:5d913b57da7c 109 {
jstephens78 17:3517251daf96 110 uLCD_mutex.lock();
jstephens78 17:3517251daf96 111
jstephens78 17:3517251daf96 112 // Clear screen
jstephens78 17:3517251daf96 113 uLCD.cls();
jstephens78 17:3517251daf96 114
jstephens78 17:3517251daf96 115 // Draw arena border
jstephens78 12:5d913b57da7c 116 uLCD.line(0, _HOCKEY_GOAL_TOP, 0, HOCKEY_ARENA_TOP, BLUE);
jstephens78 12:5d913b57da7c 117 uLCD.line(0, _HOCKEY_GOAL_BOT, 0, HOCKEY_ARENA_BOT, BLUE);
jstephens78 12:5d913b57da7c 118 uLCD.line(0, HOCKEY_ARENA_TOP, 63, HOCKEY_ARENA_TOP, BLUE);
jstephens78 12:5d913b57da7c 119 uLCD.line(0, HOCKEY_ARENA_BOT, 63, HOCKEY_ARENA_BOT, BLUE);
jstephens78 12:5d913b57da7c 120 uLCD.line(127, _HOCKEY_GOAL_TOP, 127, HOCKEY_ARENA_TOP, RED);
jstephens78 12:5d913b57da7c 121 uLCD.line(127, _HOCKEY_GOAL_BOT, 127, HOCKEY_ARENA_BOT, RED);
jstephens78 12:5d913b57da7c 122 uLCD.line(64, HOCKEY_ARENA_TOP, 127, HOCKEY_ARENA_TOP, RED);
jstephens78 12:5d913b57da7c 123 uLCD.line(64, HOCKEY_ARENA_BOT, 127, HOCKEY_ARENA_BOT, RED);
jstephens78 17:3517251daf96 124
jstephens78 17:3517251daf96 125 // Draw score
jstephens78 17:3517251daf96 126 uLCD.color(BLUE);
jstephens78 17:3517251daf96 127 uLCD.locate(0, 0);
jstephens78 17:3517251daf96 128 uLCD.printf("%i", blue_score);
jstephens78 17:3517251daf96 129 uLCD.color(RED);
jstephens78 17:3517251daf96 130 uLCD.locate(17, 0);
jstephens78 17:3517251daf96 131 uLCD.printf("%i", red_score);
jstephens78 17:3517251daf96 132
jstephens78 17:3517251daf96 133 // Draw serve indicator
jstephens78 17:3517251daf96 134 uLCD.filled_circle(
jstephens78 17:3517251daf96 135 serve_direction ? SCREEN_WIDTH - 16 : 16,
jstephens78 17:3517251daf96 136 HOCKEY_ARENA_TOP / 2,
jstephens78 17:3517251daf96 137 HOCKEY_ARENA_TOP / 6,
jstephens78 17:3517251daf96 138 serve_direction ? RED : BLUE);
jstephens78 17:3517251daf96 139
jstephens78 17:3517251daf96 140 uLCD_mutex.unlock();
jstephens78 12:5d913b57da7c 141 }
jstephens78 12:5d913b57da7c 142
jstephens78 12:5d913b57da7c 143 /**
jstephens78 12:5d913b57da7c 144 * Redraws the puck and paddles
jstephens78 12:5d913b57da7c 145 * Each elements is erased, updated, and redrawn in as short of a window as
jstephens78 12:5d913b57da7c 146 * possible.
jstephens78 17:3517251daf96 147 *
jstephens78 17:3517251daf96 148 * note: locks `uLCD_mutex`
jstephens78 12:5d913b57da7c 149 */
jstephens78 12:5d913b57da7c 150 void drawDynamicObjects()
jstephens78 12:5d913b57da7c 151 {
jstephens78 12:5d913b57da7c 152 static int puck_x = SCREEN_WIDTH / 2,
jstephens78 17:3517251daf96 153 puck_y = _HOCKEY_ARENA_MID;
jstephens78 12:5d913b57da7c 154
jstephens78 17:3517251daf96 155 uLCD_mutex.lock();
jstephens78 9:4e6fae5f9b23 156
jstephens78 17:3517251daf96 157 // Redraw puck
jstephens78 17:3517251daf96 158 uLCD.filled_circle(puck_x, puck_y, HOCKEY_PUCK_RADIUS, BLACK);
jstephens78 17:3517251daf96 159 puck_x = puck->position.x;
jstephens78 17:3517251daf96 160 puck_y = puck->position.y;
jstephens78 17:3517251daf96 161 uLCD.filled_circle(puck_x, puck_y, HOCKEY_PUCK_RADIUS, GREEN);
jstephens78 12:5d913b57da7c 162
jstephens78 12:5d913b57da7c 163 // Redraw blue paddle
jstephens78 12:5d913b57da7c 164 static int pa_x1 = 64,
jstephens78 12:5d913b57da7c 165 pa_x2 = 64,
jstephens78 12:5d913b57da7c 166 pa_y1 = 64,
jstephens78 12:5d913b57da7c 167 pa_y2 = 64;
jstephens78 12:5d913b57da7c 168 float sinA = sin(-paddle_a->orient) / 2;
jstephens78 12:5d913b57da7c 169 float cosA = cos(-paddle_a->orient) / 2;
jstephens78 12:5d913b57da7c 170 uLCD.line(pa_x1, pa_y1, pa_x2, pa_y2, BLACK);
jstephens78 12:5d913b57da7c 171 pa_x1 = paddle_a->position.x + HOCKEY_PADDLE_H * sinA;
jstephens78 12:5d913b57da7c 172 pa_x2 = paddle_a->position.x - HOCKEY_PADDLE_H * sinA;
jstephens78 12:5d913b57da7c 173 pa_y1 = paddle_a->position.y + HOCKEY_PADDLE_H * cosA;
jstephens78 12:5d913b57da7c 174 pa_y2 = paddle_a->position.y - HOCKEY_PADDLE_H * cosA;
jstephens78 12:5d913b57da7c 175 uLCD.line(pa_x1, pa_y1, pa_x2, pa_y2, BLUE);
jstephens78 12:5d913b57da7c 176
jstephens78 12:5d913b57da7c 177 // Redraw red paddle
jstephens78 12:5d913b57da7c 178 static int pb_x1 = 64,
jstephens78 12:5d913b57da7c 179 pb_x2 = 64,
jstephens78 12:5d913b57da7c 180 pb_y1 = 64,
jstephens78 12:5d913b57da7c 181 pb_y2 = 64;
jstephens78 12:5d913b57da7c 182 float sinB = sin(-paddle_b->orient) / 2;
jstephens78 12:5d913b57da7c 183 float cosB = cos(-paddle_b->orient) / 2;
jstephens78 12:5d913b57da7c 184 uLCD.line(pb_x1, pb_y1, pb_x2, pb_y2, BLACK);
jstephens78 12:5d913b57da7c 185 pb_x1 = paddle_b->position.x + HOCKEY_PADDLE_H * sinB;
jstephens78 12:5d913b57da7c 186 pb_x2 = paddle_b->position.x - HOCKEY_PADDLE_H * sinB;
jstephens78 12:5d913b57da7c 187 pb_y1 = paddle_b->position.y + HOCKEY_PADDLE_H * cosB;
jstephens78 12:5d913b57da7c 188 pb_y2 = paddle_b->position.y - HOCKEY_PADDLE_H * cosB;
jstephens78 12:5d913b57da7c 189 uLCD.line(pb_x1, pb_y1, pb_x2, pb_y2, RED);
jstephens78 17:3517251daf96 190
jstephens78 17:3517251daf96 191 uLCD_mutex.unlock();
jstephens78 12:5d913b57da7c 192 }
jstephens78 9:4e6fae5f9b23 193
jstephens78 17:3517251daf96 194 /**
jstephens78 17:3517251daf96 195 * Reset the game after a goal.
jstephens78 17:3517251daf96 196 * If the game will continue, re-draw and reset the pieces.
jstephens78 17:3517251daf96 197 * If the game is over, display end scene and then suspend the game loop until
jstephens78 17:3517251daf96 198 * re-launched.
jstephens78 17:3517251daf96 199 */
jstephens78 12:5d913b57da7c 200 void resetGame()
jstephens78 12:5d913b57da7c 201 {
jstephens78 17:3517251daf96 202 // If game over, draw an end-game screen
jstephens78 12:5d913b57da7c 203 if (red_score >= 5 || blue_score >= 5) {
jstephens78 17:3517251daf96 204 uLCD_mutex.lock();
jstephens78 12:5d913b57da7c 205 uLCD.cls();
jstephens78 17:3517251daf96 206 uLCD.locate(5, 3);
jstephens78 17:3517251daf96 207 uLCD.color(GREEN);
jstephens78 12:5d913b57da7c 208 uLCD.printf("Game Over");
jstephens78 12:5d913b57da7c 209
jstephens78 12:5d913b57da7c 210 if (red_score > blue_score) {
jstephens78 17:3517251daf96 211 uLCD.locate(5, 5);
jstephens78 17:3517251daf96 212 uLCD.color(RED);
jstephens78 17:3517251daf96 213 uLCD.printf("Red Wins!");
jstephens78 12:5d913b57da7c 214 } else {
jstephens78 17:3517251daf96 215 uLCD.locate(5, 5);
jstephens78 17:3517251daf96 216 uLCD.color(BLUE);
jstephens78 17:3517251daf96 217 uLCD.printf("Blue Wins!");
jstephens78 9:4e6fae5f9b23 218 }
jstephens78 9:4e6fae5f9b23 219
jstephens78 12:5d913b57da7c 220 Thread::wait(2000);
jstephens78 12:5d913b57da7c 221
jstephens78 12:5d913b57da7c 222 game2 = false;
jstephens78 17:3517251daf96 223 uLCD_mutex.unlock();
jstephens78 17:3517251daf96 224 }
jstephens78 17:3517251daf96 225
jstephens78 17:3517251daf96 226 // Otherwise re-draw the game board and reset the pieces
jstephens78 17:3517251daf96 227 else {
jstephens78 12:5d913b57da7c 228 drawStaticEnvironment();
jstephens78 9:4e6fae5f9b23 229
jstephens78 12:5d913b57da7c 230 puck->position.x = SCREEN_WIDTH/2;
jstephens78 17:3517251daf96 231 puck->position.y = _HOCKEY_ARENA_MID;
jstephens78 17:3517251daf96 232 puck->velocity.x = HOCKEY_PUCK_VELOCITY * (serve_direction ? 1 : -1);
jstephens78 17:3517251daf96 233 puck->velocity.y = (float)(rand() % 50) / 100;
jstephens78 17:3517251daf96 234
jstephens78 12:5d913b57da7c 235 paddle_a->position.x = 32;
jstephens78 17:3517251daf96 236 paddle_a->position.y = _HOCKEY_ARENA_MID;
jstephens78 12:5d913b57da7c 237 SetPhysicsBodyRotation(paddle_a, 0);
jstephens78 12:5d913b57da7c 238
jstephens78 12:5d913b57da7c 239 paddle_b->position.x = 96;
jstephens78 17:3517251daf96 240 paddle_b->position.y = _HOCKEY_ARENA_MID;
jstephens78 12:5d913b57da7c 241 SetPhysicsBodyRotation(paddle_b, 0);
jstephens78 12:5d913b57da7c 242 }
jstephens78 12:5d913b57da7c 243 }
jstephens78 12:5d913b57da7c 244
jstephens78 12:5d913b57da7c 245 /**
jstephens78 17:3517251daf96 246 * Handles puck bouncing off walls, goal scoring, player input, and end-game
jstephens78 17:3517251daf96 247 * conditions
jstephens78 12:5d913b57da7c 248 */
jstephens78 12:5d913b57da7c 249 void runGameLogic()
jstephens78 12:5d913b57da7c 250 {
jstephens78 12:5d913b57da7c 251 // If puck hits the ceiling or floor, reflect across the y component of
jstephens78 12:5d913b57da7c 252 // the velocity
jstephens78 12:5d913b57da7c 253 if (puck->position.y < HOCKEY_ARENA_TOP + HOCKEY_PUCK_RADIUS + 1) {
jstephens78 12:5d913b57da7c 254 puck->velocity.y *= -1;
jstephens78 12:5d913b57da7c 255 puck->position.y = maxOf(
jstephens78 12:5d913b57da7c 256 puck->position.y,
jstephens78 12:5d913b57da7c 257 HOCKEY_ARENA_TOP + HOCKEY_PUCK_RADIUS + 1);
jstephens78 12:5d913b57da7c 258 } else if (puck->position.y > HOCKEY_ARENA_BOT - HOCKEY_PUCK_RADIUS - 1) {
jstephens78 12:5d913b57da7c 259 puck->velocity.y *= -1;
jstephens78 12:5d913b57da7c 260 puck->position.y = minOf(
jstephens78 12:5d913b57da7c 261 puck->position.y,
jstephens78 12:5d913b57da7c 262 HOCKEY_ARENA_BOT - HOCKEY_PUCK_RADIUS - 1);
jstephens78 12:5d913b57da7c 263 }
jstephens78 12:5d913b57da7c 264
jstephens78 12:5d913b57da7c 265 // true if the puck is in the y range corresponding to the goal
jstephens78 12:5d913b57da7c 266 bool puckInGoalRange =
jstephens78 12:5d913b57da7c 267 puck->position.y > _HOCKEY_GOAL_TOP &&
jstephens78 12:5d913b57da7c 268 puck->position.y < _HOCKEY_GOAL_BOT;
jstephens78 12:5d913b57da7c 269
jstephens78 12:5d913b57da7c 270 // Puck collides with left or right walls
jstephens78 12:5d913b57da7c 271 if (puckInGoalRange == false) {
jstephens78 17:3517251daf96 272 if (puck->position.x < HOCKEY_PUCK_RADIUS + 1 && puck->position.x > 0) {
jstephens78 12:5d913b57da7c 273 puck->velocity.x *= -1;
jstephens78 12:5d913b57da7c 274 puck->position.x = maxOf(
jstephens78 12:5d913b57da7c 275 puck->position.x,
jstephens78 12:5d913b57da7c 276 HOCKEY_PUCK_RADIUS + 1);
jstephens78 17:3517251daf96 277 } else if (puck->position.x > SCREEN_WIDTH - HOCKEY_PUCK_RADIUS - 1 && puck->position.x < SCREEN_WIDTH) {
jstephens78 12:5d913b57da7c 278 puck->velocity.x *= -1;
jstephens78 12:5d913b57da7c 279 puck->position.x = minOf(
jstephens78 12:5d913b57da7c 280 puck->position.x,
jstephens78 12:5d913b57da7c 281 SCREEN_WIDTH - HOCKEY_PUCK_RADIUS - 2);
jstephens78 9:4e6fae5f9b23 282 }
jstephens78 12:5d913b57da7c 283 }
jstephens78 12:5d913b57da7c 284
jstephens78 12:5d913b57da7c 285 // Puck in goals
jstephens78 12:5d913b57da7c 286 else {
jstephens78 12:5d913b57da7c 287 // SCORE RED
jstephens78 17:3517251daf96 288 if (puck->position.x <= -HOCKEY_PUCK_RADIUS * 2) {
jstephens78 12:5d913b57da7c 289 red_score += 1;
jstephens78 17:3517251daf96 290 serve_direction = 0;
jstephens78 17:3517251daf96 291 uLCD.locate(4, 1);
jstephens78 17:3517251daf96 292 uLCD.color(RED);
jstephens78 17:3517251daf96 293 uLCD.printf("Red Scores!");
jstephens78 12:5d913b57da7c 294 Thread::wait(2000);
jstephens78 12:5d913b57da7c 295 resetGame();
jstephens78 12:5d913b57da7c 296 }
jstephens78 12:5d913b57da7c 297
jstephens78 12:5d913b57da7c 298 // SCORE BLUE
jstephens78 17:3517251daf96 299 else if (puck->position.x >= SCREEN_WIDTH + HOCKEY_PUCK_RADIUS * 2) {
jstephens78 12:5d913b57da7c 300 blue_score += 1;
jstephens78 17:3517251daf96 301 serve_direction = 1;
jstephens78 17:3517251daf96 302 uLCD.locate(3, 1);
jstephens78 17:3517251daf96 303 uLCD.color(BLUE);
jstephens78 17:3517251daf96 304 uLCD.printf("Blue Scores!");
jstephens78 12:5d913b57da7c 305 Thread::wait(2000);
jstephens78 12:5d913b57da7c 306 resetGame();
jstephens78 12:5d913b57da7c 307 }
jstephens78 12:5d913b57da7c 308 }
jstephens78 12:5d913b57da7c 309 }
jstephens78 12:5d913b57da7c 310
jstephens78 17:3517251daf96 311 /**
jstephens78 17:3517251daf96 312 * Process user input and update game state
jstephens78 17:3517251daf96 313 */
jstephens78 17:3517251daf96 314 void handleInput()
jstephens78 17:3517251daf96 315 {
jstephens78 17:3517251daf96 316 // Process input from the game
jstephens78 17:3517251daf96 317 blue.parseMessage();
jstephens78 17:3517251daf96 318 if (blue.button[BUTTON_UP]) {
jstephens78 17:3517251daf96 319 paddle_a->position.y -= input_sensitivity;
jstephens78 17:3517251daf96 320 }
jstephens78 17:3517251daf96 321 if (blue.button[BUTTON_DOWN]) {
jstephens78 17:3517251daf96 322 paddle_a->position.y += input_sensitivity;
jstephens78 17:3517251daf96 323 }
jstephens78 17:3517251daf96 324 if (blue.button[BUTTON_LEFT]) {
jstephens78 17:3517251daf96 325 paddle_a->position.x -= input_sensitivity;
jstephens78 17:3517251daf96 326 }
jstephens78 17:3517251daf96 327 if (blue.button[BUTTON_RIGHT]) {
jstephens78 17:3517251daf96 328 paddle_a->position.x += input_sensitivity;
jstephens78 17:3517251daf96 329 }
jstephens78 17:3517251daf96 330 if (blue.button[BUTTON_A]) {
jstephens78 17:3517251daf96 331 SetPhysicsBodyRotation(paddle_a, paddle_a->orient - input_sensitivity * 0.05);
jstephens78 17:3517251daf96 332 }
jstephens78 17:3517251daf96 333 if (blue.button[BUTTON_B]) {
jstephens78 17:3517251daf96 334 SetPhysicsBodyRotation(paddle_a, paddle_a->orient + input_sensitivity * 0.05);
jstephens78 17:3517251daf96 335 }
jstephens78 17:3517251daf96 336
jsanchez307 23:214c0c828d98 337
jsanchez307 23:214c0c828d98 338
jsanchez307 23:214c0c828d98 339
jstephens78 17:3517251daf96 340 // Player 2 Input
jsanchez307 23:214c0c828d98 341 if (myNav.up()) { // Up
jstephens78 17:3517251daf96 342 paddle_b->position.y -= input_sensitivity;
jstephens78 17:3517251daf96 343 }
jsanchez307 23:214c0c828d98 344 if (myNav.down()) { // down
jstephens78 17:3517251daf96 345 paddle_b->position.y += input_sensitivity;
jstephens78 17:3517251daf96 346 }
jsanchez307 23:214c0c828d98 347 if (myNav.left()) { // left
jstephens78 17:3517251daf96 348 paddle_b->position.x -= input_sensitivity;
jstephens78 17:3517251daf96 349 }
jsanchez307 23:214c0c828d98 350 if (myNav.right()) { // right
jstephens78 17:3517251daf96 351 paddle_b->position.x += input_sensitivity;
jstephens78 17:3517251daf96 352 }
jsanchez307 23:214c0c828d98 353 if (myNav.fire()) { // rotate
jstephens78 17:3517251daf96 354 SetPhysicsBodyRotation(paddle_b, paddle_b->orient + 3.14159 / 4);
jstephens78 17:3517251daf96 355 }
jstephens78 17:3517251daf96 356
jstephens78 17:3517251daf96 357 // Bounds checking. Don't let users steer paddles out of the arena
jstephens78 17:3517251daf96 358 paddle_a->position.y = clamp(paddle_a->position.y, HOCKEY_ARENA_TOP, HOCKEY_ARENA_BOT);
jstephens78 17:3517251daf96 359 paddle_a->position.x = clamp(paddle_a->position.x, 1, SCREEN_WIDTH - 1);
jstephens78 17:3517251daf96 360
jstephens78 17:3517251daf96 361 paddle_b->position.y = clamp(paddle_b->position.y, HOCKEY_ARENA_TOP, HOCKEY_ARENA_BOT);
jstephens78 17:3517251daf96 362 paddle_b->position.x = clamp(paddle_b->position.x, 1, SCREEN_WIDTH - 1);
jstephens78 17:3517251daf96 363 }
jstephens78 17:3517251daf96 364
jstephens78 17:3517251daf96 365 /**
jstephens78 17:3517251daf96 366 * The primary game loop for the air hockey game
jstephens78 17:3517251daf96 367 */
jstephens78 12:5d913b57da7c 368 void hockeyGame(void)
jstephens78 12:5d913b57da7c 369 {
jstephens78 17:3517251daf96 370 // Set up Physac objects & simulation
jstephens78 17:3517251daf96 371 initPhysicsObjects();
jstephens78 17:3517251daf96 372
jstephens78 20:73e4f12277bd 373 while (true) {
jstephens78 17:3517251daf96 374 // Wait until the game starts
jstephens78 12:5d913b57da7c 375 while (game2 == false) {
jstephens78 20:73e4f12277bd 376
jstephens78 20:73e4f12277bd 377 PRINTF("[HOCKEY] Idle\r\n");
jstephens78 20:73e4f12277bd 378 Thread::wait(500);
jstephens78 9:4e6fae5f9b23 379 }
jstephens78 20:73e4f12277bd 380
jstephens78 17:3517251daf96 381 // Reset game state
jstephens78 12:5d913b57da7c 382 red_score = 0;
jstephens78 12:5d913b57da7c 383 blue_score = 0;
jstephens78 17:3517251daf96 384 serve_direction = rand() % 2;
jstephens78 17:3517251daf96 385 resetGame();
jstephens78 9:4e6fae5f9b23 386
jstephens78 12:5d913b57da7c 387 // Reset screen, draw arena
jstephens78 12:5d913b57da7c 388 drawStaticEnvironment();
jstephens78 12:5d913b57da7c 389
jstephens78 12:5d913b57da7c 390 Timer timer;
jstephens78 12:5d913b57da7c 391 timer.start();
jstephens78 12:5d913b57da7c 392
jstephens78 12:5d913b57da7c 393 while (game2) {
jstephens78 12:5d913b57da7c 394 float dt = timer.read() * 1000;
jstephens78 12:5d913b57da7c 395 timer.reset();
jstephens78 9:4e6fae5f9b23 396
jstephens78 12:5d913b57da7c 397 // Update the physics of the game
jstephens78 17:3517251daf96 398 for (int i = 0; i < HOCKEY_PHYSICS_STEPS; i++) {
jstephens78 12:5d913b57da7c 399 PhysicsStep();
jstephens78 17:3517251daf96 400 runGameLogic();
jstephens78 17:3517251daf96 401 if (game2 == false) break;
jstephens78 17:3517251daf96 402 }
jstephens78 12:5d913b57da7c 403
jstephens78 17:3517251daf96 404 // Exit loop early if game over after the logic step
jstephens78 17:3517251daf96 405 if (game2 == false) continue;
jstephens78 17:3517251daf96 406
jstephens78 17:3517251daf96 407 handleInput();
jstephens78 9:4e6fae5f9b23 408
jstephens78 12:5d913b57da7c 409 // Render the game
jstephens78 12:5d913b57da7c 410 drawDynamicObjects();
jstephens78 17:3517251daf96 411
jstephens78 20:73e4f12277bd 412 PRINTF("[HOCKEY] Delta %f\r\n", dt);
jstephens78 20:73e4f12277bd 413 Thread::wait(100);
jstephens78 12:5d913b57da7c 414 }
jstephens78 17:3517251daf96 415 }
jstephens78 12:5d913b57da7c 416
jstephens78 17:3517251daf96 417 ClosePhysics();
jstephens78 9:4e6fae5f9b23 418 }