blob: 49aa1968b0f3f5966cd2f0dbc3a10a1597112ad1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
package fr.umlv.java.wallj.context;
import fr.umlv.java.wallj.block.Block;
import fr.umlv.java.wallj.block.BlockFactory;
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.*;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.World;
import java.time.Duration;
import java.util.*;
/**
* @author Pacien TRAN-GIRARD
*/
public class Stage implements Updateable {
private static final int VELOCITY_TICK_PER_MS = 6;
private static final int POSITION_TICK_PER_MS = 2;
private final World world = new World(new Vec2());
private final List<Block> blocks = new LinkedList<>();
private final Board board;
/**
* @param board the base board
*/
public Stage(Board board) {
this.board = Objects.requireNonNull(board);
blocks.addAll(BoardConverter.boardToWorld(board));
blocks.add(BlockFactory.build(BlockType.ROBOT, findAnyFreeTile(board)));
blocks.forEach(block -> block.link(world));
}
/**
* @return the JBox2D world
*/
public World getWorld() {
return world;
}
/**
* @return the base board
*/
public Board getBoard() {
return board;
}
/**
* @return the list of blocks
*/
public List<Block> getBlocks() {
return Collections.unmodifiableList(blocks);
}
/**
* @return T(this stage is cleared, i.e. does not contain any garbage block)
* @implNote TODO: profile this and consider a garbage block counter
*/
public boolean isCleared() {
return blocks.stream().noneMatch(block -> block.getType() == BlockType.GARBAGE);
}
/**
* @param context the current context
* @return the list of newly generated events
*/
@Override
public List<Event> update(Context context) {
updatePhysicalWorld(context.getTimeDelta());
handleBlockDestruction(context.getEvents());
handleBlockCreation(context.getEvents());
return Updateable.updateAll(blocks, context);
}
private void updatePhysicalWorld(Duration timeDelta) {
int dt = (int) timeDelta.toMillis();
world.step(dt, dt * VELOCITY_TICK_PER_MS, dt * POSITION_TICK_PER_MS);
}
private void handleBlockDestruction(List<Event> events) {
Events.filter(events, BlockDestroyEvent.class).forEach(event -> {
if (blocks.remove(event.getBlock())) event.getBlock().unlink(world);
});
}
private void handleBlockCreation(List<Event> events) {
Events.filter(events, BlockCreateEvent.class).forEach(event -> {
Block block = BlockFactory.build(event.getBlockType(), event.getPos());
blocks.add(block);
block.link(world);
});
}
private static TileVec2 findAnyFreeTile(Board board) {
return board.stream()
.filter(entry -> entry.getValue() == BlockType.FREE)
.findAny()
.map(Map.Entry::getKey)
.orElseThrow(IllegalArgumentException::new);
}
}
|