Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions ch_15/Exercise15_21.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package ch_15;


import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import javafx.stage.Stage;

/**
* 15.21 (Drag points) Draw a circle with three random points on the circle. Connect
* the points to form a triangle. Display the angles in the triangle. Use the mouse
* to drag a point along the perimeter of the circle. As you drag it, the triangle and
* angles are redisplayed dynamically, as shown in Figure 15.30b. For computing
* angles in a triangle, see Listing 4.1.
* <p>
* The parametric equation for a circle is
* x = cx + r * cos(a)
* y = cy + r * sin(a)
* where r is the radius, (cx, cy) the center of the circle, and a, an angle in radians.
*/
public class Exercise15_21 extends Application {
private double radius = 10;
private int centerX = 200;
private int centerY = 125;
private int radiusMainCircle = 100;
private Pane pane = new Pane();
private Circle outlineCircle = new Circle(centerX, centerY, radiusMainCircle);
private Circle[] points = new Circle[3];
private Line line1 = new Line();
private Line line2 = new Line();
private Line line3 = new Line();
private Text[] text = {new Text(), new Text(), new Text()};

@Override
public void start(Stage primaryStage) {
draw();
pane.getChildren().addAll(points[0], points[1], points[2],
line1, line2, line3, text[0], text[1], text[2]);
Scene scene = new Scene(pane, 400, 250);
primaryStage.setTitle(getClass().getName());
primaryStage.setScene(scene);
primaryStage.show();

points[0].setOnMouseDragged(e -> {
if (points[0].contains(e.getX(), e.getY())) {
// Recompute and display angles
points[0].setCenterX(e.getX());
points[0].setCenterY(e.getY());
setLines();
}
});

points[1].setOnMouseDragged(e -> {
if (points[1].contains(e.getX(), e.getY())) {
// Recompute and display angles
points[1].setCenterX(e.getX());
points[1].setCenterY(e.getY());
setLines();
}
});

points[2].setOnMouseDragged(e -> {
if (points[2].contains(e.getX(), e.getY())) {
// Recompute and display angles
points[2].setCenterX(e.getX());
points[2].setCenterY(e.getY());
setLines();
}
});
}


void draw() {
points[0] = new Circle(40, 40, 10);
points[1] = new Circle(140, 40, 10);
points[2] = new Circle(60, 140, 10);
setLines();
}

private void setLines() {
line1.setStartX(points[0].getCenterX());
line1.setStartY(points[0].getCenterY());
line1.setEndX(points[1].getCenterX());
line1.setEndY(points[1].getCenterY());
line2.setStartX(points[0].getCenterX());
line2.setStartY(points[0].getCenterY());
line2.setEndX(points[2].getCenterX());
line2.setEndY(points[2].getCenterY());
line3.setStartX(points[1].getCenterX());
line3.setStartY(points[1].getCenterY());
line3.setEndX(points[2].getCenterX());
line3.setEndY(points[2].getCenterY());

// Compute angles
double a = new Point2D(points[2].getCenterX(), points[2].getCenterY()).
distance(points[1].getCenterX(), points[1].getCenterY());
double b = new Point2D(points[2].getCenterX(), points[2].getCenterY()).
distance(points[0].getCenterX(), points[0].getCenterY());
double c = new Point2D(points[1].getCenterX(), points[1].getCenterY()).
distance(points[0].getCenterX(), points[0].getCenterY());
double[] angle = new double[3];
angle[0] = Math.acos((a * a - b * b - c * c) / (-2 * b * c));
angle[1] = Math.acos((b * b - a * a - c * c) / (-2 * a * c));
angle[2] = Math.acos((c * c - b * b - a * a) / (-2 * a * b));

for (int i = 0; i < 3; i++) {
text[i].setX(points[i].getCenterX());
text[i].setY(points[i].getCenterY() - radius);
text[i].setText(String.format("%.2f", Math.toDegrees(angle[i])));
}
}
}
163 changes: 163 additions & 0 deletions ch_15/Exercise15_29.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package ch_15;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
* **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
* button press/release and increase/decrease the car speed by pressing the UP and
* DOWN arrow keys.
*/
public class Exercise15_29 extends Application {

private final double WIDTH = 600;
private final double HEIGHT = 100;

@Override
public void start(Stage primaryStage) throws Exception {
RacingPane pane = new RacingPane(WIDTH, HEIGHT);
pane.start();
pane.setOnMousePressed(e -> pane.pause());
pane.setOnMouseReleased(e -> pane.play());

pane.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.UP) {
pane.increaseSpeed();
} else if (e.getCode() == KeyCode.DOWN) {
pane.decreaseSpeed();
}
});

Scene scene = new Scene(pane, WIDTH, HEIGHT);
primaryStage.setTitle(getClass().getName());
primaryStage.setScene(scene);
primaryStage.show();

pane.requestFocus();
}

}

class RacingPane extends Pane {
private double x;
private double y;
private CarShape car;
private Timeline animation;

/**
* Construct and animate a default CarPane
*/
RacingPane(double width, double height) {
setHeight(height);
setWidth(width);
car = new CarShape(x, y, 5, this);
x = 0;
y = 100;
animation = new Timeline(
new KeyFrame(Duration.millis(50), e -> car.moveCar(x, y, this)));
animation.setCycleCount(Timeline.INDEFINITE);
}


void start() {
animation.play();
}


/**
* Pause animation
*/
public void pause() {
animation.pause();
}

/**
* Play animation
*/
public void play() {
animation.play();
}

/**
* Increase rate by 1
*/
public void increaseSpeed() {
animation.setRate(animation.getRate() + 1);
}

/**
* decrease rate by 1
*/
public void decreaseSpeed() {
animation.setRate(animation.getRate() > 0 ? animation.getRate() - 1 : 0);
}

class CarShape {
private double wheelRadius;
private Rectangle lowerBody;
private Polygon topBody;
private Circle wheel1;
private Circle wheel2;

public CarShape(double x, double y, double wheelRadius, Pane pane) {
this.wheelRadius = wheelRadius;
drawAndRender(x, y, pane);
}

void drawAndRender(double x, double y, Pane pane) {
if (!pane.getChildren().isEmpty()) {
pane.getChildren().clear();
}

lowerBody = new Rectangle(x, y - 20, 50, 10);
topBody = new Polygon(x + 10, y - 20, x + 20, y - 30, x + 30,
y - 30, x + 40, y - 20);
wheel1 = new Circle(x + 15, y - 5, wheelRadius);
wheel2 = new Circle(x + 35, y - 5, wheelRadius);
pane.getChildren().addAll(getLowerBody(), getWheel1(), getWheel2(), getTopBody());
}

/**
* Calculate new x position and draw car
*
* @param x the current x position
* @param y the current y position
* @param pane the pane to render the car on
*/
protected void moveCar(double x, double y, Pane pane) {
x += 1;


drawAndRender(x, y, pane);
}

public Rectangle getLowerBody() {
return lowerBody;
}

public Polygon getTopBody() {
return topBody;
}

public Circle getWheel1() {
return wheel1;
}

public Circle getWheel2() {
return wheel2;
}
}
}
Loading