2016-08-17 2 views
0

Я довольно новичок в программировании, и я работал над игрой с двумя игроками Pong с JavaFX. Один игрок использует W/S для перемещения своего «весла», а другой игрок использует стрелки вверх/вниз для своего. Проблема, которую я сохраняю, состоит в том, что только один игрок может перемещать свое весло за раз. Я не могу понять, как это сделать, чтобы они могли перемещать свои отдельные весла одновременно. У меня был один обработчик событий клавиатуры, управляющий обоими веслами, я думал, что это проблема. Я сделал два отдельных обработчика клавиатуры, но получил еще один набор проблем, которые, как я думаю, вызваны встроенными методами setFocusTraversable. Я надеюсь, что то, что я пытаюсь сделать, имеет смысл. Есть идеи?Перемещение двух прямоугольников с клавиатурой в Javafx

import javafx.event.EventHandler; 
import javafx.scene.Group; 
import javafx.scene.canvas.Canvas; 
import javafx.scene.canvas.GraphicsContext; 
import javafx.scene.input.KeyCode; 
import javafx.scene.input.KeyEvent; 
import javafx.scene.paint.Color; 
import javafx.scene.paint.Paint; 
import javafx.scene.shape.Rectangle; 


public class Game{ 

Rectangle leftPaddle; 
double leftPaddleY = 260; 

Rectangle rightPaddle; 
double rightPaddleY = 260; 

public void createGame(Group gameDisplay){ 

    //creates background 
    Rectangle background = new Rectangle(0,0,800,600); 
    background.getStyleClass().add("background"); 

    //draws field lines 
    Canvas game = new Canvas(800, 600); 
    GraphicsContext gc = game.getGraphicsContext2D(); 
    gc.setStroke(Paint.valueOf("WHITE")); 
    gc.setLineWidth(5); 
    gc.strokeLine(400, 0, 400, 600); 
    gc.strokeOval(300, 200, 200, 200); 
    gc.strokeRect(0, 150, 100, 300); 
    gc.strokeRect(700, 150, 100, 300); 
    gc.setStroke(Paint.valueOf("BLACK")); 
    gc.setLineWidth(8); 
    gc.strokeRect(0, 0, 800, 600); 

    //creates red paddle 
    leftPaddle = new Rectangle(30, leftPaddleY, 20, 70); 
    leftPaddle.setOnKeyPressed(paddleMovement); 
    leftPaddle.setFocusTraversable(true); 
    leftPaddle.setFill(Color.RED); 

    //creates blue paddle 
    rightPaddle = new Rectangle(750, rightPaddleY, 20, 70); 
    rightPaddle.setOnKeyPressed(paddleMovement); 
    rightPaddle.setFocusTraversable(true); 
    rightPaddle.setFill(Color.BLUE); 


    gameDisplay.getStylesheets().add(getClass().getResource("GameDisplay.css").toExternalForm()); 
    gameDisplay.getChildren().addAll(background, game, leftPaddle, rightPaddle); 
} 

public EventHandler<KeyEvent> paddleMovement = new EventHandler<KeyEvent>(){ 

    @Override 
    public void handle(KeyEvent event) { 

     //red paddle movement 
     if(event.getCode().equals(KeyCode.W)){ 
      leftPaddle.setY(leftPaddleY -= 6); 
      if(leftPaddle.getY() < 0){ 
       leftPaddle.setY(0); 
       leftPaddleY = 0; 
      } 
     } 
     if(event.getCode().equals(KeyCode.S)){ 
      leftPaddle.setY(leftPaddleY += 6); 
      if(leftPaddle.getY() < 0){ 
       leftPaddle.setY(0); 
       leftPaddleY = 0; 
      } 
     } 

     //blue paddle movement 
     if(event.getCode().equals(KeyCode.UP)){ 
      rightPaddle.setY(rightPaddleY -= 6); 
      if(rightPaddle.getY() < 0){ 
       rightPaddle.setY(0); 
       rightPaddleY = 0; 
      } 
     } 
     if(event.getCode().equals(KeyCode.DOWN)){ 
      rightPaddle.setY(rightPaddleY += 6); 
      if(rightPaddle.getY() < 0){ 
       rightPaddle.setY(0); 
       rightPaddleY = 0; 
      } 
     } 

    } 
}; 
} 

