Files
SENG302/racevisionGame/src/main/java/mock/model/RaceLogic.java
T
Connor Taylor-Brown 554f8a2a0f Added WindCommand and multiple command execution to RaceLogic
- Dispatch commands with CompositeCommand
- Single WindCommand handles upwind and downwind logic
- Changed key bindings as Mac lacks PgUp PgDn
- ControllerServer is observable, RaceLogic updates CompositeCommand as observer
2017-08-04 23:08:07 +12:00

197 lines
5.4 KiB
Java

package mock.model;
import javafx.animation.AnimationTimer;
import mock.model.commandFactory.Command;
import mock.model.commandFactory.CommandFactory;
import mock.model.commandFactory.CompositeCommand;
import network.Messages.Enums.BoatActionEnum;
import network.Messages.Enums.BoatStatusEnum;
import network.Messages.Enums.RaceStatusEnum;
import network.Messages.LatestMessages;
import visualiser.gameController.ControllerServer;
import java.util.Observable;
import java.util.Observer;
import java.util.Stack;
public class RaceLogic implements Observer, Runnable {
/**
* State of current race modified by this object
*/
private MockRace race;
/**
* High-level interface to AC35 protocol server
*/
private RaceServer server;
private CompositeCommand commands;
/**
* Initialises race loop with state and server message queue
* @param race state of race to modify
* @param messages to send to server
*/
public RaceLogic(MockRace race, LatestMessages messages) {
this.race = race;
this.server = new RaceServer(race, messages);
this.commands = new CompositeCommand();
}
/**
* Initialise boats and start countdown timer
*/
@Override
public void run() {
race.initialiseBoats();
this.countdownTimer.start();
}
/**
* Countdown timer until race starts.
*/
protected AnimationTimer countdownTimer = new AnimationTimer() {
long currentTime = System.currentTimeMillis();
@Override
public void handle(long arg0) {
//Update race time.
race.updateRaceTime(currentTime);
//Update the race status based on the current time.
race.updateRaceStatusEnum();
//Provide boat's with an estimated time at next mark until the race starts.
race.setBoatsTimeNextMark(race.getRaceClock().getCurrentTime());
//Parse the boat locations.
server.parseBoatLocations();
//Parse the marks.
server.parseMarks();
// Change wind direction
race.changeWindDirection();
//Parse the race status.
server.parseRaceStatus();
if (race.getRaceStatusEnum() == RaceStatusEnum.STARTED) {
race.setBoatsStatusToRacing();
raceTimer.start();
this.stop();
}
//Update the animations timer's time.
currentTime = System.currentTimeMillis();
}
};
/**
* Timer that runs for the duration of the race, until all boats finish.
*/
private AnimationTimer raceTimer = new AnimationTimer() {
/**
* Start time of loop, in milliseconds.
*/
long timeRaceStarted = System.currentTimeMillis();
/**
* Current time during a loop iteration.
*/
long currentTime = System.currentTimeMillis();
/**
* The time of the previous frame, in milliseconds.
*/
long lastFrameTime = timeRaceStarted;
long framePeriod = currentTime - lastFrameTime;
@Override
public void handle(long arg0) {
//Get the current time.
currentTime = System.currentTimeMillis();
//Update race time.
race.updateRaceTime(currentTime);
//As long as there is at least one boat racing, we still simulate the race.
if (race.getNumberOfActiveBoats() != 0) {
//Get the time period of this frame.
framePeriod = currentTime - lastFrameTime;
//For each boat, we update its position, and generate a BoatLocationMessage.
for (MockBoat boat : race.getBoats()) {
//If it is still racing, update its position.
if (boat.getStatus() == BoatStatusEnum.RACING) {
commands.execute();
race.updatePosition(boat, framePeriod, race.getRaceClock().getDurationMilli());
}
}
} else {
//Otherwise, the race is over!
raceFinished.start();
race.setRaceStatusEnum(RaceStatusEnum.FINISHED);
this.stop();
}
if (race.getNumberOfActiveBoats() != 0) {
// Change wind direction
race.changeWindDirection();
//Parse the boat locations.
server.parseBoatLocations();
//Parse the marks.
server.parseMarks();
//Parse the race status.
server.parseRaceStatus();
//Update the last frame time.
this.lastFrameTime = currentTime;
}
}
};
/**
* Broadcast that the race has finished.
*/
protected AnimationTimer raceFinished = new AnimationTimer(){
int iters = 0;
@Override
public void handle(long now) {
server.parseRaceStatus();
if (iters > 500) {
stop();
}
iters++;
}
};
@Override
public void update(Observable o, Object arg) {
ControllerServer server = (ControllerServer)o;
BoatActionEnum action = server.getAction();
MockBoat boat = race.getBoats().get(0);
commands.addCommand(CommandFactory.createCommand(race, boat, action));
}
}