mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Added mark collisions
- Boats now collide with marks - Added method to MarkOrder to get all marks - Reduced the frequency at which collisions are detected. This fixed some performance issues - Added method to bounce the boat off a mark Tags: #story[1117]
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
package seng302.gameServer;
|
package seng302.gameServer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
@@ -13,6 +11,8 @@ import seng302.model.Player;
|
|||||||
import seng302.model.Yacht;
|
import seng302.model.Yacht;
|
||||||
import seng302.gameServer.server.messages.BoatActionType;
|
import seng302.gameServer.server.messages.BoatActionType;
|
||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
|
import seng302.model.mark.Mark;
|
||||||
|
import seng302.model.mark.MarkOrder;
|
||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,6 +33,7 @@ public class GameState implements Runnable {
|
|||||||
private static Boolean isRaceStarted;
|
private static Boolean isRaceStarted;
|
||||||
private static GameStages currentStage;
|
private static GameStages currentStage;
|
||||||
private static long startTime;
|
private static long startTime;
|
||||||
|
private static Set<Mark> marks;
|
||||||
|
|
||||||
private static Map<Player, String> playerStringMap = new HashMap<>();
|
private static Map<Player, String> playerStringMap = new HashMap<>();
|
||||||
/*
|
/*
|
||||||
@@ -62,12 +63,18 @@ public class GameState implements Runnable {
|
|||||||
yachts = new HashMap<>();
|
yachts = new HashMap<>();
|
||||||
|
|
||||||
new Thread(this).start();
|
new Thread(this).start();
|
||||||
|
|
||||||
|
marks = new MarkOrder().getAllMarks();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getHostIpAddress() {
|
public static String getHostIpAddress() {
|
||||||
return hostIpAddress;
|
return hostIpAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<Mark> getMarks(){
|
||||||
|
return Collections.unmodifiableSet(marks);
|
||||||
|
}
|
||||||
|
|
||||||
public static List<Player> getPlayers() {
|
public static List<Player> getPlayers() {
|
||||||
return players;
|
return players;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||||
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
||||||
import javafx.beans.property.ReadOnlyLongProperty;
|
import javafx.beans.property.ReadOnlyLongProperty;
|
||||||
@@ -31,6 +33,9 @@ public class Yacht {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final Double ROUNDING_DISTANCE = 15d; // TODO: 3/08/17 wmu16 - Look into this value further
|
private static final Double ROUNDING_DISTANCE = 15d; // TODO: 3/08/17 wmu16 - Look into this value further
|
||||||
|
private static final Double COLLISION_DISTANCE = ROUNDING_DISTANCE - 8d;
|
||||||
|
private static final Double BOUNCE_FACTOR = 0.0001;
|
||||||
|
private static final Integer COLLISION_UPDATE_INTERVAL = 100;
|
||||||
|
|
||||||
//BOTH AFAIK
|
//BOTH AFAIK
|
||||||
private String boatType;
|
private String boatType;
|
||||||
@@ -61,6 +66,7 @@ public class Yacht {
|
|||||||
private Boolean hasEnteredRoundingZone; //The distance that the boat must be from the mark to round
|
private Boolean hasEnteredRoundingZone; //The distance that the boat must be from the mark to round
|
||||||
private Boolean hasPassedFirstLine; //The line extrapolated from the next mark to the current mark
|
private Boolean hasPassedFirstLine; //The line extrapolated from the next mark to the current mark
|
||||||
private Boolean hasPassedSecondLine; //The line extrapolated from the last mark to the current mark
|
private Boolean hasPassedSecondLine; //The line extrapolated from the last mark to the current mark
|
||||||
|
private Long lastCollisionUpdate;
|
||||||
|
|
||||||
//CLIENT SIDE
|
//CLIENT SIDE
|
||||||
private List<YachtLocationListener> locationListeners = new ArrayList<>();
|
private List<YachtLocationListener> locationListeners = new ArrayList<>();
|
||||||
@@ -90,6 +96,18 @@ public class Yacht {
|
|||||||
this.hasPassedSecondLine = false;
|
this.hasPassedSecondLine = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Mark markCollidedWith(){
|
||||||
|
Set<Mark> marksInRace = GameState.getMarks();
|
||||||
|
|
||||||
|
for (Mark mark : marksInRace){
|
||||||
|
if (GeoUtility.getDistance(getLocation(), new GeoPoint(mark.getLat(), mark.getLng())) <= COLLISION_DISTANCE){
|
||||||
|
return mark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param timeInterval since last update in milliseconds
|
* @param timeInterval since last update in milliseconds
|
||||||
*/
|
*/
|
||||||
@@ -126,11 +144,18 @@ public class Yacht {
|
|||||||
Double metersCovered = velocity * secondsElapsed;
|
Double metersCovered = velocity * secondsElapsed;
|
||||||
GeoPoint calculatedPoint = getGeoCoordinate(location, heading, metersCovered);
|
GeoPoint calculatedPoint = getGeoCoordinate(location, heading, metersCovered);
|
||||||
|
|
||||||
// Collision detection. Update boat only if no collision.
|
if (shouldDoCollisionUpdate()){
|
||||||
Yacht collidedYacht = checkCollision(calculatedPoint);
|
Yacht collidedYacht = checkCollision(calculatedPoint);
|
||||||
if (collidedYacht != null) {
|
|
||||||
// System.out.println("Collision of boat " + this.getSourceId() + " and " + collidedYacht.getSourceId());
|
if (collidedYacht != null || markCollidedWith() != null) {
|
||||||
} else {
|
location = calculateBounceBack(new GeoPoint(markCollidedWith().getLat(), markCollidedWith().getLng()));
|
||||||
|
} else {
|
||||||
|
location = calculatedPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastCollisionUpdate = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
else {
|
||||||
location = calculatedPoint;
|
location = calculatedPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +168,45 @@ public class Yacht {
|
|||||||
// TODO: 3/08/17 wmu16 - Implement line cross check here
|
// TODO: 3/08/17 wmu16 - Implement line cross check here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if COLLISION_UPDATE_INTERVAL has elapsed since the last collision update
|
||||||
|
*/
|
||||||
|
private Boolean shouldDoCollisionUpdate(){
|
||||||
|
if (lastCollisionUpdate == null) {
|
||||||
|
lastCollisionUpdate = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
return System.currentTimeMillis() - lastCollisionUpdate > COLLISION_UPDATE_INTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the new position of the boat after it has had a collision
|
||||||
|
* @return The boats new position
|
||||||
|
*/
|
||||||
|
private GeoPoint calculateBounceBack(GeoPoint collidedWith){
|
||||||
|
Double lat = location.getLat();
|
||||||
|
Double lon = location.getLng();
|
||||||
|
|
||||||
|
Double heading = GeoUtility.getBearing(location, collidedWith);
|
||||||
|
|
||||||
|
|
||||||
|
if (heading >= 0 && heading <= 180){
|
||||||
|
lat -= BOUNCE_FACTOR;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
lat += BOUNCE_FACTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heading >= 90 && heading <= 360-90){
|
||||||
|
lon += BOUNCE_FACTOR;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
lon -= BOUNCE_FACTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GeoPoint(lat, lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the distance to the next mark (closest of the two if a gate mark).
|
* Calculates the distance to the next mark (closest of the two if a gate mark).
|
||||||
|
|||||||
@@ -15,10 +15,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to hold the order of the marks in the race.
|
* Class to hold the order of the marks in the race.
|
||||||
@@ -26,6 +23,7 @@ import java.util.Map;
|
|||||||
public class MarkOrder {
|
public class MarkOrder {
|
||||||
private List<Mark> raceMarkOrder;
|
private List<Mark> raceMarkOrder;
|
||||||
private Logger logger = LoggerFactory.getLogger(MarkOrder.class);
|
private Logger logger = LoggerFactory.getLogger(MarkOrder.class);
|
||||||
|
private Set<Mark> allMarks;
|
||||||
|
|
||||||
public MarkOrder(){
|
public MarkOrder(){
|
||||||
loadRaceProperties();
|
loadRaceProperties();
|
||||||
@@ -67,6 +65,10 @@ public class MarkOrder {
|
|||||||
return nextRacePosition;
|
return nextRacePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<Mark> getAllMarks(){
|
||||||
|
return Collections.unmodifiableSet(allMarks);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the race order from an XML string
|
* Loads the race order from an XML string
|
||||||
* @param xml An AC35 RaceXML
|
* @param xml An AC35 RaceXML
|
||||||
@@ -77,6 +79,7 @@ public class MarkOrder {
|
|||||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||||
DocumentBuilder db;
|
DocumentBuilder db;
|
||||||
Document doc;
|
Document doc;
|
||||||
|
allMarks = new HashSet<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db = dbf.newDocumentBuilder();
|
db = dbf.newDocumentBuilder();
|
||||||
@@ -97,6 +100,7 @@ public class MarkOrder {
|
|||||||
for (Corner corner : corners){
|
for (Corner corner : corners){
|
||||||
CompoundMark compoundMark = marks.get(corner.getCompoundMarkID());
|
CompoundMark compoundMark = marks.get(corner.getCompoundMarkID());
|
||||||
course.add(compoundMark.getMarks().get(0));
|
course.add(compoundMark.getMarks().get(0));
|
||||||
|
allMarks.addAll(compoundMark.getMarks());
|
||||||
}
|
}
|
||||||
|
|
||||||
return course;
|
return course;
|
||||||
|
|||||||
Reference in New Issue
Block a user