Merge branch 'master' into MapWindRotation
# Conflicts: # racevisionGame/src/main/java/shared/model/CompoundMark.java # racevisionGame/src/main/java/shared/model/Mark.java
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
package mock.model;
|
||||
|
||||
|
||||
import shared.model.*;
|
||||
|
||||
|
||||
@@ -74,7 +73,7 @@ public class MockBoat extends Boat {
|
||||
public Bearing calculateBearingToNextMarker() {
|
||||
|
||||
//Get the start and end points.
|
||||
GPSCoordinate currentPosition = this.getCurrentPosition();
|
||||
GPSCoordinate currentPosition = this.getPosition();
|
||||
GPSCoordinate nextMarkerPosition;
|
||||
|
||||
// if boat is at the finish
|
||||
@@ -87,7 +86,6 @@ public class MockBoat extends Boat {
|
||||
|
||||
//Calculate bearing.
|
||||
Bearing bearing = GPSCoordinate.calculateBearing(currentPosition, nextMarkerPosition);
|
||||
|
||||
return bearing;
|
||||
}
|
||||
|
||||
@@ -100,7 +98,7 @@ public class MockBoat extends Boat {
|
||||
public double calculateDistanceToNextMarker() {
|
||||
|
||||
//Get start and end markers.
|
||||
GPSCoordinate startPosition = this.getCurrentPosition();
|
||||
GPSCoordinate startPosition = this.getPosition();
|
||||
|
||||
//When boats finish, their "current leg" doesn't have an end marker.
|
||||
if (this.getCurrentLeg().getEndCompoundMark() == null) {
|
||||
@@ -111,9 +109,7 @@ public class MockBoat extends Boat {
|
||||
|
||||
|
||||
//Calculate distance.
|
||||
double distanceNauticalMiles = GPSCoordinate.calculateDistanceNauticalMiles(startPosition, endMarker);
|
||||
|
||||
return distanceNauticalMiles;
|
||||
return GPSCoordinate.calculateDistanceNauticalMiles(startPosition, endMarker);
|
||||
}
|
||||
|
||||
|
||||
@@ -160,8 +156,8 @@ public class MockBoat extends Boat {
|
||||
*/
|
||||
public void moveForwards(double meters) {
|
||||
//Updates the current position of the boat.
|
||||
GPSCoordinate newPosition = GPSCoordinate.calculateNewPosition(this.getCurrentPosition(), meters, Azimuth.fromBearing(this.getBearing()));
|
||||
this.setCurrentPosition(newPosition);
|
||||
GPSCoordinate newPosition = GPSCoordinate.calculateNewPosition(this.getPosition(), meters, Azimuth.fromBearing(this.getBearing()));
|
||||
this.setPosition(newPosition);
|
||||
|
||||
}
|
||||
|
||||
@@ -219,7 +215,7 @@ public class MockBoat extends Boat {
|
||||
* @return true if mark is on port side
|
||||
*/
|
||||
public boolean isPortSide(Mark mark){
|
||||
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getCurrentPosition(), mark.getPosition());
|
||||
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getPosition(), mark.getPosition());
|
||||
if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){
|
||||
//south quadrant
|
||||
return this.getBearing().degrees() <= 180;
|
||||
@@ -245,7 +241,7 @@ public class MockBoat extends Boat {
|
||||
*/
|
||||
public boolean isStarboardSide(Mark mark){
|
||||
//if this boat is lower than the mark check which way it is facing
|
||||
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getCurrentPosition(), mark.getPosition());
|
||||
Bearing towardsMark = GPSCoordinate.calculateBearing(this.getPosition(), mark.getPosition());
|
||||
if (towardsMark.degrees() > 315 || towardsMark.degrees() <= 45){
|
||||
//south quadrant
|
||||
return !(this.getBearing().degrees() <= 180);
|
||||
@@ -297,12 +293,11 @@ public class MockBoat extends Boat {
|
||||
this.roundingStatus = 0;
|
||||
}
|
||||
|
||||
public boolean getAutoVMG(){
|
||||
return autoVMG;
|
||||
}
|
||||
|
||||
public void setAutoVMG(boolean autoVMG) {
|
||||
this.autoVMG = autoVMG;
|
||||
}
|
||||
|
||||
public boolean getAutoVMG(){
|
||||
return autoVMG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import network.Messages.BoatLocation;
|
||||
import network.Messages.BoatStatus;
|
||||
import network.Messages.Enums.BoatStatusEnum;
|
||||
import network.Messages.Enums.RaceStatusEnum;
|
||||
import network.Messages.LatestMessages;
|
||||
import shared.dataInput.BoatDataSource;
|
||||
import shared.dataInput.RaceDataSource;
|
||||
import shared.dataInput.RegattaDataSource;
|
||||
@@ -35,8 +34,6 @@ public class MockRace extends Race {
|
||||
*/
|
||||
private List<MockBoat> boats;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A copy of the boundary list, except "shrunk" inwards by 50m.
|
||||
*/
|
||||
@@ -78,6 +75,8 @@ public class MockRace extends Race {
|
||||
|
||||
//Wind.
|
||||
this.setWind(windGenerator.generateBaselineWind());
|
||||
|
||||
this.colliderRegistry.addAllColliders(boats);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +200,7 @@ public class MockRace extends Race {
|
||||
boat.setCurrentSpeed(0d);
|
||||
|
||||
//Place the boat at its starting position.
|
||||
boat.setCurrentPosition(startPosition);
|
||||
boat.setPosition(startPosition);
|
||||
|
||||
//Boats start facing their next marker.
|
||||
boat.setBearing(boat.calculateBearingToNextMarker());
|
||||
@@ -406,7 +405,7 @@ public class MockRace extends Race {
|
||||
Bearing bearing = Bearing.fromDegrees(angle);
|
||||
|
||||
//Check that if it is acceptable.
|
||||
boolean bearingIsGood = this.checkBearingInsideCourse(bearing, boat.getCurrentPosition());
|
||||
boolean bearingIsGood = this.checkBearingInsideCourse(bearing, boat.getPosition());
|
||||
|
||||
|
||||
if (lastAngle != -1) {
|
||||
@@ -481,7 +480,7 @@ public class MockRace extends Race {
|
||||
case 0://hasn't started rounding
|
||||
if (boat.isPortSide(roundingMark) &&
|
||||
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
||||
roundingChecks.get(0), boat.getCurrentPosition(), legBearing) &&
|
||||
roundingChecks.get(0), boat.getPosition(), legBearing) &&
|
||||
gateCheck && boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) {
|
||||
boat.increaseRoundingStatus();
|
||||
if (boat.getCurrentLeg().getLegNumber() + 2 >= legs.size()){
|
||||
@@ -493,7 +492,7 @@ public class MockRace extends Race {
|
||||
case 1://has been parallel to the mark;
|
||||
if (boat.isPortSide(roundingMark) &&
|
||||
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
||||
roundingChecks.get(1), boat.getCurrentPosition(),
|
||||
roundingChecks.get(1), boat.getPosition(),
|
||||
Bearing.fromDegrees(legBearing.degrees() - 90)) &&//negative 90 from bearing because of port rounding
|
||||
boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(1)))) {
|
||||
boat.increaseRoundingStatus();
|
||||
@@ -525,7 +524,7 @@ public class MockRace extends Race {
|
||||
case 0://hasn't started rounding
|
||||
if (boat.isStarboardSide(roundingMark) &&
|
||||
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
||||
roundingChecks.get(0), boat.getCurrentPosition(), legBearing) &&
|
||||
roundingChecks.get(0), boat.getPosition(), legBearing) &&
|
||||
gateCheck &&
|
||||
boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(0)))) {
|
||||
boat.increaseRoundingStatus();
|
||||
@@ -538,7 +537,7 @@ public class MockRace extends Race {
|
||||
case 1://has been parallel to the mark
|
||||
if (boat.isStarboardSide(roundingMark) &&
|
||||
GPSCoordinate.passesLine(roundingMark.getPosition(),
|
||||
roundingChecks.get(1), boat.getCurrentPosition(), Bearing.fromDegrees(legBearing.degrees() + 90)) && //positive 90 from bearing because of starboard rounding
|
||||
roundingChecks.get(1), boat.getPosition(), Bearing.fromDegrees(legBearing.degrees() + 90)) && //positive 90 from bearing because of starboard rounding
|
||||
boat.isBetweenGate(roundingMark, Mark.tempMark(roundingChecks.get(1)))) {
|
||||
boat.increaseRoundingStatus();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package mock.model;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import mock.model.collider.Collision;
|
||||
import mock.model.commandFactory.Command;
|
||||
import mock.model.commandFactory.CompositeCommand;
|
||||
import mock.model.commandFactory.CommandFactory;
|
||||
import network.Messages.Enums.BoatActionEnum;
|
||||
@@ -9,8 +11,11 @@ import network.Messages.Enums.RaceStatusEnum;
|
||||
import network.Messages.LatestMessages;
|
||||
import shared.model.RunnableWithFramePeriod;
|
||||
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
public class RaceLogic implements RunnableWithFramePeriod {
|
||||
|
||||
public class RaceLogic implements RunnableWithFramePeriod, Observer {
|
||||
/**
|
||||
* State of current race modified by this object
|
||||
*/
|
||||
@@ -32,6 +37,8 @@ public class RaceLogic implements RunnableWithFramePeriod {
|
||||
this.race = race;
|
||||
this.server = new RaceServer(race, messages);
|
||||
this.commands = compositeCommand;
|
||||
|
||||
race.getColliderRegistry().addObserver(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +123,7 @@ public class RaceLogic implements RunnableWithFramePeriod {
|
||||
//If it is still racing, update its position.
|
||||
if (boat.getStatus() == BoatStatusEnum.RACING) {
|
||||
race.updatePosition(boat, framePeriod, race.getRaceClock().getDurationMilli());
|
||||
|
||||
race.getColliderRegistry().rayCast(boat);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -168,4 +175,14 @@ public class RaceLogic implements RunnableWithFramePeriod {
|
||||
public MockRace getRace() {
|
||||
return race;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
Collision e = (Collision)arg;
|
||||
|
||||
if(e.getBearing().degrees() == 0) System.out.println("Ahead");
|
||||
else if(e.getBearing().degrees() < 90) System.out.println("Starboard");
|
||||
else if(e.getBearing().degrees() > 270) System.out.println("Port");
|
||||
else System.out.println("Behind");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@ package mock.model;
|
||||
|
||||
import network.Messages.*;
|
||||
import network.Messages.Enums.BoatLocationDeviceEnum;
|
||||
import network.Utils.AC35UnitConverter;
|
||||
import shared.model.Bearing;
|
||||
import shared.model.CompoundMark;
|
||||
import shared.model.Constants;
|
||||
import shared.model.Mark;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -30,7 +28,6 @@ public class RaceServer {
|
||||
this.latestMessages = latestMessages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the race to create a snapshot, and places it in latestMessages.
|
||||
*/
|
||||
@@ -127,8 +124,8 @@ public class RaceServer {
|
||||
|
||||
BoatLocation boatLocation = new BoatLocation(
|
||||
boat.getSourceID(),
|
||||
boat.getCurrentPosition().getLatitude(),
|
||||
boat.getCurrentPosition().getLongitude(),
|
||||
boat.getPosition().getLatitude(),
|
||||
boat.getPosition().getLongitude(),
|
||||
this.boatLocationSequenceNumber,
|
||||
BoatLocationDeviceEnum.RacingYacht,
|
||||
boat.getBearing(),
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package mock.model.collider;
|
||||
|
||||
import shared.model.Bearing;
|
||||
import shared.model.Boat;
|
||||
import shared.model.GPSCoordinate;
|
||||
import shared.model.Locatable;
|
||||
|
||||
import java.util.Observable;
|
||||
|
||||
/**
|
||||
* Interface for all objects sensitive to collision in a race.
|
||||
*/
|
||||
public abstract class Collider extends Observable implements Locatable {
|
||||
/**
|
||||
* Indicates whether a ray cast from a boat to a target collider is within the specified length.
|
||||
* @param boat potentially colliding with target
|
||||
* @param distance distance for valid collision
|
||||
* @return whether or not a collision has occurred
|
||||
*/
|
||||
public boolean rayCast(Boat boat, double distance) {
|
||||
double actualDistance = GPSCoordinate.calculateDistanceMeters(boat.getPosition(), this.getPosition());
|
||||
// Compass direction of collider
|
||||
Bearing absolute = Bearing.fromAzimuth(GPSCoordinate.calculateAzimuth(boat.getPosition(), this.getPosition()));
|
||||
// Direction of collider from heading
|
||||
Bearing relative = Bearing.fromDegrees(absolute.degrees() - boat.getBearing().degrees());
|
||||
|
||||
if(actualDistance <= distance) {
|
||||
Collision collision = new Collision(relative, distance);
|
||||
// Notify object of collision
|
||||
onCollisionEnter(boat, collision);
|
||||
// Notify observers of collision
|
||||
notifyObservers(collision);
|
||||
this.setChanged();
|
||||
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a ray cast from a boat to a target collider triggers a collision. Distance is set by the object.
|
||||
* @param boat potentially colliding with target
|
||||
* @return whether or not a collision has occurred
|
||||
*/
|
||||
public abstract boolean rayCast(Boat boat);
|
||||
|
||||
/**
|
||||
* Handle a collision event
|
||||
* @param collider Boat that is colliding
|
||||
* @param e details of collision
|
||||
*/
|
||||
public abstract void onCollisionEnter(Boat collider, Collision e);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package mock.model.collider;
|
||||
|
||||
import shared.model.Boat;
|
||||
import shared.model.GPSCoordinate;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Registry for all Collider objects in a MockRace. Wraps the Collider interface as part of a Composite Pattern.
|
||||
*/
|
||||
public class ColliderRegistry extends Collider implements Observer {
|
||||
/**
|
||||
* List of all registered Colliders
|
||||
*/
|
||||
private List<Collider> colliders;
|
||||
|
||||
/**
|
||||
* Default constructor for ColliderRegistry
|
||||
*/
|
||||
public ColliderRegistry() {
|
||||
this.colliders = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addCollider(Collider collider) {
|
||||
collider.addObserver(this);
|
||||
colliders.add(collider);
|
||||
}
|
||||
|
||||
public void addAllColliders(Collection<? extends Collider> colliders) {
|
||||
for(Collider collider: colliders) addCollider(collider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rayCast(Boat boat) {
|
||||
for(Collider collider: colliders) {
|
||||
if(collider.rayCast(boat)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCollisionEnter(Boat collider, Collision e) {}
|
||||
|
||||
@Override
|
||||
public GPSCoordinate getPosition() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(GPSCoordinate position) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire onCollisionEnter when collision bubbles up from registered colliders.
|
||||
* @param o object collided with
|
||||
* @param arg parameters of the collision
|
||||
*/
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
Collision collision = (Collision)arg;
|
||||
|
||||
notifyObservers(collision);
|
||||
this.setChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package mock.model.collider;
|
||||
|
||||
import shared.model.Bearing;
|
||||
|
||||
/**
|
||||
* Data structure for holding collision details for ray casting and event handling.
|
||||
*/
|
||||
public class Collision {
|
||||
/**
|
||||
* Bearing from boat heading to target
|
||||
*/
|
||||
private Bearing bearing;
|
||||
/**
|
||||
* Distance from boat centre to target centre
|
||||
*/
|
||||
private double distance;
|
||||
|
||||
/**
|
||||
* Constructor for Collision structure
|
||||
* @param bearing from boat heading to target
|
||||
* @param distance from boat centre to target centre
|
||||
*/
|
||||
public Collision(Bearing bearing, double distance) {
|
||||
this.bearing = bearing;
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
public Bearing getBearing() {
|
||||
return bearing;
|
||||
}
|
||||
|
||||
public double getDistance() {
|
||||
return distance;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user