Compare commits

..

6 Commits

19 changed files with 93 additions and 95 deletions
+24 -8
View File
@@ -1,13 +1,29 @@
# SENG302 Project Template
# Party Parrots At Sea
Basic Maven project with required Maven reporting setup and basic GitLab CI.
**Authors:** Michael Rausch, William Muir, Haoming Yin, Alistair Mcintyre, Kusal Ekanayake, Calum Irwin, Peter Galloway, Tan Zhi You
It is a requirement that your product should be completely built to a deliverable form using the Maven package goal.
### SENG302
> The Software Engineering group project gives students in-depth experience in developing software applications in groups. Participants work in groups to develop a complex real application. At the end of this course you will have practiced the skills required to be a Software Engineer in the real world, including gaining the required skills to be able to develop complex applications, dealing with vague (and often conflicting) customer requirements, working under pressure and being a valuable member of a software development team.
Remember to set up your GitLab CI server (refer to the student guide for instructions).
**Find out more:** www.canterbury.ac.nz/courseinfo/GetCourses.aspx?course=SENG302
# Basic Project Structure
- `src/` Your application source
- `doc/` User and design documentation
- `doc/examples/` Demo example files for use with your application
### Running the discovery server
```
xvfb-run -a -e server.log java -jar app.jar -runAsDiscoveryServer
```
### Video
https://youtu.be/aHxJsfZLg54
### Screenshots
![Party Parrots At Sea](https://i.imgur.com/Aw5RIS6.png)
![Party Parrots At Sea](https://i.imgur.com/qOzlIet.png)
![Party Parrots At Sea](https://i.imgur.com/UfO9YTg.png)
![Party Parrots At Sea](https://i.imgur.com/BfMdDzM.png)
![Party Parrots At Sea](https://i.imgur.com/jHDRFKQ.png)
![Party Parrots At Sea](https://i.imgur.com/rerOeNo.png)
+6 -12
View File
@@ -13,9 +13,6 @@ import org.slf4j.LoggerFactory;
import seng302.discoveryServer.DiscoveryServer;
import seng302.visualiser.controllers.ViewManager;
import java.util.Timer;
import java.util.TimerTask;
public class App extends Application {
private static Logger logger = LoggerFactory.getLogger(App.class);
@@ -95,15 +92,12 @@ public class App extends Application {
}
public static void main(String[] args) throws Exception {
/*
* Do not trust Java to do garbage collection
*/
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.gc();
}
}, 0, 1_000);
// new Timer().schedule(new TimerTask() {
// @Override
// public void run() {
// System.gc();
// }
// }, 0, 1_000);
try {
parseArgs(args);
@@ -1,5 +1,6 @@
package seng302.discoveryServer;
import javafx.application.Platform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seng302.discoveryServer.util.ServerListing;
@@ -41,7 +42,10 @@ public class DiscoveryServerClient {
private void failError() {
isInInvalidState = true;
ViewManager.getInstance().showErrorSnackBar("You do not appear to be able to connect to the internet. Matchmaking will be unavailable.");
Platform.runLater(() -> {
ViewManager.getInstance().showErrorSnackBar("You do not appear to be able to connect to the internet. Matchmaking will be unavailable.");
});
}
public boolean didFail(){
@@ -11,6 +11,7 @@ import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;
import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.scene.paint.Color;
import org.slf4j.Logger;
@@ -98,7 +99,7 @@ public class GameState implements Runnable {
private static long startTime;
private static Set<Mark> marks = new HashSet<>();
private static List<Limit> courseLimit = new ArrayList<>();
private static Integer maxPlayers = 8;
private static Integer maxPlayers = 12;
private static List<Token> tokensInPlay;
private static RandomSpawn randomSpawn;
@@ -113,7 +114,7 @@ public class GameState implements Runnable {
windDirectionProperty.set(windDirection);
windSpeed = 10000d;
yachts = new HashMap<>();
tokensInPlay = new ArrayList<>();
tokensInPlay = new CopyOnWriteArrayList<>();
players = new ArrayList<>();
customizationFlag = false;
playerHasLeftFlag = false;
@@ -123,7 +124,7 @@ public class GameState implements Runnable {
newMessageListeners = new ArrayList<>();
resetStartTime();
//setCourseLimit("/server_config/race.xml");
new Thread(this, "GameState").start(); //Run the auto updates on the game state
}
@@ -284,13 +284,13 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
private void initialiseBoatPositions() {
final double DISTANCE_TO_START = 75d;
final double YACHT_SEPARATION = 20d;
final double YACHT_SEPARATION = 35d;
//Length of start line
double startLineLength = GeoUtility.getDistance(
GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(1),
GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(2)
);
) - YACHT_SEPARATION;
//How many yachts can fit along the start line
int spacesAlongLine = (int) Math.round(startLineLength / YACHT_SEPARATION);
@@ -312,7 +312,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
GameState.getMarkOrder().getMarkOrder().get(1).getMidPoint()
);
GeoPoint startingPoint = GeoUtility.getGeoCoordinate(
GeoPoint midPoint = GeoUtility.getGeoCoordinate(
GameState.getMarkOrder().getMarkOrder().get(0).getMidPoint(),
angleToStart, DISTANCE_TO_START
);
@@ -321,26 +321,24 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
Collections.shuffle(randomisedYachts);
while (randomisedYachts.size() > 0) {
int numYachtsInLine =
spacesAlongLine > randomisedYachts.size() ? randomisedYachts.size()
: spacesAlongLine;
double yachtSpace = numYachtsInLine * YACHT_SEPARATION / 2;
int numYachts = spacesAlongLine > randomisedYachts.size() ? randomisedYachts.size() : spacesAlongLine;
double yachtSpace = (numYachts - 1) * YACHT_SEPARATION / 2;
GeoPoint firstYachtPoint = GeoUtility.getGeoCoordinate(
startingPoint, startMarkToMarkAngle + 180, yachtSpace
midPoint, startMarkToMarkAngle + 180, yachtSpace
);
for (int i = 0; i < numYachtsInLine; i++) {
for (int i = 0; i < numYachts; i++) {
randomisedYachts.get(0).setHeading(angleFromStart);
randomisedYachts.get(0).setLocation(firstYachtPoint);
firstYachtPoint = GeoUtility.getGeoCoordinate(
firstYachtPoint, startMarkToMarkAngle, yachtSpace
firstYachtPoint, startMarkToMarkAngle, YACHT_SEPARATION
);
randomisedYachts.remove(0);
}
startingPoint = GeoUtility.getGeoCoordinate(
startingPoint, angleToStart, DISTANCE_TO_START
midPoint = GeoUtility.getGeoCoordinate(
midPoint, angleToStart, YACHT_SEPARATION * 1.5
);
}
}
@@ -206,7 +206,7 @@ public class MapPreview extends GameView {
}
GeoPoint secondToLastMarkAv = new GeoPoint(averageLat / numMarks, averageLng / numMarks);
for (Mark mark : course.get(course.size()-1).getMarks()) {
markerObjects.get(mark).addArrows(
markerObjects.get(mark).addFinishArrow(
mark.getRoundingSide() == RoundingSide.STARBOARD ? MarkArrowFactory.RoundingSide.STARBOARD : MarkArrowFactory.RoundingSide.PORT,
GeoUtility.getBearing(secondToLastMarkAv, mark),
GeoUtility.getBearing(mark, mark)
@@ -5,14 +5,12 @@ import com.jfoenix.controls.JFXDialog;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.collections.ListChangeListener;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
@@ -20,7 +18,6 @@ import javafx.geometry.Point3D;
import javafx.scene.Group;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
@@ -43,7 +40,6 @@ import seng302.utilities.Sounds;
import seng302.visualiser.MapPreview;
import seng302.visualiser.controllers.cells.PlayerCell;
import seng302.visualiser.controllers.dialogs.BoatCustomizeController;
import seng302.visualiser.controllers.dialogs.PopupDialogController;
import seng302.visualiser.controllers.dialogs.TokenInfoDialogController;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
import seng302.visualiser.fxObjects.assets_3D.ModelType;
@@ -357,8 +353,8 @@ public class LobbyController implements Initializable {
}
/**
*
* @param raceState
* Updates the state of the race and changes the value
* @param raceState the new race state
*/
public void updateRaceState(RaceState raceState){
this.raceState = raceState;
@@ -364,7 +364,6 @@ public class RaceViewController extends Thread {
if (yacht == player) {
blinkingTimer.cancel();
iconToDisplay.setVisible(false);
iconToDisplay = null;
}
}
@@ -86,16 +86,6 @@ public class MarkArrowFactory {
*/
public static Group constructEntryArrow (RoundingSide roundingSide, double angleOfEntry,
double angleOfExit, Paint colour) {
// Check to see if the the angle around mark would take you inside of it. (less than 180)
// If so make interior angle.
if (roundingSide == RoundingSide.PORT && angleOfEntry < angleOfExit &&
Math.abs(angleOfExit - angleOfEntry) < 180) {
return makeInteriorAngle(roundingSide, angleOfExit, angleOfEntry, colour);
} else if (roundingSide == RoundingSide.STARBOARD && angleOfEntry > angleOfExit &&
-Math.abs(angleOfEntry - angleOfExit) > -180) {
return makeInteriorAngle(roundingSide, angleOfExit, angleOfEntry, colour);
}
//Create regular exit arrow.
Group arrow = new Group();
Group exitSection = constructExitArrow(roundingSide, angleOfExit, colour);
@@ -132,7 +122,9 @@ public class MarkArrowFactory {
* @param colour colour of arrow
* @return the arrow.
*/
private static Group makeInteriorAngle (RoundingSide roundingSide, double angleOfExit, double angleOfEntry, Paint colour) {
public static Group constructInteriorArrow(RoundingSide roundingSide, double angleOfExit,
double angleOfEntry, Paint colour) {
Group arrow = new Group();
Polygon lineSegment;
//Reverse angle of exit/entry to find position between them
@@ -16,6 +16,9 @@ public abstract class Marker extends Group{
protected int exitArrowIndex = 0;
public abstract void addArrows(RoundingSide roundingSide, double entryAngle, double exitAngle);
public abstract void addFinishArrow(RoundingSide roundingSide, double entryAngle, double exitAngle);
/**
* Shows the next EnterArrow. Does nothing if there are no more enter arrows. Other arrows become hidden.
*/
@@ -7,6 +7,7 @@ import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import seng302.visualiser.fxObjects.MarkArrowFactory;
import seng302.visualiser.fxObjects.MarkArrowFactory.RoundingSide;
import seng302.visualiser.fxObjects.Marker;
/**
@@ -57,6 +58,14 @@ public class Marker2D extends Marker {
);
}
@Override
public void addFinishArrow(RoundingSide roundingSide, double entryAngle, double exitAngle){
enterArrows.add(
MarkArrowFactory.constructInteriorArrow(roundingSide, entryAngle, exitAngle, Color.RED)
);
exitArrows.add(new Group());
}
/**
* Shows the next EnterArrow. Does nothing if there are no more enter arrows. Other arrows
* become hidden.
@@ -55,6 +55,16 @@ public class Marker3D extends Marker {
);
}
public void addFinishArrow(RoundingSide roundingSide, double entryAngle,
double exitAngle) {
enterArrows.add(
MarkArrowFactory.constructEntryArrow3D(roundingSide, entryAngle, ModelType.FINISH_ARROW).getAssets()
);
exitArrows.add(
MarkArrowFactory.constructExitArrow3D(roundingSide, exitAngle, ModelType.FINISH_ARROW).getAssets()
);
}
@Override
protected void showArrow(List<Group> arrowList, int arrowListIndex) {
if (arrowListIndex < arrowList.size()) {
+1 -1
View File
@@ -6,7 +6,7 @@
<CentralLat> 57.6679590 </CentralLat>
<CentralLng> 11.8503233 </CentralLng>
<MaxPlayers> 10 </MaxPlayers>
<MaxPlayers> 8 </MaxPlayers>
<Marks>
<CompoundMark CompoundMarkID="1">
+1 -1
View File
@@ -6,7 +6,7 @@
<CentralLat> -14.6457 </CentralLat>
<CentralLng> 47.612855 </CentralLng>
<MaxPlayers> 5 </MaxPlayers>
<MaxPlayers> 8 </MaxPlayers>
<Marks>
<CompoundMark CompoundMarkID="1">
+1 -1
View File
@@ -6,7 +6,7 @@
<CentralLat> 57.6679590 </CentralLat>
<CentralLng> 11.8503233 </CentralLng>
<MaxPlayers> 5 </MaxPlayers>
<MaxPlayers> 8 </MaxPlayers>
<Marks>
<CompoundMark CompoundMarkID="1">
+1 -1
View File
@@ -6,7 +6,7 @@
<CentralLat>-15.67707</CentralLat>
<CentralLng>49.79338</CentralLng>
<MaxPlayers>10</MaxPlayers>
<MaxPlayers> 5 </MaxPlayers>
<Marks>
<CompoundMark CompoundMarkID="1">
+8 -8
View File
@@ -6,7 +6,7 @@
<CentralLat>-36.80008</CentralLat>
<CentralLng>175.012225</CentralLng>
<MaxPlayers>10</MaxPlayers>
<MaxPlayers> 6 </MaxPlayers>
<Marks>
<CompoundMark CompoundMarkID="1">
@@ -32,13 +32,13 @@
<Course>
<OpeningSegment>
<Corner CompoundMarkID="1" Rounding="PS"/>
<Corner CompoundMarkID="1" Rounding="SP"/>
<Corner CompoundMarkID="2" Rounding="P"/>
</OpeningSegment>
<RepeatingSegment>
<Corner CompoundMarkID="3" Rounding="SP"/>
<Corner CompoundMarkID="4" Rounding="PS"/>
<Corner CompoundMarkID="3" Rounding="PS"/>
<Corner CompoundMarkID="4" Rounding="SP"/>
</RepeatingSegment>
<ClosingSegment>
@@ -47,14 +47,14 @@
</Course>
<CourseLimit>
<Limit Lat="-36.7938" Lng="175.01194"/>
<Limit Lat="-36.79411" Lng="175.01555"/>
<Limit Lat="-36.79350" Lng="175.01194"/>
<Limit Lat="-36.79411" Lng="175.01455"/>
<Limit Lat="-36.79765" Lng="175.01898"/>
<Limit Lat="-36.79909" Lng="175.02149"/>
<Limit Lat="-36.80163" Lng="175.02014"/>
<Limit Lat="-36.80292" Lng="175.0175"/>
<Limit Lat="-36.80325" Lng="175.01008"/>
<Limit Lat="-36.80107" Lng="175.0089"/>
<Limit Lat="-36.80295" Lng="175.01008"/>
<Limit Lat="-36.80107" Lng="175.00960"/>
<Limit Lat="-36.79567" Lng="175.00961"/>
</CourseLimit>
+2 -15
View File
@@ -1,25 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.scene.*?>
<?import com.jfoenix.controls.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import com.jfoenix.controls.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import com.jfoenix.controls.JFXButton?>
<?import java.lang.String?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<StackPane fx:id="serverListMainStackPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.LobbyController">
<children>
+1 -12
View File
@@ -6,18 +6,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXTextField?>
<?import java.lang.String?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<StackPane fx:id="serverListMainStackPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.ServerListController">
<children>