Restarting Game by using keyPressed() not working

edited April 2018 in Questions about Code

Hi, so I have an assignment where I have to create a game. I have succeeded in creating the game but I am having trouble with restarting the game. I currently have it so when you click the screen the game starts and you use the keys to move the character around the screen and when all of the enemies have been removed the game over screen appears but when I try to press a button to go back to the beginning again it does not work? I have tried adding in a restart() function having looked at other entries on the forum but none of those were using a class so it did not work for me. I really need help as this is due in under a week and I have spent several days trying to figure it out.

I am using processing version 3.3.5

The code is shown below:

PFont font;

int Score;
//int ScoreIncrease;

Alien oneAlien;

int numberofStars = 300;
Stars[] theStars = new Stars[numberofStars];

int numberOfEnemies = 2;
Enemy [] theEnemies = new Enemy[numberOfEnemies];
int enemySize = 30;

int enemiesRemaining = numberOfEnemies;

boolean GamePlaying = false;
boolean GameOver = true;

void setup(){
  size(1000,800);
  font = loadFont("Consolas-BoldItalic-48.vlw");

  oneAlien = new Alien (150,150, (int) random(width), (int) random(height));

  for(int loop = 0; loop<theStars.length; loop++){
    theStars[loop] = new Stars((int) random(width), (int) random(height), 5,5 ,30);
  }

  for(int loop = 0; loop<theEnemies.length; loop++){
    theEnemies[loop] = new Enemy((int) random(width), (int) random(height),enemySize);
  }

}//ends setup

void draw(){
  background(0);
  stroke(0);

//draws the stars for the background      
  for (int loop = 0; loop<theStars.length;loop++){
    theStars[loop].drawStars();
  }
  //sets what is to be shown on the screen when the game is not in play
  if(!GamePlaying){
    //print
    textFont(font,48);
    textAlign(CENTER);
    fill(0,250,0);
    text("Click the screen to start", width/2, height/2);
  }

  //sets what is shown when the game is in play
  if (GamePlaying) {
   text("Score = " + Score, 800,750);
   text("Time " + millis(), 150,750);
   oneAlien.drawHead();
   oneAlien.drawBody();
   oneAlien.drawEyes();
   oneAlien.drawSpots();
   oneAlien.Bounce();

  for(int loop = 0; loop < theEnemies.length; loop++) {
    theEnemies[loop].display();
  }

  for(int loop = 0; loop < theEnemies.length; loop++) {
    theEnemies[loop].move();
  }

  for(int loop = 0; loop < theEnemies.length; loop++) {
    if(theEnemies[loop].checkForOverlap(oneAlien)) {
      theEnemies[loop].Xloc = -100;
      theEnemies[loop].Yloc = -100;

      int timeBonus = int((20000.0 / millis()) * 15);
      Score = Score + 10 +timeBonus;
      enemiesRemaining --;
      if(enemiesRemaining == 0){
        //GameOverScreen();
        GameOver = !GameOver;
      }
      }
    }
   textSize(48);
   fill(255,0,0);
   text("Click screen to pause", width/2, height/16);

  }  //ends Game Playing instructions

  if (!GameOver){
    background(0);
    textSize(64);
    fill(0,128,0);
    text("You Won!", width/2 ,height/2);
    fill(255);
    text("Press Enter to play again" , width/2, height/2 + 120);
    text("Your score = "+Score, width/2, height/2 +200);
  }//ends Game Over instructions

}//ends draw
void restart(){
  GameOver = !GameOver;
  GamePlaying = !GamePlaying;
  Score = 0;
  setup();

}//ends restart


void mousePressed(){
  //check position
  GamePlaying = !GamePlaying;
}//ends mouse Pressed

void keyPressed(){
  if (key == CODED) {
    if(keyCode ==UP) {
       oneAlien.moveUp();
    };
    if(keyCode ==DOWN) {
      oneAlien.moveDown();
    };
    if(keyCode ==LEFT) {
      oneAlien.moveLeft();
    };
    if(keyCode ==RIGHT){
     oneAlien.moveRight(); 
    };
    if(keyCode ==ENTER) {
     restart();
     GameOver = !GamePlaying;
    };

    }//ends key==coded
}//ends key pressed

///////////first class/////////////

class Alien{

  //attributes
  int bodyW;
  int bodyH;
  int bodyXloc;
  int bodyYloc;

