int ballSpeed = 15; // the multiplier of the starting speed of the ball float ballSpeedIncrement = 0; String difficulty = "Normal"; float lPaddleHeight = 80.00; float rPaddleHeight = 80.00; int myWidth = 400; int myHeight = 401; int paddleSensitivity = 5; float spinFactor = 1.2; int winningScore = 5; int winner = 0; int winnerLeft = 0; int winnerRight = 0; // handicaps int goalLeft = 0; int goalRight = 0; boolean hitWallLeft = false; boolean hitWallRight = false; boolean hitWallTop = false; boolean justCollidedLeft = false; boolean justCollidedRight = false; float[] vector = new float[2]; //vector array with positions 0 and 1 float[] prePauseVector = new float[2]; //for storing the speed before it was paused float ballPosX = myWidth/2; float ballPosY = myHeight/2; float radius = 5; float dim_ball = 2*radius; float paddleSpeed = 0.0; //Left paddle float lPaddleX = 0.00; float lPaddleY = myHeight/2; float lPaddleYPrevious = lPaddleY; float lPaddleWidth = 50.00; //Right paddle float rPaddleX = myWidth; float rPaddleY = myHeight/2; float rPaddleYPrevious = rPaddleY; float rPaddleWidth = 50.00; // colors int backgroundR = 100; int backgroundG = 100; int backgroundB = 100; int ballR = 255; int ballG = 255; int ballB = 0; int lPaddleR = 255; int lPaddleG = 255; int lPaddleB = 255; int rPaddleR = 255; int rPaddleG = 0; int rPaddleB = 0; boolean pause = false; int startMenu = 0; int inProgress = 1; int paused = 5; int gameState = startMenu; void setup() { size(400, 400); ballPosX = myWidth/2; ballPosY = myHeight/2; draw_background(); draw_ball(); fill (ballR, ballG, ballB); draw_paddles(); setRandomBallDirection(); setBallSpeed(); PFont font; // makes the variable font a 'PFont' class font = loadFont("Jono-32.vlw"); //loads the font textFont(font, 25); //makes the font active textAlign(CENTER); frameRate(30); } void keyPressed() { if (keyCode == ENTER && pause == false){ loop(); //Here we are playing gameState = inProgress; } if (key == '2'){ //Here someone scores gameState = 2; } if (key == '3'){ //Here someone wins gameState = 3; } if (key == '4'){ // A spare state for other things gameState = 4; } if ((key == 'p' || key == 'P') && gameState != startMenu){ //game is paused or restart from pause if (pause == true){ loop(); pause = false; gameState = inProgress; println("pause = "+pause); } else if (pause == false){ pause = true; noLoop(); fill(255, 255, 255); text("game paused \n (p) to restart \n or (q) to quit", myWidth/2, myHeight/4); gameState = paused; println("pause = "+pause); } } if ((key == 'q' || key == 'Q') && gameState != inProgress){ //Restarts pause = false; goalLeft = 0; goalRight = 0; gameState = startMenu; loop(); } if ((key == 'd' || key == 'D') && gameState == 0){ //Cycles through difficulty level on the start screen by pressing d if (ballSpeed == 30){ ballSpeed = 10; difficulty = "Gentle"; } else if (ballSpeed == 10){ ballSpeed = 15; difficulty = "Normal"; } else if (ballSpeed == 15){ ballSpeed = 20; difficulty = "Tough"; } else if (ballSpeed == 20){ ballSpeed = 30; difficulty = "Fiendish"; } } // right paddle if (keyCode == UP && rPaddleY > rPaddleHeight/2){ rPaddleYPrevious = rPaddleY; rPaddleY = rPaddleY - (5*paddleSensitivity); } if (keyCode == DOWN && rPaddleY < myHeight - rPaddleHeight/2){ rPaddleYPrevious = rPaddleY; rPaddleY = rPaddleY + (5*paddleSensitivity); } // left paddle if ((key == 'a' || key == 'A') && lPaddleY > lPaddleHeight/2){ lPaddleYPrevious = lPaddleY; lPaddleY =lPaddleY - (5*paddleSensitivity); } if ((key == 'z' || key == 'Z') && lPaddleY < myHeight - lPaddleHeight/2){ lPaddleYPrevious = lPaddleY; lPaddleY =lPaddleY + (5*paddleSensitivity); } } void draw(){ switch (gameState) { case 0: // before the game starts hitWallLeft = false; hitWallRight = false; hitWallTop = false; justCollidedLeft = false; justCollidedRight = false; goalRight = 0; goalLeft = 0; ballPosX = myWidth/2; ballPosY = myHeight/2; draw_background(); draw_court(); draw_paddles(); draw_ball(); setRandomBallDirection(); setBallSpeed(); fill(255); text("Welcome to Jong!", myWidth/2, myHeight/4); text("press Enter to play \n (d) difficulty: " + difficulty + "\n (p) pause or restart", myWidth/2, (myHeight/4)*3); break; case 1: //standard play draw_background(); draw_court(); draw_paddles(); draw_ball(); draw_score(); collide_paddle(); collide_wall(); move_ball(); break; case 2: //game is won if (winnerLeft == 1){ fill(255,255,255); text("Left player rocked your world", myWidth/2, 3*myHeight/4); winnerLeft = 0; } if (winnerRight == 1){ fill(255,255,255); text("Right player rules", myWidth/2, 3*myHeight/4); winnerRight = 0; } fill(255, 255, 255); text("Hit Enter to reset", myWidth/2, myHeight/2); noLoop(); gameState = 0; break; case 5: //pause draw_background(); draw_court(); draw_paddles(); draw_ball(); break; } smooth(); } void draw_ball(){ fill(ballR, ballG, ballB); ellipse (ballPosX, ballPosY, dim_ball, dim_ball); } void draw_paddles(){ lPaddleYPrevious = lPaddleY; rPaddleYPrevious = rPaddleY; rectMode(CENTER); fill(lPaddleR, lPaddleG, lPaddleB); ellipse(lPaddleX, lPaddleY, lPaddleWidth, lPaddleWidth); fill(rPaddleR, rPaddleG, rPaddleB); ellipse(rPaddleX, rPaddleY, rPaddleWidth, rPaddleWidth); } void draw_background(){ background(backgroundR, backgroundG, backgroundB); } void move_ball(){ ballPosX = ballPosX + vector[0]; ballPosY = ballPosY + vector[1]; } void draw_court(){ line (width/2, 0, width/2, height); noFill(); ellipse(myWidth/2, myHeight/2, 50, 50); } void draw_score(){ fill(lPaddleR, lPaddleG, lPaddleB); text(goalLeft, myWidth/4, myHeight-20); fill(rPaddleR, rPaddleG, rPaddleB); text(goalRight, (3*myWidth)/4, myHeight-20); } void setRandomBallDirection (){ // to separate the ballSPeed from the direction we generate a vector, normalize it and then multiply by the speed float trajX = random(-6,6)*2; float trajY = random(-6,6)*2; // using similar triangles and pythagorus float hypotenuse = sqrt(sq(trajX) + sq(trajY)); vector[0] = trajX/hypotenuse; vector[1] = trajY/hypotenuse; } void setBallSpeed(){ vector[0] = vector[0]*ballSpeed; vector[1] = vector[1]*ballSpeed; } void checkWinner(){ if (goalRight >= winningScore){ winnerRight = 1; winner = winnerRight; gameState = 2; } if (goalLeft >= winningScore){ winnerLeft = 1; winner = winnerLeft; gameState = 2; } } void collide_wall(){ // hit the left wall therefore goal for right if (ballPosX-radius < 0 && hitWallLeft == false){ vector[0] = vector[0]*-1.0; //ACME physics collision goalRight = goalRight + 1; checkWinner(); hitWallLeft = true; hitWallRight = false; hitWallTop = false; } // hit the right wall therefore goal for left if (ballPosX+radius > myWidth && hitWallRight == false){ vector[0] = vector[0]*-1.0; //ACME physics collision goalLeft = goalLeft + 1; checkWinner(); hitWallRight = true; hitWallLeft = false; hitWallTop = false; } // walls at the top and bottom - don't make a goal if ((ballPosY-radius < 0 || ballPosY+radius > myHeight)){ vector[1] = vector[1]*-1.0; //ACME physics collision } } void collide_paddle(){ // use the diagonal distance from the center of the ball to the center of the paddle // c2 = a2 + b2 //distance to the center of the left paddle double left_distance = Math.sqrt(Math.pow(ballPosX-lPaddleX, 2) + Math.pow(ballPosY-lPaddleY, 2)); //distance to the center of the right paddle double right_distance = Math.sqrt(Math.pow(ballPosX-rPaddleX, 2) + Math.pow(ballPosY-rPaddleY, 2)); // Collision left if ((left_distance < (lPaddleWidth/2 + radius*2)) && (justCollidedLeft == false) && vector[0] < 0 ){ paddleSpeed = lPaddleY - lPaddleYPrevious; vector[0] = vector[0]*-1.0 + spinFactor*paddleSpeed; //ACME Physics - change in X justCollidedLeft = true; justCollidedRight = false; hitWallRight = false; hitWallLeft = false; hitWallTop = false; } // Collision right if ((right_distance < (rPaddleWidth/2 + radius*2)) && (justCollidedRight == false) && vector[0] > 0){ paddleSpeed = rPaddleY - rPaddleYPrevious; vector[0] = vector[0]*-1.0 + spinFactor*paddleSpeed; //ACME Physics - change in X justCollidedRight = true; justCollidedLeft = false; hitWallRight = false; hitWallLeft = false; hitWallTop = false; } }