Merge branch 'master' into storyD-3D

# Conflicts:
#	.gitignore
#	racevisionGame/src/main/java/mock/model/RaceServer.java
#	racevisionGame/src/main/java/mock/model/collider/Collider.java
#	racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java
#	racevisionGame/src/main/java/shared/model/Boat.java
#	racevisionGame/src/main/java/shared/model/Mark.java
#	racevisionGame/src/main/java/visualiser/Controllers/HostController.java
#	racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java
#	racevisionGame/src/main/java/visualiser/Controllers/MainController.java
#	racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java
#	racevisionGame/src/main/java/visualiser/Controllers/TitleController.java
#	racevisionGame/src/main/java/visualiser/layout/Plane3D.java
#	racevisionGame/src/main/java/visualiser/layout/SeaSurface.java
#	racevisionGame/src/main/java/visualiser/layout/View3D.java
#	racevisionGame/src/main/java/visualiser/utils/PerlinNoiseGenerator.java
#	racevisionGame/src/main/resources/visualiser/scenes/title.fxml
This commit is contained in:
Joseph Gardner
2017-09-14 16:34:28 +12:00
107 changed files with 3366 additions and 2018 deletions
@@ -0,0 +1,27 @@
package mock.model.commandFactory;
import java.util.Observable;
/**
* Used to track the current active observer command. This is to ensure two commands that do similar things do not overlap.
*/
public class ActiveObserverCommand {
private ObserverCommand currentVelocityCommand;
private ObserverCommand currentAngularCommand;
public ActiveObserverCommand() {
}
public void changeVelocityCommand(Observable o, ObserverCommand c) {
o.deleteObserver(currentVelocityCommand);
o.addObserver(c);
currentVelocityCommand = c;
}
public void changeAngularCommand(Observable o, ObserverCommand c) {
o.deleteObserver(currentAngularCommand);
o.addObserver(c);
currentAngularCommand = c;
}
}
@@ -0,0 +1,45 @@
package mock.model.commandFactory;
import mock.model.MockBoat;
import mock.model.MockRace;
import shared.model.Azimuth;
import shared.model.GPSCoordinate;
import java.util.Observable;
/**
* Command class for collisions
*/
public class CollisionCommand extends ObserverCommand {
private GPSCoordinate startingPosition;
private Azimuth azimuth;
private double distance;
/**
* Constructor for class
* @param race race context
* @param boat boat controlled by command
*/
public CollisionCommand(MockRace race, MockBoat boat) {
super(race, boat);
race.addObserver(this);
}
@Override
public void execute() {
this.azimuth = Azimuth.fromDegrees(boat.getBearing().degrees() - 180d);
this.startingPosition = boat.getPosition();
this.distance = 30;
boat.setVelocityDefault(false);
}
@Override
public void update(Observable o, Object arg) {
if(GPSCoordinate.calculateDistanceMeters(boat.getPosition(), startingPosition) < distance) {
boat.setPosition(GPSCoordinate.calculateNewPosition(boat.getPosition(), 2, azimuth));
} else {
race.deleteObserver(this);
boat.setVelocityDefault(true);
}
}
}
@@ -3,6 +3,8 @@ package mock.model.commandFactory;
import mock.model.MockBoat;
import mock.model.MockRace;
import java.util.Observer;
/**
* Allows RaceLogic to control MockRace state according to the Command pattern
*/
@@ -0,0 +1,20 @@
package mock.model.commandFactory;
import mock.model.MockBoat;
import mock.model.MockRace;
import java.util.Observer;
/**
* Command that can observe the race
*/
public abstract class ObserverCommand implements Command, Observer {
MockRace race;
MockBoat boat;
public ObserverCommand(MockRace race, MockBoat boat) {
this.race = race;
this.boat = boat;
boat.setAutoVMG(false);
}
}
@@ -2,20 +2,50 @@ package mock.model.commandFactory;
import mock.model.MockBoat;
import mock.model.MockRace;
import mock.model.NewPolars;
import mock.model.VMG;
public class SailsCommand implements Command {
private MockRace race;
private MockBoat boat;
import java.util.Observable;
public class SailsCommand extends ObserverCommand {
private boolean sailsOut;
private double goalVelocity;
public SailsCommand(MockRace race, MockBoat boat, Boolean sailsOut) {
this.race = race;
this.boat = boat;
public SailsCommand(MockRace race, MockBoat boat, boolean sailsOut) {
super(race, boat);
race.addVelocityCommand(this);
this.sailsOut = sailsOut;
}
@Override
public void execute() {
this.boat.setSailsOut(this.sailsOut);
boat.setVelocityDefault(false);
if(sailsOut) {
// Accelerate to VMG speed
double polarSpeed = NewPolars.calculateSpeed(race.getWindDirection(), race.getWindSpeed(), boat.getBearing());
VMG vmg = new VMG(polarSpeed, boat.getBearing());
goalVelocity = vmg.getSpeed();
} else {
// Decelerate to 0
goalVelocity = 0;
}
}
@Override
public void update(Observable o, Object arg) {
double acceleration = 0.5;
if(sailsOut && boat.getCurrentSpeed() < goalVelocity) {
boat.setCurrentSpeed(Math.min(goalVelocity, boat.getCurrentSpeed() + acceleration));
} else if (!sailsOut && boat.getCurrentSpeed() > goalVelocity) {
// Apply deceleration to strictly 0 speed
boat.setCurrentSpeed(Math.max(0, boat.getCurrentSpeed() - acceleration));
} else {
// Release boat from SailsCommand control
if(sailsOut) boat.setVelocityDefault(true);
race.deleteObserver(this);
}
}
}
@@ -4,12 +4,16 @@ import mock.model.MockBoat;
import mock.model.MockRace;
import shared.model.Bearing;
import java.util.Observable;
/**
* Command class for tacking and gybing
*/
public class TackGybeCommand implements Command {
private MockRace race;
private MockBoat boat;
public class TackGybeCommand extends ObserverCommand {
private double goalRotation;
private double totalRotation = 0;
private int direction; // -1 for anticlockwise, 1 for clockwise
private double goalAngle;
/**
* Constructor for class
@@ -17,24 +21,32 @@ public class TackGybeCommand implements Command {
* @param boat mock boat to update
*/
public TackGybeCommand(MockRace race, MockBoat boat) {
this.race = race;
this.boat = boat;
super(race, boat);
race.addAngularCommand(this);
}
@Override
public void execute() {
boat.setAutoVMG(false);
double boatAngle = boat.getBearing().degrees();
double windAngle =race.getWindDirection().degrees();
double windAngle = race.getWindDirection().degrees();
double differenceAngle = calcDistance(boatAngle, windAngle);
double angleA = windAngle + differenceAngle;
double angleB = windAngle - differenceAngle;
if(angleA % 360 == boatAngle){
boat.setBearing(Bearing.fromDegrees(angleB));
if (angleA % 360 == boatAngle) {
goalAngle = angleB % 360;
} else {
boat.setBearing(Bearing.fromDegrees(angleA));
goalAngle = angleA % 360;
}
goalRotation = goalAngle - boatAngle;
if (goalRotation < 0) {
goalRotation += 360;
}
if (goalRotation > 180) {
goalRotation = 360 - goalRotation;
direction = -1;
} else {
direction = 1;
}
}
@@ -49,5 +61,16 @@ public class TackGybeCommand implements Command {
return phi > 180 ? 360 - phi : phi;
}
@Override
public void update(Observable o, Object arg) {
double offset = 3.0;
if (totalRotation < goalRotation) {
boat.setBearing(Bearing.fromDegrees(boat.getBearing().degrees() + offset * direction));
totalRotation += offset;
} else {
boat.setBearing(Bearing.fromDegrees(goalAngle));
race.deleteObserver(this);
}
}
}
@@ -2,13 +2,20 @@ package mock.model.commandFactory;
import mock.model.MockBoat;
import mock.model.MockRace;
import mock.model.NewPolars;
import mock.model.VMG;
import shared.model.Bearing;
import java.util.Observable;
/**
* Command class for autoVMG
*/
public class VMGCommand implements Command {
private MockRace race;
private MockBoat boat;
public class VMGCommand extends ObserverCommand {
private double goalAngle;
private double goalRotation;
private double totalRotation = 0;
private int direction;
/**
* Constructor for class
@@ -16,8 +23,8 @@ public class VMGCommand implements Command {
* @param boat mock boat to update
*/
public VMGCommand(MockRace race, MockBoat boat) {
this.race = race;
this.boat = boat;
super(race, boat);
race.addAngularCommand(this);
}
@Override
@@ -27,5 +34,37 @@ public class VMGCommand implements Command {
} else {
boat.setAutoVMG(true);
}
newOptimalVMG(boat);
goalRotation = goalAngle - boat.getBearing().degrees();
if (goalRotation < 0) {
goalRotation += 360;
}
if (goalRotation > 180) {
goalRotation = 360 - goalRotation;
direction = -1;
} else {
direction = 1;
}
}
private void newOptimalVMG(MockBoat boat) {
long tackPeriod = 1000;
if (boat.getTimeSinceTackChange() > tackPeriod) {
VMG newVMG = NewPolars.setBestVMG(race.getWindDirection(), race.getWindSpeed(), boat.getBearing());
goalAngle = newVMG.getBearing().degrees();
}
}
@Override
public void update(Observable o, Object arg) {
double offset = 3.0;
if (totalRotation < goalRotation) {
boat.setBearing(Bearing.fromDegrees(boat.getBearing().degrees() + offset * direction));
totalRotation += offset;
} else {
boat.setBearing(Bearing.fromDegrees(goalAngle));
race.deleteObserver(this);
}
}
}
@@ -4,17 +4,23 @@ import mock.model.MockBoat;
import mock.model.MockRace;
import shared.model.Bearing;
import java.util.Observable;
/**
* Created by connortaylorbrown on 4/08/17.
* Command class for upwind and downwind controls
*/
public class WindCommand implements Command {
private MockRace race;
private MockBoat boat;
public class WindCommand extends ObserverCommand {
private int direction;
/**
* Constructor for class
* @param race race context
* @param boat boat controlled by command
* @param upwind if true, downwind if false
*/
public WindCommand(MockRace race, MockBoat boat, boolean upwind) {
this.race = race;
this.boat = boat;
super(race, boat);
race.addAngularCommand(this);
this.direction = upwind? -1 : 1;
}
@@ -34,4 +40,9 @@ public class WindCommand implements Command {
boat.setBearing(Bearing.fromDegrees(heading + offset));
}
@Override
public void update(Observable o, Object arg) {
race.deleteObserver(this);
}
}