> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://cisc1600.sketchpad.cc/sp/pad/view/ro.ZMYWeFq2vC0/rev.266
 * 
 * authors: 
 *   benedah

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



/******************************************************************************************
* Project 2. This is a clear ripoff of Pong. You will play as the paddle on the left      *
* against the paddle on the right and the objective is to get the ball past him. When the *
* ball passes, player and enemy will score respectively. Those who score get to serve.    *
* PRESS THE 'a' KEY TO SERVE!                                                             *
*******************************************************************************************/

Court court;
Ball ball; 
Player player;
Enemy enemy;
color col;
var gameState = 0; //Variable to keep track of when the round starts, 0 for serving phase and 1 for round phase
int playerScore = 0;
int enemyScore = 0;
int screenW = 300, screenH = 300;
 
void setup() { 
    size(screenW, screenH); 
    court = new Court();
    ball = new Ball();
    player = new Player(ball);
    enemy = new Enemy(ball);
    fill( 0 );
    textSize(50);
    textAlign(CENTER);
}

//Draws all the objects and calls update
void draw() { 
    background(250);
    court.draw();
    ball.draw();
    player.draw();
    enemy.draw();
    update();
} 

/******************************************************************************
* This is where all the code that keeps track of the game state goes.Variable *
* gameState is a public variable that defines the two states of the game      *
* serving and volleying Code to display the scores and prompt user to serve   *
* the ball goes here                                                          *  
*******************************************************************************/                
void update(){
    //If the game state is 0, player is in serving state.
    //Player presses 'a' key for both the player and enemys serves, sets gameState to 1
    if(gameState == 0){
         
        if(keyPressed){
            if(key == 'a' || key == 'A')
                gameState = 1;
        }
        //Press a to serve the ball
        text("Press a!", width/2, height/2);
    }
    
    if(gameState == 1){
        //If the ball passes the player game goes back to serving phase and enemy scores
        //Reset the ball position
        if(ball.getX() < player.getX() - 5){
            gameState = 0;
            enemyScore++;
            ball.setX(width - 20);
            ball.setY(height/2 - 5);   
    }
        //If the ball passes the enemy game goes back to serving phase and player scores
        //Ball is reset to the position for player serve
        //Reset the ball position
    else if(ball.getX() >= enemy.getX() + 5){
            playerScore++;
            gameState = 0;
            ball.setX(20);
            ball.setY(height/2 - 5);
        }
    }
    
    //Player Score
    text(playerScore, width/2 - width/4, height/5);
     
    //Enemy Score
    text(enemyScore, width/2 + width/4, height/5);
     
}

/****************************************************************************
* This is function definition of the ball that bounces around in the game.  *
* When the game state is 1, it is constantly moving in respective velocity. *
* When the ball hits the top or bottom boundaries, its direction is flipped *  
* to give the effect of bouncing off of the wall.                           * 
*****************************************************************************/
function Ball(){
    int x = 20, y = width/2 - 5, vX = 5, vY = 5, radius = 10;
   
    this.draw = function(){
        ellipse(x,y,radius,radius);
        this.update();
    };

    this.update = function() { 
        
        /*Volleying state, the ball will continuously move in the x and y and the velocity
        will be flipped when bouncing off of the north and south borders.*/
        if(gameState == 1){
            x += vX;
            y += vY;
        
            //South Boundary
            if(y >= height - 5)
                vY *= -1;
           
            //North Boundary
            if(y <= 5)
                vY *= -1;
       }            
    };
    
    //Flips the trajectory of the ball via the x-axis and changes the fill to a random color
    this.flipTrajectory = function(){
        vX *= -1; 
        col = color(random(255), random(255), random(255));
        fill( col ); 
    };
   
    this.getX = function(){
        return x;
    };
    
    this.getY = function(){
        return y;
    };
    
    this.setX = function(int a){
        x = a;
    };
    
    this.setY = function(int b){
        y = b;
    };
    
    this.setvX = function(int a){
        vX = a;
    };
    
    this.setvY = function(int b){
        vY = b;
    };
    
} 

