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
main
Connor Taylor-Brown 8 years ago
parent 851bbb4fde
commit 554f8a2a0f

@ -1,12 +1,20 @@
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 shared.model.Race;
import visualiser.gameController.ControllerServer;
public class RaceLogic implements Runnable {
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
*/
@ -16,6 +24,8 @@ public class RaceLogic implements Runnable {
*/
private RaceServer server;
private CompositeCommand commands;
/**
* Initialises race loop with state and server message queue
* @param race state of race to modify
@ -24,6 +34,7 @@ public class RaceLogic implements Runnable {
public RaceLogic(MockRace race, LatestMessages messages) {
this.race = race;
this.server = new RaceServer(race, messages);
this.commands = new CompositeCommand();
}
/**
@ -123,7 +134,7 @@ public class RaceLogic implements Runnable {
//If it is still racing, update its position.
if (boat.getStatus() == BoatStatusEnum.RACING) {
commands.execute();
race.updatePosition(boat, framePeriod, race.getRaceClock().getDurationMilli());
}
@ -173,4 +184,13 @@ public class RaceLogic implements Runnable {
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));
}
}

@ -19,6 +19,8 @@ public class CommandFactory {
switch(action) {
case AUTO_PILOT: return new VMGCommand(race, boat);
case TACK_GYBE: return new TackGybeCommand(race, boat);
case UPWIND: return new WindCommand(race, boat, true);
case DOWNWIND: return new WindCommand(race, boat, false);
default: return null; // TODO - please please have discussion over what to default to
}
}

@ -0,0 +1,23 @@
package mock.model.commandFactory;
import java.util.Stack;
/**
* Wraps multiple commands into a composite to execute queued commands during a frame.
*/
public class CompositeCommand implements Command {
private Stack<Command> commands;
public CompositeCommand() {
this.commands = new Stack<>();
}
public void addCommand(Command command) {
commands.push(command);
}
@Override
public void execute() {
while(!commands.isEmpty()) commands.pop().execute();
}
}

@ -0,0 +1,30 @@
package mock.model.commandFactory;
import mock.model.MockBoat;
import mock.model.MockRace;
import shared.model.Bearing;
/**
* Created by connortaylorbrown on 4/08/17.
*/
public class WindCommand implements Command {
private MockRace race;
private MockBoat boat;
private int direction;
public WindCommand(MockRace race, MockBoat boat, boolean upwind) {
this.race = race;
this.boat = boat;
this.direction = upwind? 1 : -1;
}
@Override
public void execute() {
double wind = race.getWindDirection().degrees();
double heading = boat.getBearing().degrees();
double offset = 3;
if(wind - heading < 0) offset *= -1 * direction;
boat.setBearing(Bearing.fromDegrees(heading + offset));
}
}

@ -1,5 +1,7 @@
package visualiser.gameController;
import mock.model.commandFactory.Command;
import mock.model.commandFactory.CommandFactory;
import network.BinaryMessageDecoder;
import network.MessageDecoders.BoatActionDecoder;
import network.Messages.Enums.BoatActionEnum;
@ -9,11 +11,12 @@ import visualiser.gameController.Keys.KeyFactory;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Observable;
/**
* Service for dispatching key press data to race from client
*/
public class ControllerServer implements Runnable {
public class ControllerServer extends Observable implements Runnable {
/**
* Socket to client
*/
@ -22,6 +25,10 @@ public class ControllerServer implements Runnable {
* Wrapper for input from client
*/
private DataInputStream inputStream;
/**
* Last received boat action
*/
private BoatActionEnum action;
/**
* Initialise server-side controller with live client socket
@ -36,6 +43,10 @@ public class ControllerServer implements Runnable {
}
}
public BoatActionEnum getAction() {
return action;
}
/**
* Wait for controller key input from client and loop.
*/
@ -48,8 +59,10 @@ public class ControllerServer implements Runnable {
inputStream.read(message);
BinaryMessageDecoder encodedMessage = new BinaryMessageDecoder(message);
BoatActionDecoder boatActionDecoder = new BoatActionDecoder(encodedMessage.getMessageBody());
BoatActionEnum decodedMessage = boatActionDecoder.getBoatAction();
System.out.println("Received key: " + decodedMessage);
action = boatActionDecoder.getBoatAction();
this.notifyObservers();
this.setChanged();
}
} catch (IOException e) {
e.printStackTrace();

@ -27,8 +27,8 @@ public class KeyFactory {
keyState.put("SPACE", new VMGKey("VMG"));
keyState.put("SHIFT", new SailsToggleKey("Toggle Sails"));
keyState.put("ENTER", new TackGybeKey("Tack/Gybe"));
keyState.put("PAGE_UP", new UpWindKey("Upwind"));
keyState.put("PAGE_DOWN", new DownWindKey("Downwind"));
keyState.put("UP", new UpWindKey("Upwind"));
keyState.put("DOWN", new DownWindKey("Downwind"));
}
/**

@ -0,0 +1,31 @@
package mock.model.commandFactory;
import mock.model.MockRace;
import network.Messages.Enums.BoatActionEnum;
import org.junit.Before;
import org.junit.Test;
import shared.model.Boat;
import shared.model.Race;
import visualiser.model.VisualiserRace;
import static org.testng.Assert.*;
/**
* Created by connortaylorbrown on 4/08/17.
*/
public class WindCommandTest {
private Race race;
private Boat boat;
private Command upwind;
private Command downwind;
@Before
public void setUp() {
boat = new Boat(0, "Bob", "NZ");
}
@Test
public void upwindCommandDecreasesAngle() {
}
}
Loading…
Cancel
Save