  int headW;
  int headH;
  int headXloc;
  int headYloc;

  int spotW;
  int spotH;
  int spotXloc;
  int spotYloc;

  int moveBy, moveBy2;

  Alien(){
    bodyW = 300;
    bodyH = 400;
    bodyXloc = 450;
    bodyYloc = 450;

    moveBy = 1;
    moveBy2 = 1;
  }//end Alien

  Alien(int bW, int bH, int xl, int yl){
    bodyW = bW;
    bodyH = bH;
    bodyXloc = xl;
    bodyYloc = yl;

    moveBy = 5;
    moveBy2 = 5;
  // do {
   //  moveBy = (int) random(-5,0);
   //  moveBy2 = (int) random(-5,5);
  // }while (moveBy == 0 || moveBy2 == 0);
  }//end

  void drawBody(){
    fill(66,149,244);
    rectMode(CENTER);
    rect(bodyXloc, bodyYloc, bodyW, bodyH);
  }//end draw body

  void drawHead(){
    fill(244,158,66);
    headW = bodyW / 2;
    headH = bodyH / 2;
    headXloc = bodyXloc;
    headYloc = (bodyYloc - (bodyH / 2) - (headH / 2));
    rect(headXloc, headYloc, headW, headH);
  }//ends draw head

  void drawEyes(){
    fill(0);
    rect (headXloc, headYloc, (headW/2), (headH/2));
    float r = random(255);
    float g = random(255);
    float b = random(255);
    fill(r,g,b);
    rect (headXloc, headYloc, (headW/4), (headH/4));    
  }//end eyes

  void drawSpots(){
    float r = random(255);
    float g = random(255);
    float b = random(255);
    fill(r,g,b);
    spotW = bodyW / 2;
    spotH = bodyH / 2;
    spotXloc = bodyXloc;
    spotYloc = (bodyYloc - (bodyH / 1500) - (spotH / 1500));
    ellipse(spotXloc, spotYloc, spotW, spotH);     
  }//end draw spots

  void Bounce(){
    //checking when hitting right side
    if(bodyXloc >= (width - (bodyW/2))){
      //moveBy = moveBy * -1;
      bodyXloc = (width - (bodyW/2));
    }

    //checking when hitting left side
    if(bodyXloc <= (0 +(bodyW / 2))){
     // moveBy = moveBy * -1;
     bodyXloc = (bodyW / 2);
    }

    //checking when hitting the top of screen
    if(bodyYloc >= (height - (bodyH/2))){
     // moveBy2 = moveBy2 * -1;
      bodyYloc = (height - (bodyH/2));
    }
    //checking when hitting the bottom of screen
    if(bodyYloc <= (0 +(bodyH / 2 +headH))){
      //moveBy2 = moveBy2 * -1
      bodyYloc = (bodyH / 2 +headH);
    }
  }//ends bounce

  void moveUp(){
    bodyYloc = bodyYloc - moveBy2;
  }//end moveUp

  void moveDown(){
    bodyYloc = bodyYloc + moveBy2;
  }//ends moveDown

  void moveLeft(){
   bodyXloc = bodyXloc - moveBy; 
  }//ends moveLeft

  void moveRight(){
    bodyXloc = bodyXloc + moveBy;
  }//ends moveRight

  void move(){
    bodyXloc = bodyXloc + moveBy;
    bodyYloc = bodyYloc + moveBy2;
  }//ends move

}//ends class


///////////starts a new class/////////////

class Enemy{

  //attributes
  int enemySize;
  int Xloc;
  int Yloc;
  int xSpeed, ySpeed;

  Enemy(int Xl, int Yl, int Size) {
    Xloc = Xl;
    Yloc = Yl;
    enemySize = Size;

    do{
      xSpeed = (int) random(-10,10);
      ySpeed = (int) random(-10,10);
    }while(xSpeed == 0 || ySpeed == 0);
  }//ends

  void display(){
    fill (255,247,0);
    ellipse(Xloc, Yloc, enemySize, enemySize);
  }//ends

  void move(){
    Xloc = Xloc + xSpeed;
    Yloc = Yloc + ySpeed;

    //checks to make sure that the object will bounce off the top and bottom of the screen
    if (Xloc > width - (enemySize / 2) || Xloc < 0 + (enemySize / 2)){
      xSpeed = xSpeed * -1;
    }

    //makes sure that the enemy bounces on the sides of the screen
    if (Yloc > height - (enemySize / 2) || Yloc < 0 + (enemySize / 2)){
      ySpeed = ySpeed * -1;
    }

  }//ends

