Zen Pong Game : Animation « JavaFX « Java






Zen Pong Game

 

/*
 * Copyright (c) 2011, Pro JavaFX Authors
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of JFXtras nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * ZenPongMain.java - A simple example of the intersects function and 
 * event handlers to create a very basic Pong game.
 *
 *
 *  Developed 2011 by James L. Weaver jim.weaver [at] javafxpert.com
 *  as a JavaFX SDK 2.0 example for the Pro JavaFX book.
 */
//package projavafx.zenpong.ui;

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.TimelineBuilder;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.GroupBuilder;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.LinearGradientBuilder;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Circle;
import javafx.scene.shape.CircleBuilder;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 *  Main class for the ZenPong example
 */
public class Main extends Application {
  /**
   * The center points of the moving ball
   */
  DoubleProperty centerX = new SimpleDoubleProperty();
  DoubleProperty centerY = new SimpleDoubleProperty();

  /**
   * The Y coordinate of the left paddle
   */
  DoubleProperty leftPaddleY = new SimpleDoubleProperty();

  /**
   * The Y coordinate of the right paddle
   */
  DoubleProperty rightPaddleY = new SimpleDoubleProperty();

  /**
   * The drag anchor for left and right paddles
   */
  double leftPaddleDragAnchorY;
  double rightPaddleDragAnchorY;

  /**
   * The initial translateY property for the left and right paddles
   */
  double initLeftPaddleTranslateY;
  double initRightPaddleTranslateY;

  /**
   * The moving ball
   */
  Circle ball;

  /**
   * The Group containing all of the walls, paddles, and ball.  This also allows
   * us to requestFocus for KeyEvents on the Group
   */
  Group pongComponents;

  /**
   * The left and right paddles
   */
  Rectangle leftPaddle;
  Rectangle rightPaddle;

  /**
   * The walls
   */
  Rectangle topWall;
  Rectangle rightWall;
  Rectangle leftWall;
  Rectangle bottomWall;

  Button startButton;
  
  /**
   * Controls whether the startButton is visible
   */
  BooleanProperty startVisible = new SimpleBooleanProperty(true);

  /**
   * The animation of the ball
   */
  Timeline pongAnimation = TimelineBuilder.create()
    .keyFrames(
      new KeyFrame(
        new Duration(10.0),
        new EventHandler<ActionEvent>() {
          public void handle(javafx.event.ActionEvent t) {
            checkForCollision();
            int horzPixels = movingRight ? 1 : -1;
            int vertPixels = movingDown ? 1 : -1;
            centerX.setValue(centerX.getValue() + horzPixels);
            centerY.setValue(centerY.getValue() + vertPixels);
          }
        }
      )
    )
    .cycleCount(Timeline.INDEFINITE)
    .build();

  /**
   * Controls whether the ball is moving right
   */
  boolean movingRight = true;

  /**
   * Controls whether the ball is moving down
   */
  boolean movingDown = true;

  /**
   * Sets the initial starting positions of the ball and paddles
   */
  void initialize() {
    centerX.setValue(250);
    centerY.setValue(250);
    leftPaddleY.setValue(235);
    rightPaddleY.setValue(235);
    startVisible.set(true);
    pongComponents.requestFocus();
  }

  /**
   * Checks whether or not the ball has collided with either the paddles,
   * topWall, or bottomWall.  If the ball hits the wall behind the paddles,
   * the game is over.
   */
  void checkForCollision() {
    if (ball.intersects(rightWall.getBoundsInLocal()) ||
        ball.intersects(leftWall.getBoundsInLocal())) {
      pongAnimation.stop();
      initialize();
    }
    else if (ball.intersects(bottomWall.getBoundsInLocal()) ||
             ball.intersects(topWall.getBoundsInLocal())) {
      movingDown = !movingDown;
    }
    else if (ball.intersects(leftPaddle.getBoundsInParent()) && !movingRight) {
      movingRight = !movingRight;
    }
    else if (ball.intersects(rightPaddle.getBoundsInParent()) && movingRight) {
      movingRight = !movingRight;
    }
  }
  
  /**
   * @param args the command line arguments
   */
  public static void main(String[] args) {
    Application.launch(args);
  }
  
