Mini Pool game for two players

Dependencies:   PokittoLib

/media/uploads/Pokitto/minipool.bin.1.gif

This is a small, fully documented Mini Pool game for 2 players intended as a programming tutorial

Committer:
Pokitto
Date:
Fri Oct 12 17:09:04 2018 +0000
Revision:
0:1850dcae680f
initial

Who changed what in which revision?

UserRevisionLine numberNew 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 }