content: /*
   * FXGL - JavaFX Game Library. The MIT License (MIT).
   * Copyright (c) AlmasB (almaslvl@gmail.com).
   * See LICENSE for details.
   */
  
  package tutorial;
  
  import com.almasb.fxgl.app.GameApplication;
  import com.almasb.fxgl.app.GameSettings;
  import com.almasb.fxgl.entity.Entity;
  import javafx.geometry.Point2D;
  import javafx.scene.input.KeyCode;
  import javafx.scene.paint.Color;
  import javafx.scene.shape.Rectangle;
  import javafx.scene.text.Text;
  
  import java.util.Map;
  
  import static com.almasb.fxgl.dsl.FXGL.*;
  
  public class PongApp extends GameApplication {
  
      private static final int PADDLE_WIDTH = 30;
      private static final int PADDLE_HEIGHT = 100;
      private static final int BALL_SIZE = 20;
      private static final int PADDLE_SPEED = 5;
      private static final int BALL_SPEED = 5;
  
      private Entity paddle1;
      private Entity paddle2;
      private Entity ball;
  
      @Override
      protected void initSettings(GameSettings settings) {
          settings.setTitle("Pong");
      }
  
      @Override
      protected void initInput() {
          onKey(KeyCode.W, () -> paddle1.translateY(-PADDLE_SPEED));
          onKey(KeyCode.S, () -> paddle1.translateY(PADDLE_SPEED));
          onKey(KeyCode.UP, () -> paddle2.translateY(-PADDLE_SPEED));
          onKey(KeyCode.DOWN, () -> paddle2.translateY(PADDLE_SPEED));
      }
  
      @Override
      protected void initGameVars(Map<String, Object> vars) {
          vars.put("score1", 0);
          vars.put("score2", 0);
      }
  
      @Override
      protected void initGame() {
          paddle1 = spawnBat(0, getAppHeight() / 2 - PADDLE_HEIGHT / 2);
          paddle2 = spawnBat(getAppWidth() - PADDLE_WIDTH, getAppHeight() / 2 - PADDLE_HEIGHT / 2);
  
          ball = spawnBall(getAppWidth() / 2 - BALL_SIZE / 2, getAppHeight() / 2 - BALL_SIZE / 2);
      }
  
      @Override
      protected void initUI() {
          Text textScore1 = getUIFactoryService().newText("", Color.BLACK, 22);
          Text textScore2 = getUIFactoryService().newText("", Color.BLACK, 22);
  
          textScore1.textProperty().bind(getip("score1").asString());
          textScore2.textProperty().bind(getip("score2").asString());
  
          addUINode(textScore1, 10, 50);
          addUINode(textScore2, getAppWidth() - 30, 50);
      }
  
      @Override
      protected void onUpdate(double tpf) {
          Point2D velocity = ball.getObject("velocity");
          ball.translate(velocity);
  
          if (ball.getX() == paddle1.getRightX()
                  && ball.getY() < paddle1.getBottomY()
                  && ball.getBottomY() > paddle1.getY()) {
              ball.setProperty("velocity", new Point2D(-velocity.getX(), velocity.getY()));
          }
  
          if (ball.getRightX() == paddle2.getX()
                  && ball.getY() < paddle2.getBottomY()
                  && ball.getBottomY() > paddle2.getY()) {
              ball.setProperty("velocity", new Point2D(-velocity.getX(), velocity.getY()));
          }
  
          if (ball.getX() <= 0) {
              inc("score2", +1);
              resetBall();
          }
  
          if (ball.getRightX() >= getAppWidth()) {
              inc("score1", +1);
              resetBall();
          }
  
          if (ball.getY() <= 0) {
              ball.setY(0);
              ball.setProperty("velocity", new Point2D(velocity.getX(), -velocity.getY()));
          }
  
          if (ball.getBottomY() >= getAppHeight()) {
              ball.setY(getAppHeight() - BALL_SIZE);
              ball.setProperty("velocity", new Point2D(velocity.getX(), -velocity.getY()));
          }
      }
  
      private Entity spawnBat(double x, double y) {
          return entityBuilder()
                  .at(x, y)
                  .viewWithBBox(new Rectangle(PADDLE_WIDTH, PADDLE_HEIGHT))
                  .buildAndAttach();
      }
  
      private Entity spawnBall(double x, double y) {
          return entityBuilder()
                  .at(x, y)
                  .viewWithBBox(new Rectangle(BALL_SIZE, BALL_SIZE))
                  .with("velocity", new Point2D(BALL_SPEED, BALL_SPEED))
                  .buildAndAttach();
      }
  
      private void resetBall() {
          ball.setPosition(getAppWidth() / 2 - BALL_SIZE / 2, getAppHeight() / 2 - BALL_SIZE / 2);
          ball.setProperty("velocity", new Point2D(BALL_SPEED, BALL_SPEED));
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  }
  