2017-08-29 1 views
1

Ich versuche ein Pong-ähnliches Spiel zu erstellen, und ich habe angefangen, Code bezüglich der Bewegung des Paddels zu implementieren. Alles funktioniert gut in Bezug auf die Bewegung des Paddels selbst. Es treten jedoch Probleme auf, wenn ich plötzlich die Richtung des Paddels ändere (genauer gesagt, wenn ich sofort das Paddel nach oben und nach unten schiebe und umgekehrt). Das Paddel friert ein paar Sekunden ein und geht dann in die gewünschte Richtung.JavaFX: Plötzliches Bewegen des Rechtecks ​​mit der Tastatur führt dazu, dass das Rechteck "hängenbleibt"

Ich habe versucht zu sehen, was passiert, wenn ich die canvas.setOnKeyReleased(new KeyReleasedHandler()); entfernen, aber dann bewegt sich das Paddel in die gleiche Richtung ohne zu stoppen. Ich möchte in der Lage sein, die Bewegung des Paddels zu stoppen, sobald ich den Schlüssel loslasse. Hier

ist die Hauptanwendung:

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; 
     } 
    } 

} 

}

Hier ist die Paddle-Klasse:

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); 
} 

}

Thank you!

Antwort

2

Wenn Sie z.B. W, drücken Sie dann S, dann W loslassen, Sie rufen, um,

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

was wahrscheinlich ist, nicht das, was Sie zu tun beabsichtigen: es ergibt sich vY=0, obwohl S immer noch gedrückt wird.

Irgendwann kurz danach wird die native Tastaturwiederholung einen weiteren Druck auf S auslösen, so dass Sie wieder setvY(PADDLE_SPEED) aufrufen, und das Paddel beginnt sich zu bewegen. Erwägen Sie, zwei boolesche Werte zu verwenden (moveUp und moveDown) und setzen Sie sie auf true und false und aktualisieren Sie dann die Geschwindigkeit basierend auf ihren beiden Werten. Z.B.

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) 
     ); 
    } 

    // ... 
} 

Dann in Ihrem Handler tun

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; 
     } 

    } 

} 

und

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

Wie würde ich sie in der Animation Timer Überprüfung gehen über? –

+1

@PhillipLagoc Ah, kein echtes Bedürfnis. Überprüfen Sie einfach beide booleschen Werte, wenn Sie sie ändern, und rufen Sie 'setvY (...)' mit einem Wert auf, der von beiden abhängt. Ich habe die Antwort aktualisiert. –

Verwandte Themen