> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.WWFaopyGaNS/rev.10409
 * 
 * authors: 
 *   Skanda Rao

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



boolean m = true;                                                                                             //control with mouse or keys
float y1;                                                                                                    //positions of paddles (left is 1, right is 2, top is 3, bottom is 4)
float y2;
float x3;
float x4;
float cx;                                                                                                     //position of center of ball
float cy;
float s = 5;                                                                                                   //speed of ball
float dx = (-2*round(random(0,1))+1)*random(s/3, 2*s/3); //speed of ball in x direction                        //speed of ball in x direction
float dy = (-2*round(random(0,1))+1)*sqrt(sq(s)-sq(dx)); //speed of ball in y direction                        //speed of ball in y direction
int p1 = 0;                                                                                                  //points scored by each bar
int p2 = 0;
int p3 = 0;
int p4 = 0;
int lt = 0;                                                                                                          //last to touch the ball (null at start)
float w1 = 60;                                                                                                           //width of each bar
float w2 = 60;
float w3 = 60;
float w4 = 60;
int wboost = 0;                                                                                                    //initial setting for appearance of green square
int wdrop = 0;                                                                                                     //initial setting for appearance of red square
int full_shield = 0;                                                                                               //initial setting for appearance of purple square
int reverse = 0;                                                                                                   //initial setting for appearance of white square
float wbx;                                                                                                         //x position of green square
float wby;                                                                                                         //y position of green square
float wdx;                                                                                                         //x position of red square
float wdy;                                                                                                         //y position of red square
float fsx;                                                                                                         //x position of purple square
float fsy;                                                                                                         //y position of purple square
float rx;                                                                                                          //x position of white square
float ry;                                                                                                          //y position of white square
float t = 0;                                                                                                      //time (for single player) starts at 0
float hs = 0;                                                                                                      //high score time starts at 0
int rev = 0;                                                                                                                    //effects of boxes are initially off 
boolean start = false;                                                                                                          //does not start automatically

void setup () {
    size (500, 500);                                                                                                          //sets the size of the sketch
    y1 = height/2;
    y2 = height/2;
    x3 = width/2;
    x4 = width/2;
    cx = width/2;
    cy = height/2;
}

void mouseClicked () {
    if (m == true) {                                                                                          //if mouse control is on, it is deactivated
        m = false;
    } else {                                                                                                   //if keyboard control is on, mouse is control reactivated
        m = true;
    }
    p1 = 0;                                                                                                  //point values go to zero (keyboard control is two-player, mouse control is one-player)
    p2 = 0;
    p3 = 0;
    p4 = 0;
}

void keyPressed () {
    if (key == '-' && s > 1) {
        s -= 1;            //the speed decreases if '-' is typed
    } else if (key == '+') {
        s += 1;            //the speed increases if '+' is typed
    }
    if (key == ENTER || key == 'w' || key == 's' || key == 'a' || key == 'd' || keyCode == UP || keyCode == DOWN || keyCode == RIGHT || keyCode == LEFT) {            //starts the game when ENTER is pressed
        start = true;
    }
}

