Created ray casting methods for MockBoat and CompoundMark
- Added ColliderRegistry to Race - Added collision triggering to RaceLogic - Created basic collision handlers for MockBoat and CompoundMark
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package mock.model;
|
package mock.model;
|
||||||
|
|
||||||
|
|
||||||
|
import mock.model.collider.Collider;
|
||||||
|
import mock.model.collider.Collision;
|
||||||
import shared.model.*;
|
import shared.model.*;
|
||||||
|
|
||||||
|
|
||||||
@@ -8,7 +10,7 @@ import shared.model.*;
|
|||||||
* Represents a Boat on the mock side of a race.
|
* Represents a Boat on the mock side of a race.
|
||||||
* This adds mock specific functionality to a boat.
|
* This adds mock specific functionality to a boat.
|
||||||
*/
|
*/
|
||||||
public class MockBoat extends Boat {
|
public class MockBoat extends Boat implements Collider {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -203,4 +205,19 @@ public class MockBoat extends Boat {
|
|||||||
public void setAutoVMG(boolean autoVMG) {
|
public void setAutoVMG(boolean autoVMG) {
|
||||||
this.autoVMG = autoVMG;
|
this.autoVMG = autoVMG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean rayCast(MockBoat boat) {
|
||||||
|
double distance = GPSCoordinate.calculateDistanceMeters(boat.getCurrentPosition(), this.getCurrentPosition());
|
||||||
|
Bearing bearing = Bearing.fromAzimuth(GPSCoordinate.calculateAzimuth(boat.getCurrentPosition(), this.getCurrentPosition()));
|
||||||
|
if(distance < 100 && boat != this) {
|
||||||
|
onCollisionEnter(new Collision(bearing, distance));
|
||||||
|
return true;
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCollisionEnter(Collision e) {
|
||||||
|
System.out.println(e.getBearing().degrees());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package mock.model;
|
package mock.model;
|
||||||
|
|
||||||
|
import mock.model.collider.ColliderRegistry;
|
||||||
import network.Messages.Enums.BoatStatusEnum;
|
import network.Messages.Enums.BoatStatusEnum;
|
||||||
import network.Messages.LatestMessages;
|
import network.Messages.LatestMessages;
|
||||||
import org.opengis.geometry.primitive.*;
|
import org.opengis.geometry.primitive.*;
|
||||||
@@ -30,8 +31,6 @@ public class MockRace extends Race {
|
|||||||
*/
|
*/
|
||||||
private List<MockBoat> boats;
|
private List<MockBoat> boats;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A copy of the boundary list, except "shrunk" inwards by 50m.
|
* A copy of the boundary list, except "shrunk" inwards by 50m.
|
||||||
*/
|
*/
|
||||||
@@ -79,6 +78,8 @@ public class MockRace extends Race {
|
|||||||
|
|
||||||
//Wind.
|
//Wind.
|
||||||
this.setWind(windGenerator.generateBaselineWind());
|
this.setWind(windGenerator.generateBaselineWind());
|
||||||
|
|
||||||
|
this.colliderRegistry.addAllColliders(boats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package mock.model;
|
package mock.model;
|
||||||
|
|
||||||
import javafx.animation.AnimationTimer;
|
import javafx.animation.AnimationTimer;
|
||||||
import mock.model.commandFactory.Command;
|
|
||||||
import mock.model.commandFactory.CommandFactory;
|
import mock.model.commandFactory.CommandFactory;
|
||||||
import mock.model.commandFactory.CompositeCommand;
|
import mock.model.commandFactory.CompositeCommand;
|
||||||
import network.Messages.Enums.BoatActionEnum;
|
import network.Messages.Enums.BoatActionEnum;
|
||||||
@@ -12,7 +11,6 @@ import visualiser.gameController.ControllerServer;
|
|||||||
|
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
public class RaceLogic implements Observer, Runnable {
|
public class RaceLogic implements Observer, Runnable {
|
||||||
/**
|
/**
|
||||||
@@ -136,7 +134,7 @@ public class RaceLogic implements Observer, Runnable {
|
|||||||
if (boat.getStatus() == BoatStatusEnum.RACING) {
|
if (boat.getStatus() == BoatStatusEnum.RACING) {
|
||||||
commands.execute();
|
commands.execute();
|
||||||
race.updatePosition(boat, framePeriod, race.getRaceClock().getDurationMilli());
|
race.updatePosition(boat, framePeriod, race.getRaceClock().getDurationMilli());
|
||||||
|
race.getColliderRegistry().rayCast(boat);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,9 @@ public interface Collider {
|
|||||||
/**
|
/**
|
||||||
* Indicates whether a ray cast from a boat to a target collider triggers a collision.
|
* Indicates whether a ray cast from a boat to a target collider triggers a collision.
|
||||||
* @param boat potentially colliding with target
|
* @param boat potentially colliding with target
|
||||||
* @param collision details of potential collision
|
|
||||||
* @return whether or not a collision has occurred
|
* @return whether or not a collision has occurred
|
||||||
*/
|
*/
|
||||||
boolean rayCast(MockBoat boat, Collision collision);
|
boolean rayCast(MockBoat boat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a collision event
|
* Handle a collision event
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package mock.model.collider;
|
|||||||
import mock.model.MockBoat;
|
import mock.model.MockBoat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,10 +30,14 @@ public class ColliderRegistry implements Collider {
|
|||||||
colliders.remove(collider);
|
colliders.remove(collider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addAllColliders(Collection<? extends Collider> colliders) {
|
||||||
|
for(Collider collider: colliders) addCollider(collider);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean rayCast(MockBoat boat, Collision collision) {
|
public boolean rayCast(MockBoat boat) {
|
||||||
for(Collider collider: colliders) {
|
for(Collider collider: colliders) {
|
||||||
if(collider.rayCast(boat, collision)) return true;
|
if(collider.rayCast(boat)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
package shared.model;
|
package shared.model;
|
||||||
|
|
||||||
|
|
||||||
|
import mock.model.MockBoat;
|
||||||
|
import mock.model.collider.Collider;
|
||||||
|
import mock.model.collider.Collision;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a compound mark - that is, either one or two individual marks which form a single compound mark.
|
* Represents a compound mark - that is, either one or two individual marks which form a single compound mark.
|
||||||
*/
|
*/
|
||||||
public class CompoundMark {
|
public class CompoundMark implements Collider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID of the compound mark.
|
* The ID of the compound mark.
|
||||||
@@ -110,7 +119,7 @@ public class CompoundMark {
|
|||||||
* @return The position of the second mark in the compound mark.
|
* @return The position of the second mark in the compound mark.
|
||||||
*/
|
*/
|
||||||
public GPSCoordinate getMark2Position() {
|
public GPSCoordinate getMark2Position() {
|
||||||
return mark2.getPosition();
|
return mark2 == null? mark1.getPosition() : mark2.getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -128,17 +137,32 @@ public class CompoundMark {
|
|||||||
* @return The average coordinate of the compound mark.
|
* @return The average coordinate of the compound mark.
|
||||||
*/
|
*/
|
||||||
private GPSCoordinate calculateAverage() {
|
private GPSCoordinate calculateAverage() {
|
||||||
|
|
||||||
//If the compound mark only contains one mark, the average is simply the first mark's position.
|
|
||||||
if (this.mark2 == null) {
|
|
||||||
return this.getMark1Position();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Otherwise, calculate the average of both marks.
|
//Otherwise, calculate the average of both marks.
|
||||||
GPSCoordinate averageCoordinate = GPSCoordinate.calculateAverageCoordinate(this.getMark1Position(), this.getMark2Position());
|
GPSCoordinate averageCoordinate = GPSCoordinate.calculateAverageCoordinate(this.getMark1Position(), this.getMark2Position());
|
||||||
|
|
||||||
return averageCoordinate;
|
return averageCoordinate;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mark closestMark(GPSCoordinate coordinate) {
|
||||||
|
double mark1distance = GPSCoordinate.calculateDistanceMeters(getMark1Position(), coordinate);
|
||||||
|
double mark2distance = GPSCoordinate.calculateDistanceMeters(getMark2Position(), coordinate);
|
||||||
|
return mark1distance <= mark2distance? mark1 : mark2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean rayCast(MockBoat boat) {
|
||||||
|
GPSCoordinate position = boat.getCurrentPosition();
|
||||||
|
double distance = GPSCoordinate.calculateDistanceMeters(position, closestMark(position).getPosition());
|
||||||
|
Bearing bearing = Bearing.fromAzimuth(GPSCoordinate.calculateAzimuth(position, closestMark(position).getPosition()));
|
||||||
|
if(distance < 100) {
|
||||||
|
onCollisionEnter(new Collision(bearing, distance));
|
||||||
|
return true;
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCollisionEnter(Collision e) {
|
||||||
|
System.out.println(e.getBearing().degrees());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import javafx.beans.property.IntegerProperty;
|
|||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.beans.property.SimpleIntegerProperty;
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import mock.model.collider.ColliderRegistry;
|
||||||
import network.Messages.Enums.RaceStatusEnum;
|
import network.Messages.Enums.RaceStatusEnum;
|
||||||
import network.Messages.Enums.RaceTypeEnum;
|
import network.Messages.Enums.RaceTypeEnum;
|
||||||
import network.Messages.LatestMessages;
|
import network.Messages.LatestMessages;
|
||||||
@@ -20,90 +21,72 @@ import java.util.List;
|
|||||||
* Has a course, state, wind, boundaries, etc.... Boats are added by inheriting classes (see {@link Boat}, {@link mock.model.MockBoat}, {@link visualiser.model.VisualiserBoat}.
|
* Has a course, state, wind, boundaries, etc.... Boats are added by inheriting classes (see {@link Boat}, {@link mock.model.MockBoat}, {@link visualiser.model.VisualiserBoat}.
|
||||||
*/
|
*/
|
||||||
public abstract class Race {
|
public abstract class Race {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source of race related data.
|
* The source of race related data.
|
||||||
*/
|
*/
|
||||||
protected RaceDataSource raceDataSource;
|
protected RaceDataSource raceDataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source of boat related data.
|
* The source of boat related data.
|
||||||
*/
|
*/
|
||||||
protected BoatDataSource boatDataSource;
|
protected BoatDataSource boatDataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source of regatta related data.
|
* The source of regatta related data.
|
||||||
*/
|
*/
|
||||||
protected RegattaDataSource regattaDataSource;
|
protected RegattaDataSource regattaDataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The collection of latest race messages.
|
* The collection of latest race messages.
|
||||||
* Can be either read from or written to.
|
* Can be either read from or written to.
|
||||||
*/
|
*/
|
||||||
protected LatestMessages latestMessages;
|
protected LatestMessages latestMessages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of compound marks in the race.
|
* A list of compound marks in the race.
|
||||||
*/
|
*/
|
||||||
protected List<CompoundMark> compoundMarks;
|
protected List<CompoundMark> compoundMarks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of legs in the race.
|
* A list of legs in the race.
|
||||||
*/
|
*/
|
||||||
protected List<Leg> legs;
|
protected List<Leg> legs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of coordinates describing the boundary of the course.
|
* A list of coordinates describing the boundary of the course.
|
||||||
*/
|
*/
|
||||||
protected List<GPSCoordinate> boundary;
|
protected List<GPSCoordinate> boundary;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The clock which tracks the race's start time, current time, and elapsed duration.
|
* The clock which tracks the race's start time, current time, and elapsed duration.
|
||||||
*/
|
*/
|
||||||
protected RaceClock raceClock;
|
protected RaceClock raceClock;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The race ID of the course.
|
* The race ID of the course.
|
||||||
*/
|
*/
|
||||||
protected int raceId;
|
protected int raceId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the regatta.
|
* The name of the regatta.
|
||||||
*/
|
*/
|
||||||
protected String regattaName;
|
protected String regattaName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current status of the race.
|
* The current status of the race.
|
||||||
*/
|
*/
|
||||||
protected RaceStatusEnum raceStatusEnum;
|
protected RaceStatusEnum raceStatusEnum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of race this is.
|
* The type of race this is.
|
||||||
*/
|
*/
|
||||||
protected RaceTypeEnum raceType;
|
protected RaceTypeEnum raceType;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The race's wind.
|
* The race's wind.
|
||||||
*/
|
*/
|
||||||
protected Property<Wind> raceWind = new SimpleObjectProperty<>();
|
protected Property<Wind> raceWind = new SimpleObjectProperty<>();
|
||||||
|
/**
|
||||||
|
* Registry for all collider object in this race
|
||||||
|
*/
|
||||||
|
protected ColliderRegistry colliderRegistry;
|
||||||
/**
|
/**
|
||||||
* The number of frames per second.
|
* The number of frames per second.
|
||||||
* We essentially track the number of frames generated per second, over a one second period. When {@link #lastFpsResetTime} reaches 1 second, {@link #currentFps} is reset.
|
* We essentially track the number of frames generated per second, over a one second period. When {@link #lastFpsResetTime} reaches 1 second, {@link #currentFps} is reset.
|
||||||
*/
|
*/
|
||||||
private int currentFps = 0;
|
private int currentFps = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of frames per second we generated over the last 1 second period.
|
* The number of frames per second we generated over the last 1 second period.
|
||||||
*/
|
*/
|
||||||
private IntegerProperty lastFps = new SimpleIntegerProperty(0);
|
private IntegerProperty lastFps = new SimpleIntegerProperty(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time, in milliseconds, since we last reset our {@link #currentFps} counter.
|
* The time, in milliseconds, since we last reset our {@link #currentFps} counter.
|
||||||
*/
|
*/
|
||||||
@@ -156,9 +139,13 @@ public abstract class Race {
|
|||||||
//Wind.
|
//Wind.
|
||||||
this.setWind(Bearing.fromDegrees(0), 0);
|
this.setWind(Bearing.fromDegrees(0), 0);
|
||||||
|
|
||||||
|
this.colliderRegistry = new ColliderRegistry();
|
||||||
|
this.colliderRegistry.addAllColliders(compoundMarks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ColliderRegistry getColliderRegistry() {
|
||||||
|
return colliderRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise the boats in the race.
|
* Initialise the boats in the race.
|
||||||
@@ -272,14 +259,6 @@ public abstract class Race {
|
|||||||
return raceWind.getValue().getWindSpeed();
|
return raceWind.getValue().getWindSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the race's wind.
|
|
||||||
* @return The race's wind.
|
|
||||||
*/
|
|
||||||
public Property<Wind> windProperty() {
|
|
||||||
return raceWind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the RaceClock for this race.
|
* Returns the RaceClock for this race.
|
||||||
* This is used to track the start time, current time, and elapsed duration of the race.
|
* This is used to track the start time, current time, and elapsed duration of the race.
|
||||||
|
|||||||
Reference in New Issue
Block a user