/***********************************************************************************
* This is the function definition of the player (the usable paddle on the left).   *
* During the serving state (gameState 0) the player is stationary. When the player *
* holds the ball, it is ready to serve via the 'a' key. The player is passed a     *
* reference to the ball to track where its position by calling the ball's inner    *
* methods.                                                                         *
************************************************************************************/
function Player(Ball ball){
    int x = 10, y = screenH/2.5, width = 5, height = 50, speed = 5;
  
    this.draw = function(){
        rect(x,y,width,height);   
        this.update();
    };  
    
    this.update = function(){
        //Serving State
        if(gameState == 0){
            x = 10;
            y = screenH/2.5;
        }
        
        //During the serving state, the user can coordinate the vertical positioning of the 
        //player by pressing the up and down arrow keys.
        //Volleying state
        if(gameState == 1){
            if(keyPressed){
                if(key == CODED && keyCode==DOWN){
                    if(y <= screenH - 55)
                    y += speed;
                }
        
                else if(key == CODED && keyCode == UP){
                    if(y > 0)
                    y -= speed;  
                }
            }
            
            //If the ball hits the player, flip its trajectory
            if(ball.getX() < x+10 && ball.getY() > y && ball.getY() < y + height){
                    ball.flipTrajectory();
            }
        }
    };
    
    this.getX = function(){
        return x;
    };
    
    this.getY = function(){
        return y;
    };
    
    this.getStatus = function(){
        return status;
    };
}

/*****************************************************************************************************
* This is the function definition of the enemy (the paddle on the right).During the serving state    *
* (gameState 0) the enemy is stationary. When the enemy holds the ball, it is ready to serve via the *
* 'a' key. The enemy is passed a reference to the ball to track where its position by calling the    *
* ball's inner functions.                                                                                *
*                                                                                                    *
* The AI works by utilizing two variables defined. The first variable is named target, it represents *
* the y value where the paddle aims to hit the ball. The target could either be within the paddle    *  
* (a direct hit) or greater than the paddle (a miss). This variable is set a random value during     *  
* the serving state. The reactPos variable works in a similar way in that it is also set a random    *
* value during serving state. reactPos is the x value that is used to keep track of when the enemy   *
* will start to move in respect to the ball's position. The greater the reactPos means the less time *
* the enemy starts to move to the ball. The smaller the reactPos, means the less time the enemy      *
* starts to move to the ball.                                                                        *
*                                                                                                    *
* These two variables work together to coordinate the movements of the enemy paddle and are defined  *
* before the volleying state begins.                                                                 *     
******************************************************************************************************/
function Enemy(Ball ball){
    int x = screenW - 15, y = screenH/2.5, width = 5, height = 50, target, reactPos;
     
    this.draw = function(){
        rect(x,y,width,height);   
        this.update();
    };  
    
    this.update = function(){
    
    //Serving State
    if(gameState == 0){
            x = screenW - 15;
            y = screenH / 2.5;
            target = random(10, height-10);
            reactPos = random(screenW/4, screenW/3);
    }
        
    //Volleying state
    if(gameState == 1 ){
        /**Enemy moves down if the ball is lower than its target position
           When the enemy hits the south boundary, it means the ball has 
           bounced and now it needs to react by moving upwards*/
        if(ball.getX()>reactPos && ball.getY()>y+target){
            if(y >= 5 && y <= screenH - 55)
                 y += 5;
            else if(y >= screenH - 55)    
                 y -= 5;
         }            
        
        /**Enemy moves up if the ball is higher than its target position
           When the enemy hits the north boundary, it means the ball has 
           bounced and now it needs to react by moving downwards*/
        else  if(ball.getX()>reactPos && ball.getY()<y+target){
             if(y >= 5 && y <= screenH) 
                  y -= 5;
             if(y <= 0)    
                  y+=5;
            }
        }
        
        //If the ball hits the enemy, flip its trajectory
        if(ball.getX() >x-5 && ball.getY() > y && ball.getY() < y+height){
            ball.flipTrajectory();
        }
        
    };
    
    this.getStatus = function(){
        return status;
    };
    
    this.getX = function(){
        return x;
    };
    
    this.getY = function(){
        return y;
    };
}

//Code to draw the playing field
function Court(){
    int width = 5, height = 10;
    int x = screenW/2 - width, y = 2;
    
    this.draw = function(){
        for(var j = 0; j<20; j++){
            rect(x, y, width, height);
            y += height + 5;
        }
        y = 2;
        
        rect(0,0,screenW,5);
        rect(0,screenH-6,screenW,5);
    };
}