From 6c0fa25c9d6829e9a3990d952571433751616bee Mon Sep 17 00:00:00 2001 From: pacien Date: Sun, 4 Feb 2018 13:40:07 +0100 Subject: Handle simulation start Signed-off-by: pacien --- .../java/fr/umlv/java/wallj/block/BombBlock.java | 10 ++++- .../java/fr/umlv/java/wallj/block/RobotBlock.java | 21 ++++++++++ .../java/fr/umlv/java/wallj/context/Stage.java | 45 ++++++++++++++-------- 3 files changed, 60 insertions(+), 16 deletions(-) (limited to 'src') 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 { private static final Duration MAX_TIME = Duration.ofSeconds(9); private Duration timer = MIN_TIME; + private boolean ignited = false; BombBlock(Vec2 pos) { super(BlockType.BOMB, BodyType.STATIC, SolidDef.squareShape(), pos); @@ -44,6 +45,7 @@ public class BombBlock extends JBoxBlock { public Stream update(Context context) { return Updateables.updateAll(context, this::handleBombConfiguration, + this::handleSimulationStart, this::consume, this::paint); } @@ -55,8 +57,14 @@ public class BombBlock extends JBoxBlock { return Stream.empty(); } + private Stream handleSimulationStart(Context context) { + Events.findFirst(context.getEvents(), SimulationStartEvent.class) + .ifPresent(startEvent -> ignited = true); + return Stream.empty(); + } + private Stream consume(Context context) { - decrementTimer(context.getTimeDelta()); + if (ignited) decrementTimer(context.getTimeDelta()); return timer.isNegative() ? Stream.of(new BombExplosionEvent(TileVec2.of(getPos())), new BlockDestroyEvent(this)) : 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; public class RobotBlock extends Block { private static final float SPEED = 10f; // px/ms + private final TileVec2 initialPos; private Vec2 pos; private PathFinder pathFinder; private Deque path = new LinkedList<>(); private int droppedBombCount = 0; + private boolean isHiding = false; RobotBlock(Vec2 pos) { super(BlockType.ROBOT); + this.initialPos = TileVec2.of(pos); this.pos = pos; } @@ -51,12 +54,29 @@ public class RobotBlock extends Block { @Override public Stream update(Context context) { return Updateables.updateAll(context, + this::handleSimulationStart, this::updatePath, this::move, + this::disappear, this::paint, this::setupBomb); } + private Stream handleSimulationStart(Context context) { + return Events.findFirst(context.getEvents(), SimulationStartEvent.class) + .map(startEvent -> { + isHiding = true; + return Stream.of(new MoveRobotOrder(initialPos)); + }) + .orElse(Stream.empty()); + } + + private Stream disappear(Context context) { + return isHiding && Objects.equals(TileVec2.of(pos), initialPos) ? + Stream.of(new BlockDestroyEvent(this)) : + Stream.empty(); + } + private Stream setupBomb(Context context) { return Events.findFirst(context.getEvents(), BombSetupOrder.class) .flatMap(event -> isOnBomb(context.getGame().getCurrentStage()) ? @@ -78,6 +98,7 @@ public class RobotBlock extends Block { Board board = context.getGame().getCurrentStage().getBoard(); TileVec2 target = event.getTarget(); if (!board.inside(target) || !board.getBlockTypeAt(target).isTraversable()) return; + if (isHiding && !Objects.equals(target, initialPos)) return; if (pathFinder == null) pathFinder = new PathFinder(board); path = new LinkedList<>(pathFinder.findPath(TileVec2.of(pos), target)); }); 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; import fr.umlv.java.wallj.board.Board; import fr.umlv.java.wallj.board.BoardConverter; import fr.umlv.java.wallj.board.TileVec2; -import fr.umlv.java.wallj.event.BlockCreateEvent; -import fr.umlv.java.wallj.event.BlockDestroyEvent; -import fr.umlv.java.wallj.event.Event; -import fr.umlv.java.wallj.event.Events; +import fr.umlv.java.wallj.event.*; import org.jbox2d.common.Vec2; import org.jbox2d.dynamics.World; @@ -27,6 +24,7 @@ public class Stage implements Updateable { private final World world = new World(new Vec2()); private final List blocks = new LinkedList<>(); private final Board board; + private boolean running = false; /** * @param board the base board @@ -68,15 +66,6 @@ public class Stage implements Updateable { .noneMatch(block -> block.getType() == BlockType.GARBAGE); } - /** - * @return T(the physics simulation can start, i.e. the player has placed all their bombs) - */ - public boolean isReady() { - return blocks.stream() - .filter(block -> block.getType() == BlockType.BOMB) - .count() == BOMB_PLACEMENTS; - } - /** * @param context the current context * @return the stream of newly generated events @@ -84,15 +73,32 @@ public class Stage implements Updateable { @Override public Stream update(Context context) { return Updateables.updateAll(context, + this::handleSimulationStartOrder, + this::handleSimulationStartEvent, this::updatePhysicalWorld, this::handleBlockDestruction, this::handleBlockCreation, ctx -> Updateables.updateAll(ctx, blocks)); } + private Stream handleSimulationStartOrder(Context context) { + return Events.findFirst(context.getEvents(), SimulationStartOrder.class) + .flatMap(order -> isReady() ? Optional.of(new SimulationStartEvent()) : Optional.empty()) + .map(Stream::of) // Optional.stream() only available in Java 9 + .orElseGet(Stream::empty); + } + + private Stream handleSimulationStartEvent(Context context) { + Events.findFirst(context.getEvents(), SimulationStartEvent.class) + .ifPresent(startEvent -> running = true); + return Stream.empty(); + } + private Stream updatePhysicalWorld(Context context) { - int dt = (int) context.getTimeDelta().toMillis(); - world.step(dt, dt * VELOCITY_TICK_PER_MS, dt * POSITION_TICK_PER_MS); + if (running) { + int dt = (int) context.getTimeDelta().toMillis(); + world.step(dt, dt * VELOCITY_TICK_PER_MS, dt * POSITION_TICK_PER_MS); + } return Stream.empty(); } @@ -112,6 +118,15 @@ public class Stage implements Updateable { return Stream.empty(); } + /** + * @implNote TODO: profile this and consider a bomb block counter + */ + private boolean isReady() { + return blocks.stream() + .filter(block -> block.getType() == BlockType.BOMB) + .count() == BOMB_PLACEMENTS; + } + private static TileVec2 findAnyFreeTile(Board board) { return board.stream() .filter(entry -> entry.getValue() == BlockType.FREE) -- cgit v1.2.3