  boolean checkForOverlap(Alien oneAlien){
    //System.out.println("Alien x is " +Xloc);
    //System.out.println("Alien y is " +Yloc);    
    //System.out.println("Enemy x is " +oneAlien.bodyXloc);  
    //System.out.println("Enemy y is " +oneAlien.bodyXloc);


    int alienX = oneAlien.bodyXloc;
    int alienY = oneAlien.bodyYloc;

    int distanceApart = (int) dist(Xloc, Yloc, alienX, alienY);
    //System.out.println(distanceApart);

    if (distanceApart >(enemySize / 2) + (oneAlien.bodyW / 2) + (oneAlien.headW)){
     // System.out.println("Miss");
      return false;
    }
    else {
     // System.out.println("Crash");
     return true; 
    }

  }//end check for overlap

}//ends class

////////////starts last class/////////////

class Stars{

  int starX;
  int starY;
  int starSize;
  int starWidth;
  int starHeight;


  Stars(){
    starSize = 5;
  }

  Stars(int sX, int sY, int sW, int sH, int size){
   starX = sX;
   starY = sY;
   starWidth = sW;
   starHeight = sH;
   starSize = size;
  }

  void drawStars(){
    fill(255);
    ellipse(starX, starY, starWidth, starHeight);
  }
}//end of the class
Tagged:

