package class8_1_SimplifiedTourists_BinaryIO_inClass_start; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.geometry.Point2D; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.text.Text; import javafx.util.Duration; /** * Represents anything that can move around town. * * Basic functionality to display the item on the cityMap and move in straight lines. */ public abstract class MobileEntity { public static final int HEIGHT = 30; public static final int MAX_INITIAL_SPEED_PIXELS_PER_STEP = 2; public static final int TAG_DISTANCE_PIXELS = 10; public static final int TURNING_MARGIN = 10; public static final int EAST_TURNING_MARGIN = 200; /* This keeps things off the lake (and off of the observers!) */ public static final int MEAN_DISTANCE_BEFORE_TURN = 100; public static final int MAP_HEIGHT = 500; public static final int MAP_WIDTH = 600; private Point2D location; /* Position use for translateX. In pixels. */ protected Point2D stepSize; /* Position use for translateX. In pixels. */ private Image icon; private final ImageView iconView; protected static int instanceCount = 0; private String name = "Person "+ ++instanceCount; private final Text nameText; public MobileEntity() { // We use an EAST_TURNING_MARGIN to allow for the lake boundary. location = new Point2D( TURNING_MARGIN+ ((MAP_HEIGHT -TURNING_MARGIN-EAST_TURNING_MARGIN)*Math.random()), TURNING_MARGIN+ ((MAP_WIDTH -2*TURNING_MARGIN)*Math.random())); if(Math.random()>0) { stepSize = new Point2D(MAX_INITIAL_SPEED_PIXELS_PER_STEP * (Math.random() * 2 - 1), 0); } else { stepSize = new Point2D(0,MAX_INITIAL_SPEED_PIXELS_PER_STEP * (Math.random()*2-1)); } iconView = new ImageView(icon); iconView.setPreserveRatio(true); iconView.setFitHeight(HEIGHT); nameText = new Text(name); setPosition(); Timeline timeline = new Timeline(new KeyFrame(Duration.millis(1000./30),(e)->{ step(); })); timeline.setCycleCount(Timeline.INDEFINITE); timeline.play(); } public MobileEntity(double carX, double carY) { this(); location = new Point2D(carX, carY); setPosition(); } public void setName(String name) { this.name = name; nameText.setText(name); } public String getName() { return name; } public Point2D getLocation() { return location; } private void setPosition() { double iconCornerX = location.getX()- iconView.boundsInParentProperty().get().getWidth()/2; double iconCornerY = location.getY()- iconView.boundsInParentProperty().get().getHeight()/2; iconView.relocate(iconCornerX,iconCornerY); double textCornerX = location.getX()- nameText.boundsInParentProperty().get().getWidth()/2; nameText.relocate(textCornerX, location.getY()+(double)HEIGHT/2+5); } /** Increment velocity and perform basic functions to not walk off screen */ protected void step() { location = location.add(stepSize); setPosition(); checkBounds(TURNING_MARGIN, MAP_HEIGHT - EAST_TURNING_MARGIN, TURNING_MARGIN, MAP_WIDTH - TURNING_MARGIN); } /** * Turn right if outside of the bounds given. * @param leftEdge * @param rightEdge * @param topEdge * @param bottomEdge */ protected void checkBounds(double leftEdge, double rightEdge, double topEdge, double bottomEdge) { // basic strategy: If currently going in a bad direction, turn! // Should correct to not wander further, even if other wrong turns are made. if(location.getX() > rightEdge && stepSize.getX() > 0) { turnRight(); } else if(location.getY() > bottomEdge && stepSize.getY() > 0) { turnRight(); } else if(location.getX() < leftEdge && stepSize.getX() < 0) { turnRight(); } else if(location.getY() < topEdge && stepSize.getY() < 0) { turnRight(); } // else no turn needed! } protected void turnRight() { stepSize = new Point2D(-stepSize.getY(), stepSize.getX()); // Turn right } @Override public String toString() { return name; } }