Jay Balar / Mbed 2 deprecated 4180_Project_3

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

Committer:
jsanchez307
Date:
Thu Dec 08 02:12:14 2022 +0000
Revision:
26:163d7ca8c42d
Parent:
23:214c0c828d98
Child:
28:bccd14334bb9
No speaker. LED works for Tetris by going through RGB one at a time. LCD successfully clears the screen after Tetris is in Game Over and goes to the Menu.

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
jsanchez307 26:163d7ca8c42d 222 uLCD.cls();
jsanchez307 26:163d7ca8c42d 223 menu_flag = 0;
jsanchez307 26:163d7ca8c42d 224
jstephens78 12:5d913b57da7c 225 game2 = false;
jstephens78 17:3517251daf96 226 uLCD_mutex.unlock();
jstephens78 17:3517251daf96 227 }
jstephens78 17:3517251daf96 228
jstephens78 17:3517251daf96 229 // Otherwise re-draw the game board and reset the pieces
jstephens78 17:3517251daf96 230 else {
jstephens78 12:5d913b57da7c 231 drawStaticEnvironment();
jstephens78 9:4e6fae5f9b23 232
jstephens78 12:5d913b57da7c 233 puck->position.x = SCREEN_WIDTH/2;
jstephens78 17:3517251daf96 234 puck->position.y = _HOCKEY_ARENA_MID;
jstephens78 17:3517251daf96 235 puck->velocity.x = HOCKEY_PUCK_VELOCITY * (serve_direction ? 1 : -1);
jstephens78 17:3517251daf96 236 puck->velocity.y = (float)(rand() % 50) / 100;
jstephens78 17:3517251daf96 237
jstephens78 12:5d913b57da7c 238 paddle_a->position.x = 32;
jstephens78 17:3517251daf96 239 paddle_a->position.y = _HOCKEY_ARENA_MID;
jstephens78 12:5d913b57da7c 240 SetPhysicsBodyRotation(paddle_a, 0);
jstephens78 12:5d913b57da7c 241
jstephens78 12:5d913b57da7c 242 paddle_b->position.x = 96;
jstephens78 17:3517251daf96 243 paddle_b->position.y = _HOCKEY_ARENA_MID;
jstephens78 12:5d913b57da7c 244 SetPhysicsBodyRotation(paddle_b, 0);
jstephens78 12:5d913b57da7c 245 }
jstephens78 12:5d913b57da7c 246 }
jstephens78 12:5d913b57da7c 247
jstephens78 12:5d913b57da7c 248 /**
jstephens78 17:3517251daf96 249 * Handles puck bouncing off walls, goal scoring, player input, and end-game
jstephens78 17:3517251daf96 250 * conditions
jstephens78 12:5d913b57da7c 251 */
jstephens78 12:5d913b57da7c 252 void runGameLogic()
jstephens78 12:5d913b57da7c 253 {
jstephens78 12:5d913b57da7c 254 // If puck hits the ceiling or floor, reflect across the y component of
jstephens78 12:5d913b57da7c 255 // the velocity
jstephens78 12:5d913b57da7c 256 if (puck->position.y < HOCKEY_ARENA_TOP + HOCKEY_PUCK_RADIUS + 1) {
jstephens78 12:5d913b57da7c 257 puck->velocity.y *= -1;
jstephens78 12:5d913b57da7c 258 puck->position.y = maxOf(
jstephens78 12:5d913b57da7c 259 puck->position.y,
jstephens78 12:5d913b57da7c 260 HOCKEY_ARENA_TOP + HOCKEY_PUCK_RADIUS + 1);
jstephens78 12:5d913b57da7c 261 } else if (puck->position.y > HOCKEY_ARENA_BOT - HOCKEY_PUCK_RADIUS - 1) {
jstephens78 12:5d913b57da7c 262 puck->velocity.y *= -1;
jstephens78 12:5d913b57da7c 263 puck->position.y = minOf(
jstephens78 12:5d913b57da7c 264 puck->position.y,
jstephens78 12:5d913b57da7c 265 HOCKEY_ARENA_BOT - HOCKEY_PUCK_RADIUS - 1);
jstephens78 12:5d913b57da7c 266 }
jstephens78 12:5d913b57da7c 267
jstephens78 12:5d913b57da7c 268 // true if the puck is in the y range corresponding to the goal
jstephens78 12:5d913b57da7c 269 bool puckInGoalRange =
jstephens78 12:5d913b57da7c 270 puck->position.y > _HOCKEY_GOAL_TOP &&
jstephens78 12:5d913b57da7c 271 puck->position.y < _HOCKEY_GOAL_BOT;
jstephens78 12:5d913b57da7c 272
jstephens78 12:5d913b57da7c 273 // Puck collides with left or right walls
jstephens78 12:5d913b57da7c 274 if (puckInGoalRange == false) {
jstephens78 17:3517251daf96 275 if (puck->position.x < HOCKEY_PUCK_RADIUS + 1 && puck->position.x > 0) {
jstephens78 12:5d913b57da7c 276 puck->velocity.x *= -1;
jstephens78 12:5d913b57da7c 277 puck->position.x = maxOf(
jstephens78 12:5d913b57da7c 278 puck->position.x,
jstephens78 12:5d913b57da7c 279 HOCKEY_PUCK_RADIUS + 1);
jstephens78 17:3517251daf96 280 } else if (puck->position.x > SCREEN_WIDTH - HOCKEY_PUCK_RADIUS - 1 && puck->position.x < SCREEN_WIDTH) {
jstephens78 12:5d913b57da7c 281 puck->velocity.x *= -1;
jstephens78 12:5d913b57da7c 282 puck->position.x = minOf(
jstephens78 12:5d913b57da7c 283 puck->position.x,
jstephens78 12:5d913b57da7c 284 SCREEN_WIDTH - HOCKEY_PUCK_RADIUS - 2);
jstephens78 9:4e6fae5f9b23 285 }
jstephens78 12:5d913b57da7c 286 }
jstephens78 12:5d913b57da7c 287
jstephens78 12:5d913b57da7c 288 // Puck in goals
jstephens78 12:5d913b57da7c 289 else {
jstephens78 12:5d913b57da7c 290 // SCORE RED
jstephens78 17:3517251daf96 291 if (puck->position.x <= -HOCKEY_PUCK_RADIUS * 2) {
jstephens78 12:5d913b57da7c 292 red_score += 1;
jstephens78 17:3517251daf96 293 serve_direction = 0;
jstephens78 17:3517251daf96 294 uLCD.locate(4, 1);
jstephens78 17:3517251daf96 295 uLCD.color(RED);
jstephens78 17:3517251daf96 296 uLCD.printf("Red Scores!");
jstephens78 12:5d913b57da7c 297 Thread::wait(2000);
jstephens78 12:5d913b57da7c 298 resetGame();
jstephens78 12:5d913b57da7c 299 }
jstephens78 12:5d913b57da7c 300
jstephens78 12:5d913b57da7c 301 // SCORE BLUE
jstephens78 17:3517251daf96 302 else if (puck->position.x >= SCREEN_WIDTH + HOCKEY_PUCK_RADIUS * 2) {
jstephens78 12:5d913b57da7c 303 blue_score += 1;
jstephens78 17:3517251daf96 304 serve_direction = 1;
jstephens78 17:3517251daf96 305 uLCD.locate(3, 1);
jstephens78 17:3517251daf96 306 uLCD.color(BLUE);
jstephens78 17:3517251daf96 307 uLCD.printf("Blue Scores!");
jstephens78 12:5d913b57da7c 308 Thread::wait(2000);
jstephens78 12:5d913b57da7c 309 resetGame();
jstephens78 12:5d913b57da7c 310 }
jstephens78 12:5d913b57da7c 311 }
jstephens78 12:5d913b57da7c 312 }
jstephens78 12:5d913b57da7c 313
jstephens78 17:3517251daf96 314 /**
jstephens78 17:3517251daf96 315 * Process user input and update game state
jstephens78 17:3517251daf96 316 */
jstephens78 17:3517251daf96 317 void handleInput()
jstephens78 17:3517251daf96 318 {
jstephens78 17:3517251daf96 319 // Process input from the game
jstephens78 17:3517251daf96 320 blue.parseMessage();
jstephens78 17:3517251daf96 321 if (blue.button[BUTTON_UP]) {
jstephens78 17:3517251daf96 322 paddle_a->position.y -= input_sensitivity;
jstephens78 17:3517251daf96 323 }
jstephens78 17:3517251daf96 324 if (blue.button[BUTTON_DOWN]) {
jstephens78 17:3517251daf96 325 paddle_a->position.y += input_sensitivity;
jstephens78 17:3517251daf96 326 }
jstephens78 17:3517251daf96 327 if (blue.button[BUTTON_LEFT]) {
jstephens78 17:3517251daf96 328 paddle_a->position.x -= input_sensitivity;
jstephens78 17:3517251daf96 329 }
jstephens78 17:3517251daf96 330 if (blue.button[BUTTON_RIGHT]) {
jstephens78 17:3517251daf96 331 paddle_a->position.x += input_sensitivity;
jstephens78 17:3517251daf96 332 }
jstephens78 17:3517251daf96 333 if (blue.button[BUTTON_A]) {
jstephens78 17:3517251daf96 334 SetPhysicsBodyRotation(paddle_a, paddle_a->orient - input_sensitivity * 0.05);
jstephens78 17:3517251daf96 335 }
jstephens78 17:3517251daf96 336 if (blue.button[BUTTON_B]) {
jstephens78 17:3517251daf96 337 SetPhysicsBodyRotation(paddle_a, paddle_a->orient + input_sensitivity * 0.05);
jstephens78 17:3517251daf96 338 }
jstephens78 17:3517251daf96 339
jsanchez307 23:214c0c828d98 340
jsanchez307 23:214c0c828d98 341
jsanchez307 23:214c0c828d98 342
jstephens78 17:3517251daf96 343 // Player 2 Input
jsanchez307 23:214c0c828d98 344 if (myNav.up()) { // Up
jstephens78 17:3517251daf96 345 paddle_b->position.y -= input_sensitivity;
jstephens78 17:3517251daf96 346 }
jsanchez307 23:214c0c828d98 347 if (myNav.down()) { // down
jstephens78 17:3517251daf96 348 paddle_b->position.y += input_sensitivity;
jstephens78 17:3517251daf96 349 }
jsanchez307 23:214c0c828d98 350 if (myNav.left()) { // left
jstephens78 17:3517251daf96 351 paddle_b->position.x -= input_sensitivity;
jstephens78 17:3517251daf96 352 }
jsanchez307 23:214c0c828d98 353 if (myNav.right()) { // right
jstephens78 17:3517251daf96 354 paddle_b->position.x += input_sensitivity;
jstephens78 17:3517251daf96 355 }
jsanchez307 23:214c0c828d98 356 if (myNav.fire()) { // rotate
jstephens78 17:3517251daf96 357 SetPhysicsBodyRotation(paddle_b, paddle_b->orient + 3.14159 / 4);
jstephens78 17:3517251daf96 358 }
jstephens78 17:3517251daf96 359
jstephens78 17:3517251daf96 360 // Bounds checking. Don't let users steer paddles out of the arena
jstephens78 17:3517251daf96 361 paddle_a->position.y = clamp(paddle_a->position.y, HOCKEY_ARENA_TOP, HOCKEY_ARENA_BOT);
jstephens78 17:3517251daf96 362 paddle_a->position.x = clamp(paddle_a->position.x, 1, SCREEN_WIDTH - 1);
jstephens78 17:3517251daf96 363
jstephens78 17:3517251daf96 364 paddle_b->position.y = clamp(paddle_b->position.y, HOCKEY_ARENA_TOP, HOCKEY_ARENA_BOT);
jstephens78 17:3517251daf96 365 paddle_b->position.x = clamp(paddle_b->position.x, 1, SCREEN_WIDTH - 1);
jstephens78 17:3517251daf96 366 }
jstephens78 17:3517251daf96 367
jstephens78 17:3517251daf96 368 /**
jstephens78 17:3517251daf96 369 * The primary game loop for the air hockey game
jstephens78 17:3517251daf96 370 */
jstephens78 12:5d913b57da7c 371 void hockeyGame(void)
jstephens78 12:5d913b57da7c 372 {
jstephens78 17:3517251daf96 373 // Set up Physac objects & simulation
jstephens78 17:3517251daf96 374 initPhysicsObjects();
jstephens78 17:3517251daf96 375
jstephens78 20:73e4f12277bd 376 while (true) {
jstephens78 17:3517251daf96 377 // Wait until the game starts
jstephens78 12:5d913b57da7c 378 while (game2 == false) {
jstephens78 20:73e4f12277bd 379
jstephens78 20:73e4f12277bd 380 PRINTF("[HOCKEY] Idle\r\n");
jstephens78 20:73e4f12277bd 381 Thread::wait(500);
jstephens78 9:4e6fae5f9b23 382 }
jstephens78 20:73e4f12277bd 383
jstephens78 17:3517251daf96 384 // Reset game state
jstephens78 12:5d913b57da7c 385 red_score = 0;
jstephens78 12:5d913b57da7c 386 blue_score = 0;
jstephens78 17:3517251daf96 387 serve_direction = rand() % 2;
jstephens78 17:3517251daf96 388 resetGame();
jstephens78 9:4e6fae5f9b23 389
jstephens78 12:5d913b57da7c 390 // Reset screen, draw arena
jstephens78 12:5d913b57da7c 391 drawStaticEnvironment();
jstephens78 12:5d913b57da7c 392
jstephens78 12:5d913b57da7c 393 Timer timer;
jstephens78 12:5d913b57da7c 394 timer.start();
jstephens78 12:5d913b57da7c 395
jstephens78 12:5d913b57da7c 396 while (game2) {
jstephens78 12:5d913b57da7c 397 float dt = timer.read() * 1000;
jstephens78 12:5d913b57da7c 398 timer.reset();
jstephens78 9:4e6fae5f9b23 399
jstephens78 12:5d913b57da7c 400 // Update the physics of the game
jstephens78 17:3517251daf96 401 for (int i = 0; i < HOCKEY_PHYSICS_STEPS; i++) {
jstephens78 12:5d913b57da7c 402 PhysicsStep();
jstephens78 17:3517251daf96 403 runGameLogic();
jstephens78 17:3517251daf96 404 if (game2 == false) break;
jstephens78 17:3517251daf96 405 }
jstephens78 12:5d913b57da7c 406
jstephens78 17:3517251daf96 407 // Exit loop early if game over after the logic step
jstephens78 17:3517251daf96 408 if (game2 == false) continue;
jstephens78 17:3517251daf96 409
jstephens78 17:3517251daf96 410 handleInput();
jstephens78 9:4e6fae5f9b23 411
jstephens78 12:5d913b57da7c 412 // Render the game
jstephens78 12:5d913b57da7c 413 drawDynamicObjects();
jstephens78 17:3517251daf96 414
jstephens78 20:73e4f12277bd 415 PRINTF("[HOCKEY] Delta %f\r\n", dt);
jstephens78 20:73e4f12277bd 416 Thread::wait(100);
jstephens78 12:5d913b57da7c 417 }
jstephens78 17:3517251daf96 418 }
jstephens78 12:5d913b57da7c 419
jstephens78 17:3517251daf96 420 ClosePhysics();
jstephens78 9:4e6fae5f9b23 421 }