  @Override
  public void start(Stage stage) {
    Scene scene  = SceneBuilder.create()
      .width(500)
      .height(500)
      .fill(
        LinearGradientBuilder.create()
          .startX(0.0)
          .startY(0.0)
          .endX(0.0)
          .endY(1.0)
          .stops(
            new Stop(0.0, Color.BLACK),
            new Stop(0.0, Color.GRAY)
           )
          .build()
      )
      .root(
        pongComponents = GroupBuilder.create()
          .focusTraversable(true)
          .children(
            ball = CircleBuilder.create()
              .radius(5.0)
              .fill(Color.WHITE)
              .build(),
            topWall = RectangleBuilder.create()
              .x(0)
              .y(0)
              .width(500)
              .height(1)
              .build(),
            leftWall = RectangleBuilder.create()
              .x(0)
              .y(0)
              .width(1)
              .height(500)
              .build(),
            rightWall = RectangleBuilder.create()
              .x(500)
              .y(0)
              .width(1)
              .height(500)
              .build(),
            bottomWall = RectangleBuilder.create()
              .x(0)
              .y(500)
              .width(500)
              .height(1)
              .build(),
            leftPaddle = RectangleBuilder.create()
              .x(20)
              .width(10)
              .height(30)
              .fill(Color.LIGHTBLUE)
              .cursor(Cursor.HAND)
              .onMousePressed(new EventHandler<MouseEvent>() {
                public void handle(MouseEvent me) {
                  initLeftPaddleTranslateY =  leftPaddle.getTranslateY();
                  leftPaddleDragAnchorY = me.getSceneY();
                }
              })
              .onMouseDragged(new EventHandler<MouseEvent>() {
                public void handle(MouseEvent me) {
                  double dragY = me.getSceneY() - leftPaddleDragAnchorY;
                  leftPaddleY.setValue(initLeftPaddleTranslateY + dragY);
                }
              })
              .build(),
            rightPaddle = RectangleBuilder.create()
              .x(470)
              .width(10)
              .height(30)
              .fill(Color.LIGHTBLUE)
              .cursor(Cursor.HAND)
              .onMousePressed(new EventHandler<MouseEvent>() {
                public void handle(MouseEvent me) {
                  initRightPaddleTranslateY =  rightPaddle.getTranslateY();
                  rightPaddleDragAnchorY = me.getSceneY();
                }
              })
              .onMouseDragged(new EventHandler<MouseEvent>() {
                public void handle(MouseEvent me) {
                  double dragY = me.getSceneY() - rightPaddleDragAnchorY;
                  rightPaddleY.setValue(initRightPaddleTranslateY + dragY);
                }
              })
              .build(),
            startButton = ButtonBuilder.create()
              .layoutX(225)
              .layoutY(470)
              .text("Start!")
              .onAction(new EventHandler<javafx.event.ActionEvent>() {
                @Override public void handle(javafx.event.ActionEvent e) {
                  startVisible.set(false);
                  pongAnimation.playFromStart();
                  pongComponents.requestFocus();
                }
              })
              .build()
          )
          .onKeyPressed(new EventHandler<KeyEvent>() {
            @Override public void handle(KeyEvent k) {
              if (k.getCode() == KeyCode.SPACE &&
                  pongAnimation.statusProperty()
                      .equals(Animation.Status.STOPPED)) {
                rightPaddleY.setValue(rightPaddleY.getValue() - 6);
              }
              else if (k.getCode() == KeyCode.L &&
                  !rightPaddle.getBoundsInParent().intersects(topWall.getBoundsInLocal())) {
                rightPaddleY.setValue(rightPaddleY.getValue() - 6);
              }
              else if (k.getCode() == KeyCode.COMMA &&
                  !rightPaddle.getBoundsInParent().intersects(bottomWall.getBoundsInLocal())) {
                rightPaddleY.setValue(rightPaddleY.getValue() + 6);
              }
              else if (k.getCode() == KeyCode.A &&
                  !leftPaddle.getBoundsInParent().intersects(topWall.getBoundsInLocal())) {
                leftPaddleY.setValue(leftPaddleY.getValue() - 6);
              }
              else if (k.getCode() == KeyCode.Z &&
                  !leftPaddle.getBoundsInParent().intersects(bottomWall.getBoundsInLocal())) {
                leftPaddleY.setValue(leftPaddleY.getValue() + 6);
              }
            }
          })  
          .build()
      )
      .build();

    ball.centerXProperty().bind(centerX);
    ball.centerYProperty().bind(centerY);
    leftPaddle.translateYProperty().bind(leftPaddleY);
    rightPaddle.translateYProperty().bind(rightPaddleY);
    startButton.visibleProperty().bind(startVisible);
    
    stage.setScene(scene);
    initialize();
    stage.setTitle("ZenPong Example");
    stage.show();
  }
}

   
  








Related examples in the same category

1.Animation along a path
2.Earth Rise
3.Metronome animation
4.Metronome using TranslateTransition
5.Start, Stop and resume an animation
6.A sequence of animation
7.Text typing effect
8.Make Animation movement along a path
9.Provides the animated scrolling behavior for the text