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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user