void draw () {                                                                                                                    //loops constantly
    stroke(0,255,0, 10);
    int i = 0;
    while (i <= width) {
        line (i, 0, i, height);                                                                                                  //creates vertical green lines across the screen
        i += 20;
    }
    int j = 0;
    while (j <= height) {
        line (0, j, width, j);                                                                                                  //creates horizontal green lines
        j += 20;
    }
    line (width-21,0,width-21,height);                                                                                          //draws last vertical line
    line (0,height-21,width,height-21);                                                                                        //draws last horizontal line
    noStroke();                                                                                                                //gets rid of stroke
    fill (0);
    rect (0,0,20,height);                                                                                                      //lays out a hard black border
    rect (width-20,0,20,height);
    rect (0,0,width,20);
    rect (0,height-20,width,20);
    fill (0, 50);                                                                                                              //previous frames covered with a faint rectangle to fade them away
    rect (0,0,width,height);
    fill(255);
    textSize(10);
    textAlign(LEFT);
    text("Speed: " + round(s), 25, 35);                                                                                        //displays speed
    noStroke();
    if (m == false) {                                                                                                          //mouse control deactivated
        if (keyPressed && key == 's' && y1 + 5 < height && start == true) {                                                    //moves a bar if a certain key is pressed and the game is started
            y1 += 10;                                                                                                          //'s' moves the left bar (1) down
        } else if (keyPressed && key == 'w' && y1 -5 > 0 && start == true) {
            y1 -= 10;                                                                                                          //'w' moves the left bar up
        }
        if (keyPressed && keyCode == DOWN && y2 + 5 < height && start == true) {
            y2 += 10;                                                                                                          //down arrow moves the right bar (2) down
        } else if (keyPressed && keyCode == UP && y2 - 5 > 0 && start == true) {
            y2 -= 10;                                                                                                          //up arrow moves the right bar up
        }
        if (keyPressed && key == 'd' && x3 + 5 < width && start == true) {
            x3 += 10;                                                                                                          //'d' moves the top bar (3) right
        } else if (keyPressed && key == 'a' && x3 -5 > 0 && start == true) {
            x3 -= 10;                                                                                                          //'a' moves the right bar left
        }
        if (keyPressed && keyCode == RIGHT && x4 + 5 < width && start == true) {
            x4 += 10;                                                                                                          //right arrow moves the bottobar (4) right
        } else if (keyPressed && keyCode == LEFT && x4 - 5 > 0 && start == true) {
            x4 -= 10;                                                                                                          //left arrow moves the bottobar left
        }
        textAlign(CENTER);
        fill(255,125,68);            //colors players controlled with WASD (1 and 3) red
        rect(0, y1-w1/2, 20, w1);        //draws bars with depth of 20
        rect(x3-w3/2, 0, w3, 20);
        textSize(20);
        text(p1+p3,width/2-50,height/2-50);        //displays WASD player points
        fill(255,125,68,100);
        text("W",10,50);
        text("S",10,height-30);
        text("A",50,20);
        text("D",width-50,20);
        fill(255,125,68);
        textSize(15);
        text(p1,width/2-50,height/2);
        text(p3,width/2,height/2-50);
        fill(68,125,255);            //colors players controlled with arrows (2 and 4) blue
        rect(x4-w4/2, height-20, w4, 20);   //draws bars with depth of 20
        rect(width-20, y2-w2/2, 20, w2);
        text(p2,width/2+50,height/2);        //displays arrow player points
        text(p4,width/2,height/2+50);
        textSize(20);
        fill(68,125,255,100);
        text(p2+p4,width/2+50,height/2+50);
        text("^",width-10,50);
        text("v",width-10,height-30);
        text("<",50,height);
        text(">",width-50,height);
    } else if (m == true) {
        if (rev == 0) {
            y1 = mouseY;              //shifts left and right bars to mouseY
            y2 = mouseY;
            x3 = mouseX;              //shifts top and bottom bars to mouseX
            x4 = mouseX;
        } else {
            y1 = height-mouseY;
            y2 = height-mouseY;
            x3 = width-mouseX;
            x4 = width-mouseX;
        }
        textSize(20);
        textAlign(CENTER);
        fill (255);
        rect(0,y1-w1/2,20,w1);        //draws bars with depth of 20
        rect(width-20,y2-w2/2,20,w2);
        rect(x3-w3/2,0,w3,20);
        rect(x4-w4/2,height-20,w4,20);
        text(t,width/2,height/2-25);        //displays time since last loss
        text(hs, width/2, height/2+25);    //displays high score
    }
    fill (255);
    ellipse (cx, cy, 20, 20);        //draws ball
    if (cx >= width-20 && cx <= width && cy>=y2-w2/2 && cy<=y2+w2/2) {        //ball is within right bar
        dx = -abs(dx);        //deflects the ball in x direction
        lt = 2;                //identifies right bar as the last to touch the ball
    } else if (cx >= 0 && cx <= 20 && cy>=y1-w1/2 && cy<=y1+w1/2) {        //ball passes into left bar
        dx = abs(dx);        //deflects the ball in x direction
        lt = 1;                //identifies left bar as the last to touch the ball
    } else if (cx >= width-20) {        //ball passes right bar
        dx = random(-2*s/3,-s/3);    //x component of speed is negative in a certain range
        dy = (-2*round(random(0,1))+1)*sqrt(sq(s)-sq(dx));    //speed of ball in y direction
        cx = width/2;            //centers ball
        cy = height/2;
        if (lt == 1 && m == false) {            //increases points for player that last touch ball unless on same team (if on same team, increases opposite team's points by 2)
            p1 += 1;
        } else if (lt == 3 && m == false) {
            p3 += 1;
        } else if (lt == 4 && m == false) {
            p1 += 1;
            p3 += 1;
        } else if (m == true) {        //if mouse control on
            if (t >= hs) {        //high score is highest time achieved
                hs = t;
            }
            t = 0;                //time reset to 0
        }
        lt = 0;                //nullifies last touch
        w1 = 60;            //all widths go back to normal
        w2 = 60;
        w3 = 60;
        w4 = 60;
        start = false;
    } else if (cx <= 10) {        //ball passes left bar
        dx = random(s/3,2*s/3);        //speed of ball in positive x direction
        dy = (-2*round(random(0,1))+1)*sqrt(sq(s)-sq(dx));    //speed of ball in y direction
        cx = width/2;        //centers ball
        cy = height/2;
        if (lt == 2 && m == false) {            //increases points for player that last touch ball unless on same team (if on same team, increases opposite team's points by 2)
            p2 += 2;
        } else if (lt == 3 && m == false) {
            p2 += 1;
            p4 += 1;
        } else if (lt == 4 && m == false) {
            p4 += 1;
        } else if (m == true) {        //if mouse control on
            if (t >= hs) {        //high score is highest time achieved
                hs = t;
            }
            t = 0;                //time reset to 0
        }
        w1 = 60;            //all widths go back to normal
        w2 = 60;
        w3 = 60;
        w4 = 60;
        start = false;
        lt = 0;                //nullifies last touch
    }
    if (cy >= height-20 && cy <= height && cx>=x4-w4/2 && cx<=x4+w4/2) {
        dy = -abs(dy);        //deflects ball in y direction
        lt = 4;
    } else if (cy >= 0 && cy <= 20 && cx>=x3-w3/2 && cx<=x3+w3/2) {
        dy = abs(dy);
        lt = 3;
    } else if (cy >= height-10) {
        dy = random(-2*s/3,-s/3);
        dx = (-2*round(random(0,1))+1)*sqrt(sq(s)-sq(dy));
        cx = width/2;
        cy = height/2;
        if (lt == 1 && m == false) {            //increases points for player that last touch ball unless on same team (if on same team, increases opposite team's points by 2)
            p1 += 1;
        } else if (lt == 2 && m == false) {
            p1 += 1;
            p3 += 1;
        } else if (lt == 3 && m == false) {
            p3 += 1;
        } else if (m == true) {        //if mouse control on
            if (t >= hs) {        //high score is highest time achieved
                hs = t;
            }
            t = 0;                //time reset to 0
        }
        lt = 0;
        w1 = 60;            //all widths go back to normal
        w2 = 60;
        w3 = 60;
        w4 = 60;
        start = false;
    } else if (cy <= 10) {
        dy = random(s/3, 2*s/3);
        dx = (-2*round(random(0,1))+1)*sqrt(sq(s)-sq(dy));
        cx = width/2;
        cy = height/2;
        if (lt == 1 && m == false) {            //increases points for player that last touch ball unless on same team (if on same team, increases opposite team's points by 2)
            p2 += 1;
            p4 += 1;
        } else if (lt == 2 && m == false) {
            p2 += 1;
        } else if (lt == 4 && m == false) {
            p4 += 1;
        } else if (m == true) {        //if mouse control on
            if (t >= hs) {        //high score is highest time achieved
                hs = t;
            }
            t = 0;                //time reset to 0
        }
        lt = 0;
        w1 = 60;            //all widths go back to normal
        w2 = 60;
        w3 = 60;
        w4 = 60;
        start = false;
    }
    if (wboost == 1000) {
        fill (70,255,70);
        rect (wbx, wby, 20, 20);
        wby += s/5;
        if (cx >= wbx && cx <= wbx+20 && cy >= wby && cy <= wby + 20) {
            if (lt == 1) {
                w1 *= 2;
            } else if (lt == 2) {
                w2 *= 2;
            } else if (lt == 3) {
                w3 *= 2;
            } else if (lt == 4) {
                w4 *= 2;
            }
            wboost = 0;
        } else if (wby >= height) {
            wboost = 0;
        }
    } else {
        wboost += 4;
        wbx = random (0,width);
        wby = random (0, height/2);
    }
    if (full_shield >= 2000) {
        fill (255,0,255);
        rect (fsx, fsy, 20, 20);
        fsy += s/3;                //full shield box goes down
        if (cx >= fsx && cx <= fsx+20 && cy >= fsy && cy <= fsy + 20) {
            if (lt == 1) {                //makes width of last to touch full size of screen
                w1 = 2*height;
            } else if (lt == 2) {
                w2 = 2*height;
            } else if (lt == 3) {
                w3 = 2*width;
            } else if (lt == 4) {
                w4 = 2*width;
            }
            full_shield = 0;        //resets full shield box
        } else if (fsy >= height) {
            full_shield = 0;        //full shield reset if box reaches 0
        }
    } else {
        full_shield += 3;
        fsx = random (0,width);
        fsy = random (0, height/2);
    }
    if (wdrop >= 600) {
        fill (255,70,70);
        rect (wdx, wdy, 20, 20);
        wdy += s/10;
        if (cx >= wdx && cx <= wdx+20 && cy >= wdy && cy <= wdy + 20) {
            if (lt == 1) {
                w1 *= 0.5;
            } else if (lt == 2) {
                w2 *= 0.5;
            } else if (lt == 3) {
                w3 *= 0.5;
            } else if (lt == 4) {
                w4 *= 0.5;
            }
            wdrop = 0;
        } else if (wdy >= height) {
            wdrop = 0;
        }
    } else {
        wdrop += 7;
        wdx = random (0,width);
        wdy = random (0, height/2);
    }
    if (reverse >= 10000) {
        stroke(0,0,255);
        fill (255);
        rect (rx, ry, 20, 20);
        ry += s/10;
        if (cx >= rx && cx <= rx+20 && cy >= ry && cy <= ry + 20) {
            rev = 1000;
        } else if (ry >= height) {
            reverse = 0;
        }
    } else {
        reverse += 7;
        rx = random (0,width);
        ry = random (0, height/2);
    }
    if (rev > 0) {
        if (start == true) {
            rev -= 1;
        } else {
            rev = 0;
        }
    }
    if (start == true) {            //only if the game is started
        cx += dx;
        cy += dy;
        if (m == true) {
            t += 1/frameRate;
        }
    } else {
        fill(255);
        textSize(20);
        text("Press ENTER to play",width/2,height/2+100);
        fill(128);
        textSize(10);
        text("Click to toggle between single player and two-player modes",width/2,height-55);
        textAlign(LEFT);
        text("+ to increase speed",25,55);
        text("- to decrease speed",25,75);
    }
    if (w1 > 60) {
        w1 -= w1/2000;
    } else if (w1 < 60) {
        w1 += w1/2000;
    }
    if (w2 > 60) {
        w2 -= w2/2000;
    } else if (w2 < 60) {
        w2 += w2/2000;
    }
    if (w3 > 60) {
        w3 -= w3/2000;
    } else if (w3 < 60) {
        w3 += w3/2000;
    }
    if (w4 > 60) {
        w4 -= w4/2000;
    } else if (w4 < 60) {
        w4 += w4/2000;
    }
}