Answers

  • Thanks for your answer, I am unclear as to what I need to do to fix my problem, maybe you could explain a bit more?

  • (that was a spam link. deleted)

  • Oh thanks koogs, thankfully I hadn't actually clicked on the link

  • don't call setup() from within your code (line 106). it does a lot of things that should only be done once.

    instead, move all the initialisation code into a separate method and call that from setup() and from where you want to re-init your structures.

  • Okay so I've made the changes you have suggested and it is still not helping me get from the GameOver part back to the original screen so that the game restarts. I think it will be something I have done in lines 102-106 or 130-133 but I just don't know what to do to fix it

  • Here's a working example. You can put your code into this.

    boolean paused;
    boolean gameover;
    int counter;
    
    void setup(){
      size(400,400);
      reset();
    }
    
    void reset(){
      paused = true;
      gameover = false;
      counter = 500;
    }
    
    void draw(){
      background(0);
      if( gameover ){
        text("Gameover", 20, 20);
        text("Press Enter to replay!", 20, 120);
      } else {
        if( paused ){
          text("Paused", 20, 20);
          text("Click to unpause.", 20, 120);
        } else {
          text("Playing", 20, 20);
          text("Click to pause.", 20, 120);
          text("Game ends when this counter hits zero:  " + counter, 20, 220);
          counter--;
          if(counter <= 0){
            gameover = true;
          }
        }
      }
    }
    
    void mousePressed(){
      if( !gameover ){
        paused = !paused;
      }
    }
    
    void keyPressed(){
      if( gameover ){
        reset();
      }
    }
    
  • edited April 2018

    thank you for your help TfGuy44. I have inserted my code into your example and it now goes back to the 'game paused' (i.e. the original screen) but when I am moving around my Alien character with the arrow keys and I finish the game the gameover screen only flashes up for a moment before going back to the 'game paused' screen. As well as this when I then click the screen to restart the ending of the game does not work? (basically when trying to play the game a second time it does not work). I also have the problem that my 'Stars' no longer display?

    I have inserted my code for the first screen (I have not included the Classes again as they have not been changed since the original question was asked.)

    PFont font;
    
    int Score;
    
    Alien oneAlien;
    
    int numberofStars = 300;
    Stars[] theStars = new Stars[numberofStars];
    
    int numberOfEnemies = 2;
    Enemy [] theEnemies = new Enemy[numberOfEnemies];
    int enemySize = 30;
    
    int enemiesRemaining = numberOfEnemies;
    
    
    boolean paused;
    boolean gameover;
    int counter;
    
    void setup(){
      size(1000,800);
      font = loadFont("Consolas-BoldItalic-48.vlw");
      reset();
    }
    
    void reset(){
      paused = true;
      gameover = false;
      counter = 3000;
      createCharacters();
      Score = 0;
    }
    
    void draw(){
      background(0);
    
      if( gameover ){
       for(int loop = 0; loop<theStars.length; loop++){
        theStars[loop] = new Stars((int) random(width), (int) random(height), 5,5 ,30);
       }
        fill(0,128,0);
        text("You Won!", width/2 ,height/2);
        fill(255);
        text("Press Enter to play again" , width/2, height/2 + 120);
        text("Your score = "+Score, width/2, height/2 +200);
      } else {
        if( paused ){
          for(int loop = 0; loop<theStars.length; loop++){
            theStars[loop] = new Stars((int) random(width), (int) random(height), 5,5 ,30);
          }
          textFont(font,48);
          textAlign(CENTER);
          fill(0,250,0);
          text("Click the screen to start", width/2, height/2);
        } else {
          for(int loop = 0; loop<theStars.length; loop++){
            theStars[loop] = new Stars((int) random(width), (int) random(height), 5,5 ,30);
          }
          text("Score = " + Score, 800,750);
          text("Time " + millis(), 150,750);
          oneAlien.drawHead();
          oneAlien.drawBody();
          oneAlien.drawEyes();
          oneAlien.drawSpots();
          oneAlien.Bounce();
    
         for(int loop = 0; loop < theEnemies.length; loop++) {
            theEnemies[loop].display();
         }
    
         for(int loop = 0; loop < theEnemies.length; loop++) {
            theEnemies[loop].move();
         }
           for(int loop = 0; loop < theEnemies.length; loop++) {
        if(theEnemies[loop].checkForOverlap(oneAlien)) {
          theEnemies[loop].Xloc = -100;
          theEnemies[loop].Yloc = -100;
    
          //speedBonus = theEnemies.xSpeed; theEnemies.ySpeed;
          int timeBonus = int((20000.0 / millis()) * 15);
          Score = Score + 10 +timeBonus;
          enemiesRemaining --;
          if(enemiesRemaining == 0){
            //GameOverScreen();
            gameover = !gameover;
          }
          }
        }
       textSize(48);
       fill(255,0,0);
       text("Click screen to pause", width/2, height/16);
    
    
         counter--;
         if(counter <= 0){
           gameover = true;
          }
        }
      }
    }//ends draw
    
    void createCharacters(){
      oneAlien = new Alien (150,150, (int) random(width), (int) random(height));
    
      for(int loop = 0; loop<theStars.length; loop++){
        theStars[loop] = new Stars((int) random(width), (int) random(height), 5,5 ,30);
      }
    
      for(int loop = 0; loop<theEnemies.length; loop++){
        theEnemies[loop] = new Enemy((int) random(width), (int) random(height),enemySize);
    }//ends create characters
    }
    
    void mousePressed(){
      if( !gameover ){
        paused = !paused;
      }
    }//ends mouse pressed
    
    void keyPressed(){
      if( gameover ){
        reset();
      }
      if (key == CODED) {
        if(keyCode ==UP) {
           oneAlien.moveUp();
        };
        if(keyCode ==DOWN) {
          oneAlien.moveDown();
        };
        if(keyCode ==LEFT) {
          oneAlien.moveLeft();
        };
        if(keyCode ==RIGHT){
         oneAlien.moveRight(); 
        };  
    }
    }//ends key pressed
    
  • edited April 2018

    @PF201 -- in general, when you are having trouble restarting that means you have some state that isn't being reset.

    Often that state is in a global variable or object that you forgot to reinitialize.

    For example, all of these things seem like they should happen at the beginning of a game:

    int numberofStars = 300;
    Stars[] theStars = new Stars[numberofStars];
    int numberOfEnemies = 2;
    Enemy [] theEnemies = new Enemy[numberOfEnemies];
    int enemySize = 30;
    int enemiesRemaining = numberOfEnemies;
    ...
    

    Unless they are CONSTANTS, declare them (without defining them) in the header, then define them in reset. If they are constants, name them in all caps and prefix them with final.

    For example: whenever reset happens, do you always set boolean paused to false? Should you?

  • edited April 2018 Answer ✓

    There's no need to cram everything into one place. I took some time to put logical sections of your code into functions, and now it runs much smoother:

    PFont font;
    
    int Score;
    
    Alien oneAlien;
    
    int numberofStars = 300;
    Stars[] theStars = new Stars[numberofStars];
    
    int numberOfEnemies = 2;
    Enemy [] theEnemies = new Enemy[numberOfEnemies];
    int enemySize = 30;
    
    int enemiesRemaining;
    boolean paused;
    boolean gameover;
    
    void setup() {
      size(1000, 800);
      //font = loadFont("Consolas-BoldItalic-48.vlw");
      textSize(48);
      reset();
    }
    
    void reset() {
      paused = true;
      gameover = false;
      createCharacters();
      Score = 0;
      enemiesRemaining = numberOfEnemies;
    }
    
    void draw() {
      background(0);
      draw_stars();
      if ( gameover ) {
        draw_gameover();
      } else {
        if ( paused ) {
          draw_paused();
        } else {
          draw_playing();
        }
      }
    }
    
    void draw_stars() {
      for (int loop = 0; loop<theStars.length; loop++) {
        theStars[loop].drawStars();
      }
    }
    
    void draw_gameover() {
      fill(0, 128, 0);
      text("You Won!", width/2, height/2);
      fill(255);
      text("Press Enter to play again", width/2, height/2 + 120);
      text("Your score = "+Score, width/2, height/2 +200);
    }
    
    void draw_paused() {
      //textFont(font, 48);
      textAlign(CENTER);
      fill(0, 250, 0);
      text("Click the screen to start", width/2, height/2);
    }
    
    void draw_alien_parts() {
      oneAlien.drawHead();
      oneAlien.drawBody();
      oneAlien.drawEyes();
      oneAlien.drawSpots();
      oneAlien.Bounce();
    }
    
    void move_enemies() {
      for (int loop = 0; loop < theEnemies.length; loop++) {
        theEnemies[loop].move();
      }
    }  
    
    void draw_enemies() {
      for (int loop = 0; loop < theEnemies.length; loop++) {
        theEnemies[loop].display();
      }
    }
    
    void collision_with_enemies() {
      for (int loop = 0; loop < theEnemies.length; loop++) {
        if (theEnemies[loop].checkForOverlap(oneAlien)) {
          theEnemies[loop].Xloc = -100;
          theEnemies[loop].Yloc = -100;
          //speedBonus = theEnemies.xSpeed; theEnemies.ySpeed;
          int timeBonus = int((20000.0 / millis()) * 15);
          Score = Score + 10 +timeBonus;
          enemiesRemaining --;
        }
      }
    }
    
    void check_for_gameover() {
      if (enemiesRemaining == 0) {
        gameover = true;
      }
    }
    
    void draw_playing() {
      text("Score = " + Score, 800, 750);
      text("Time " + millis(), 150, 750);
      draw_alien_parts();
      move_enemies();
      draw_enemies();
      collision_with_enemies();
      check_for_gameover();
    }
    
    void createCharacters() {
      oneAlien = new Alien (150, 150, (int) random(width), (int) random(height));
    
      for (int loop = 0; loop<theStars.length; loop++) {
        theStars[loop] = new Stars((int) random(width), (int) random(height), 5, 5, 30);
      }
    
      for (int loop = 0; loop<theEnemies.length; loop++) {
        theEnemies[loop] = new Enemy((int) random(width), (int) random(height), enemySize);
      }
    }
    
    void mousePressed() {
      if ( !gameover ) paused = !paused;
    }
    
    void keyPressed() {
      if (key == CODED) {
        if (keyCode == UP) oneAlien.moveUp();
        if (keyCode == DOWN) oneAlien.moveDown();
        if (keyCode == LEFT) oneAlien.moveLeft();
        if (keyCode == RIGHT) oneAlien.moveRight();
      }
      if ( gameover && ( key == ENTER || key == RETURN ) ) {
        reset();
      }
    }
    

    Classes ommitted as they are unchanged.

    There were a couple of problems. You had the check for gameover inside the loop for enemy collisions, and since it was doing a toggle (gameover = !gameover;), this might have been causing trouble. It's much clearer to just set it directly (gameover = true;).

    You were drawing your stars no matter what state the game was in, so it makes more sense to have the draw_stars() function called once, before messing about with the game states. Also your stars were not displaying because you copied the loop that created the positions for the stars, not the one that called Star::drawStars()to draw your stars (which might be better named Star::drawStar(), since it only draws one star.)

    I didn't have your font so I removed it. General code cleanups here and there too. EnemiesRemaining needed to be reset to the starting value inside reset().

    Notice how much easier it is to understand what your draw() function is actually doing now!

  • Wow thank you TfGuy44, that's really helpful! much appreciated, its working now :

Sign In or Register to comment.