2017-08-29 72 views
1

我正在嘗試創建一個類似Pong的遊戲,並且我已經開始實施一些關於槳板運動的代碼。一切工作正常關於槳本身的運動。但是,當我突然改變槳的方向時(更具體地,當我立即將槳從向上移動到向下,反之亦然)時,會出現問題。槳葉在幾秒鐘內凍結,然後朝着期望的方向行進。JavaFX:突然用鍵盤移動矩形導致矩形變得「卡住」

我試過看到會發生什麼,當我刪除canvas.setOnKeyReleased(new KeyReleasedHandler());,但然後槳不停地移動相同的方向。一旦我釋放鑰匙,我希望能夠停止槳的運動。

這裏是MainApplication:

public class Pong2App extends Application { 
private static final double CANVAS_WIDTH = 900; 
private static final double CANVAS_HEIGHT = 500; 

private static final double ELAPSED_TIME_SPEED = 1.85; 

Ball testBall; 
Paddle leftPaddle; 

@Override 
public void start(Stage primaryStage) throws Exception { 
    Group root = new Group(); 
    Scene scene = new Scene(root); 
    primaryStage.setScene(scene); 

    Canvas canvas = new Canvas(CANVAS_WIDTH, CANVAS_HEIGHT); 
    Bounds canvasBounds = canvas.getBoundsInLocal(); 
    root.getChildren().add(canvas); 

    GraphicsContext gc = canvas.getGraphicsContext2D(); 

    // TODO: remove testBall and leftPaddle; Gives testBall random vX and vY 
    testBall = new Ball(CANVAS_WIDTH/2, CANVAS_HEIGHT/2.5, 30, 30, gc); 
    Random tempRand = new Random(); 
    testBall.setvX((tempRand.nextDouble() * 4) * (tempRand.nextBoolean() ? -1 : 1)); 
    testBall.setvY((tempRand.nextDouble() * 4) * (tempRand.nextBoolean() ? -1 : 1)); 

    leftPaddle = new Paddle(70, CANVAS_HEIGHT/2.5, 10, 100, "Left", gc); 

    canvas.setFocusTraversable(true); 
    canvas.setOnKeyPressed(new KeyPressedHandler()); 
    canvas.setOnKeyReleased(new KeyReleasedHandler()); 

    new AnimationTimer() { 

     @Override 
     public void handle(long currentTime) { 

      testBall.didCollideWithWalls(canvas); 

      if (leftPaddle.getY() <= canvasBounds.getMinY() + 5) 
       leftPaddle.setY(canvasBounds.getMinY() + 5); 

      if (leftPaddle.getY() >= canvasBounds.getMaxY() - 105) 
       leftPaddle.setY(canvasBounds.getMaxY() - 105); 

      if (leftPaddle.didCollideWith(testBall)) { 
       testBall.setvX(-testBall.getvX()); 
       testBall.setX(testBall.getX() + testBall.getvX()); 
      } 

      testBall.update(ELAPSED_TIME_SPEED); 

      leftPaddle.update(ELAPSED_TIME_SPEED); 

      gc.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); 

      testBall.render(gc); 

      leftPaddle.render(gc); 

     } 

    }.start(); 

    primaryStage.show(); 
} 

public static void main(String[] args) { 
    launch(args); 
} 

/** 
* Handles what happens when a key is pressed. Depending on what key is pressed, 
* the paddle will move up or down. 
* 
* @author Phillip 
* 
*/ 
private class KeyPressedHandler implements EventHandler<KeyEvent> { 

    @Override 
    public void handle(KeyEvent event) { 
     switch (event.getCode()) { 
     case W: 
      leftPaddle.moveUp(); 
      break; 
     case S: 
      leftPaddle.moveDown(); 
      break; 
     default: 
      break; 
     } 

    } 

} 

/** 
* Handles what happens when a key is released. Depending on what key is 
* released, the paddle will stop moving. 
* 
* @author Phillip 
* 
*/ 
private class KeyReleasedHandler implements EventHandler<KeyEvent> { 

    @Override 
    public void handle(KeyEvent event) { 
     switch (event.getCode()) { 
     case W: 
     case S: 
      leftPaddle.setvY(0); 
      break; 
     default: 
      break; 
     } 
    } 

} 

}

這裏是槳類:

