> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.5GIKV0vwh-Z/rev.4746
 * 
 * authors: 
 *   Benjamin Y

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



// Pressing Control-R will render this sketch.
/*

Version History:
1.1: easy game, got the balls and paddle working
1.3: make the real paddle respond to the ball hitting it (you're supposed to dodge the balls), add maxmin speed
1.4: make the field
2.0: make HP and levels and make the balls faster with increasing levels (that's the point!')
2.1: make power-ups
2.2: make power-ups to increase health by 1, makes game much harder
2.3: made info lists to list info for all of the objects except the paddle, which has its info defined in the other sections
2.4: make the powerups have a max to it, prevent from growing too much to fill the entire screen


Info list for powerups:
Index    Value(s)     Definition                               Short Name
0        null         null value                               null
1        int          how much health gained by this powerup   health
2        int          how much does the bubble wobble          wobble
3        int          maximum bubble size                      maxsize
4        int          minimum bubble size                      minsize

Info list for balls:
Index    Value(s)     Definition                               Short Name
0        null         null value                               null
1        int          ball size                                size



*/

int i = 0; 
int[][] balls = { { null,11 },{ null,9 },{ null,10 },{ null,9 },{ null,11 } };// blank ball info list
int[] ballX = { 100,300,150,200,350 };// original x (it will become random once they go to the bottom edge
int[] ballY = { 0,0,0,0,0 };
int[] ballDX = { 0,6,4,0,0 }; // movement
int[] ballDY = { 6,5,6,5,6 };
int[][] powerups = { { null,1,4,40,25 },{ null,1,4,40,25 } }; // powerups restore health
int[] powerupX = { 50,250 }; // same principles, but powerups have different effects when hit
int[] powerupY = { 0,0 }; // they start at the same Y
int[] powerupDX = { 0,0 };
int[] powerupDY = { 8,8 };
int buconst = 1/10; // burst constant, currently equal to 0.1 or one tenth
float buconstM = 0.75; // burst constant multiplier adjust, for level
int lastBallHit = -1; // prevent multi-hits, -1 is the notselected value for lastBallHit
int maxSpeed = 6; // maxspeed multiplier
int minSpeed = 5; // minspeed multiplier
int pwrMaxSpeed = 9; // for power-ups
int pwrMinSpeed = 7;
int mamiConst = 0.78; // maxspeedminspeed adjust
int paddleX = 200; // paddle x, will go to mouse
int score = 0; // score
int scoreM = 160; // score multiplier (score needed to level up = scoreM*(level*level)
int minAng = 45; // in degrees
int maxAng = 135;
int level = 1;
int health = 2; // hitpoints
int maxHP = 2; // max hitpoints
int maxLevel = 4; // max level, after that you win
int mxmiX = 8; // max min X movement
int powerupmxmiX = 1; // max min X movement for powerups
boolean Cpaddle = true; // if paddle connects to mouse
boolean Cwobble = true; // start/stop wobbling
georgiaFont = createFont('Georgia',20);
textFont(georgiaFont);
float dist(int nx,int ny,int dx,int dy) {// distance function
    return sqrt(sq(nx-dx)+sq(ny-dy));
}
void setup() {  // this is run once.   
    
    // set the background color
    background(255);
    
    // canvas size (Variable aren't evaluated. Integers only, please.)
    size(400, 400); 
    
    // smooth edges
    smooth();
    
    // limit the number of frames per second
    frameRate(30);
    
    // set the width of the line. 
    strokeWeight(2);
} 
void endgame() {
    text('Score: '+score,200,200);
    for (i = 0;i < balls.length;i+=1) {
        ballDX[i] = 0;// freeze
        ballDY[i] = 0;
    }
    for (i = 0;i < powerups.length;i+=1) {
        powerupDX[i] = 0;// freeze the powerups too
        powerupDY[i] = 0;
    }
    Cpaddle = false;// freeze paddle and powerups
    Cwobble = false;
}
void draw() {  // this is run repeatedly.  
    if (Cpaddle) {
        paddleX = mouseX; // make the paddle connect to the mouse
    }
    background(0,0,255);
    fill(255);
    stroke(0);
    line(10,130,60,130);// health bar
    stroke(255);
    text('Dodge It 2.2',150,30);
    text('Dodgeball',130,79);
    text(score,10,30);
    text(level,10,90);
    text(max(health,0)+"/"+(maxHP*level),10,120);
    line(10,130,((max(health,0)/maxHP)*(50/level))+10,130);
    noFill();
    line(0,350,width,350);
    line(200,51,200,349);
    ellipse(200,350,75,75);
    line(100,350,100,400);
    line(300,350,300,400);
    line(0,50,width,50);
    line(200,349,200,51);
    ellipse(200,50,75,75);
    line(100,0,100,50);
    line(300,0,300,50);
    fill(153,153,255);
    for (i = 0;i < balls.length;i+=1) {
        ellipse(ballX[i],ballY[i],balls[i][1],balls[i][1]);
        ballX[i] += ballDX[i];
        ballY[i] += ballDY[i];
        //ballDX[i] += int(random(-2.0000000000000001,2));
        if (ballX[i] <= 0) {// fell off screen
            ballX[i] = 0;
            ballDX[i] = -ballDX[i]
        } else if (ballX[i] >= width) {
            ballX[i] = width;
            ballDX[i] = -ballDX[i]
        }
        if (ballY[i] > height) { // check if reached bottom of screen
            ballY[i] = 0;
            ballDY[i] = int(random((minSpeed*level)*mamiConst, (maxSpeed*level)*mamiConst));// reset
            ballDX[i] = int(random(-mxmiX*level,mxmiX*level));
            ballX[i] = int(random(width));
            score += 10;
            if (i == lastBallHit) {// clear lastBallHit only if i is lastBallHit
                // this needs to happen or else you can hit the same ball after it has gone off screen
                lastBallHit = -1;// no last ball hit
            }
        } else if (dist(paddleX,350,ballX[i],ballY[i])<=30 && lastBallHit != i) {
            // avoid the balls
            health -= 1;
            lastBallHit = i;
            if(health < 1) {
                // die
                endgame();
                text('Score: '+score, 200,200);
            }
            
        }
            
    }
    
    ellipse(paddleX,350,20,20);
    for (i = 0;i < powerups.length;i+=1) {
        fill(255,0,0);// make powerups red
        ellipse(powerupX[i],powerupY[i],20,20);
        fill(255,0,0,153);// make circles
        if (Cwobble) {
            wobble = random(-powerups[i][2],powerups[i][2]);
        } else {
            wobble = 0; // prevent "no variable being found" errors
        }
        rad = 20+(powerupY[i]*buconst*(level*buconstM))+wobble;// allow it to set rad to 40
        if (rad > powerups[i][3]) {
            rad = powerups[i][3];
        } else if (rad < powerups[i][4]) {
            rad = powerups[i][4];
        }
        ellipse(powerupX[i],powerupY[i],rad,rad);// make powerups "burst" and make it larger with levels
        powerupX[i] += powerupDX[i];
        powerupY[i] += powerupDY[i];
        //ballDX[i] += int(random(-2.0000000000000001,2));
        if (powerupX[i] < 0) {// fell off screen
            powerupX[i] = 0;
            powerupDX[i] = -powerupDX[i];
        } else if (powerupX[i] > width) {
            powerupX[i] = width;
            powerupDX[i] = -powerupDX[i]

        }
        if (powerupY[i] > height) { // check if reached bottom of screen
            powerupY[i] = 0;
            powerupDY[i] = int(random((pwrMinSpeed*level)*mamiConst, (pwrMaxSpeed*level)*mamiConst));// reset
            powerupDX[i] = int(random(-(powerupmxmiX*level),(powerupmxmiX*level)));// delta-x
            powerupX[i] = int(random(width));
            //score += 10;
        } else if (dist(paddleX,350,powerupX[i],powerupY[i])<=30) {
            // powerups increase health
            health += powerups[i][1];
            if (health > maxHP*level) {
                health = maxHP*level;
            }
            
        }
            
    }
    if (score >= scoreM*(level*level)) {
        // level up
        level += 1;
        health = maxHP*level
        if (level == maxLevel+1) {
            // last level
            text('You Win!',200,200);
            endgame();
            
        }
    }
}