我怎样才能避免 keyPressed 方法使我在 Processing 3 中永久绘制?

How can I avoid keyPressed method to make my draw permenant in Processing 3?

我正在尝试创建 HangMan 游戏,因为这是一项作业。在 game() 方法中,如果玩家输入错误,我想从 dead class 调用一些方法。这些方法创建了 HangMan。当我输入一个错误的字母并按 Enter(增加 numWrong)时,相关方法被调用但仅闪烁并消失。我知道它是因为 keyPressed 方法,但我怎样才能在屏幕上绘制 HangMan 并使其永久保留到游戏结束。

String[] words = {"dictionary","game","player","result"};
char[] strChar, guessed, wrong;

float x, y;
String str, display, display2, typing="", guess="", win = "", lost = "", wrongAnswers;
int rnd, c, numRight=0, winner=0, numWrong=0;

void setup() {
  size(800, 800); 
  surface.setLocation(960, 0);

  x = width;
  y = height;

  rnd = words.length-1;  
  str = words[(int)random(rnd)].toUpperCase();
  strChar = new char[str.length()];

  winner = str.length();

  guessed = new char[str.length()];

  for (int c=0; c<str.length(); c++) {
    strChar[c] = str.charAt(c);
    guessed[c] = '_';
  }

  wrong = new char[6];
  for (int i=0; i<wrong.length; i++) {
    wrong[i] = '*';
  }
}

void draw() {
  background(10);

  display = "Write a letter then press ENTER.";
  display2 = " ";
  wrongAnswers = "Incorrect Guesses: ";  

  for (int d=0; d<guessed.length; d++) {
    display2 = display2 +" "+guessed[d];
  }

  for (int i=0; i<wrong.length; i++) {
    wrongAnswers = wrongAnswers+" "+wrong[i];
  }

  fill(255);
  textSize(40);
  text(display2, 40, 750);

  textSize(20);
  text(display, 450, 380);

  textSize(250);
  text(typing.toUpperCase(), 450, 245);

  strokeWeight(1);
  d.gallows(); 

  fill(55, 200, 155);
  textSize(50);
  text(win, 110, 680);
  textSize(50);
  text(lost, 110, 680);
  textSize(20);
  text(wrongAnswers, 410, 690);

  //origins
  stroke(100, 150, 200);
  strokeWeight(2);
  line(0, 700, x, 700);//seperate line
  line(x/2, 0, x/2, 700);//vertical line
  line(x/2, y/2, x, y/2);//horizontal line

  fill(255);
  textSize(35);
  text(str, 90, 560);
}

void game(String guess) {
  guess = guess.toUpperCase();
  char myGuess = guess.charAt(0);
  boolean guessedRight = false;

  for (int m=0; m<str.length(); m++) {    
    if (myGuess==str.charAt(m)) {      
      if (exist(display2, myGuess)) {
        guessed[m] = myGuess;
        numRight++;
        guessedRight = true;
      } 
      if (numRight == winner) {        
        win = "YOU WIN!!";
      }
    }
  }
  if (guessedRight == false) {
    wrong[numWrong] = myGuess;
    numWrong++;

    noStroke();
    fill(255);

    if (numWrong==1) {
      d.headAndRope();
    } 
    if (numWrong==2) { 
      d.body(); 
      d.headAndRope();
    }  
    if (numWrong==3) { 
      d.leftArm(); 
      d.body(); 
      d.headAndRope();
    }  
    if (numWrong==4) {
      d.rightArm(); 
      d.leftArm(); 
      d.body(); 
      d.headAndRope();
    }  
    if (numWrong==5) {
      d.leftLeg(); 
      d.rightArm(); 
      d.leftArm(); 
      d.body(); 
      d.headAndRope();
    }  
    if (numWrong==6) {
      d.rightLeg(); 
      d.leftLeg(); 
      d.rightArm(); 
      d.leftArm(); 
      d.body(); 
      d.headAndRope();
    }

    if (numWrong == wrong.length) {
      lost = "YOU LOSE!!";
    }
  }
}

void keyPressed() {
  if (key == '\n') {
    game(typing);
    typing = "";    
  } else {    
    typing+=key;
  }
}

boolean exist(String sng, char cha) {
  for (int i=0; i<sng.length(); i++) {
    if (sng.charAt(i)==cha) {
      return false;
    }
  }  
  return true;
}

//DEAD CLASS

class Dead {

  void gallows() {   

    stroke(0);

    //base
    fill(127);
    rect(40, 600, 340, 30);

    //left vertical rect
    fill(200, 100, 50);
    rect(60, 50, 10, 550);

    //right vertical rect
    fill(100, 50, 25);
    rect(70, 50, 10, 550);

    //top horizontal rect
    fill(200, 100, 50);
    rect(60, 40, 300, 10);

    //bottom horizontal rect
    fill(100, 50, 25);
    rect(70, 50, 290, 10);

    //diagonal bottom rect
    fill(100, 50, 25);
    beginShape();
    vertex(80, 250);
    vertex(80, 265);
    vertex(265, 60);
    vertex(250, 60);
    endShape(CLOSE);

    //diagonal top rect
    fill(200, 100, 50);
    beginShape();
    vertex(70, 245);
    vertex(70, 260);
    vertex(260, 50);
    vertex(245, 50);
    endShape(CLOSE);
  }

  void headAndRope() {
    //rope
    fill(255);
    rect(300, 40, 2, 95);
    //head
    fill(255);
    ellipse(301, 155, 50, 75);
  }
  void body() {
    //body
    stroke(255);
    strokeWeight(3);
    line(301, 193, 301, 375);
  }
  void leftArm() {
    //left arm
    stroke(255);
    strokeWeight(2);
    line(301, 223, 251, 300);
  }
  void rightArm() {
    //right arm
    stroke(255);
    strokeWeight(2);
    line(301, 223, 351, 300);
  }
  void leftLeg() {
    //left leg
    stroke(255);
    strokeWeight(2);
    line(301, 375, 251, 450);
  }
  void rightLeg() {
    //right leg
    stroke(255);
    strokeWeight(2);
    line(301, 375, 351, 450);
  }
}

在处理过程中,每帧都会调用 draw 函数,完全重绘屏幕上的所有内容。因此,如果您希望刽子手始终出现在屏幕上,您需要在 draw 函数(或从 draw 调用的函数)中绘制它。

如果您稍微重组代码,一切都应该有效:

void draw() {
  // draw UI and input prompt based on `numRight` value
  // NEW: draw the current state of the hangman based on `numWrong` value
}

void game(String guess) {
  // update the game state (`numRight` and `numWrong` variables)
  // based on `guess` input
  // NEW: since this is only called momentarily, don't do any drawing here
}

void keyPressed() {
  // receive key input and pass it to `game`
}

由于 game 只会在用户输入猜测时立即调用,因此您不希望在其中进行任何绘图。它将在下一个 draw 周期中被覆盖。您仍然可以在 game 中更新游戏状态,但该游戏状态的绘图表示应该从 draw 开始,以确保每次屏幕更新时都会绘制它。