public class Paddle extends Sprite { 
private int points; 
private String name; 

private static final double PADDLE_SPEED = 2.5; 

public Paddle(double x, double y, double width, double height, String name, GraphicsContext gc) { 
    super(x, y, width, height, gc); 
    this.points = 0; 
    this.name = name; 
} 

@Override 
public boolean didCollideWith(Sprite other) { 
    Ball ball = (Ball) other; 
    double ballCenterX = ball.getCenterX(); 
    double ballRadius = ball.getRadius(); 
    double ballCenterY = ball.getCenterY(); 

    double halfWidth = this.getHalfWidth(); 
    double halfHeight = this.getHalfHeight(); 
    double centerX = this.getCenterX(); 
    double centerY = this.getCenterY(); 

    if (getName().equals("Left")) { 
     boolean hitXBounds = ballCenterX - ballRadius <= centerX + halfWidth; 
     boolean hitTopPartOfBall = ballCenterY - ballRadius <= centerY + halfHeight 
       && ballCenterY - ballRadius >= centerY - halfHeight; 
     boolean hitBotPartOfBall = ballCenterY + ballRadius <= centerY + halfHeight 
       && ballCenterY + ballRadius >= centerY - halfHeight; 

     return hitXBounds && (hitTopPartOfBall || hitBotPartOfBall); 
    } 
    return false; 
} 

@Override 
public void render(GraphicsContext gc) { 
    gc.fillRect(getX(), getY(), getWidth(), getHeight()); 
} 

@Override 
public boolean didCollideWithWalls(Canvas canvas) { 
    Bounds bounds = canvas.getBoundsInLocal(); 

    boolean atTopWall = this.getY() <= bounds.getMinY(); 
    boolean atBotWall = this.getY() >= bounds.getMaxY(); 

    if (atTopWall || atBotWall) { 
     return true; 
    } 

    return false; 
} 

public int getPoints() { 
    return points; 
} 

public void setPoints(int points) { 
    this.points = points; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public void moveUp() { 
    this.setvY(-PADDLE_SPEED); 
} 

public void moveDown() { 
    this.setvY(PADDLE_SPEED); 
} 

}

謝謝!

回答

2

如果您按,例如W,然後按S,然後釋放W,你打電話時,爲了,

  • setvY(-PADDLE_SPEED)
  • setvY(PADDLE_SPEED)
  • setvY(0)

這可能不是你想要做什麼:它會導致vY=0,即使S仍然被按下。

在此之後不久,本地鍵盤重複將觸發另一次按S,因此您再次呼叫setvY(PADDLE_SPEED),並且槳開始移動。考慮使用兩個布爾(moveUpmoveDown)並將它們設置爲truefalse,然後根據它們的值更新速度。例如。

public class Paddle extends Sprite { 

    private boolean moveUp ; 
    private boolean moveDown ; 

    // ... 

    public void setMoveUp(boolean moveUp) { 
     this.moveUp = moveUp ; 
     updateVy(); 
    } 

    public void setMoveDown(booleam moveDown) { 
     this.moveDown = moveDown ; 
     updateVy(); 
    } 

    private void updateVy() { 
     setvY(
      (moveUp ? -PADDLE_SPEED : 0) + 
      (moveDown ? PADDLE_SPEED : 0) 
     ); 
    } 

    // ... 
} 

然後在你的處理器做

private class KeyPressedHandler implements EventHandler<KeyEvent> { 

    @Override 
    public void handle(KeyEvent event) { 
     switch (event.getCode()) { 
     case W: 
      leftPaddle.setMoveUp(true); 
      break; 
     case S: 
      leftPaddle.setMoveDown(true); 
      break; 
     default: 
      break; 
     } 

    } 

} 

private class KeyReleasedHandler implements EventHandler<KeyEvent> { 

    @Override 
    public void handle(KeyEvent event) { 
     switch (event.getCode()) { 
     case W: 
      leftPaddle.setMoveUp(false); 
      break ; 
     case S: 
      leftPaddle.setMoveDown(false); 
      break; 
     default: 
      break; 
     } 

    } 

} 
+0

我怎麼會去動畫定時檢查呢? –

+1

@PhillipLagoc啊,沒有真正的需要。只需在更改它們時檢查兩個布爾值,然後根據它們的值調用'setvY(...)'。我更新了答案。 –