Monday 26 December 2016

Chapter 15 Exercise 29, Introduction to Java Programming, Tenth Edition Y. Daniel LiangY.

15.29 (Racing car) Write a program that simulates car racing, as shown in
Figure 15.34a. The car moves from left to right. When it hits the right end, it
restarts from the left and continues the same process. You can use a timer to
control animation. Redraw the car with a new base coordinates (x, y), as shown
in Figure  15.34b. Also let the user pause/resume the animation with a but-
ton press/release and increase/decrease the car speed by pressing the UP and
DOWN arrow keys.


import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polyline;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Exercise_29 extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        CarPane carPane = new CarPane(600, 200);

        Timeline timeline = new Timeline(
                new KeyFrame(Duration.millis(10), e-> carPane.moveCar(1)));
        timeline.setCycleCount(carPane.getOneCycleDuration());
        timeline.play();
        timeline.setOnFinished(e-> {
            carPane.reset();
            timeline.play();
        });

        // Buttons pause, resume, increase, decrease
        Button pause = new Button("Pause");
        pause.setOnAction(e-> timeline.pause());

        Button resume = new Button("Resume");
        resume.setOnAction(e-> timeline.play());

        Button increase = new Button("Increase");
        increase.setOnAction(e-> {
            timeline.setRate(timeline.getCurrentRate() + 1);
        });

        Button decrease = new Button("Decrease");
        decrease.setOnAction(e-> {
            if (timeline.getCurrentRate() <= 0) return;

            timeline.setRate(timeline.getCurrentRate() - 1);
        });

        HBox hButtons = new HBox(pause,resume,increase,decrease);
        hButtons.setSpacing(10);
        hButtons.setAlignment(Pos.CENTER);
        hButtons.setPadding(new Insets(5, 5, 5, 5));


        BorderPane borderPane = new BorderPane(carPane, null, null, hButtons, null);
        borderPane.setOnKeyPressed(e-> {
            switch (e.getCode()) {
                case UP: increase.fire(); break;
                case DOWN: decrease.fire(); break;
            }
        });
        primaryStage.setScene(new Scene(borderPane));
        primaryStage.setTitle("Moving Car");
        primaryStage.show();

    }

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

    }

    private class CarPane extends Pane {

        private double w; // pane width
        private double h; // pane height

        // left Tire x,y and radius
        private double leftTireX; // left tire is the car's drawing start point
        private double leftTireY;
        private double tireRadius;

        Circle[] tires = new Circle[2]; // Index 0, 1 = left and right tire
        Polyline cover = new Polyline();
        ObservableList<Double> points;
        Rectangle base;

        private CarPane(double width, double height){

            // Get width height and measurements for the left tire (starting point)
            w = width;
            h = height;
            leftTireX = w * 0.2;
            leftTireY = h * 0.9;
            tireRadius = h * 0.1;

            // set MIN and MAX width
            setMinWidth(w);
            setMinHeight(h);

            setMaxWidth(w);
            setMaxHeight(h);

            reset(); // draws and adjusts car to starting position
        }

        public void reset() {

            if (points != null)
                points.clear();
            getChildren().clear();
            drawCar();
            moveCar(tireRadius * 13 * -1);
        }

        public void drawCar() {
            for (int i = 0; i < tires.length; i++) {
                tires[i] = new Circle(leftTireX + (i * 4 * tireRadius), leftTireY, tireRadius);
                tires[i].setStroke(Color.BLACK);
                tires[i].setFill(Color.TRANSPARENT);

            }

            double baseX = tires[0].getCenterX() - tires[0].getRadius() * 3;
            double baseY = tires[0].getCenterY() - tires[0].getRadius() * 3;
            base = new Rectangle(baseX, baseY, tireRadius * 10, tireRadius * 2);
            base.setFill(Color.TRANSPARENT);
            base.setStroke(Color.BLACK);

            // draw the car's top cover
            double startX = base.getX() + tireRadius * 2;
            double startY = base.getY();
            double currentX = startX;
            double currentY = startY;

            points = cover.getPoints();

            double distance = tireRadius * 2;
            points.addAll(currentX, currentY); // start point

            currentX += distance;
            currentY -= distance;
            points.addAll(currentX, currentY); // up right

            currentX += distance;
            points.addAll(currentX,currentY); // right

            currentX += distance;
            currentY += distance;
            points.addAll(currentX,currentY); // down right

            points.addAll(startX, startY); // connect to starting point
            cover.setFill(Color.BLUE);

            getChildren().addAll(tires);
            getChildren().add(base);
            getChildren().add(cover);
        }

        private void moveCar(double distance) {

            // tires
            for (Circle c : tires) {
                c.setCenterX(c.getCenterX() + distance);
            }

            base.setX(base.getX() + distance);

            for (int i = 0; i < points.size(); i += 2) {
                points.set(i, points.get(i) + distance);
            }

        }

        public int getOneCycleDuration(){
            return (int)w;
        }
    }
}

No comments :

Post a Comment