Игра в понг в обработке - проблемы с keyPressed() и keyReleased()

У меня проблемы с программированием игры в понг в процессинге, которая сводит меня с ума. Сначала весла работают нормально. Но через некоторое время они не отвечают и блокируются, казалось бы, наугад. Я вставил некоторый код, чтобы увидеть, что было не так, и программе иногда не удается зарегистрировать keyPressed(), но она напечатает keyReleased(), когда я отпущу ключ. Я проверил другие темы и не знаю, что происходит. (Для домашней работы, но наш инструктор рекомендует размещать на переполнении стека.)

Вот пример журнала. Последняя строка - это проблема. Я нажал "d" и выпустил его. Обратите внимание, что "d" отображается как отпущенный, но не нажатый. Это не имеет смысла для меня...

НАЖМИТЕ КЛАВИШУ: d

КЛЮЧ ВЫПУЩЕН: d

НАЖМИТЕ КЛАВИШУ:

КЛЮЧ ВЫПУЩЕН:

КЛЮЧ ВЫПУЩЕН: d

Редактировать Я на самом деле просто пошел и установил мои настройки "Key Repeat" на "Off", и это, похоже, решило проблему! (Я на macOS Sierra.) Почему это может быть? Могу ли я изменить свой код, чтобы эта ошибка не повлияла ни на кого другого?

// Pong Game
// Starter Code
import java.util.*;

Ball ball;
Paddle paddle1;
Paddle paddle2;
HeadsUp hup;

boolean right;
boolean left;
boolean a;
boolean d;

void setup() {
  frameRate(100);
  size(300, 600);
  hup = new HeadsUp();
  paddle1 = new Paddle();
  paddle2 = new Paddle();
  paddle2.setY(height * .05);
  ball = new Ball();
}

public void keyPressed() {
  println("KEY PRESSED: " + key);
  changeDirection(true);
}

public void keyReleased() {
  println("KEY RELEASED: " + key); 
  changeDirection(false);
}

public void changeDirection(boolean val) {
    if (keyCode == LEFT) {
    left = val;
  }
  if (keyCode == RIGHT) {
    right = val;
  }
  if (key == 'a' || key == 'A') {
    a = val;
  }
  if (key == 'd' || key == 'D') {
    d = val;
  }
}

private void updatePaddles(){
  if (left) {
    paddle1.moveLeft();
  }
  if (right) { 
    paddle1.moveRight();
  }
  if (a) {
    paddle2.moveLeft();
  }
  if (d) {
    paddle2.moveRight();
  }
}



void draw() {
  if (!hup.isGameOver()) {
    background(0);
    updatePaddles();
    paddle1.draw();
    paddle2.draw();
    hup.draw();
    ball.draw();
    if (ball.update(hup, paddle1, paddle2)) { 
      ball = new Ball();  
    }
  }
  else {
    stop();
  }
}


void stop(){
  background(0);
  noLoop();
  PFont f = createFont("Menlo", 16, true);
  textFont(f);
  fill(255);
  text("GAME OVER!", 100, 300);
  if (hup.p1BallsLeft != 0) {
    text("Player One Wins!", 80, 350);
  } else {
    text("Player Two Wins!", 80, 350);
  }
}

class Paddle {
  float x;
  float y;
  float w;
  float h;
  
  Paddle() {
    w = 75;
    h = 15;
    x = width / 4;
    y = height * .9;
  }
  
  public void setY(float y) {
    this.y = y;
  }
  
  public void moveLeft() {
    if (x >= 0) x -= 2;
  }
  
  public void moveRight() {
    if (x < 225) x += 2;
  }
    
  private void draw() {
      fill(255);
      rect(x, y, w, h, 0.1, 0.1, 0.1, 0.1);
  }
}

class Ball {
  PVector position;
  PVector velocity;
  static final int BALL_WIDTH = 16;
  static final int BALL_HEIGHT = 16;
  static final int BALL_RADIUS = BALL_WIDTH / 2;
  
  
  Ball() {
    Random rand = new Random();
    boolean direction = rand.nextBoolean();
    float vel = 2;
    if (direction) vel *= -1;
    position = new PVector(rand.nextInt(300), 300);
    velocity = new PVector(2, vel);
  }
  
  boolean update(HeadsUp hup, Paddle paddle1, Paddle paddle2) {
    position.add(velocity);
    if (position.y > height) {
      hup.update(1);
      return true;
    }
    if (position.y < 0) {
      hup.update(2);
      return true;
    }
    checkIfHitWall();
    if (velocity.y > 0) checkIfHitPaddle(paddle1);
    else checkIfHitPaddle(paddle2);
    return false;
}
  
  void draw() {
      fill(#ffff00);
      ellipse(position.x, position.y, BALL_WIDTH, BALL_HEIGHT);
  }
  
  void checkIfHitWall() {
    if ((position.x > width) || (position.x < 0)) {
      velocity.x *= -1;
    }
    if (position.y < 0) {
      velocity.y *= -1;
    }
  }
  
  void checkIfHitPaddle(Paddle paddle) {
    
    float distX = Math.abs(position.x - paddle.x - paddle.w / 2);
    float distY = Math.abs(position.y - paddle.y - paddle.h /2);
    boolean check = false;
    if (distX > (paddle.w / 2 + BALL_RADIUS)) { return; }
    if (distY > (paddle.h / 2 + BALL_RADIUS)) { return; }
    if (distX <= (paddle.w/2)) { check = true; } 
    if (distY <= (paddle.h/2)) { check = true; }
    float dx = distX - paddle.w / 2;
    float dy = distY - paddle.h / 2;
    if (dx * dx + dy * dy <= (BALL_RADIUS * BALL_RADIUS)) check = true;
    if (check) {
      velocity.y *= -1;
    }
  }
}

class HeadsUp {
  int p1BallsLeft;
  int p2BallsLeft;
  boolean gameOver;
  
  HeadsUp() {
    p1BallsLeft = 3;
    p2BallsLeft = 3;
    gameOver = false;
  }
  
  void draw() {
    text("Player 1 Balls Left: " + p1BallsLeft + "\nPlayer 2 Balls Left: " + p2BallsLeft, 125, 300 );
  }
  
  void update(int player) {
    if (player == 1) {  
      p1BallsLeft--;
    }
    if (player == 2) {
      p2BallsLeft--;
    }
    if (p1BallsLeft == 0 || p2BallsLeft == 0) gameOver = true;
    if (!hup.isGameOver()) {
    }
  }
  
  boolean isGameOver() {
    
    return gameOver;
  }
}

1 ответ

Я взял твой код и запустил его, чтобы выяснить проблему, и твоя проблема определенно не в keyReleased() функция. Когда вы нажимаете клавишу и затем отпускаете ее, она должна сказать это только один раз, когда я нажимала кнопки a и s, получилось так:

НАЖМИТЕ КЛАВИШУ:

НАЖМИТЕ КЛАВИШУ: s

НАЖМИТЕ КЛАВИШУ:

НАЖМИТЕ КЛАВИШУ: s

Теперь я полагаю, что ваша программа думает, что, поскольку клавиши a и s были нажаты, а затем отпущены одновременно, предполагается, что я нажал клавиши a и s, что позволяет считать, что они были нажаты и затем отпущены одновременно время.

Единственный совет, который я могу вам дать, - это выполнить процесс отладки, чтобы увидеть, где ваша ошибка.

Другие вопросы по тегам