mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge branch 'master'
Conflicts: src/main/java/seng302/controllers/CanvasController.java src/main/resources/RaceView.fxml
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
package seng302.controllers;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.KeyValue;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.animation.*;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.util.Duration;
|
||||
import seng302.models.Boat;
|
||||
import seng302.models.Event;
|
||||
@@ -22,13 +22,13 @@ import seng302.models.mark.GateMark;
|
||||
import seng302.models.mark.Mark;
|
||||
import seng302.models.mark.MarkType;
|
||||
import seng302.models.mark.SingleMark;
|
||||
import seng302.models.parsers.ConfigParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
|
||||
/**
|
||||
* Created by ptg19 on 15/03/17.
|
||||
* Modified by Haoming Yin (hyi25) on 20/3/2017.
|
||||
@@ -42,13 +42,94 @@ public class CanvasController {
|
||||
private Race race;
|
||||
private GraphicsContext gc;
|
||||
private HashMap<Boat, TimelineInfo> timelineInfos;
|
||||
private final double VIEW_CORNER_LAT = 32.280808;
|
||||
private final double VIEW_CORNER_LON = -64.858401;
|
||||
|
||||
private AnchorPane raceResults;
|
||||
|
||||
private final double ORIGIN_LAT = 32.320504;
|
||||
private final double ORIGIN_LON = -64.857063;
|
||||
|
||||
@FXML
|
||||
private AnchorPane contentAnchorPane;
|
||||
@FXML
|
||||
private Text windArrowText, windDirectionText;
|
||||
|
||||
@FXML Pane raceTimer;
|
||||
|
||||
private Animation.Status raceStatus = Animation.Status.PAUSED;
|
||||
|
||||
/**
|
||||
* Display the list of boats in the order they finished the race
|
||||
*/
|
||||
private void loadRaceResultView() {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/FinishView.fxml"));
|
||||
loader.setController(new RaceResultController(race));
|
||||
|
||||
try {
|
||||
contentAnchorPane.getChildren().removeAll();
|
||||
contentAnchorPane.getChildren().clear();
|
||||
contentAnchorPane.getChildren().addAll((Pane) loader.load());
|
||||
|
||||
} catch (javafx.fxml.LoadException e) {
|
||||
System.err.println(e.getCause());
|
||||
} catch (IOException e) {
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the race timer
|
||||
*/
|
||||
private void loadTimerView(){
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/raceTimer.fxml"));
|
||||
loader.setController(new RaceTimerController(race));
|
||||
|
||||
try{
|
||||
raceTimer.getChildren().clear();
|
||||
raceTimer.getChildren().removeAll();
|
||||
raceTimer.getChildren().addAll((Pane) loader.load());
|
||||
}
|
||||
catch(javafx.fxml.LoadException e){
|
||||
System.out.println(e);
|
||||
}
|
||||
catch(IOException e){
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Play each boats timeline
|
||||
*/
|
||||
private void playTimelines(){
|
||||
for (TimelineInfo timelineInfo : timelineInfos.values()){
|
||||
Timeline timeline = timelineInfo.getTimeline();
|
||||
|
||||
if (timeline.getStatus() == Animation.Status.PAUSED){
|
||||
timeline.play();
|
||||
}
|
||||
}
|
||||
raceStatus = Animation.Status.RUNNING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause each boats timeline
|
||||
*/
|
||||
private void pauseTimelines(){
|
||||
for (TimelineInfo timelineInfo : timelineInfos.values()){
|
||||
Timeline timeline = timelineInfo.getTimeline();
|
||||
|
||||
if (timeline.getStatus() == Animation.Status.RUNNING){
|
||||
timeline.pause();
|
||||
}
|
||||
}
|
||||
raceStatus = Animation.Status.PAUSED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the controller
|
||||
*/
|
||||
public void initialize() {
|
||||
gc = canvas.getGraphicsContext2D();
|
||||
gc.scale(22, 22);
|
||||
gc.scale(15, 15);
|
||||
RaceController raceController = new RaceController();
|
||||
raceController.initializeRace();
|
||||
race = raceController.getRace();
|
||||
@@ -62,17 +143,53 @@ public class CanvasController {
|
||||
drawCourse();
|
||||
drawBoats();
|
||||
|
||||
// If race has started, draw the boats and play the timeline
|
||||
if (race.getRaceTime() > 1){
|
||||
playTimelines();
|
||||
|
||||
}
|
||||
// Race has not started, pause the timelines
|
||||
else if (race.getRaceTime() < 1 || raceStatus == Animation.Status.RUNNING){
|
||||
pauseTimelines();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
generateTimeline();
|
||||
|
||||
// starts the timer and reads events from each boat's time line
|
||||
timer.start();
|
||||
|
||||
loadTimerView();
|
||||
|
||||
Double maxDuration = 0.0;
|
||||
Timeline maxTimeline = null;
|
||||
|
||||
for (TimelineInfo timelineInfo : timelineInfos.values()) {
|
||||
|
||||
Timeline timeline = timelineInfo.getTimeline();
|
||||
System.out.println();
|
||||
|
||||
if (timeline.getTotalDuration().toMillis() >= maxDuration) {
|
||||
maxDuration = timeline.getTotalDuration().toMillis();
|
||||
maxTimeline = timeline;
|
||||
}
|
||||
|
||||
// Timelines are paused by default
|
||||
timeline.play();
|
||||
timeline.pause();
|
||||
raceStatus = Animation.Status.RUNNING;
|
||||
}
|
||||
|
||||
maxTimeline.setOnFinished(event -> {
|
||||
race.setRaceFinished();
|
||||
loadRaceResultView();
|
||||
});
|
||||
|
||||
//set wind direction!!!!!!! can't find another place to put my code --haoming
|
||||
double windDirection = new ConfigParser("doc/examples/config.xml").getWindDirection();
|
||||
windDirectionText.setText(String.format("%.1f°", windDirection));
|
||||
windArrowText.setRotate(windDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,13 +214,22 @@ public class CanvasController {
|
||||
|
||||
// iterates all events and convert each event to keyFrame, then add them into a list
|
||||
for (Event event : events) {
|
||||
keyFrames.add(
|
||||
new KeyFrame(Duration.seconds(event.getTime() / 60 / 60 / 5),
|
||||
onFinished,
|
||||
new KeyValue(x, event.getThisMark().getLatitude()),
|
||||
new KeyValue(y, event.getThisMark().getLongitude())
|
||||
)
|
||||
);
|
||||
if (event.getIsFinishingEvent()) {
|
||||
keyFrames.add(
|
||||
new KeyFrame(Duration.seconds(event.getTime() / 60 / 60 / 5),
|
||||
event1 -> race.setBoatFinished(boat),
|
||||
new KeyValue(x, event.getThisMark().getLatitude()),
|
||||
new KeyValue(y, event.getThisMark().getLongitude())
|
||||
)
|
||||
);
|
||||
} else {
|
||||
keyFrames.add(
|
||||
new KeyFrame(Duration.seconds(event.getTime() / 60 / 60 / 5),
|
||||
new KeyValue(x, event.getThisMark().getLatitude()),
|
||||
new KeyValue(y, event.getThisMark().getLongitude())
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// uses the lists generated above to create a Timeline for the boat.
|
||||
@@ -121,22 +247,6 @@ public class CanvasController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the distance between the two marks
|
||||
*/
|
||||
public double getDistanceBetweenMarks(Mark mark1, Mark mark2) {
|
||||
double earth_radius = 6378.137;
|
||||
double dLat = mark2.getLatitude() * Math.PI / 180 - mark1.getLatitude() * Math.PI / 180;
|
||||
double dLon = mark2.getLongitude() * Math.PI / 180 - mark1.getLongitude() * Math.PI / 180;
|
||||
|
||||
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(mark1.getLatitude() * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
||||
|
||||
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
double d = earth_radius * c;
|
||||
|
||||
return d * 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a boat with given (x, y) position in the given color
|
||||
*
|
||||
@@ -146,13 +256,11 @@ public class CanvasController {
|
||||
*/
|
||||
private void drawBoat(double lat, double lon, Color color) {
|
||||
// Latitude
|
||||
//Double x = (MAP_WIDTH / 360.0) * (180 + lon);
|
||||
//Double y = (MAP_HEIGHT / 180.0) * (80 - lat);
|
||||
|
||||
double x = (lat - VIEW_CORNER_LAT) * 1000; // to prevent negative longitude
|
||||
double y = (lon - VIEW_CORNER_LON) * 1000; // to prevent negative latitude
|
||||
double x = (lon - ORIGIN_LON) * 1000;
|
||||
double y = (ORIGIN_LAT - lat) * 1000;
|
||||
|
||||
double diameter = 0.5;
|
||||
|
||||
gc.setFill(color);
|
||||
gc.fillOval(x, y, diameter, diameter);
|
||||
}
|
||||
@@ -163,7 +271,7 @@ public class CanvasController {
|
||||
private void drawCourse() {
|
||||
for (Mark mark : race.getCourse()) {
|
||||
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
|
||||
drawSingleMark((SingleMark) mark);
|
||||
drawSingleMark((SingleMark) mark, Color.BLACK);
|
||||
} else if (mark.getMarkType() == MarkType.GATE_MARK) {
|
||||
drawGateMark((GateMark) mark);
|
||||
}
|
||||
@@ -175,12 +283,12 @@ public class CanvasController {
|
||||
*
|
||||
* @param singleMark
|
||||
*/
|
||||
private void drawSingleMark(SingleMark singleMark) {
|
||||
double x = (singleMark.getLatitude() - VIEW_CORNER_LAT) * 1000; // to prevent negative longitude
|
||||
double y = (singleMark.getLongitude() - VIEW_CORNER_LON) * 1000; // to prevent negative latitude
|
||||
private void drawSingleMark(SingleMark singleMark, Color color) {
|
||||
double x = (singleMark.getLongitude() - ORIGIN_LON) * 1000;
|
||||
double y = (ORIGIN_LAT - singleMark.getLatitude()) * 1000;
|
||||
|
||||
gc.setFill(Color.BLACK);
|
||||
gc.fillOval(x, y, 0.5, 0.5);
|
||||
gc.setFill(color);
|
||||
gc.fillRect(x,y,0.5,0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +297,35 @@ public class CanvasController {
|
||||
* @param gateMark
|
||||
*/
|
||||
private void drawGateMark(GateMark gateMark) {
|
||||
drawSingleMark(gateMark.getSingleMark1());
|
||||
drawSingleMark(gateMark.getSingleMark2());
|
||||
Color color = Color.BLUE;
|
||||
|
||||
if (gateMark.getName().equals("Start")){
|
||||
color = Color.RED;
|
||||
}
|
||||
|
||||
if (gateMark.getName().equals("Finish")){
|
||||
color = Color.GREEN;
|
||||
}
|
||||
|
||||
drawSingleMark(gateMark.getSingleMark1(), color);
|
||||
drawSingleMark(gateMark.getSingleMark2(), color);
|
||||
|
||||
GraphicsContext gc = canvas.getGraphicsContext2D();
|
||||
|
||||
gc.setStroke(color);
|
||||
|
||||
// Convert lat/lon to x,y
|
||||
double x1 = (gateMark.getSingleMark1().getLongitude()- ORIGIN_LON) * 1000;
|
||||
double y1 = (ORIGIN_LAT - gateMark.getSingleMark1().getLatitude()) * 1000;
|
||||
|
||||
double x2 = (gateMark.getSingleMark2().getLongitude() - ORIGIN_LON) * 1000;
|
||||
double y2 = (ORIGIN_LAT - gateMark.getSingleMark2().getLatitude()) * 1000;
|
||||
|
||||
gc.setLineWidth(0.07);
|
||||
gc.strokeLine(x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
public Race getRace(){
|
||||
return this.race;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user