ответ

2

keyPressed событие будет срабатывать только раз для последнего нажатия клавиши.

Чтобы обойти это, просто «запомните» желаемое движение для каждого весла и прислушайтесь к событию keyReleased. Вы можете выполнять движения с помощью AnimationTimer для выполнения обновлений каждого кадра (вместо этого вы можете использовать Timeline, чтобы иметь больше контроля над частотой обновлений).

Кроме того, я рекомендую немного ограничивать видимость переменных-членов, поскольку обычно вы не хотите, чтобы другие классы могли напрямую писать поля вашего класса. Также я рекомендую обрабатывать события в одном Node. Только один Node может иметь фокус за раз, и обработка события в разных местах приводит к дублированию кода.

public class Game { 

    private Rectangle leftPaddle; 
    private double leftPaddleY = 260; 

    private Rectangle rightPaddle; 
    private double rightPaddleY = 260; 

    private double leftPaddleDY; 
    private double rightPaddleDY; 
    private AnimationTimer timer = new AnimationTimer() { 

     @Override 
     public void handle(long now) { 
      // update paddle positions 
      leftPaddleY += leftPaddleDY; 
      rightPaddleY += rightPaddleDY; 
      if (leftPaddleY < 0) { 
       leftPaddleY = 0; 
      } 
      if (rightPaddleY < 0) { 
       rightPaddleY = 0; 
      } 

      leftPaddle.setY(leftPaddleY); 
      rightPaddle.setY(rightPaddleY); 
     } 

    }; 

    public void createGame(Group gameDisplay) { 

     //creates background 
     Rectangle background = new Rectangle(0, 0, 800, 600); 
     background.getStyleClass().add("background"); 

     //draws field lines 
     Canvas game = new Canvas(800, 600); 
     GraphicsContext gc = game.getGraphicsContext2D(); 
     gc.setStroke(Paint.valueOf("WHITE")); 
     gc.setLineWidth(5); 
     gc.strokeLine(400, 0, 400, 600); 
     gc.strokeOval(300, 200, 200, 200); 
     gc.strokeRect(0, 150, 100, 300); 
     gc.strokeRect(700, 150, 100, 300); 
     gc.setStroke(Paint.valueOf("BLACK")); 
     gc.setLineWidth(8); 
     gc.strokeRect(0, 0, 800, 600); 

     //creates red paddle 
     leftPaddle = new Rectangle(30, leftPaddleY, 20, 70); 
     leftPaddle.setFill(Color.RED); 

     //creates blue paddle 
     rightPaddle = new Rectangle(750, rightPaddleY, 20, 70); 
     rightPaddle.setFill(Color.BLUE); 

     // register event handlers to Canvas 
     game.setFocusTraversable(true); 
     game.setOnKeyPressed(keyPressed); 
     game.setOnKeyReleased(keyReleased); 

     gameDisplay.getStylesheets().add(getClass().getResource("GameDisplay.css").toExternalForm()); 
     gameDisplay.getChildren().addAll(background, game, leftPaddle, rightPaddle); 
     // start updates of paddle positions 
     timer.start(); 
    } 

    private EventHandler<KeyEvent> keyReleased = new EventHandler<KeyEvent>() { 

     @Override 
     public void handle(KeyEvent event) { 
      // set movement to 0, if the released key was responsible for the paddle 
      switch (event.getCode()) { 
       case W: 
       case S: 
        leftPaddleDY = 0; 
        break; 
       case UP: 
       case DOWN: 
        rightPaddleDY = 0; 
        break; 
      } 
     } 

    }; 

    private EventHandler<KeyEvent> keyPressed = new EventHandler<KeyEvent>() { 

     @Override 
     public void handle(KeyEvent event) { 
      // start movement according to key pressed 
      switch (event.getCode()) { 
       case W: 
        leftPaddleDY = -6; 
        break; 
       case S: 
        leftPaddleDY = 6; 
        break; 
       case UP: 
        rightPaddleDY = -6; 
        break; 
       case DOWN: 
        rightPaddleDY = 6; 
        break; 
      } 

     } 
    }; 
} 
+0

большое спасибо. Это работает, и все это имеет смысл теперь ха-ха. Я не мог для жизни понять, как использовать AnimationTimer. И спасибо за дополнительные советы – Jorg1776