Игра в понг в обработке - проблемы с 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, что позволяет считать, что они были нажаты и затем отпущены одновременно время.
Единственный совет, который я могу вам дать, - это выполнить процесс отладки, чтобы увидеть, где ваша ошибка.