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

Revision:
0:1850dcae680f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Oct 12 17:09:04 2018 +0000
@@ -0,0 +1,227 @@
+#include "Pokitto.h"    // Include the Pokitto library
+#include "GameObject.h" // Include the simple physics library
+
+Pokitto::Core mygame; // Create a Pokitto app/game object
+
+#define MAX_BALL_OBJECTS 7 // max amount of balls
+
+GameObject balls[MAX_BALL_OBJECTS]; // Array of balls
+GameObject player;   // player-object (for aiming)
+GameObject bumpers[4]; // Four sides of table
+GameObject pockets[4]; // Four pockets
+
+enum GameStates { Start, Aim, Hit, Win }; // Game states
+
+/** global variables (accessible from everywhere in the code **/
+GameStates gamestate = Start; 
+int ballsinplay = 7; // how many balls in the game
+int player1points = 0; 
+int player2points = 0;
+int gameturn = 1; // which players turn
+bool player_pocketed = false; //continue turn if player pocketed their own color ball on their turn
+
+// starting arrangement of the balls
+void initballs(){
+    balls[0].x = -30; balls[0].y =   0; balls[0].active = true; balls[0].visible = true; balls[0].setColor(1); 
+    balls[1].x = 10; balls[1].y =   0; balls[1].active = true; balls[1].visible = true; balls[1].setColor(7);
+    balls[2].x = 10; balls[2].y =  10; balls[2].active = true; balls[2].visible = true; balls[2].setColor(4); 
+    balls[3].x = 10; balls[3].y = -10; balls[3].active = true; balls[3].visible = true; balls[3].setColor(4); 
+    balls[4].x = 20; balls[4].y = -10; balls[4].active = true; balls[4].visible = true; balls[4].setColor(7); 
+    balls[5].x = 20; balls[5].y =   0; balls[5].active = true; balls[5].visible = true; balls[5].setColor(4);
+    balls[6].x = 20; balls[6].y =  10; balls[6].active = true; balls[6].visible = true; balls[6].setColor(7);     
+} 
+
+/** MAIN is where a typical C++ program begins executing the program **/
+
+int main () { 
+    mygame.begin(); // start Pokitto engine (display, buttons, sound)
+    mygame.display.setFont(fontTiny); // Tiny font active
+    mygame.display.bgcolor = 13; // Background color to dark green (13)
+    mygame.display.invisiblecolor = 13; // Make text background (13) invisible
+    
+    /** PROGRAM LOOP... runs the entire life of the program
+    ie. as long as  mygame.isRunning() returns logical true (=1) **/
+    
+    while (mygame.isRunning()) {
+        
+        // Draw table bumpers
+        for (int i=0; i<4; i++) bumpers[i].draw();
+        // Draw table pockets
+        for (int i=0; i<4; i++) pockets[i].draw();
+        // Calculate balls vs. bumpers collisions
+        for (int i=0; i<ballsinplay; i++) {
+            for (int j=0; j<4; j++) {
+             if (balls[i].checkCollision(bumpers[j]) && gamestate != Start) {
+                    balls[i].doCollision(bumpers[j]);        
+                 }
+            }
+        }
+        
+        // Calculate balls vs. balls collisions
+        for (int i=0; i<ballsinplay; i++) {
+            for (int j=0; j<ballsinplay; j++) {
+             if (i != j) { // do not check collision with self!!
+                    if (balls[i].checkCollision(balls[j]) && gamestate != Start) {
+                        balls[i].doCollision(balls[j]);        
+                    }
+                }
+            }
+        }
+        
+        // Calculate balls colliding with pockets
+        for (int i=0; i<ballsinplay; i++) {
+            for (int j=0; j<4; j++) {
+                if (balls[i].checkCollision(pockets[j]) && gamestate != Start) {
+                    // Ball in pocket!
+                    balls[i].remove(); // remove ball from table
+                    if (balls[i].color == 7) {
+                        player1points++; // red ball point for player 1
+                        if (gameturn == 1) player_pocketed = true; // player gets a new shot!
+                        }
+                    if (balls[i].color == 4) {
+                        player2points++; // yellow ball point for player 2
+                        if (gameturn == 2) player_pocketed = true; // player gets a new shot!
+                    }
+                    if (balls[i].color == 1) {
+                        // White ball in pocket, player lost
+                        if (gameturn==1) { player1points=0; player2points = (ballsinplay-1)/2; } //player 2 vwins
+                        else { player1points = (ballsinplay-1)/2; player2points = 0;} //player 1 wins
+                    }
+                    if (player1points == (ballsinplay-1)/2 || player2points == (ballsinplay-1)/2) gamestate = Win;
+                }
+            }
+        }
+        
+        /** UPDATE loop, refresh the display **/
+        if (mygame.update()) {  
+            int balls_stopped = 0; // for calculating balls that have come to a standstill
+            // Draw balls 
+            for (int i=0; i<ballsinplay; i++) balls[i].draw();
+            // Select white color for text
+            mygame.display.color = 1; 
+            switch (gamestate) {
+            case Start:
+                /** case Start ... initialize table and game **/
+                mygame.display.print(16,8,"MiniPool");
+                mygame.display.print(16,16,"Press A");
+                
+                // Zero points and variables
+                player1points = 0; 
+                player2points = 0;
+                gameturn = 1;
+                
+                // Put balls in starting position
+                initballs();
+                
+                /** Table **/
+                // Top bumper in place
+                bumpers[0].x = 0; bumpers[0].y = -49; bumpers[0].width = 110; bumpers[0].height=20; 
+                bumpers[0].setColor(5); 
+                // Bottom bumper in place
+                bumpers[1].x = 0; bumpers[1].y = 49; bumpers[1].width = 110; bumpers[1].height=20; 
+                bumpers[1].setColor(5); 
+                // Left bumper in place
+                bumpers[2].x = -59; bumpers[2].y = 0; bumpers[2].width = 20; bumpers[2].height=88; 
+                bumpers[2].setColor(5); 
+                // Right bumper in place
+                bumpers[3].x = 59; bumpers[3].y = 0; bumpers[3].width = 20; bumpers[3].height=88; 
+                bumpers[3].setColor(5); 
+                // Make bumpers stationary
+                bumpers[0].movable = bumpers[1].movable = bumpers[2].movable = bumpers[3].movable = false;        
+                
+                /** Pockets **/
+                // Left top pocket in place
+                pockets[0].x = -59; pockets[0].y = -49; pockets[0].width = 30; pockets[0].height=30; 
+                pockets[0].setColor(0); 
+                // Right top pocket in place
+                pockets[1].x = 59; pockets[1].y = -49; pockets[1].width = 30; pockets[1].height=30; 
+                pockets[1].setColor(0); 
+                // Right bottom pocket in place
+                pockets[2].x = 59; pockets[2].y = 49; pockets[2].width = 30; pockets[2].height=30; 
+                pockets[2].setColor(0); 
+                // Left bottom pocket in place
+                pockets[3].x = -59; pockets[3].y = 49; pockets[3].width = 30; pockets[3].height=30; 
+                pockets[3].setColor(0); 
+                // Make all pockets stationary
+                bumpers[0].movable = pockets[1].movable = pockets[2].movable = pockets[3].movable = false; 
+                
+                // if A pressed, move to Aim game state
+                if (mygame.buttons.released(BTN_A)) {
+                    player.x = balls[0].x; player.y = balls[0].y;
+                    gamestate = Aim;
+                    }
+                break;
+            case Aim:
+                player_pocketed = false; // put this back to false, its for checking if a ball was pocketed during the Hit state
+                /** case Aim ... in this gamestate, player moves targetting line **/
+                if (gameturn == 1) {
+                   mygame.display.color = 7; // red
+                   mygame.display.print(16,8,"player 1 turn");   
+                } else {
+                   mygame.display.color = 4; // yellow
+                   mygame.display.print(16,8,"player 2 turn");  
+                }
+    
+                // draw targetting line
+                mygame.display.setColor(1); // white
+                mygame.display.drawLine(player.centerX,player.centerY,balls[0].centerX,balls[0].centerY);
+                // check button presses
+                if (mygame.buttons.rightBtn()) player.moveX(1);
+                if (mygame.buttons.leftBtn()) player.moveX(-1);
+                if (mygame.buttons.upBtn()) player.moveY(-1);
+                if (mygame.buttons.downBtn()) player.moveY(1);
+                // if button A released, a hit begins
+                if (mygame.buttons.released(BTN_A)) {
+                    // give initial speed to the cue ball (the white ball)
+                    balls[0].vx = (player.x - balls[0].x) * balls[0].acceleration; // X direction strength
+                    balls[0].vy = (player.y - balls[0].y) * balls[0].acceleration; // Y direction strength
+                    gamestate = Hit; // go to next gamestate
+                }
+                break;
+            case Hit:
+                /** case Hit ... in this state balls move until they are all stopped **/
+                // now count all stationary balls
+                for (int i=0; i < ballsinplay; i++) {
+                    // if ball is stationary or no longer on the table
+                    if (balls[i].isMoving() == false || balls[i].active == false) { 
+                         balls_stopped++; // count inactive balls
+                    }
+                }
+                if (balls_stopped == ballsinplay) {
+                    // all balls in play are no longer active, time for a new shot
+                    player.x = balls[0].x; player.y = balls[0].y;
+                    if (player_pocketed == false) {
+                        // player did not pocket any of his/her own balls, so does not get a new turn
+                        if (gameturn == 1) gameturn = 2;
+                        else gameturn = 1; // change game turn
+                    }
+                    gamestate = Aim;
+                }
+                break;
+            case Win:
+                /** case Win ... player 1 or 2 won **/
+                if (player1points > player2points) {
+                   mygame.display.color = 7; // red
+                   mygame.display.print(16,8,"player 1 WON!");   
+                } else {
+                   mygame.display.color = 4; // yellow
+                   mygame.display.print(16,8,"player 2 WON!");  
+                }
+                mygame.display.color = 1; // white
+                mygame.display.print(16,16,"Press A");
+                // if button A released, game begins again
+                if (mygame.buttons.released(BTN_A)) {
+                    gamestate = Start;
+                }
+                break;
+                
+            }          
+        } 
+        // Calculate movement of balls (outside of display update loop, we get more calculations and therefore more accuracy like this!)
+        for (int i = 0; i< ballsinplay; i++) balls[i].move();
+        // needed for updating targetting line 
+        player.move();
+        // draw white ball always, even outside display update loop (speed streak effect!)
+        balls[0].draw();
+    }    
+}
\ No newline at end of file