aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpacien2018-02-04 13:40:07 +0100
committerpacien2018-02-04 13:40:07 +0100
commit6c0fa25c9d6829e9a3990d952571433751616bee (patch)
tree9a8f6a32cf2187db96d2f7eabb953787d6d76a5d
parentd214d357ff0b03205ba9a8d753c93c9fa17094f3 (diff)
downloadwallj-6c0fa25c9d6829e9a3990d952571433751616bee.tar.gz
Handle simulation start
Signed-off-by: pacien <pacien.trangirard@pacien.net>
-rw-r--r--src/main/java/fr/umlv/java/wallj/block/BombBlock.java10
-rw-r--r--src/main/java/fr/umlv/java/wallj/block/RobotBlock.java21
-rw-r--r--src/main/java/fr/umlv/java/wallj/context/Stage.java45
3 files changed, 60 insertions, 16 deletions
diff --git a/src/main/java/fr/umlv/java/wallj/block/BombBlock.java b/src/main/java/fr/umlv/java/wallj/block/BombBlock.java
index 4f310eb..5570583 100644
--- a/src/main/java/fr/umlv/java/wallj/block/BombBlock.java
+++ b/src/main/java/fr/umlv/java/wallj/block/BombBlock.java
@@ -26,6 +26,7 @@ public class BombBlock extends JBoxBlock {
26 private static final Duration MAX_TIME = Duration.ofSeconds(9); 26 private static final Duration MAX_TIME = Duration.ofSeconds(9);
27 27
28 private Duration timer = MIN_TIME; 28 private Duration timer = MIN_TIME;
29 private boolean ignited = false;
29 30
30 BombBlock(Vec2 pos) { 31 BombBlock(Vec2 pos) {
31 super(BlockType.BOMB, BodyType.STATIC, SolidDef.squareShape(), pos); 32 super(BlockType.BOMB, BodyType.STATIC, SolidDef.squareShape(), pos);
@@ -44,6 +45,7 @@ public class BombBlock extends JBoxBlock {
44 public Stream<Event> update(Context context) { 45 public Stream<Event> update(Context context) {
45 return Updateables.updateAll(context, 46 return Updateables.updateAll(context,
46 this::handleBombConfiguration, 47 this::handleBombConfiguration,
48 this::handleSimulationStart,
47 this::consume, 49 this::consume,
48 this::paint); 50 this::paint);
49 } 51 }
@@ -55,8 +57,14 @@ public class BombBlock extends JBoxBlock {
55 return Stream.empty(); 57 return Stream.empty();
56 } 58 }
57 59
60 private Stream<Event> handleSimulationStart(Context context) {
61 Events.findFirst(context.getEvents(), SimulationStartEvent.class)
62 .ifPresent(startEvent -> ignited = true);
63 return Stream.empty();
64 }
65
58 private Stream<Event> consume(Context context) { 66 private Stream<Event> consume(Context context) {
59 decrementTimer(context.getTimeDelta()); 67 if (ignited) decrementTimer(context.getTimeDelta());
60 return timer.isNegative() ? 68 return timer.isNegative() ?
61 Stream.of(new BombExplosionEvent(TileVec2.of(getPos())), new BlockDestroyEvent(this)) : 69 Stream.of(new BombExplosionEvent(TileVec2.of(getPos())), new BlockDestroyEvent(this)) :
62 Stream.empty(); 70 Stream.empty();
diff --git a/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java b/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java
index 11cf25f..6909555 100644
--- a/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java
+++ b/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java
@@ -23,13 +23,16 @@ import java.util.stream.Stream;
23public class RobotBlock extends Block { 23public class RobotBlock extends Block {
24 private static final float SPEED = 10f; // px/ms 24 private static final float SPEED = 10f; // px/ms
25 25
26 private final TileVec2 initialPos;
26 private Vec2 pos; 27 private Vec2 pos;
27 private PathFinder pathFinder; 28 private PathFinder pathFinder;
28 private Deque<TileVec2> path = new LinkedList<>(); 29 private Deque<TileVec2> path = new LinkedList<>();
29 private int droppedBombCount = 0; 30 private int droppedBombCount = 0;
31 private boolean isHiding = false;
30 32
31 RobotBlock(Vec2 pos) { 33 RobotBlock(Vec2 pos) {
32 super(BlockType.ROBOT); 34 super(BlockType.ROBOT);
35 this.initialPos = TileVec2.of(pos);
33 this.pos = pos; 36 this.pos = pos;
34 } 37 }
35 38
@@ -51,12 +54,29 @@ public class RobotBlock extends Block {
51 @Override 54 @Override
52 public Stream<Event> update(Context context) { 55 public Stream<Event> update(Context context) {
53 return Updateables.updateAll(context, 56 return Updateables.updateAll(context,
57 this::handleSimulationStart,
54 this::updatePath, 58 this::updatePath,
55 this::move, 59 this::move,
60 this::disappear,
56 this::paint, 61 this::paint,
57 this::setupBomb); 62 this::setupBomb);
58 } 63 }
59 64
65 private Stream<Event> handleSimulationStart(Context context) {
66 return Events.findFirst(context.getEvents(), SimulationStartEvent.class)
67 .map(startEvent -> {
68 isHiding = true;
69 return Stream.<Event>of(new MoveRobotOrder(initialPos));
70 })
71 .orElse(Stream.empty());
72 }
73
74 private Stream<Event> disappear(Context context) {
75 return isHiding && Objects.equals(TileVec2.of(pos), initialPos) ?
76 Stream.of(new BlockDestroyEvent(this)) :
77 Stream.empty();
78 }
79
60 private Stream<Event> setupBomb(Context context) { 80 private Stream<Event> setupBomb(Context context) {
61 return Events.findFirst(context.getEvents(), BombSetupOrder.class) 81 return Events.findFirst(context.getEvents(), BombSetupOrder.class)
62 .flatMap(event -> isOnBomb(context.getGame().getCurrentStage()) ? 82 .flatMap(event -> isOnBomb(context.getGame().getCurrentStage()) ?
@@ -78,6 +98,7 @@ public class RobotBlock extends Block {
78 Board board = context.getGame().getCurrentStage().getBoard(); 98 Board board = context.getGame().getCurrentStage().getBoard();
79 TileVec2 target = event.getTarget(); 99 TileVec2 target = event.getTarget();
80 if (!board.inside(target) || !board.getBlockTypeAt(target).isTraversable()) return; 100 if (!board.inside(target) || !board.getBlockTypeAt(target).isTraversable()) return;
101 if (isHiding && !Objects.equals(target, initialPos)) return;
81 if (pathFinder == null) pathFinder = new PathFinder(board); 102 if (pathFinder == null) pathFinder = new PathFinder(board);
82 path = new LinkedList<>(pathFinder.findPath(TileVec2.of(pos), target)); 103 path = new LinkedList<>(pathFinder.findPath(TileVec2.of(pos), target));
83 }); 104 });
diff --git a/src/main/java/fr/umlv/java/wallj/context/Stage.java b/src/main/java/fr/umlv/java/wallj/context/Stage.java
index 44fad7b..9b66e03 100644
--- a/src/main/java/fr/umlv/java/wallj/context/Stage.java
+++ b/src/main/java/fr/umlv/java/wallj/context/Stage.java
@@ -6,10 +6,7 @@ import fr.umlv.java.wallj.block.BlockType;
6import fr.umlv.java.wallj.board.Board; 6import fr.umlv.java.wallj.board.Board;
7import fr.umlv.java.wallj.board.BoardConverter; 7import fr.umlv.java.wallj.board.BoardConverter;
8import fr.umlv.java.wallj.board.TileVec2; 8import fr.umlv.java.wallj.board.TileVec2;
9import fr.umlv.java.wallj.event.BlockCreateEvent; 9import fr.umlv.java.wallj.event.*;
10import fr.umlv.java.wallj.event.BlockDestroyEvent;
11import fr.umlv.java.wallj.event.Event;
12import fr.umlv.java.wallj.event.Events;
13import org.jbox2d.common.Vec2; 10import org.jbox2d.common.Vec2;
14import org.jbox2d.dynamics.World; 11import org.jbox2d.dynamics.World;
15 12
@@ -27,6 +24,7 @@ public class Stage implements Updateable {
27 private final World world = new World(new Vec2()); 24 private final World world = new World(new Vec2());
28 private final List<Block> blocks = new LinkedList<>(); 25 private final List<Block> blocks = new LinkedList<>();
29 private final Board board; 26 private final Board board;
27 private boolean running = false;
30 28
31 /** 29 /**
32 * @param board the base board 30 * @param board the base board
@@ -69,30 +67,38 @@ public class Stage implements Updateable {
69 } 67 }
70 68
71 /** 69 /**
72 * @return T(the physics simulation can start, i.e. the player has placed all their bombs)
73 */
74 public boolean isReady() {
75 return blocks.stream()
76 .filter(block -> block.getType() == BlockType.BOMB)
77 .count() == BOMB_PLACEMENTS;
78 }
79
80 /**
81 * @param context the current context 70 * @param context the current context
82 * @return the stream of newly generated events 71 * @return the stream of newly generated events
83 */ 72 */
84 @Override 73 @Override
85 public Stream<Event> update(Context context) { 74 public Stream<Event> update(Context context) {
86 return Updateables.updateAll(context, 75 return Updateables.updateAll(context,
76 this::handleSimulationStartOrder,
77 this::handleSimulationStartEvent,
87 this::updatePhysicalWorld, 78 this::updatePhysicalWorld,
88 this::handleBlockDestruction, 79 this::handleBlockDestruction,
89 this::handleBlockCreation, 80 this::handleBlockCreation,
90 ctx -> Updateables.updateAll(ctx, blocks)); 81 ctx -> Updateables.updateAll(ctx, blocks));
91 } 82 }
92 83
84 private Stream<Event> handleSimulationStartOrder(Context context) {
85 return Events.findFirst(context.getEvents(), SimulationStartOrder.class)
86 .flatMap(order -> isReady() ? Optional.<Event>of(new SimulationStartEvent()) : Optional.empty())
87 .map(Stream::of) // Optional.stream() only available in Java 9
88 .orElseGet(Stream::empty);
89 }
90
91 private Stream<Event> handleSimulationStartEvent(Context context) {
92 Events.findFirst(context.getEvents(), SimulationStartEvent.class)
93 .ifPresent(startEvent -> running = true);
94 return Stream.empty();
95 }
96
93 private Stream<Event> updatePhysicalWorld(Context context) { 97 private Stream<Event> updatePhysicalWorld(Context context) {
94 int dt = (int) context.getTimeDelta().toMillis(); 98 if (running) {
95 world.step(dt, dt * VELOCITY_TICK_PER_MS, dt * POSITION_TICK_PER_MS); 99 int dt = (int) context.getTimeDelta().toMillis();
100 world.step(dt, dt * VELOCITY_TICK_PER_MS, dt * POSITION_TICK_PER_MS);
101 }
96 return Stream.empty(); 102 return Stream.empty();
97 } 103 }
98 104
@@ -112,6 +118,15 @@ public class Stage implements Updateable {
112 return Stream.empty(); 118 return Stream.empty();
113 } 119 }
114 120
121 /**
122 * @implNote TODO: profile this and consider a bomb block counter
123 */
124 private boolean isReady() {
125 return blocks.stream()
126 .filter(block -> block.getType() == BlockType.BOMB)
127 .count() == BOMB_PLACEMENTS;
128 }
129
115