Mini Pool game for two players
Dependencies: PokittoLib
This is a small, fully documented Mini Pool game for 2 players intended as a programming tutorial
main.cpp@0:1850dcae680f, 2018-10-12 (annotated)
- Committer:
- Pokitto
- Date:
- Fri Oct 12 17:09:04 2018 +0000
- Revision:
- 0:1850dcae680f
initial
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Pokitto | 0:1850dcae680f | 1 | #include "Pokitto.h" // Include the Pokitto library |
Pokitto | 0:1850dcae680f | 2 | #include "GameObject.h" // Include the simple physics library |
Pokitto | 0:1850dcae680f | 3 | |
Pokitto | 0:1850dcae680f | 4 | Pokitto::Core mygame; // Create a Pokitto app/game object |
Pokitto | 0:1850dcae680f | 5 | |
Pokitto | 0:1850dcae680f | 6 | #define MAX_BALL_OBJECTS 7 // max amount of balls |
Pokitto | 0:1850dcae680f | 7 | |
Pokitto | 0:1850dcae680f | 8 | GameObject balls[MAX_BALL_OBJECTS]; // Array of balls |
Pokitto | 0:1850dcae680f | 9 | GameObject player; // player-object (for aiming) |
Pokitto | 0:1850dcae680f | 10 | GameObject bumpers[4]; // Four sides of table |
Pokitto | 0:1850dcae680f | 11 | GameObject pockets[4]; // Four pockets |
Pokitto | 0:1850dcae680f | 12 | |
Pokitto | 0:1850dcae680f | 13 | enum GameStates { Start, Aim, Hit, Win }; // Game states |
Pokitto | 0:1850dcae680f | 14 | |
Pokitto | 0:1850dcae680f | 15 | /** global variables (accessible from everywhere in the code **/ |
Pokitto | 0:1850dcae680f | 16 | GameStates gamestate = Start; |
Pokitto | 0:1850dcae680f | 17 | int ballsinplay = 7; // how many balls in the game |
Pokitto | 0:1850dcae680f | 18 | int player1points = 0; |
Pokitto | 0:1850dcae680f | 19 | int player2points = 0; |
Pokitto | 0:1850dcae680f | 20 | int gameturn = 1; // which players turn |
Pokitto | 0:1850dcae680f | 21 | bool player_pocketed = false; //continue turn if player pocketed their own color ball on their turn |
Pokitto | 0:1850dcae680f | 22 | |
Pokitto | 0:1850dcae680f | 23 | // starting arrangement of the balls |
Pokitto | 0:1850dcae680f | 24 | void initballs(){ |
Pokitto | 0:1850dcae680f | 25 | balls[0].x = -30; balls[0].y = 0; balls[0].active = true; balls[0].visible = true; balls[0].setColor(1); |
Pokitto | 0:1850dcae680f | 26 | balls[1].x = 10; balls[1].y = 0; balls[1].active = true; balls[1].visible = true; balls[1].setColor(7); |
Pokitto | 0:1850dcae680f | 27 | balls[2].x = 10; balls[2].y = 10; balls[2].active = true; balls[2].visible = true; balls[2].setColor(4); |
Pokitto | 0:1850dcae680f | 28 | balls[3].x = 10; balls[3].y = -10; balls[3].active = true; balls[3].visible = true; balls[3].setColor(4); |
Pokitto | 0:1850dcae680f | 29 | balls[4].x = 20; balls[4].y = -10; balls[4].active = true; balls[4].visible = true; balls[4].setColor(7); |
Pokitto | 0:1850dcae680f | 30 | balls[5].x = 20; balls[5].y = 0; balls[5].active = true; balls[5].visible = true; balls[5].setColor(4); |
Pokitto | 0:1850dcae680f | 31 | balls[6].x = 20; balls[6].y = 10; balls[6].active = true; balls[6].visible = true; balls[6].setColor(7); |
Pokitto | 0:1850dcae680f | 32 | } |
Pokitto | 0:1850dcae680f | 33 | |
Pokitto | 0:1850dcae680f | 34 | /** MAIN is where a typical C++ program begins executing the program **/ |
Pokitto | 0:1850dcae680f | 35 | |
Pokitto | 0:1850dcae680f | 36 | int main () { |
Pokitto | 0:1850dcae680f | 37 | mygame.begin(); // start Pokitto engine (display, buttons, sound) |
Pokitto | 0:1850dcae680f | 38 | mygame.display.setFont(fontTiny); // Tiny font active |
Pokitto | 0:1850dcae680f | 39 | mygame.display.bgcolor = 13; // Background color to dark green (13) |
Pokitto | 0:1850dcae680f | 40 | mygame.display.invisiblecolor = 13; // Make text background (13) invisible |
Pokitto | 0:1850dcae680f | 41 | |
Pokitto | 0:1850dcae680f | 42 | /** PROGRAM LOOP... runs the entire life of the program |
Pokitto | 0:1850dcae680f | 43 | ie. as long as mygame.isRunning() returns logical true (=1) **/ |
Pokitto | 0:1850dcae680f | 44 | |
Pokitto | 0:1850dcae680f | 45 | while (mygame.isRunning()) { |
Pokitto | 0:1850dcae680f | 46 | |
Pokitto | 0:1850dcae680f | 47 | // Draw table bumpers |
Pokitto | 0:1850dcae680f | 48 | for (int i=0; i<4; i++) bumpers[i].draw(); |
Pokitto | 0:1850dcae680f | 49 | // Draw table pockets |
Pokitto | 0:1850dcae680f | 50 | for (int i=0; i<4; i++) pockets[i].draw(); |
Pokitto | 0:1850dcae680f | 51 | // Calculate balls vs. bumpers collisions |
Pokitto | 0:1850dcae680f | 52 | for (int i=0; i<ballsinplay; i++) { |
Pokitto | 0:1850dcae680f | 53 | for (int j=0; j<4; j++) { |
Pokitto | 0:1850dcae680f | 54 | if (balls[i].checkCollision(bumpers[j]) && gamestate != Start) { |
Pokitto | 0:1850dcae680f | 55 | balls[i].doCollision(bumpers[j]); |
Pokitto | 0:1850dcae680f | 56 | } |
Pokitto | 0:1850dcae680f | 57 | } |
Pokitto | 0:1850dcae680f | 58 | } |
Pokitto | 0:1850dcae680f | 59 | |
Pokitto | 0:1850dcae680f | 60 | // Calculate balls vs. balls collisions |
Pokitto | 0:1850dcae680f | 61 | for (int i=0; i<ballsinplay; i++) { |
Pokitto | 0:1850dcae680f | 62 | for (int j=0; j<ballsinplay; j++) { |
Pokitto | 0:1850dcae680f | 63 | if (i != j) { // do not check collision with self!! |
Pokitto | 0:1850dcae680f | 64 | if (balls[i].checkCollision(balls[j]) && gamestate != Start) { |
Pokitto | 0:1850dcae680f | 65 | balls[i].doCollision(balls[j]); |
Pokitto | 0:1850dcae680f | 66 | } |
Pokitto | 0:1850dcae680f | 67 | } |
Pokitto | 0:1850dcae680f | 68 | } |
Pokitto | 0:1850dcae680f | 69 | } |
Pokitto | 0:1850dcae680f | 70 | |
Pokitto | 0:1850dcae680f | 71 | // Calculate balls colliding with pockets |
Pokitto | 0:1850dcae680f | 72 | for (int i=0; i<ballsinplay; i++) { |
Pokitto | 0:1850dcae680f | 73 | for (int j=0; j<4; j++) { |
Pokitto | 0:1850dcae680f | 74 | if (balls[i].checkCollision(pockets[j]) && gamestate != Start) { |
Pokitto | 0:1850dcae680f | 75 | // Ball in pocket! |
Pokitto | 0:1850dcae680f | 76 | balls[i].remove(); // remove ball from table |
Pokitto | 0:1850dcae680f | 77 | if (balls[i].color == 7) { |
Pokitto | 0:1850dcae680f | 78 | player1points++; // red ball point for player 1 |
Pokitto | 0:1850dcae680f | 79 | if (gameturn == 1) player_pocketed = true; // player gets a new shot! |
Pokitto | 0:1850dcae680f | 80 | } |
Pokitto | 0:1850dcae680f | 81 | if (balls[i].color == 4) { |
Pokitto | 0:1850dcae680f | 82 | player2points++; // yellow ball point for player 2 |
Pokitto | 0:1850dcae680f | 83 | if (gameturn == 2) player_pocketed = true; // player gets a new shot! |
Pokitto | 0:1850dcae680f | 84 | } |
Pokitto | 0:1850dcae680f | 85 | if (balls[i].color == 1) { |
Pokitto | 0:1850dcae680f | 86 | // White ball in pocket, player lost |
Pokitto | 0:1850dcae680f | 87 | if (gameturn==1) { player1points=0; player2points = (ballsinplay-1)/2; } //player 2 vwins |
Pokitto | 0:1850dcae680f | 88 | else { player1points = (ballsinplay-1)/2; player2points = 0;} //player 1 wins |
Pokitto | 0:1850dcae680f | 89 | } |
Pokitto | 0:1850dcae680f | 90 | if (player1points == (ballsinplay-1)/2 || player2points == (ballsinplay-1)/2) gamestate = Win; |
Pokitto | 0:1850dcae680f | 91 | } |
Pokitto | 0:1850dcae680f | 92 | } |
Pokitto | 0:1850dcae680f | 93 | } |
Pokitto | 0:1850dcae680f | 94 | |
Pokitto | 0:1850dcae680f | 95 | /** UPDATE loop, refresh the display **/ |
Pokitto | 0:1850dcae680f | 96 | if (mygame.update()) { |
Pokitto | 0:1850dcae680f | 97 | int balls_stopped = 0; // for calculating balls that have come to a standstill |
Pokitto | 0:1850dcae680f | 98 | // Draw balls |
Pokitto | 0:1850dcae680f | 99 | for (int i=0; i<ballsinplay; i++) balls[i].draw(); |
Pokitto | 0:1850dcae680f | 100 | // Select white color for text |
Pokitto | 0:1850dcae680f | 101 | mygame.display.color = 1; |
Pokitto | 0:1850dcae680f | 102 | switch (gamestate) { |
Pokitto | 0:1850dcae680f | 103 | case Start: |
Pokitto | 0:1850dcae680f | 104 | /** case Start ... initialize table and game **/ |
Pokitto | 0:1850dcae680f | 105 | mygame.display.print(16,8,"MiniPool"); |
Pokitto | 0:1850dcae680f | 106 | mygame.display.print(16,16,"Press A"); |
Pokitto | 0:1850dcae680f | 107 | |
Pokitto | 0:1850dcae680f | 108 | // Zero points and variables |
Pokitto | 0:1850dcae680f | 109 | player1points = 0; |
Pokitto | 0:1850dcae680f | 110 | player2points = 0; |
Pokitto | 0:1850dcae680f | 111 | gameturn = 1; |
Pokitto | 0:1850dcae680f | 112 | |
Pokitto | 0:1850dcae680f | 113 | // Put balls in starting position |
Pokitto | 0:1850dcae680f | 114 | initballs(); |
Pokitto | 0:1850dcae680f | 115 | |
Pokitto | 0:1850dcae680f | 116 | /** Table **/ |
Pokitto | 0:1850dcae680f | 117 | // Top bumper in place |
Pokitto | 0:1850dcae680f | 118 | bumpers[0].x = 0; bumpers[0].y = -49; bumpers[0].width = 110; bumpers[0].height=20; |
Pokitto | 0:1850dcae680f | 119 | bumpers[0].setColor(5); |
Pokitto | 0:1850dcae680f | 120 | // Bottom bumper in place |
Pokitto | 0:1850dcae680f | 121 | bumpers[1].x = 0; bumpers[1].y = 49; bumpers[1].width = 110; bumpers[1].height=20; |
Pokitto | 0:1850dcae680f | 122 | bumpers[1].setColor(5); |
Pokitto | 0:1850dcae680f | 123 | // Left bumper in place |
Pokitto | 0:1850dcae680f | 124 | bumpers[2].x = -59; bumpers[2].y = 0; bumpers[2].width = 20; bumpers[2].height=88; |
Pokitto | 0:1850dcae680f | 125 | bumpers[2].setColor(5); |
Pokitto | 0:1850dcae680f | 126 | // Right bumper in place |
Pokitto | 0:1850dcae680f | 127 | bumpers[3].x = 59; bumpers[3].y = 0; bumpers[3].width = 20; bumpers[3].height=88; |
Pokitto | 0:1850dcae680f | 128 | bumpers[3].setColor(5); |
Pokitto | 0:1850dcae680f | 129 | // Make bumpers stationary |
Pokitto | 0:1850dcae680f | 130 | bumpers[0].movable = bumpers[1].movable = bumpers[2].movable = bumpers[3].movable = false; |
Pokitto | 0:1850dcae680f | 131 | |
Pokitto | 0:1850dcae680f | 132 | /** Pockets **/ |
Pokitto | 0:1850dcae680f | 133 | // Left top pocket in place |
Pokitto | 0:1850dcae680f | 134 | pockets[0].x = -59; pockets[0].y = -49; pockets[0].width = 30; pockets[0].height=30; |
Pokitto | 0:1850dcae680f | 135 | pockets[0].setColor(0); |
Pokitto | 0:1850dcae680f | 136 | // Right top pocket in place |
Pokitto | 0:1850dcae680f | 137 | pockets[1].x = 59; pockets[1].y = -49; pockets[1].width = 30; pockets[1].height=30; |
Pokitto | 0:1850dcae680f | 138 | pockets[1].setColor(0); |
Pokitto | 0:1850dcae680f | 139 | // Right bottom pocket in place |
Pokitto | 0:1850dcae680f | 140 | pockets[2].x = 59; pockets[2].y = 49; pockets[2].width = 30; pockets[2].height=30; |
Pokitto | 0:1850dcae680f | 141 | pockets[2].setColor(0); |
Pokitto | 0:1850dcae680f | 142 | // Left bottom pocket in place |
Pokitto | 0:1850dcae680f | 143 | pockets[3].x = -59; pockets[3].y = 49; pockets[3].width = 30; pockets[3].height=30; |
Pokitto | 0:1850dcae680f | 144 | pockets[3].setColor(0); |
Pokitto | 0:1850dcae680f | 145 | // Make all pockets stationary |
Pokitto | 0:1850dcae680f | 146 | bumpers[0].movable = pockets[1].movable = pockets[2].movable = pockets[3].movable = false; |
Pokitto | 0:1850dcae680f | 147 | |
Pokitto | 0:1850dcae680f | 148 | // if A pressed, move to Aim game state |
Pokitto | 0:1850dcae680f | 149 | if (mygame.buttons.released(BTN_A)) { |
Pokitto | 0:1850dcae680f | 150 | player.x = balls[0].x; player.y = balls[0].y; |
Pokitto | 0:1850dcae680f | 151 | gamestate = Aim; |
Pokitto | 0:1850dcae680f | 152 | } |
Pokitto | 0:1850dcae680f | 153 | break; |
Pokitto | 0:1850dcae680f | 154 | case Aim: |
Pokitto | 0:1850dcae680f | 155 | player_pocketed = false; // put this back to false, its for checking if a ball was pocketed during the Hit state |
Pokitto | 0:1850dcae680f | 156 | /** case Aim ... in this gamestate, player moves targetting line **/ |
Pokitto | 0:1850dcae680f | 157 | if (gameturn == 1) { |
Pokitto | 0:1850dcae680f | 158 | mygame.display.color = 7; // red |
Pokitto | 0:1850dcae680f | 159 | mygame.display.print(16,8,"player 1 turn"); |
Pokitto | 0:1850dcae680f | 160 | } else { |
Pokitto | 0:1850dcae680f | 161 | mygame.display.color = 4; // yellow |
Pokitto | 0:1850dcae680f | 162 | mygame.display.print(16,8,"player 2 turn"); |
Pokitto | 0:1850dcae680f | 163 | } |
Pokitto | 0:1850dcae680f | 164 | |
Pokitto | 0:1850dcae680f | 165 | // draw targetting line |
Pokitto | 0:1850dcae680f | 166 | mygame.display.setColor(1); // white |
Pokitto | 0:1850dcae680f | 167 | mygame.display.drawLine(player.centerX,player.centerY,balls[0].centerX,balls[0].centerY); |
Pokitto | 0:1850dcae680f | 168 | // check button presses |
Pokitto | 0:1850dcae680f | 169 | if (mygame.buttons.rightBtn()) player.moveX(1); |
Pokitto | 0:1850dcae680f | 170 | if (mygame.buttons.leftBtn()) player.moveX(-1); |
Pokitto | 0:1850dcae680f | 171 | if (mygame.buttons.upBtn()) player.moveY(-1); |
Pokitto | 0:1850dcae680f | 172 | if (mygame.buttons.downBtn()) player.moveY(1); |
Pokitto | 0:1850dcae680f | 173 | // if button A released, a hit begins |
Pokitto | 0:1850dcae680f | 174 | if (mygame.buttons.released(BTN_A)) { |
Pokitto | 0:1850dcae680f | 175 | // give initial speed to the cue ball (the white ball) |
Pokitto | 0:1850dcae680f | 176 | balls[0].vx = (player.x - balls[0].x) * balls[0].acceleration; // X direction strength |
Pokitto | 0:1850dcae680f | 177 | balls[0].vy = (player.y - balls[0].y) * balls[0].acceleration; // Y direction strength |
Pokitto | 0:1850dcae680f | 178 | gamestate = Hit; // go to next gamestate |
Pokitto | 0:1850dcae680f | 179 | } |
Pokitto | 0:1850dcae680f | 180 | break; |
Pokitto | 0:1850dcae680f | 181 | case Hit: |
Pokitto | 0:1850dcae680f | 182 | /** case Hit ... in this state balls move until they are all stopped **/ |
Pokitto | 0:1850dcae680f | 183 | // now count all stationary balls |
Pokitto | 0:1850dcae680f | 184 | for (int i=0; i < ballsinplay; i++) { |
Pokitto | 0:1850dcae680f | 185 | // if ball is stationary or no longer on the table |
Pokitto | 0:1850dcae680f | 186 | if (balls[i].isMoving() == false || balls[i].active == false) { |
Pokitto | 0:1850dcae680f | 187 | balls_stopped++; // count inactive balls |
Pokitto | 0:1850dcae680f | 188 | } |
Pokitto | 0:1850dcae680f | 189 | } |
Pokitto | 0:1850dcae680f | 190 | if (balls_stopped == ballsinplay) { |
Pokitto | 0:1850dcae680f | 191 | // all balls in play are no longer active, time for a new shot |
Pokitto | 0:1850dcae680f | 192 | player.x = balls[0].x; player.y = balls[0].y; |
Pokitto | 0:1850dcae680f | 193 | if (player_pocketed == false) { |
Pokitto | 0:1850dcae680f | 194 | // player did not pocket any of his/her own balls, so does not get a new turn |
Pokitto | 0:1850dcae680f | 195 | if (gameturn == 1) gameturn = 2; |
Pokitto | 0:1850dcae680f | 196 | else gameturn = 1; // change game turn |
Pokitto | 0:1850dcae680f | 197 | } |
Pokitto | 0:1850dcae680f | 198 | gamestate = Aim; |
Pokitto | 0:1850dcae680f | 199 | } |
Pokitto | 0:1850dcae680f | 200 | break; |
Pokitto | 0:1850dcae680f | 201 | case Win: |
Pokitto | 0:1850dcae680f | 202 | /** case Win ... player 1 or 2 won **/ |
Pokitto | 0:1850dcae680f | 203 | if (player1points > player2points) { |
Pokitto | 0:1850dcae680f | 204 | mygame.display.color = 7; // red |
Pokitto | 0:1850dcae680f | 205 | mygame.display.print(16,8,"player 1 WON!"); |
Pokitto | 0:1850dcae680f | 206 | } else { |
Pokitto | 0:1850dcae680f | 207 | mygame.display.color = 4; // yellow |
Pokitto | 0:1850dcae680f | 208 | mygame.display.print(16,8,"player 2 WON!"); |
Pokitto | 0:1850dcae680f | 209 | } |
Pokitto | 0:1850dcae680f | 210 | mygame.display.color = 1; // white |
Pokitto | 0:1850dcae680f | 211 | mygame.display.print(16,16,"Press A"); |
Pokitto | 0:1850dcae680f | 212 | // if button A released, game begins again |
Pokitto | 0:1850dcae680f | 213 | if (mygame.buttons.released(BTN_A)) { |
Pokitto | 0:1850dcae680f | 214 | gamestate = Start; |
Pokitto | 0:1850dcae680f | 215 | } |
Pokitto | 0:1850dcae680f | 216 | break; |
Pokitto | 0:1850dcae680f | 217 | |
Pokitto | 0:1850dcae680f | 218 | } |
Pokitto | 0:1850dcae680f | 219 | } |
Pokitto | 0:1850dcae680f | 220 | // Calculate movement of balls (outside of display update loop, we get more calculations and therefore more accuracy like this!) |
Pokitto | 0:1850dcae680f | 221 | for (int i = 0; i< ballsinplay; i++) balls[i].move(); |
Pokitto | 0:1850dcae680f | 222 | // needed for updating targetting line |
Pokitto | 0:1850dcae680f | 223 | player.move(); |
Pokitto | 0:1850dcae680f | 224 | // draw white ball always, even outside display update loop (speed streak effect!) |
Pokitto | 0:1850dcae680f | 225 | balls[0].draw(); |
Pokitto | 0:1850dcae680f | 226 | } |
Pokitto | 0:1850dcae680f | 227 | } |