Merge branch 'tom' into nightmode
# Conflicts: # racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java
This commit is contained in:
@@ -77,7 +77,7 @@ public class Event {
|
||||
String boatsXMLFile = "mock/mockXML/boatTest.xml";
|
||||
String regattaXMLFile = "mock/mockXML/regattaTest.xml";
|
||||
switch (mapIndex){
|
||||
case 0:raceXMLFile = "mock/mockXML/raceSixPlayers.xml";
|
||||
case 0:raceXMLFile = "mock/mockXML/ac35MapLayout.xml";
|
||||
break;
|
||||
case 1:raceXMLFile = "mock/mockXML/oMapLayout.xml";
|
||||
break;
|
||||
@@ -90,13 +90,12 @@ public class Event {
|
||||
boatsXMLFile = "mock/mockXML/boatTutorial.xml";
|
||||
regattaXMLFile = "mock/mockXML/regattaTutorial.xml";
|
||||
break;
|
||||
default: raceXMLFile = "mock/mockXML/raceSixPlayers.xml";
|
||||
default: raceXMLFile = "mock/mockXML/ac35MapLayout.xml";
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (singlePlayer) {
|
||||
raceXMLFile = "mock/mockXML/raceSinglePlayer.xml";
|
||||
boatsXMLFile = "mock/mockXML/boatsSinglePlayer.xml";
|
||||
}
|
||||
|
||||
|
||||
@@ -109,8 +109,6 @@ public class MockRace extends RaceState {
|
||||
colliderRegistry.addCollider(mark.getMark1());
|
||||
if(mark.getMark2() != null) colliderRegistry.addCollider(mark.getMark2());
|
||||
}
|
||||
|
||||
this.colliderRegistry.addAllColliders(boats);
|
||||
}
|
||||
|
||||
|
||||
@@ -133,9 +131,9 @@ public class MockRace extends RaceState {
|
||||
|
||||
this.boats.add(mockBoat);
|
||||
this.activeObserverCommands.put(boat.getSourceID(), new ActiveObserverCommand());
|
||||
this.colliderRegistry.addCollider(mockBoat);
|
||||
|
||||
getRaceDataSource().incrementSequenceNumber();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,7 @@ public class Constants {
|
||||
* Frame periods are multiplied by this to get the amount of time a single frame represents.
|
||||
* E.g., frame period = 20ms, scale = 5, frame represents 20 * 5 = 100ms, and so boats are simulated for 100ms, even though only 20ms actually occurred.
|
||||
*/
|
||||
public static final int RaceTimeScale = 2;
|
||||
public static final int RaceTimeScale = 1;
|
||||
|
||||
/**
|
||||
* The race pre-start time, in milliseconds. 30 seconds.
|
||||
|
||||
@@ -17,8 +17,9 @@ public class MarkRoundingSequence {
|
||||
|
||||
/**
|
||||
* For each leg, mark rounding information.
|
||||
* Maps between leg number and rounding data.
|
||||
*/
|
||||
private Map<Leg, MarkRoundingData> roundingPoints;
|
||||
private Map<Integer, MarkRoundingData> roundingPoints;
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +35,7 @@ public class MarkRoundingSequence {
|
||||
* @return Rounding points for leg.
|
||||
*/
|
||||
public MarkRoundingData getRoundingData(Leg leg) {
|
||||
return roundingPoints.get(leg);
|
||||
return roundingPoints.get(leg.getLegNumber());
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +140,7 @@ public class MarkRoundingSequence {
|
||||
roundingData.setRoundCheck2Halfway(roundCheck2Halfway);
|
||||
|
||||
|
||||
this.roundingPoints.put(currentLeg, roundingData);
|
||||
this.roundingPoints.put(currentLeg.getLegNumber(), roundingData);
|
||||
|
||||
|
||||
//Rounding points:
|
||||
|
||||
@@ -62,7 +62,7 @@ public class HostGameController extends Controller {
|
||||
});
|
||||
|
||||
// set values and marks to be displayed
|
||||
sliderLength.setMin(2);
|
||||
sliderLength.setMin(5);
|
||||
sliderLength.setMax(MAX_RACE_LENGTH);
|
||||
sliderLength.setShowTickLabels(true);
|
||||
sliderLength.setMajorTickUnit(MAX_RACE_LENGTH-1);
|
||||
|
||||
@@ -8,11 +8,14 @@ import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.AmbientLight;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.PointLight;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ButtonType;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.effect.Light;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
@@ -145,15 +148,23 @@ public class InGameLobbyController extends Controller {
|
||||
|
||||
for (VisualiserBoat boat : copy) {
|
||||
View3D playerBoatToSet = new View3D();
|
||||
|
||||
playerBoatToSet.setItems(subjects);
|
||||
|
||||
playerContainer.add(playerBoatToSet, (count % 3) , row);
|
||||
playerContainer.setMargin(playerBoatToSet, new Insets(10, 10, 10, 10));
|
||||
|
||||
SeaSurface sea = new SeaSurface(750, 200);
|
||||
sea.setX(250);
|
||||
sea.setZ(210);
|
||||
subjects.add(sea);
|
||||
// SeaSurface sea = new SeaSurface(750, 200);
|
||||
// sea.setX(250);
|
||||
// sea.setZ(210);
|
||||
// subjects.add(sea);
|
||||
//
|
||||
NewSeaSurface sea = new NewSeaSurface();
|
||||
Subject3D seaSubject = new Annotation3D(sea);
|
||||
seaSubject.setX(50);
|
||||
seaSubject.setZ(50);
|
||||
seaSubject.setXRot(0);
|
||||
subjects.add(seaSubject);
|
||||
|
||||
// MeshView mesh = new MeshView(importer.getImport());
|
||||
// Subject3D subject = new Subject3D(mesh,0);
|
||||
@@ -177,12 +188,14 @@ public class InGameLobbyController extends Controller {
|
||||
|
||||
|
||||
if (boat.isClientBoat()) {
|
||||
Shockwave boatHighlight = new Shockwave(10);
|
||||
boatHighlight.getMesh().setMaterial(new PhongMaterial(new Color(1, 1, 0, 0.1)));
|
||||
boatHighlight.setX(subject.getPosition().getX());
|
||||
boatHighlight.setY(subject.getPosition().getY());
|
||||
boatHighlight.setZ(subject.getPosition().getZ());
|
||||
subjects.add(boatHighlight);
|
||||
/*Shockwave boatHighlight = new Shockwave(10);
|
||||
boatHighlight.getMesh().setMaterial(new PhongMaterial(new Color(1, 1, 0, 0.1)));*/
|
||||
|
||||
Assets3D.boatHighlight.setX(subject.getPosition().getX());
|
||||
Assets3D.boatHighlight.setY(subject.getPosition().getY());
|
||||
Assets3D.boatHighlight.setZ(subject.getPosition().getZ());
|
||||
|
||||
subjects.add(Assets3D.boatHighlight);
|
||||
subject.getMesh().toFront();
|
||||
}
|
||||
|
||||
@@ -326,6 +339,11 @@ public class InGameLobbyController extends Controller {
|
||||
* Start button pressed. Currently only prints out start
|
||||
*/
|
||||
public void startBtnPressed(){
|
||||
try {
|
||||
HttpMatchBrowserHost.httpMatchBrowserHost.sendStarted();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
App.game.getRaceLogic().getRace().startRace(App.game.getRaceLogic().getRace().getRacePreparatoryTime(), true);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,13 @@ import javafx.scene.shape.Cylinder;
|
||||
import javafx.scene.paint.Stop;
|
||||
import javafx.scene.shape.MeshView;
|
||||
import javafx.scene.shape.Shape3D;
|
||||
import javafx.scene.shape.Sphere;
|
||||
import javafx.scene.transform.Translate;
|
||||
import javafx.util.Callback;
|
||||
import network.Messages.Enums.BoatStatusEnum;
|
||||
import network.Messages.Enums.RaceStatusEnum;
|
||||
import shared.dataInput.RaceDataSource;
|
||||
import shared.enums.RoundingType;
|
||||
import shared.exceptions.BoatNotFoundException;
|
||||
import shared.model.*;
|
||||
import visualiser.app.App;
|
||||
@@ -88,6 +90,13 @@ public class RaceViewController extends Controller {
|
||||
*/
|
||||
private AnimationTimer pointToMark;
|
||||
|
||||
//seagulls
|
||||
private ObservableList<Subject3D> seagulls = FXCollections.observableArrayList();
|
||||
//seagulls goto
|
||||
private Map<Subject3D, List<Double>> seagullsGoToX = new HashMap<>();
|
||||
private Map<Subject3D, List<Double>> seagullsGoToY = new HashMap<>();
|
||||
private double seagullSpeed = 0.01;
|
||||
|
||||
// note: it says it's not used but it is! do not remove :)
|
||||
private @FXML ArrowController arrowController;
|
||||
private @FXML NextMarkController nextMarkController;
|
||||
@@ -109,6 +118,7 @@ public class RaceViewController extends Controller {
|
||||
private @FXML TableColumn<VisualiserBoat, Number> boatHealthColumn;
|
||||
private @FXML LineChart<Number, Number> sparklineChart;
|
||||
private @FXML Label tutorialText;
|
||||
private @FXML ImageView tom;
|
||||
private @FXML AnchorPane infoWrapper;
|
||||
private @FXML AnchorPane lineChartWrapper;
|
||||
private @FXML StackPane speedPane;
|
||||
@@ -148,6 +158,7 @@ public class RaceViewController extends Controller {
|
||||
if (App.gameType == 4) {
|
||||
isTutorial = true;
|
||||
tutorialText.setVisible(true);
|
||||
tom.setVisible(true);
|
||||
tutorialStates = new ArrayList<>(Arrays.asList(TutorialState.values()));
|
||||
currentState = tutorialStates.get(0);
|
||||
tutorialStates.remove(0);
|
||||
@@ -160,6 +171,7 @@ public class RaceViewController extends Controller {
|
||||
} else {
|
||||
isTutorial = false;
|
||||
tutorialText.setVisible(false);
|
||||
tom.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,21 +402,39 @@ public class RaceViewController extends Controller {
|
||||
RaceDataSource raceData = visualiserRace.getVisualiserRaceState().getRaceDataSource();
|
||||
gpsConverter = new GPSConverter(raceData, 450, 450);
|
||||
|
||||
SkyBox skyBox = new SkyBox(750, 200, 250, 0, 210);
|
||||
SkyBox skyBox = Assets3D.skyBox;
|
||||
viewSubjects.addAll(skyBox.getSkyBoxPlanes());
|
||||
|
||||
|
||||
// Set up sea surface
|
||||
SeaSurface sea = new SeaSurface(750, 200);
|
||||
sea.setX(250);
|
||||
sea.setZ(210);
|
||||
viewSubjects.add(sea);
|
||||
// SeaSurface sea = new SeaSurface(750, 200);
|
||||
// sea.setX(250);
|
||||
// sea.setZ(210);
|
||||
// viewSubjects.add(sea);
|
||||
|
||||
// Set up sea surface overlay
|
||||
SeaSurface seaOverlay = new SeaSurface(4000, 200);
|
||||
seaOverlay.setX(250);
|
||||
seaOverlay.setZ(210);
|
||||
viewSubjects.add(seaOverlay);
|
||||
// SeaSurface seaOverlay = new SeaSurface(4000, 200);
|
||||
// seaOverlay.setX(250);
|
||||
// seaOverlay.setZ(210);
|
||||
// viewSubjects.add(seaOverlay);
|
||||
// int seaX = 15;
|
||||
// int seaY = 15;
|
||||
int seaX = 15;
|
||||
int seaY = 15;
|
||||
for (int x = 0; x < seaX; x++) {
|
||||
for (int y = 0; y < seaY; y++) {
|
||||
NewSeaSurface seaSurface = new NewSeaSurface();
|
||||
Subject3D seaSubject = new Annotation3D(seaSurface);
|
||||
seaSubject.setXRot(0);
|
||||
// seaSubject.setX(-75 + x * 50);
|
||||
// seaSubject.setZ(-150 + y * 50);
|
||||
// seaSubject.setX(-150 + x * 250);
|
||||
// seaSubject.setZ(-80 + y * 250);
|
||||
seaSubject.setX(-75 + x * 100);
|
||||
seaSubject.setZ(-150 + y * 100);
|
||||
seaSubject.setY(3);
|
||||
viewSubjects.add(seaSubject);
|
||||
}
|
||||
}
|
||||
|
||||
Boundary3D boundary3D = new Boundary3D(visualiserRace.getVisualiserRaceState().getRaceDataSource().getBoundary(), gpsConverter);
|
||||
for (Subject3D subject3D: boundary3D.getBoundaryNodes()){
|
||||
@@ -412,8 +442,9 @@ public class RaceViewController extends Controller {
|
||||
}
|
||||
// Position and add each mark to view
|
||||
for(Mark mark: race.getVisualiserRaceState().getMarks()) {
|
||||
MeshView mesh = new MeshView(importerMark.getImport());
|
||||
Subject3D markModel = new Subject3D(mesh, mark.getSourceID());
|
||||
// MeshView mesh = new MeshView(importerMark.getImport());
|
||||
// Subject3D markModel = new Subject3D(mesh, mark.getSourceID());
|
||||
Subject3D markModel = new Subject3D(Assets3D.getMark(), mark.getSourceID());
|
||||
|
||||
markModel.setX(gpsConverter.convertGPS(mark.getPosition()).getX());
|
||||
markModel.setZ(gpsConverter.convertGPS(mark.getPosition()).getY());
|
||||
@@ -432,14 +463,16 @@ public class RaceViewController extends Controller {
|
||||
// Configure visualiser for client's boat
|
||||
if (boat.isClientBoat()) {
|
||||
// Add player boat highlight
|
||||
Shockwave boatHighlight = new Shockwave(10);
|
||||
boatHighlight.getMesh().setMaterial(new PhongMaterial(new Color(1, 1, 0, 0.1)));
|
||||
viewSubjects.add(boatHighlight);
|
||||
// Shockwave boatHighlight = new Shockwave(10);
|
||||
// boatHighlight.getMesh().setMaterial(new PhongMaterial(new Color(1, 1, 0, 0.1)));
|
||||
// viewSubjects.add(boatHighlight);
|
||||
|
||||
viewSubjects.add(Assets3D.boatHighlight);
|
||||
|
||||
// Track player boat with camera
|
||||
viewSubjects.add(boatModel);
|
||||
Platform.runLater(() -> {
|
||||
view3D.trackSubject(boatModel);
|
||||
view3D.trackSubject(boatModel, 0);
|
||||
view3D.setThirdPerson();
|
||||
});
|
||||
|
||||
@@ -449,8 +482,8 @@ public class RaceViewController extends Controller {
|
||||
public void handle(long now) {
|
||||
double boatX = gpsConverter.convertGPS(boat.getPosition()).getX();
|
||||
double boatZ = gpsConverter.convertGPS(boat.getPosition()).getY();
|
||||
boatHighlight.setX(boatX);
|
||||
boatHighlight.setZ(boatZ);
|
||||
Assets3D.boatHighlight.setX(boatX);
|
||||
Assets3D.boatHighlight.setZ(boatZ);
|
||||
pointLight.setTranslateX(boatX);
|
||||
pointLight.setTranslateZ(boatZ);
|
||||
}
|
||||
@@ -458,15 +491,22 @@ public class RaceViewController extends Controller {
|
||||
highlightTrack.start();
|
||||
|
||||
// Highlight next mark only for player boat
|
||||
Material markColor = new PhongMaterial(new Color(0.15,0.9,0.2,1));
|
||||
CompoundMark nextMark = boat.getCurrentLeg().getEndCompoundMark();
|
||||
view3D.getShape(nextMark.getMark1().getSourceID()).getMesh().setMaterial(markColor);
|
||||
if(nextMark.getMark2() != null) {
|
||||
view3D.getShape(nextMark.getMark2().getSourceID()).getMesh().setMaterial(markColor);
|
||||
}
|
||||
boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> swapColours(curr)));
|
||||
// Material markColor = new PhongMaterial(new Color(0.15,0.9,0.2,1));
|
||||
// CompoundMark nextMark = boat.getCurrentLeg().getEndCompoundMark();
|
||||
// view3D.getShape(nextMark.getMark1().getSourceID()).getMesh().setMaterial(markColor);
|
||||
// if(nextMark.getMark2() != null) {
|
||||
// view3D.getShape(nextMark.getMark2().getSourceID()).getMesh().setMaterial(markColor);
|
||||
// }
|
||||
// boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> swapColours(curr)));
|
||||
|
||||
//next mark indicator
|
||||
changeNextMark(boat.getCurrentLeg());
|
||||
viewSubjects.add(Assets3D.ccwNextArrow);
|
||||
viewSubjects.add(Assets3D.cwNextArrow);
|
||||
boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> changeNextMark(curr)));
|
||||
} else {
|
||||
viewSubjects.add(boatModel);
|
||||
boatModel.getMesh().toFront();
|
||||
}
|
||||
|
||||
//Create health effect
|
||||
@@ -481,9 +521,31 @@ public class RaceViewController extends Controller {
|
||||
sails3D.setMaterial(boatColorMat);
|
||||
sailsSubject.setXRot(0d);
|
||||
sailsSubject.setHeading(visualiserRace.getVisualiserRaceState().getWindDirection().degrees());
|
||||
|
||||
viewSubjects.add(sailsSubject);
|
||||
|
||||
|
||||
// SeagullFlock seagullFlock = new SeagullFlock(67, 43, 0);
|
||||
//// seagullFlock.addToFlock();
|
||||
//// seagullFlock.addToFlock();
|
||||
// seagullFlock.setxBound(450);
|
||||
// seagullFlock.setyBound(450);
|
||||
// viewSubjects.addAll(seagullFlock.getSeagulls());
|
||||
//
|
||||
// Subject3D textSubject = new Annotation3D(new SeagullMesh());
|
||||
// textSubject.setY(-10);
|
||||
// viewSubjects.add(textSubject);
|
||||
addToFlock();
|
||||
seagullGoTo.start();
|
||||
|
||||
AnimationTimer rotateArrows = new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
Assets3D.ccwNextArrow.setHeading(Assets3D.ccwNextArrow.getHeading().getAngle() - 3.0);
|
||||
Assets3D.cwNextArrow.setHeading(Assets3D.cwNextArrow.getHeading().getAngle() + 3.0);
|
||||
}
|
||||
};
|
||||
rotateArrows.start();
|
||||
|
||||
AnimationTimer sailsFollowBoat = new AnimationTimer() {
|
||||
double sailCurrent = visualiserRace.getVisualiserRaceState().getWindDirection().degrees();
|
||||
boolean canLuff = true;
|
||||
@@ -542,7 +604,7 @@ public class RaceViewController extends Controller {
|
||||
}
|
||||
sailsSubject.setX(gpsConverter.convertGPS(boat.getPosition()).getX());
|
||||
sailsSubject.setZ(gpsConverter.convertGPS(boat.getPosition()).getY());
|
||||
|
||||
sailsSubject.getMesh().toFront();
|
||||
}
|
||||
};
|
||||
sailsFollowBoat.start();
|
||||
@@ -566,9 +628,19 @@ public class RaceViewController extends Controller {
|
||||
};
|
||||
trackBoat.start();
|
||||
|
||||
//next mark indicator
|
||||
//Material markColor = new PhongMaterial(new Color(0.15,0.9,0.2,1));
|
||||
/*CompoundMark nextMark = boat.getCurrentLeg().getEndCompoundMark();
|
||||
|
||||
view3D.getShape(nextMark.getMark1().getSourceID()).getMesh().setMaterial(markColor);
|
||||
if(nextMark.getMark2() != null) {
|
||||
view3D.getShape(nextMark.getMark2().getSourceID()).getMesh().setMaterial(markColor);
|
||||
}*/
|
||||
|
||||
Subject3D shockwave = new Shockwave(10);
|
||||
viewSubjects.add(shockwave);
|
||||
|
||||
//boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> swapColours(curr)));
|
||||
boat.hasCollidedProperty().addListener((o, prev, curr) -> Platform.runLater(() -> showCollision(boat, shockwave)));
|
||||
}
|
||||
// Fix initial bird's-eye position
|
||||
@@ -584,7 +656,12 @@ public class RaceViewController extends Controller {
|
||||
|
||||
// Bind zooming to scrolling
|
||||
view3D.setOnScroll(e -> {
|
||||
view3D.updateDistance(e.getDeltaY());
|
||||
//view3D.updateDistance(e.getDeltaY());
|
||||
if (e.getDeltaY() > 0) {
|
||||
view3D.zoomIn();
|
||||
} else {
|
||||
view3D.zoomOut();
|
||||
}
|
||||
});
|
||||
|
||||
// Bind zooming to keypress (Z/X default)
|
||||
@@ -681,11 +758,71 @@ public class RaceViewController extends Controller {
|
||||
nextMarkController.show2d();
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap the colour of the next mark to pass with the last mark passed
|
||||
* @param leg boat has started on
|
||||
*/
|
||||
private void swapColours(Leg leg) {
|
||||
private void setNextMarkArrowDirection(Mark mark1, Mark mark2, RoundingType roundingType, int direction){
|
||||
boolean port = roundingType == RoundingType.Port;
|
||||
Mark chosenMark = null;
|
||||
|
||||
if (mark2 == null){
|
||||
chosenMark = mark1;
|
||||
} else {
|
||||
boolean rounding = port;
|
||||
switch (direction) {
|
||||
case 2:
|
||||
rounding = !port;
|
||||
case 0:
|
||||
if (rounding){
|
||||
if (mark1.getPosition().getLongitude() < mark2.getPosition().getLongitude()){
|
||||
chosenMark = mark1;
|
||||
} else {
|
||||
chosenMark = mark2;
|
||||
}
|
||||
} else {
|
||||
if (mark1.getPosition().getLongitude() > mark2.getPosition().getLongitude()){
|
||||
chosenMark = mark1;
|
||||
} else {
|
||||
chosenMark = mark2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
rounding = !port;
|
||||
case 1:
|
||||
if (rounding){
|
||||
if (mark1.getPosition().getLatitude() > mark2.getPosition().getLatitude()){
|
||||
chosenMark = mark1;
|
||||
} else {
|
||||
chosenMark = mark2;
|
||||
}
|
||||
} else {
|
||||
if (mark1.getPosition().getLatitude() < mark2.getPosition().getLatitude()){
|
||||
chosenMark = mark1;
|
||||
} else {
|
||||
chosenMark = mark2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chosenMark == null){
|
||||
System.err.println("Mark to pick is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (port){
|
||||
Assets3D.ccwNextArrow.setX(gpsConverter.convertGPS(chosenMark.getPosition()).getX());
|
||||
Assets3D.ccwNextArrow.setZ(gpsConverter.convertGPS(chosenMark.getPosition()).getY());
|
||||
Assets3D.ccwNextArrow.getMesh().setVisible(true);
|
||||
Assets3D.cwNextArrow.getMesh().setVisible(false);
|
||||
} else {
|
||||
Assets3D.cwNextArrow.setX(gpsConverter.convertGPS(chosenMark.getPosition()).getX());
|
||||
Assets3D.cwNextArrow.setZ(gpsConverter.convertGPS(chosenMark.getPosition()).getY());
|
||||
Assets3D.cwNextArrow.getMesh().setVisible(true);
|
||||
Assets3D.ccwNextArrow.getMesh().setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void changeNextMark(Leg leg){
|
||||
CompoundMark start = leg.getStartCompoundMark();
|
||||
CompoundMark end = leg.getEndCompoundMark();
|
||||
|
||||
@@ -694,23 +831,28 @@ public class RaceViewController extends Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
Shape3D start1 = view3D.getShape(start.getMark1().getSourceID()).getMesh();
|
||||
Shape3D end1 = view3D.getShape(end.getMark1().getSourceID()).getMesh();
|
||||
|
||||
Material nextMark = start1.getMaterial();
|
||||
Material lastMark = end1.getMaterial();
|
||||
|
||||
start1.setMaterial(lastMark);
|
||||
if(start.getMark2() != null) {
|
||||
Shape3D start2 = view3D.getShape(start.getMark2().getSourceID()).getMesh();
|
||||
start2.setMaterial(lastMark);
|
||||
//find direction coming
|
||||
double angle = gpsConverter.getAngle(gpsConverter.convertGPS(start.getMark1().getPosition()),
|
||||
gpsConverter.convertGPS(end.getMark1Position()));
|
||||
angle = (Math.toDegrees(angle) % 360 + 360) % 360;
|
||||
int dir = 0; //0 = top 1 = right 2 = down 3 = down
|
||||
if (angle < 315){
|
||||
if (angle > 45){
|
||||
dir ++;
|
||||
}
|
||||
if (angle > 135){
|
||||
dir ++;
|
||||
}
|
||||
if (angle > 225){
|
||||
dir ++;
|
||||
}
|
||||
}
|
||||
|
||||
end1.setMaterial(nextMark);
|
||||
if(end.getMark2() != null) {
|
||||
Shape3D end2 = view3D.getShape(end.getMark2().getSourceID()).getMesh();
|
||||
end2.setMaterial(nextMark);
|
||||
}
|
||||
Mark startMark1 = end.getMark1();
|
||||
Mark startMark2 = end.getMark2();
|
||||
|
||||
setNextMarkArrowDirection(startMark1, startMark2, end.getRoundingType(), dir);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -924,14 +1066,18 @@ public class RaceViewController extends Controller {
|
||||
if(boat.getHealth()<=0){
|
||||
//Boat is dead. Don't check it anymore for hp
|
||||
fp.displayDeath(fp.getSourceID()==raceState.getPlayerBoatID());
|
||||
fp.setSourceID(0);
|
||||
try {
|
||||
raceState.getBoat(boat.getSourceID()).setStatus(BoatStatusEnum.DNF);
|
||||
Annotation3D sharks = new Annotation3D(Assets3D.getSharks());
|
||||
sharks.setX(gpsConverter.convertGPS(boat.getPosition()).getX());
|
||||
sharks.setZ(gpsConverter.convertGPS(boat.getPosition()).getY());
|
||||
viewSubjects.add(sharks);
|
||||
new AnimationTimer(){
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
sharks.setHeading(sharks.getHeading().getAngle() - 0.5);
|
||||
}
|
||||
}.start();
|
||||
|
||||
raceState.updateBoatPositions(raceState.getBoats());
|
||||
} catch (BoatNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
fp.setSourceID(0);
|
||||
}
|
||||
else
|
||||
//Speed up tick when <=10 hp
|
||||
@@ -1118,4 +1264,85 @@ public class RaceViewController extends Controller {
|
||||
deathPane.setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
private AnimationTimer seagullGoTo = new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
for (Subject3D seagull: seagulls) {
|
||||
if (seagullsGoToX.get(seagull).size() > 0) {
|
||||
//System.out.println(xPosition + " " + yPosition);
|
||||
seagull.setHeading(GPSConverter.getAngle(new GraphCoordinate(seagull.getX(), seagull.getZ()),
|
||||
new GraphCoordinate(seagullsGoToX.get(seagull).get(0), seagullsGoToY.get(seagull).get(0))));
|
||||
double delx = seagullsGoToX.get(seagull).get(0) - seagull.getX();
|
||||
double dely = seagullsGoToY.get(seagull).get(0) - seagull.getZ();
|
||||
double scale = seagullSpeed / Math.sqrt(delx * delx + dely * dely);
|
||||
if (scale < 1) {
|
||||
seagull.setX(seagull.getX() + delx * scale);
|
||||
seagull.setZ(seagull.getZ() + dely * scale);
|
||||
} else {
|
||||
seagullsGoToX.get(seagull).remove(0);
|
||||
seagullsGoToY.get(seagull).remove(0);
|
||||
}
|
||||
} else {
|
||||
randSeagullNewAction(seagull);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public void randSeagullNewAction(Subject3D seagull){
|
||||
Random rand = new Random();
|
||||
int nextAction = rand.nextInt(1);
|
||||
switch(nextAction){
|
||||
case 0:
|
||||
//do a straight line
|
||||
double nextX = rand.nextInt((int)gpsConverter.getLongitudeFactor());
|
||||
/*if (nextX > this.xBound/2){
|
||||
nextX = - nextX/2;
|
||||
}*/
|
||||
double nextY = rand.nextInt((int)gpsConverter.getLatitudeFactor());
|
||||
/*if (nextY > this.yBound/2){
|
||||
nextY = - nextY/2;
|
||||
}*/
|
||||
seagullsGoToX.get(seagull).add(nextX);
|
||||
seagullsGoToY.get(seagull).add(nextY);
|
||||
break;
|
||||
case 1:
|
||||
//do a octogan circle
|
||||
seagullsGoToX.get(seagull).add(seagull.getX() - 3);
|
||||
seagullsGoToX.get(seagull).add(seagull.getX() - 3);
|
||||
seagullsGoToX.get(seagull).add(seagull.getX());
|
||||
seagullsGoToX.get(seagull).add(seagull.getX() + 3);
|
||||
seagullsGoToX.get(seagull).add(seagull.getX() + 6);
|
||||
seagullsGoToX.get(seagull).add(seagull.getX() + 6);
|
||||
seagullsGoToX.get(seagull).add(seagull.getX() + 3);
|
||||
seagullsGoToX.get(seagull).add(seagull.getX());
|
||||
//y
|
||||
seagullsGoToY.get(seagull).add(seagull.getZ() - 3);
|
||||
seagullsGoToY.get(seagull).add(seagull.getZ() - 6);
|
||||
seagullsGoToY.get(seagull).add(seagull.getZ() - 9);
|
||||
seagullsGoToY.get(seagull).add(seagull.getZ() - 9);
|
||||
seagullsGoToY.get(seagull).add(seagull.getZ() - 6);
|
||||
seagullsGoToY.get(seagull).add(seagull.getZ() - 3);
|
||||
seagullsGoToY.get(seagull).add(seagull.getZ());
|
||||
seagullsGoToY.get(seagull).add(seagull.getZ());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addToFlock(){
|
||||
Annotation3D newSeagull = new Annotation3D(new SeagullMesh());
|
||||
newSeagull.setY(-15);
|
||||
newSeagull.setX(67);
|
||||
newSeagull.setZ(43);
|
||||
newSeagull.setXRot(0);
|
||||
seagulls.add(newSeagull);
|
||||
seagullsGoToX.put(newSeagull, new ArrayList<>());
|
||||
seagullsGoToY.put(newSeagull, new ArrayList<>());
|
||||
viewSubjects.add(newSeagull);
|
||||
randSeagullNewAction(newSeagull);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
package visualiser.Controllers;
|
||||
|
||||
import com.interactivemesh.jfx.importer.stl.StlMeshImporter;
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.AmbientLight;
|
||||
import javafx.scene.PointLight;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.RadioButton;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.media.AudioClip;
|
||||
import javafx.scene.media.Media;
|
||||
import javafx.scene.media.MediaPlayer;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.MeshView;
|
||||
import javafx.stage.Modality;
|
||||
import mock.exceptions.EventConstructionException;
|
||||
import visualiser.app.App;
|
||||
import visualiser.layout.SeaSurface;
|
||||
import visualiser.layout.SkyBox;
|
||||
import visualiser.layout.Subject3D;
|
||||
import visualiser.layout.View3D;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -30,9 +44,69 @@ import java.util.logging.Logger;
|
||||
public class TitleController extends Controller {
|
||||
private @FXML RadioButton dayModeRD;
|
||||
private @FXML RadioButton nightModeRD;
|
||||
private @FXML Label tutorialLabel;
|
||||
private @FXML Pane menuPane;
|
||||
private @FXML Button tutorialButton;
|
||||
private @FXML ImageView imgSun;
|
||||
private @FXML GridPane view3DContainer;
|
||||
private ToggleGroup toggleGroup = new ToggleGroup();
|
||||
|
||||
public void initialize() {
|
||||
dayModeRD.setToggleGroup(toggleGroup);
|
||||
nightModeRD.setToggleGroup(toggleGroup);
|
||||
|
||||
AmbientLight ambientLight = new AmbientLight(Color.web("#CCCCFF"));
|
||||
ambientLight.setTranslateX(250);
|
||||
ambientLight.setTranslateZ(210);
|
||||
ambientLight.setLightOn(true);
|
||||
|
||||
PointLight pointLight = new PointLight(Color.web("#AAAAFF"));
|
||||
pointLight.setTranslateX(250);
|
||||
pointLight.setTranslateZ(210);
|
||||
pointLight.setLightOn(true);
|
||||
|
||||
ObservableList<Subject3D> subjects = FXCollections.observableArrayList();
|
||||
View3D view3D = new View3D();
|
||||
view3D.addAmbientLight(ambientLight);
|
||||
view3D.addPointLight(pointLight);
|
||||
view3D.setDistance(10);
|
||||
view3D.setPitch(5);
|
||||
view3D.setItems(subjects);
|
||||
|
||||
SkyBox skyBox = new SkyBox(750,200,250,0,250);
|
||||
subjects.addAll(skyBox.getSkyBoxPlanes());
|
||||
|
||||
SeaSurface seaSurface = new SeaSurface(750, 200);
|
||||
seaSurface.setX(250);
|
||||
seaSurface.setZ(250);
|
||||
subjects.add(seaSurface);
|
||||
|
||||
URL asset = RaceViewController.class.getClassLoader().getResource("assets/V1.2 Complete Boat.stl");
|
||||
StlMeshImporter importer = new StlMeshImporter();
|
||||
importer.read(asset);
|
||||
Subject3D boat = new Subject3D(new MeshView(importer.getImport()), 0);
|
||||
|
||||
double radius = 100;
|
||||
boat.setX(0);
|
||||
boat.setZ(radius);
|
||||
boat.setScale(0.1);
|
||||
|
||||
subjects.add(boat);
|
||||
view3D.trackSubject(boat, -45);
|
||||
|
||||
view3DContainer.add(view3D, 0, 0);
|
||||
|
||||
AnimationTimer loop = new AnimationTimer() {
|
||||
double angle = -90;
|
||||
double offset = 0.05;
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
boat.setX(radius * Math.cos(angle * Math.PI/180));
|
||||
boat.setZ(radius * Math.sin(angle * Math.PI/180));
|
||||
boat.setHeading(-angle);
|
||||
angle += offset;
|
||||
}
|
||||
};
|
||||
loop.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called when the 'host a game' button is pressed.
|
||||
@@ -58,10 +132,7 @@ public class TitleController extends Controller {
|
||||
*/
|
||||
public void setDayMode(){
|
||||
dayModeRD.getScene().getStylesheets().clear();
|
||||
menuPane.getStylesheets().clear();
|
||||
imgSun.setImage(new Image(getClass().getResource("/visualiser/images/sun.png").toExternalForm()));
|
||||
dayModeRD.getScene().getStylesheets().add("/css/dayMode.css");
|
||||
menuPane.setStyle("-fx-background-color: #6be6ff;");
|
||||
nightModeRD.setSelected(false);
|
||||
App.dayMode = true;
|
||||
}
|
||||
@@ -71,10 +142,7 @@ public class TitleController extends Controller {
|
||||
*/
|
||||
public void setNightMode(){
|
||||
nightModeRD.getScene().getStylesheets().clear();
|
||||
menuPane.getStylesheets().clear();
|
||||
imgSun.setImage(new Image(getClass().getResource("/visualiser/images/sunsleep.png").toExternalForm()));
|
||||
nightModeRD.getScene().getStylesheets().add("/css/nightMode.css");
|
||||
menuPane.setStyle("-fx-background-color: #1f2c60;");
|
||||
dayModeRD.setSelected(false);
|
||||
App.dayMode = false;
|
||||
}
|
||||
|
||||
@@ -134,7 +134,6 @@ public class App extends Application {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource
|
||||
("/visualiser/scenes/title.fxml"));
|
||||
Parent root = loader.load();
|
||||
stage.setResizable(false);
|
||||
Scene scene = new Scene(root);
|
||||
stage.setTitle("The Boat Game - Burgers & Boats");
|
||||
stage.getIcons().add(new Image(getClass().getClassLoader().getResourceAsStream("images/SailIcon.png")));
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package visualiser.layout;
|
||||
|
||||
import com.interactivemesh.jfx.importer.obj.ObjModelImporter;
|
||||
import com.interactivemesh.jfx.importer.stl.StlMeshImporter;
|
||||
import com.interactivemesh.jfx.importer.x3d.X3dModelImporter;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Material;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.MeshView;
|
||||
import javafx.scene.shape.Shape3D;
|
||||
import visualiser.Controllers.HostGameController;
|
||||
@@ -16,12 +20,66 @@ import java.net.URL;
|
||||
public class Assets3D {
|
||||
|
||||
public static MeshView[] sails;
|
||||
public static MeshView[] sea;
|
||||
public static MeshView[] seagull;
|
||||
public static Subject3D windArrow;
|
||||
public static Subject3D compass;
|
||||
public static Subject3D cwNextArrow;
|
||||
public static Subject3D ccwNextArrow;
|
||||
public static SkyBox skyBox;
|
||||
public static Subject3D boatHighlight;
|
||||
public static Subject3D sharks;
|
||||
|
||||
public static void loadAssets(){
|
||||
loadSails();
|
||||
loadWindArrow();
|
||||
loadNextArrow();
|
||||
loadSeaSurface();
|
||||
loadSkybox();
|
||||
loadSeagull();
|
||||
loadBoatHightlight();
|
||||
}
|
||||
|
||||
private static void loadNextArrow(){
|
||||
StlMeshImporter objModelImporter = new StlMeshImporter();
|
||||
String cwPath = "assets/Next Mark Arrow CW V1.0.stl";
|
||||
URL asset = Assets3D.class.getClassLoader().getResource(cwPath);
|
||||
objModelImporter.read(asset);
|
||||
Material markColor = new PhongMaterial(new Color(0.15,0.9,0.2,1));
|
||||
|
||||
MeshView cwMesh = new MeshView(objModelImporter.getImport());
|
||||
cwMesh.setMaterial(markColor);
|
||||
cwMesh.setMouseTransparent(true);
|
||||
cwMesh.toBack();
|
||||
cwMesh.setVisible(false);
|
||||
cwNextArrow = new Annotation3D(cwMesh);
|
||||
|
||||
String ccwPath = "assets/Next Mark Arrow CCW V1.0.stl";
|
||||
URL ccwAsset = Assets3D.class.getClassLoader().getResource(ccwPath);
|
||||
objModelImporter.read(ccwAsset);
|
||||
|
||||
MeshView ccwMesh = new MeshView(objModelImporter.getImport());
|
||||
ccwMesh.setMaterial(markColor);
|
||||
ccwMesh.setMouseTransparent(true);
|
||||
ccwMesh.toBack();
|
||||
cwMesh.setVisible(false);
|
||||
ccwNextArrow = new Annotation3D(ccwMesh);
|
||||
|
||||
}
|
||||
|
||||
private static void loadBoatHightlight(){
|
||||
Material markColor = new PhongMaterial(new Color(0,1,0,0.5));
|
||||
StlMeshImporter objModelImporter = new StlMeshImporter();
|
||||
String path = "assets/V1.0 Boat Highlight.stl";
|
||||
URL highlight = Assets3D.class.getClassLoader().getResource(path);
|
||||
objModelImporter.read(highlight);
|
||||
|
||||
MeshView hMesh = new MeshView(objModelImporter.getImport());
|
||||
hMesh.setMaterial(markColor);
|
||||
hMesh.setMouseTransparent(true);
|
||||
hMesh.toBack();
|
||||
boatHighlight = new Subject3D(hMesh, 0);
|
||||
|
||||
}
|
||||
|
||||
private static void loadSails(){
|
||||
@@ -40,11 +98,46 @@ public class Assets3D {
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadSeaSurface(){
|
||||
sea = new MeshView[100];
|
||||
ObjModelImporter objModelImporter = new ObjModelImporter();
|
||||
|
||||
for (int i = 0; i < sea.length; i++){
|
||||
// String path = String.format("assets/Ocean V1.0 Small Animation/Ocean V1.0 Large Animation_%06d.obj", i + 1);
|
||||
// String path = String.format("assets/Ocean V1.0 Animation/Ocean V1.0_%06d.obj", i + 1);
|
||||
String path = String.format("assets/Ocean Animation/Ocean Animation_%06d.obj", i + 1);
|
||||
URL asset = Assets3D.class.getClassLoader().getResource(path);
|
||||
objModelImporter.read(asset);
|
||||
if (objModelImporter.getImport().length > 0) {
|
||||
sea[i] = objModelImporter.getImport()[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadSeagull(){
|
||||
seagull = new MeshView[30];
|
||||
ObjModelImporter objModelImporter = new ObjModelImporter();
|
||||
|
||||
for (int i = 0; i < seagull.length; i++){
|
||||
String path = String.format("assets/V1.1 Animated/Seagull V1.1_%06d.obj", i + 1);
|
||||
URL asset = Assets3D.class.getClassLoader().getResource(path);
|
||||
objModelImporter.read(asset);
|
||||
if (objModelImporter.getImport().length > 0) {
|
||||
seagull[i] = objModelImporter.getImport()[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Shape3D getBoat(){
|
||||
String path = "assets/V1.4 Boat.x3d";
|
||||
return loadX3d(path);
|
||||
}
|
||||
|
||||
public static Shape3D getMark(){
|
||||
String path = "assets/Burger Bouy V1.1.x3d";
|
||||
return loadX3d(path);
|
||||
}
|
||||
|
||||
private static void loadWindArrow(){
|
||||
String compassPath = "assets/wind_compass.x3d";
|
||||
compass = new Annotation3D(loadX3d(compassPath));
|
||||
@@ -52,6 +145,11 @@ public class Assets3D {
|
||||
windArrow = new Annotation3D(loadX3d(arrowPath));
|
||||
}
|
||||
|
||||
public static Shape3D getSharks(){
|
||||
String path = "assets/V1.0 Sharks.x3d";
|
||||
return loadX3d(path);
|
||||
}
|
||||
|
||||
public static Shape3D loadX3d(String path){
|
||||
X3dModelImporter x3dModelImporter = new X3dModelImporter();
|
||||
URL asset = Assets3D.class.getClassLoader().getResource(path);
|
||||
@@ -68,4 +166,8 @@ public class Assets3D {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void loadSkybox(){
|
||||
skyBox = new SkyBox(750, 200, 250, 0, 210);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package visualiser.layout;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Material;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.MeshView;
|
||||
|
||||
/**
|
||||
* Created by Gondr on 27/09/2017.
|
||||
*/
|
||||
public class NewSeaSurface extends MeshView{
|
||||
private int seaIndex = 0;
|
||||
|
||||
private AnimationTimer seaRipple = new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
seaIndex = (seaIndex + 1) % Assets3D.sea.length;
|
||||
setMesh(Assets3D.sea[seaIndex].getMesh());
|
||||
}
|
||||
};
|
||||
|
||||
public NewSeaSurface(){
|
||||
super(Assets3D.sea[0].getMesh());
|
||||
Color seaBlue = new Color(0.284, 0.573, 1.00, 1);
|
||||
Material seaMat = new PhongMaterial(seaBlue);
|
||||
setMaterial(seaMat);
|
||||
setMouseTransparent(true);
|
||||
seaRipple.start();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package visualiser.layout;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
@@ -16,7 +17,7 @@ import visualiser.utils.PerlinNoiseGenerator;
|
||||
/**
|
||||
* Creates a SeaSurface
|
||||
*/
|
||||
public class SeaSurface extends Subject3D {
|
||||
public class SeaSurface extends Annotation3D {
|
||||
private static Image image;
|
||||
|
||||
/**
|
||||
@@ -26,7 +27,7 @@ public class SeaSurface extends Subject3D {
|
||||
* @param freq frequency the perlin noise is to be generated at
|
||||
*/
|
||||
public SeaSurface(int size, double freq) {
|
||||
super(createSurface(size, freq), 0);
|
||||
super(createSurface(size, freq));
|
||||
image = new Image(getClass().getClassLoader().getResourceAsStream("images/skybox/ThickCloudsWaterDown2048.png"));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package visualiser.layout;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.transform.Translate;
|
||||
import visualiser.model.GraphCoordinate;
|
||||
import visualiser.utils.GPSConverter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Gondr on 28/09/2017.
|
||||
*/
|
||||
public class SeagullFlock{
|
||||
private ObservableList<Subject3D> seagulls = FXCollections.observableArrayList();
|
||||
private double xPos = 0;
|
||||
private double yPos = 0;
|
||||
private double zPos = 20;
|
||||
private double heading = 0;
|
||||
private double[] xOffset = {0, -5, -5};
|
||||
private double[] yOffset = {0, -5, 5};
|
||||
private double xBound = Integer.MAX_VALUE;//-/+
|
||||
private double yBound = Integer.MAX_VALUE;
|
||||
private List<Double> goToX = new ArrayList<>();
|
||||
private List<Double> goToY = new ArrayList<>();
|
||||
|
||||
private double speed = 0.01;
|
||||
|
||||
private AnimationTimer goTo = new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
if (goToX.size() > 0) {
|
||||
//System.out.println(xPosition + " " + yPosition);
|
||||
heading = GPSConverter.getAngle(new GraphCoordinate(xPos, yPos),
|
||||
new GraphCoordinate(goToX.get(0), goToY.get(0)));
|
||||
double delx = goToX.get(0) - xPos;
|
||||
double dely = goToY.get(0) - yPos;
|
||||
double scale = speed / Math.sqrt(delx * delx + dely * dely);
|
||||
if (scale < 1) {
|
||||
xPos += delx * scale;
|
||||
yPos += dely * scale;
|
||||
} else {
|
||||
goToX.remove(0);
|
||||
goToY.remove(0);
|
||||
}
|
||||
}else {
|
||||
stop();
|
||||
randNewAction();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private AnimationTimer update = new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
for (int i = 0; i < seagulls.size(); i++){
|
||||
Subject3D seagull = seagulls.get(i);
|
||||
seagull.getMesh().setTranslateY(zPos);
|
||||
|
||||
seagull.setHeading(heading);
|
||||
seagull.setX(xPos + xOffset[i]);
|
||||
seagull.setZ(yPos + yOffset[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public SeagullFlock() {
|
||||
this(0d, 0d, 0d);
|
||||
}
|
||||
|
||||
public SeagullFlock(double x, double y, double z){
|
||||
xPos = x;
|
||||
yPos = y;
|
||||
zPos = z;
|
||||
addToFlock();
|
||||
update.start();
|
||||
randNewAction();
|
||||
}
|
||||
|
||||
public void addToFlock(){
|
||||
if (seagulls.size() < 3) {
|
||||
Annotation3D newSeagull = new Annotation3D(new SeagullMesh());
|
||||
newSeagull.setXRot(0);
|
||||
seagulls.add(newSeagull);
|
||||
// seagulls.add(new Annotation3D(new Sphere(5)));
|
||||
}
|
||||
}
|
||||
|
||||
public void setxBound(double xBound) {
|
||||
this.xBound = xBound;
|
||||
}
|
||||
|
||||
public void setyBound(double yBound) {
|
||||
this.yBound = yBound;
|
||||
}
|
||||
|
||||
public void randNewAction(){
|
||||
Random rand = new Random();
|
||||
int nextAction = rand.nextInt(1);
|
||||
switch(nextAction){
|
||||
case 0:
|
||||
//do a straight line
|
||||
double nextX = rand.nextInt((int)this.xBound);
|
||||
/*if (nextX > this.xBound/2){
|
||||
nextX = - nextX/2;
|
||||
}*/
|
||||
double nextY = rand.nextInt((int)this.yBound);
|
||||
/*if (nextY > this.yBound/2){
|
||||
nextY = - nextY/2;
|
||||
}*/
|
||||
goToX.add(nextX);
|
||||
goToY.add(nextY);
|
||||
break;
|
||||
case 1:
|
||||
//do a octogan circle
|
||||
goToX.add(xPos - 3);
|
||||
goToX.add(xPos - 3);
|
||||
goToX.add(xPos);
|
||||
goToX.add(xPos + 3);
|
||||
goToX.add(xPos + 6);
|
||||
goToX.add(xPos + 6);
|
||||
goToX.add(xPos + 3);
|
||||
goToX.add(xPos);
|
||||
//y
|
||||
goToX.add(yPos - 3);
|
||||
goToX.add(yPos - 6);
|
||||
goToX.add(yPos - 9);
|
||||
goToX.add(yPos - 9);
|
||||
goToX.add(yPos - 6);
|
||||
goToX.add(yPos - 3);
|
||||
goToX.add(yPos);
|
||||
goToX.add(yPos);
|
||||
break;
|
||||
}
|
||||
goTo.start();
|
||||
}
|
||||
|
||||
public List<Subject3D> getSeagulls() {
|
||||
return seagulls;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package visualiser.layout;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.MeshView;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Gondr on 28/09/2017.
|
||||
*/
|
||||
public class SeagullMesh extends MeshView{
|
||||
private int index = 0;
|
||||
private int isFlapping = 0;
|
||||
private int flapPeriod;
|
||||
private int flapStrength;
|
||||
private int periodElapsed = 0;
|
||||
|
||||
public SeagullMesh() {
|
||||
setMesh(Assets3D.seagull[0].getMesh());
|
||||
PhongMaterial white = new PhongMaterial(Color.WHITE);
|
||||
setMaterial(white);
|
||||
Random rand = new Random();
|
||||
flapPeriod = rand.nextInt(9);
|
||||
flapPeriod = 60 * (11 + flapPeriod);
|
||||
flapStrength = rand.nextInt(3) + 2;
|
||||
scheduledFlap.start();
|
||||
}
|
||||
|
||||
private AnimationTimer flap = new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
index = (index + 1) % Assets3D.seagull.length;
|
||||
setMesh(Assets3D.seagull[index].getMesh());
|
||||
if (index == 0){
|
||||
isFlapping ++;
|
||||
if (isFlapping >= flapStrength){
|
||||
stop();
|
||||
setMesh(Assets3D.seagull[0].getMesh());
|
||||
isFlapping = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private AnimationTimer scheduledFlap = new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
if (periodElapsed == 0 && isFlapping == 0){
|
||||
startFlapping();
|
||||
}
|
||||
periodElapsed = (periodElapsed + 1) % flapPeriod;
|
||||
}
|
||||
};
|
||||
|
||||
public void startFlapping(){
|
||||
flap.start();
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,7 @@ public class View3D extends Pane {
|
||||
PickResult result = e.getPickResult();
|
||||
if(result != null && result.getIntersectedNode() != null && result.getIntersectedNode() instanceof Shape3D) {
|
||||
untrackSubject();
|
||||
trackSubject(shapeMap.get(result.getIntersectedNode()));
|
||||
trackSubject(shapeMap.get(result.getIntersectedNode()), 0);
|
||||
setThirdPerson();
|
||||
}
|
||||
});
|
||||
@@ -215,15 +215,16 @@ public class View3D extends Pane {
|
||||
/**
|
||||
* Set camera to follow the selected subject
|
||||
* @param subject to track
|
||||
* @param yaw to add to boat heading
|
||||
*/
|
||||
public void trackSubject(Subject3D subject) {
|
||||
public void trackSubject(Subject3D subject, double yaw) {
|
||||
target.set(subject);
|
||||
|
||||
this.trackBoat = new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
updatePivot(target.get().getPosition());
|
||||
setYaw(target.get().getHeading().getAngle());
|
||||
setYaw(target.get().getHeading().getAngle() + yaw);
|
||||
}
|
||||
};
|
||||
trackBoat.start();
|
||||
@@ -268,8 +269,10 @@ public class View3D extends Pane {
|
||||
public void updateDistance(double delta) {
|
||||
double newDistance = -this.distance.getZ() + delta;
|
||||
if (target.get() == null){
|
||||
if (newDistance > MAX_ZOOM_LIMIT){
|
||||
if (newDistance > MAX_ZOOM_LIMIT) {
|
||||
setDistance(MAX_ZOOM_LIMIT);
|
||||
} else if (newDistance <= ZOOM_IN_LIMIT) {
|
||||
setDistance(ZOOM_IN_LIMIT);
|
||||
} else {
|
||||
setDistance(newDistance);
|
||||
}
|
||||
@@ -372,4 +375,4 @@ public class View3D extends Pane {
|
||||
public void addPointLight(PointLight pointLight) {
|
||||
this.world.getChildren().add(pointLight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,10 @@ public class HttpMatchBrowserHost extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendStarted() throws IOException {
|
||||
sendHttp("http://api.umbrasheep.com/seng/match_started/");
|
||||
}
|
||||
|
||||
/**
|
||||
* THe host starts sending out heartbeat messages every 2 seconds.
|
||||
*/
|
||||
|
||||
@@ -111,4 +111,11 @@ public class GPSConverter {
|
||||
return Math.atan2(coord2.getX() - coord1.getX(), coord2.getY() - coord1.getY());
|
||||
}
|
||||
|
||||
public double getLongitudeFactor() {
|
||||
return longitudeFactor;
|
||||
}
|
||||
|
||||
public double getLatitudeFactor() {
|
||||
return latitudeFactor;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user