diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index dcc5b407..0bdcb8c1 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -4,6 +4,9 @@ import mock.dataInput.PolarParser; import mock.exceptions.EventConstructionException; import mock.model.*; import mock.model.commandFactory.CompositeCommand; +import mock.model.wind.RandomWindGenerator; +import mock.model.wind.ShiftingWindGenerator; +import mock.model.wind.WindGenerator; import mock.xml.RaceXMLCreator; import network.Messages.LatestMessages; import org.xml.sax.SAXException; @@ -18,11 +21,8 @@ import shared.model.Constants; import javax.xml.bind.JAXBException; import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.TransformerException; import java.io.IOException; -import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; -import java.time.Duration; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; @@ -124,14 +124,10 @@ public class Event { this.compositeCommand = new CompositeCommand(); this.latestMessages = new LatestMessages(); - //Create and start race. - WindGenerator windGenerator = new RandomWindGenerator( + WindGenerator windGenerator = new ShiftingWindGenerator( Bearing.fromDegrees(225), - Bearing.fromDegrees(215), - Bearing.fromDegrees(235), - 12d, - 8d, - 16d ); + 12 + ); RaceLogic newRace = new RaceLogic( new MockRace( boatDataSource, diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index f606c29d..f62a016d 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -1,5 +1,6 @@ package mock.model; +import mock.model.wind.WindGenerator; import javafx.animation.AnimationTimer; import mock.model.collider.ColliderRegistry; import mock.xml.*; diff --git a/racevisionGame/src/main/java/mock/model/ConstantWindGenerator.java b/racevisionGame/src/main/java/mock/model/wind/ConstantWindGenerator.java similarity index 96% rename from racevisionGame/src/main/java/mock/model/ConstantWindGenerator.java rename to racevisionGame/src/main/java/mock/model/wind/ConstantWindGenerator.java index ae14daac..6cdfafe9 100644 --- a/racevisionGame/src/main/java/mock/model/ConstantWindGenerator.java +++ b/racevisionGame/src/main/java/mock/model/wind/ConstantWindGenerator.java @@ -1,11 +1,9 @@ -package mock.model; +package mock.model.wind; import shared.model.Bearing; import shared.model.Wind; -import java.util.Random; - /** * This class generates Wind objects for use in a MockRace. * Initialised with a baseline wind speed and direction, and keeps it constant. diff --git a/racevisionGame/src/main/java/mock/model/RandomWindGenerator.java b/racevisionGame/src/main/java/mock/model/wind/RandomWindGenerator.java similarity index 99% rename from racevisionGame/src/main/java/mock/model/RandomWindGenerator.java rename to racevisionGame/src/main/java/mock/model/wind/RandomWindGenerator.java index 4f981b8d..bd7b13c3 100644 --- a/racevisionGame/src/main/java/mock/model/RandomWindGenerator.java +++ b/racevisionGame/src/main/java/mock/model/wind/RandomWindGenerator.java @@ -1,4 +1,4 @@ -package mock.model; +package mock.model.wind; import shared.model.Bearing; diff --git a/racevisionGame/src/main/java/mock/model/wind/ShiftingWindGenerator.java b/racevisionGame/src/main/java/mock/model/wind/ShiftingWindGenerator.java new file mode 100644 index 00000000..5d5e4995 --- /dev/null +++ b/racevisionGame/src/main/java/mock/model/wind/ShiftingWindGenerator.java @@ -0,0 +1,152 @@ +package mock.model.wind; + +import shared.model.Bearing; +import shared.model.Wind; + +import java.util.Random; + +public class ShiftingWindGenerator implements WindGenerator { + private Bearing baselineBearing; + private double baseLineSpeed; + private double windSpeedVariance = 5; + private double bearingVariance = 5; // In degrees + private double oscillationVariance = 0.25; + private double oscillationPeriod = 1e3 * 60 * 1; // In milliseconds + private double shiftTime = 1e3 * 60; + private double shiftedSoFar = 0; + + private double timeOfLastOscillationReset = 0; + private double timeOfLastChange = 0; + private double timeOfLastShift = 0; // Back / veer + + private boolean anticlockwise = false; + private boolean shiftAnticlockwise = false;//true for Back, false for veer + private boolean shiftThisRace = Math.random() > 0.5; + + /** + * Constructor + * @param baselineBearing baseline bearing for wind + * @param baseLineSpeed base line speed for wind + */ + public ShiftingWindGenerator(Bearing baselineBearing, double baseLineSpeed) { + this.baselineBearing = baselineBearing; + this.baseLineSpeed = baseLineSpeed; + initialiseOscillationDirection(); + } + + @Override + public Wind generateBaselineWind() { + return new Wind(baselineBearing, baseLineSpeed); + } + + @Override + public Wind generateNextWind(Wind currentWind) { + return changeWind(currentWind); + } + + /** + * @param wind the wind to change + * @return the changed wind + */ + private Wind changeWind(Wind wind) { + Wind newWind = new Wind(wind.getWindDirection(), wind.getWindSpeed()); + oscillateWind(newWind); + if (shiftThisRace){shiftWind(newWind);} + changeWindSpeed(newWind); + timeOfLastChange = System.currentTimeMillis(); + return newWind; + } + + /** + * moves the wind 5 degrees up and down + * @param wind the wind to oscillate + */ + private void oscillateWind(Wind wind) { + double timeSinceLastOscillationReset = System.currentTimeMillis() - timeOfLastOscillationReset; + double timeSinceLastChange = System.currentTimeMillis() - timeOfLastChange; + double newBearing = wind.getWindDirection().degrees(); + double degreeChange = timeSinceLastChange * 2 * bearingVariance / oscillationPeriod; + degreeChange = (1 - oscillationVariance) * degreeChange + (2 * oscillationVariance) * degreeChange * Math.random(); + + if (timeSinceLastOscillationReset >= oscillationPeriod) { + timeOfLastOscillationReset = System.currentTimeMillis(); + anticlockwise = !anticlockwise; + } + if (anticlockwise) { + newBearing -= degreeChange; + if (newBearing < baselineBearing.degrees() - bearingVariance) { + anticlockwise = !anticlockwise; + timeOfLastOscillationReset = System.currentTimeMillis(); + } else { + wind.setWindDirection(Bearing.fromDegrees(newBearing % 360)); + } + } else { + newBearing += degreeChange; + if (newBearing > baselineBearing.degrees() + bearingVariance) { + anticlockwise = !anticlockwise; + timeOfLastOscillationReset = System.currentTimeMillis(); + } else { + wind.setWindDirection(Bearing.fromDegrees(newBearing % 360)); + } + } + } + + /** + * Slowly shifts the wind up to 180 degrees from where it started + * @param wind the wind to change + */ + private void shiftWind(Wind wind) { + double timeSinceLastShift = System.currentTimeMillis() - timeOfLastShift; + double newBearing = wind.getWindDirection().degrees(); + double degreeChange = 7; + + if (timeSinceLastShift >= shiftTime){ + shiftedSoFar += degreeChange; + if (shiftedSoFar >= 180){ + shiftAnticlockwise = Math.random() > 0.5; + shiftedSoFar = 0; + System.out.println("Swapping"); + } + + timeOfLastShift = System.currentTimeMillis(); + if (shiftAnticlockwise){ + newBearing -= degreeChange; + wind.setWindDirection(Bearing.fromDegrees(newBearing % 360)); + } else { + newBearing += degreeChange; + wind.setWindDirection(Bearing.fromDegrees(newBearing % 360)); + } + } + } + + /** + * Change the wind speed + * @param wind the wind to change + */ + private void changeWindSpeed(Wind wind) { + double offsetAngle = (wind.getWindDirection().radians() - baselineBearing.radians()); + double offset = Math.sin(offsetAngle) * windSpeedVariance; + double newWindSpeed = baseLineSpeed + offset; + wind.setWindSpeed(newWindSpeed); + } + + /** + * starts the wind oscillation direction + */ + private void initialiseOscillationDirection() { + anticlockwise = new Random().nextBoolean(); + timeOfLastOscillationReset = System.currentTimeMillis(); + } + + public void setBearingVariance(double maxBearingVariance) { + this.bearingVariance = maxBearingVariance; + } + + public void setWindSpeedVariance(double windSpeedVariance) { + this.windSpeedVariance = windSpeedVariance; + } + + public void setOscillationPeriod(double oscillationPeriod) { + this.oscillationPeriod = oscillationPeriod; + } +} diff --git a/racevisionGame/src/main/java/mock/model/WindGenerator.java b/racevisionGame/src/main/java/mock/model/wind/WindGenerator.java similarity index 96% rename from racevisionGame/src/main/java/mock/model/WindGenerator.java rename to racevisionGame/src/main/java/mock/model/wind/WindGenerator.java index 8285d5d3..52ee2cd6 100644 --- a/racevisionGame/src/main/java/mock/model/WindGenerator.java +++ b/racevisionGame/src/main/java/mock/model/wind/WindGenerator.java @@ -1,4 +1,4 @@ -package mock.model; +package mock.model.wind; import shared.model.Wind; diff --git a/racevisionGame/src/main/java/shared/model/Wind.java b/racevisionGame/src/main/java/shared/model/Wind.java index 08d391c2..531d8473 100644 --- a/racevisionGame/src/main/java/shared/model/Wind.java +++ b/racevisionGame/src/main/java/shared/model/Wind.java @@ -48,4 +48,11 @@ public class Wind { return windSpeed; } + public void setWindSpeed(double windSpeed) { + this.windSpeed = windSpeed; + } + + public void setWindDirection(Bearing windDirection) { + this.windDirection = windDirection; + } } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/MainController.java b/racevisionGame/src/main/java/visualiser/Controllers/MainController.java index 57d18830..e1aa1ede 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/MainController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/MainController.java @@ -3,7 +3,6 @@ package visualiser.Controllers; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.layout.AnchorPane; -import visualiser.app.App; import visualiser.gameController.ControllerClient; import visualiser.model.VisualiserBoat; import visualiser.model.VisualiserRaceEvent; @@ -40,6 +39,7 @@ public class MainController extends Controller { * Transitions from the StartController screen (displays pre-race information) to the RaceController (displays the actual race). * @param visualiserRace The object modelling the race. * @param controllerClient Socket Client that manipulates the controller. + * @param isHost if the client is the host of a race or not. */ public void beginRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient, Boolean isHost) { raceController.startRace(visualiserRace, controllerClient, isHost); diff --git a/racevisionGame/src/main/resources/visualiser/images/arrow.png b/racevisionGame/src/main/resources/visualiser/images/arrow.png index fab6e21d..cd7bab10 100644 Binary files a/racevisionGame/src/main/resources/visualiser/images/arrow.png and b/racevisionGame/src/main/resources/visualiser/images/arrow.png differ diff --git a/racevisionGame/src/test/java/mock/model/ConstantWindGeneratorTest.java b/racevisionGame/src/test/java/mock/model/ConstantWindGeneratorTest.java index 6f67dc30..f7c69acf 100644 --- a/racevisionGame/src/test/java/mock/model/ConstantWindGeneratorTest.java +++ b/racevisionGame/src/test/java/mock/model/ConstantWindGeneratorTest.java @@ -1,5 +1,7 @@ package mock.model; +import mock.model.wind.ConstantWindGenerator; +import mock.model.wind.WindGenerator; import org.junit.Before; import org.junit.Test; import shared.model.Bearing; diff --git a/racevisionGame/src/test/java/mock/model/MockRaceTest.java b/racevisionGame/src/test/java/mock/model/MockRaceTest.java index 4f3f7705..f53b2970 100644 --- a/racevisionGame/src/test/java/mock/model/MockRaceTest.java +++ b/racevisionGame/src/test/java/mock/model/MockRaceTest.java @@ -1,7 +1,8 @@ package mock.model; import mock.dataInput.PolarParserTest; -import network.Messages.LatestMessages; +import mock.model.wind.ConstantWindGenerator; +import mock.model.wind.WindGenerator; import shared.dataInput.*; import shared.exceptions.InvalidBoatDataException; import shared.exceptions.InvalidRaceDataException; @@ -9,8 +10,6 @@ import shared.exceptions.InvalidRegattaDataException; import shared.model.Bearing; import shared.model.Constants; -import static org.junit.Assert.*; - public class MockRaceTest { //TODO diff --git a/racevisionGame/src/test/java/mock/model/RandomWindGeneratorTest.java b/racevisionGame/src/test/java/mock/model/RandomWindGeneratorTest.java index 76eed977..0f60bcea 100644 --- a/racevisionGame/src/test/java/mock/model/RandomWindGeneratorTest.java +++ b/racevisionGame/src/test/java/mock/model/RandomWindGeneratorTest.java @@ -1,5 +1,6 @@ package mock.model; +import mock.model.wind.RandomWindGenerator; import org.junit.Before; import org.junit.Test; import shared.model.Bearing; diff --git a/settings/keyBindings.xml b/settings/keyBindings.xml new file mode 100644 index 00000000..2b807e17 --- /dev/null +++ b/settings/keyBindings.xml @@ -0,0 +1,33 @@ + + + + + SPACE + + + + SHIFT + + + + DOWN + + + + X + + + + ENTER + + + + Z + + + + UP + + + +