We are about to switch to a new forum software. Until then we have removed the registration on this forum.
So I am doing a project for my programming class that is a pong game. The problem I currently have is getting the game to restart after the score limit of 10 is reached by either player. I am trying something I read from another post which is to make a reset function, redraw the background, reset variables, etc. but I'm having trouble getting it to work properly even though I feel I did the right things, I've been trying different options but nothing is fixing it. So I'm wondering if any of you see any problem with my code?
Restart function inside Ball class (line 79):
class Ball {
float x = width/2; // variables for ball class x,y locations, radius, and x/y speeds
float y = height/2;
int r = 15;
float xspeed;
float yspeed;
float ballAngle = random(-PI/4, PI/4);
Ball() { // ball class constructor
reset(); // reset function
}
void move() { // function to move ball
x = x + xspeed;
y = y + yspeed;
}
void display() { // function to display ball
fill(170);
stroke(0);
strokeWeight(1);
ellipse(x, y, r*2, r*2);
}
void checkEdges() { // function to check the top and bottom so ball doesn't go off the screen // also score function
if (y < 0 + r || y > height - r) {
yspeed = yspeed *-1;
}
if (x + r < 0) {
cpuScore++;
reset();
}
if (x - r > width) {
userScore++;
reset();
}
}
void reset() { // reset the ball when it reaches the end of the right or left side of the screen
xspeed = 8 * cos(ballAngle);
yspeed = 8 * sin(ballAngle);
if (x < 0 - r) {
x = width/2;
y = random(0+r*2, 400-r*2);
}
if (x > width + r) {
x = width/2;
y = random(0+r*2, 400-r*2);
xspeed *= -1;
}
}
void isUserPHit(Paddle p) { // detect if user paddle is hit
if (y < p.y + p.h/2 + r && y > p.y - p.h/2 - r && x - r < p.x + p.w/2) {
if (xspeed < 0) {
//paddlehit.play();
float diff = y - (p.y - p.h/2);
float rad = radians(45);
float angle = map(diff, 0, p.h, -rad, rad);
xspeed = 8 * cos(angle);
yspeed = 8 * sin(angle);
}
}
}
void isCPUPHit(Paddle p) { // detect if cpu paddle is hit
if (y < p.y + p.h/2 + r && y > p.y - p.h/2 - r && x + r > p.x - p.w/2) {
if (xspeed > 0) {
//paddlehit.play();
float diff = y - (p.y - p.h/2);
float angle = map(diff, 0, p.h, radians(225), radians(135));
xspeed = 8 * cos(angle);
yspeed = 8 * sin(angle);
}
}
}
void restart() {
xspeed = 8 * cos(ballAngle);
yspeed = 8 * sin(ballAngle);
userScore = 0;
cpuScore = 0;
background(255);
// line to divide the two sides
strokeWeight(3);
line(width/2, 0, width/2, height);
fill(0);
textSize(20);
textAlign(CENTER);
text("User Score:", 78, 25); // text for the scores
text("CPU Score:", 493, 25);
text(userScore, 147, 25); // text for the numbers, currently set at “0”, but will update later
text(cpuScore, 558, 25);
display(); // display the ball
move(); // move the ball
checkEdges(); // check if the ball is reaching the top or bottom so it bounces off rather than going off the screen
userP.display(); // display the paddles
cpuP.display();
userP.moveY(mouseY); // move the user’s paddle vertically with the mouse’s y position
isUserPHit(userP); // detect if either paddle comes in contact with the ball
isCPUPHit(cpuP);
cpuP.cpuAI(ball); // initiate computer AI for the computer paddle
scorelimit(ball); // check to see if either player reaches the score limit(10)
}
}
Main tab (a lot of code I know, sorry):
int userScore = 0; // variables for both scores in order to update it as points are scored
int cpuScore = 0;
int state = 0; // state of the game
boolean startgame = false; // boolean to make it so a button works to start the game scene
boolean help = false; // boolean to make it so a button works to display the help scene
boolean back = false; // boolean to make it so a button works to go back to main scene
boolean endofgame = false;
Ball ball; // declare Ball object
Paddle userP; // declare Paddle objects
Paddle cpuP;
void setup() {
// screen size
size(600, 400);
smooth();
frameRate(60);
//paddlehit = new SoundFile(this, "paddlehit.wav");
ball = new Ball(); // initialize Ball object to create a new ball
userP = new Paddle(15, 200); // initialize Paddle object to create two new paddles
cpuP = new Paddle(585, 200);
}
void draw() {
if (state == 0) {
mainScene();
}
if (state == 1) {
gameScene();
}
if (state == 2) {
helpScene();
}
if (startgame == true) {
state = 1;
}
if (help == true) {
state = 2;
}
if (back == true) {
state = 0;
}
if (endofgame == true) {
ball.restart();
}
// E - for (Ball2 b : ball2s) b.run(); // for loop to make all balls in arraylist to have functions located inside of run().
}
void scorelimit(Ball b) { // endgame for when someone reaches the score limit
if (userScore >= 1) {
b.x = width/2;
b.y = height/2;
b.xspeed = 0;
b.yspeed = 0;
fill(0, 75, 255);
textSize(24);
textAlign(CENTER);
text("You win!", width/2-140, height/2);
textSize(20);
fill(0);
text("Press ENTER to restart", width/2+150, height/2-100);
} else if (cpuScore >= 1) {
b.x = width/2;
b.y = height/2;
b.xspeed = 0;
b.yspeed = 0;
fill(255, 0, 75);
textSize(24);
text("CPU wins..", width/2+140, height/2);
textSize(20);
fill(0);
text("Press ENTER to restart", width/2-150, height/2-100);
}
}
void mainScene() {
background(255);
fill(0); // border around main scene
strokeWeight(3);
line(0, 0+1, width, 0+1);
line(0, height-2, width, height-2);
line(0+1, 0, 0+1, height);
line(width-2, 0, width-2, height);
textSize(64); // title
textAlign(CENTER);
strokeWeight(1);
text("Pong", width/2, 70);
// buttons for start / how to play
fill(175);
stroke(0);
rectMode(CENTER);
rect(width/2, 130, 160, 50);
rect(width/2, 210, 200, 50);
// text for buttons
fill(0);
textSize(32);
text("Start", width/2, 140);
text("How to play", width/2, 220);
}
void gameScene() {
background(255);
// line to divide the two sides
strokeWeight(3);
line(width/2, 0, width/2, height);
fill(0);
textSize(20);
textAlign(CENTER);
text("User Score:", 78, 25); // text for the scores
text("CPU Score:", 493, 25);
text(userScore, 147, 25); // text for the numbers, currently set at “0”, but will update later
text(cpuScore, 558, 25);
ball.move(); // move the ball
ball.display(); // display the ball
ball.checkEdges(); // check if the ball is reaching the top or bottom so it bounces off rather than going off the screen
userP.display(); // display the paddles
cpuP.display();
userP.moveY(mouseY); // move the user’s paddle vertically with the mouse’s y position
ball.isUserPHit(userP); // detect if either paddle comes in contact with the ball
ball.isCPUPHit(cpuP);
cpuP.cpuAI(ball); // initiate computer AI for the computer paddle
scorelimit(ball); // check to see if either player reaches the score limit(10)
}
void helpScene() {
rectMode(CENTER);
background(255); // set background to white
fill(175); // grey fill
strokeWeight(1);
stroke(0);
rect(525, 35, 80, 30); // back button
textSize(16);
textAlign(CENTER);
fill(0);
text("BACK", 525, 40);
fill(0); // border around edges
strokeWeight(3);
line(0, 0+1, width, 0+1);
line(0, height-2, width, height-2);
line(0+1, 0, 0+1, height);
line(width-2, 0, width-2, height);
textAlign(CENTER); // title
textSize(48);
text("How to Play", width/2, 50);
textAlign(LEFT);
textSize(10);
// information on game and how to play
text("- In Pong, you control one paddle and you typically play against another user or a computer controlled paddle.", 15, 90);
text("- In this version there is a computer controlled paddle that you play against.", 15, 120);
text("- You control your own paddle on the right side with your mouse's y position, mouse your mouse up/down to move it.", 15, 150);
text("- Once you or the computer reach the score limit(10), it will end the game.", 15, 180);
text("- The ball bounces off at different angles based off where it hits the paddle.", 15, 210);
text("- Higher on paddle, bounces higher off paddle, lower on paddle, bounces lower off paddle.", 15, 240);
text("- Make sure the ball doesn't go past your paddle, and try to get it by your opponents' paddle.", 15, 270);
text("- P.S - as of now the computer can't lose so don't try too hard.", 15, 300);
textSize(30);
textAlign(CENTER);
text("* Move the mouse to move the paddle *", width/2, 350);
disPaddle(); // display the paddle
}
void disPaddle() { // function to display the paddle
rectMode(CENTER);
fill(0);
rect(x, y, w, h);
y = constrain(mouseY, 0 + h/2, height - h/2); // constrain the paddle so it doesn't go off the screen
}
/* E - void mousePressed() {
ball2s.add(new Ball2(mouseX, mouseY)); // add balls to arraylist when the mouse is pressed at the mouseX/Y locations
}
*/
void mouseClicked() {
if (state == 0) {
if (mouseX >= 240 && mouseX <= 360 && mouseY >= 105 && mouseY <= 155) { // if the mouse is pressed within the button "Start" while the state is 0, change startgame to true
startgame = true;
} else if (state == 0) {
if (mouseX >= 200 && mouseX <= 400 && mouseY >= 185 && mouseY <= 235) { // if the mouse is pressed within the button "How to Play" while the state is 0, change help to true
help = true;
}
}
}
if (state == 2) {
if (mouseX >= 485 && mouseX <= 565 && mouseY >= 20 && mouseY <= 50) { // if the mouse is clicked within the button "BACK" while the state is 2, change back to true
back = true;
}
}
}
void keyPressed() {
if (state == 1) {
if (key == ENTER || key == RETURN) {
endofgame = true;
}
}
}
Answers
Your code should look like this:
I don't know why you have your restart() function inside your Ball class. I don't know why your restart() function is checking the positions of paddles.
In restart you have to set also the state and
Set endofgame to false etc.
And the other variables
Appreciate the help, I also have a problem where the if command in the mousePressed() function where it is supposed to go back to the main scene if the mouse is pressed within the "back" button in scene 2. But when I press it, it goes back to the main scene but doesn't allow me to then click the other two buttons in the main scene, so I have to restart the sketch, I was wondering if there's just something I need to put in there to give the other buttons their functionality back after back is set to true.
(EDITED) Fixed it, just set other booleans to false in other if statements
You have state architecture in your sketch which is good
But you are using additional variables you could also cover by the variable state: startgame, help and back namely.
You can also name your states
and then use those as values of
state
also use
switch
in draw: