aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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.java24
-rw-r--r--src/main/java/fr/umlv/java/wallj/context/Stage.java45
3 files changed, 62 insertions, 17 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..1ab4f01 100644
--- a/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java
+++ b/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java
@@ -22,14 +22,18 @@ import java.util.stream.Stream;
22 */ 22 */
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 private static final float ROBOT_SIZE = TileVec2.TILE_DIM * 1.25f;
25 26
27 private final TileVec2 initialPos;
26 private Vec2 pos; 28 private Vec2 pos;
27 private PathFinder pathFinder; 29 private PathFinder pathFinder;
28 private Deque<TileVec2> path = new LinkedList<>(); 30 private Deque<TileVec2> path = new LinkedList<>();
29 private int droppedBombCount = 0; 31 private int droppedBombCount = 0;
32 private boolean isHiding = false;
30 33
31 RobotBlock(Vec2 pos) { 34 RobotBlock(Vec2 pos) {
32 super(BlockType.ROBOT); 35 super(BlockType.ROBOT);
36 this.initialPos = TileVec2.of(pos);
33 this.pos = pos; 37 this.pos = pos;
34 } 38 }
35 39
@@ -51,12 +55,29 @@ public class RobotBlock extends Block {
51 @Override 55 @Override
52 public Stream<Event> update(Context context) { 56 public Stream<Event> update(Context context) {
53 return Updateables.updateAll(context, 57 return Updateables.updateAll(context,
58 this::handleSimulationStart,
54 this::updatePath, 59 this::updatePath,
55 this::move, 60 this::move,
61 this::disappear,
56 this::paint, 62 this::paint,
57 this::setupBomb); 63 this::setupBomb);
58 } 64 }
59 65
66 private Stream<Event> handleSimulationStart(Context context) {
67 return Events.findFirst(context.getEvents(), SimulationStartEvent.class)
68 .map(startEvent -> {
69 isHiding = true;
70 return Stream.<Event>of(new MoveRobotOrder(initialPos));
71 })
72 .orElse(Stream.empty());
73 }
74
75 private Stream<Event> disappear(Context context) {
76 return isHiding && Objects.equals(TileVec2.of(pos), initialPos) ?
77 Stream.of(new BlockDestroyEvent(this)) :
78 Stream.empty();
79 }
80
60 private Stream<Event> setupBomb(Context context) { 81 private Stream<Event> setupBomb(Context context) {
61 return Events.findFirst(context.getEvents(), BombSetupOrder.class) 82 return Events.findFirst(context.getEvents(), BombSetupOrder.class)
62 .flatMap(event -> isOnBomb(context.getGame().getCurrentStage()) ? 83 .flatMap(event -> isOnBomb(context.getGame().getCurrentStage()) ?
@@ -78,6 +99,7 @@ public class RobotBlock extends Block {
78 Board board = context.getGame().getCurrentStage().getBoard(); 99 Board board = context.getGame().getCurrentStage().getBoard();
79 TileVec2 target = event.getTarget(); 100 TileVec2 target = event.getTarget();
80 if (!board.inside(target) || !board.getBlockTypeAt(target).isTraversable()) return; 101 if (!board.inside(target) || !board.getBlockTypeAt(target).isTraversable()) return;
102 if (isHiding && !Objects.equals(target, initialPos)) return;
81 if (pathFinder == null) pathFinder = new PathFinder(board); 103 if (pathFinder == null) pathFinder = new PathFinder(board);
82 path = new LinkedList<>(pathFinder.findPath(TileVec2.of(pos), target)); 104 path = new LinkedList<>(pathFinder.findPath(TileVec2.of(pos), target));
83 }); 105 });
@@ -96,7 +118,7 @@ public class RobotBlock extends Block {
96 } 118 }
97 119
98 private Stream<Event> paint(Context context) { 120 private Stream<Event> paint(Context context) {
99 context.getGraphicsContext().paintCircle(Color.BLUE, getPos(), TileVec2.TILE_DIM / 2); 121 context.getGraphicsContext().paintCircle(Color.BLUE, getPos(), ROBOT_SIZE);
100 return Stream.empty(); 122 return Stream.empty();
101 } 123 }
102 124
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 }