aboutsummaryrefslogtreecommitdiff
path: root/src/ch/epfl/xblast/client/XBlastComponent.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/ch/epfl/xblast/client/XBlastComponent.java')
-rw-r--r--src/ch/epfl/xblast/client/XBlastComponent.java178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/ch/epfl/xblast/client/XBlastComponent.java b/src/ch/epfl/xblast/client/XBlastComponent.java
new file mode 100644
index 0000000..388a208
--- /dev/null
+++ b/src/ch/epfl/xblast/client/XBlastComponent.java
@@ -0,0 +1,178 @@
1package ch.epfl.xblast.client;
2
3import ch.epfl.xblast.Cell;
4import ch.epfl.xblast.Lists;
5import ch.epfl.xblast.PlayerID;
6
7import javax.swing.*;
8import java.awt.*;
9import java.awt.image.ImageObserver;
10import java.util.*;
11import java.util.List;
12import java.util.stream.Collectors;
13import java.util.stream.IntStream;
14
15/**
16 * The game graphical component.
17 *
18 * @author Pacien TRAN-GIRARD (261948)
19 * @author Timothée FLOURE (257420)
20 */
21public final class XBlastComponent extends JComponent {
22
23 private static class Grid {
24
25 private static final Dimension CELL_DIMENSION = new Dimension(64, 48);
26 private static final Dimension SCORE_IMG_DIMENSION = new Dimension(48, 48);
27 private static final Dimension TIME_LED_DIMENSION = new Dimension(16, 16);
28 private static final Dimension FRAME_DIMENSION = totalDimension();
29
30 private static final List<Point> CELL_POSITIONS = buildCellGrid(CELL_DIMENSION);
31 private static final List<Point> SCORE_BG_POSITIONS = buildScoreGrid();
32 private static final List<Point> TIME_LINE_POSITIONS = buildTimeLineGrid();
33 private static final Map<PlayerID, Point> SCORE_TXT_POSITIONS = buildScoreMap(659);
34
35 private static Dimension totalDimension() {
36 return new Dimension(
37 CELL_DIMENSION.width * Cell.COLUMNS,
38 CELL_DIMENSION.height * Cell.ROWS + SCORE_IMG_DIMENSION.height + TIME_LED_DIMENSION.height);
39 }
40
41 private static List<Point> buildCellGrid(Dimension elementDim) {
42 return Collections.unmodifiableList(Cell.ROW_MAJOR_ORDER.stream()
43 .map(c -> new Point(c.x() * elementDim.width, c.y() * elementDim.height))
44 .collect(Collectors.toList()));
45 }
46
47 private static List<Point> buildLine(Dimension elementDim, int len, Point shift) {
48 return Collections.unmodifiableList(IntStream.range(0, len)
49 .mapToObj(x -> new Point(x * elementDim.width + shift.x, shift.y))
50 .collect(Collectors.toList()));
51 }
52
53 private static List<Point> buildScoreGrid() {
54 return buildLine(
55 SCORE_IMG_DIMENSION,
56 FRAME_DIMENSION.width / SCORE_IMG_DIMENSION.width,
57 new Point(0, CELL_DIMENSION.height * Cell.ROWS));
58 }
59
60 private static List<Point> buildTimeLineGrid() {
61 return buildLine(
62 TIME_LED_DIMENSION,
63 FRAME_DIMENSION.width / TIME_LED_DIMENSION.width,
64 new Point(0, CELL_DIMENSION.height * Cell.ROWS + SCORE_IMG_DIMENSION.height));
65 }
66
67 private static Map<PlayerID, Point> buildScoreMap(int vShift) {
68 Map<PlayerID, Point> m = new EnumMap<>(PlayerID.class);
69 m.put(PlayerID.PLAYER_1, new Point(96, vShift));
70 m.put(PlayerID.PLAYER_2, new Point(240, vShift));
71 m.put(PlayerID.PLAYER_3, new Point(768, vShift));
72 m.put(PlayerID.PLAYER_4, new Point(912, vShift));
73 return m;
74 }
75
76 private static Point positionForPlayer(GameState.Player p) {
77 return new Point(
78 4 * p.position().x() - 24,
79 3 * p.position().y() - 52);
80 }
81
82 }
83
84 private static class Painter {
85
86 private static final ImageObserver IMG_OBSERVER = null;
87 private static final Font TXT_FONT = new Font("Arial", Font.BOLD, 25);
88 private static final Color TXT_COLOR = Color.WHITE;
89
90 private static void drawString(Graphics2D g, Point pos, String str) {
91 g.setColor(TXT_COLOR);
92 g.setFont(TXT_FONT);
93 g.drawString(str, pos.x, pos.y);
94 }
95
96 private static void drawImage(Graphics2D g, Point pos, Image img) {
97 g.drawImage(img, pos.x, pos.y, IMG_OBSERVER);
98 }
99
100 private static void drawImageMap(Graphics2D g, Map<Point, Image> m) {
101 for (Map.Entry<Point, Image> e : m.entrySet())
102 drawImage(g, e.getKey(), e.getValue());
103 }
104
105 private static <T> void drawStringMap(Graphics2D g, Map<Point, T> m) {
106 for (Map.Entry<Point, T> e : m.entrySet())
107 drawString(g, e.getKey(), e.getValue().toString());
108 }
109
110 }
111
112 private static Comparator<GameState.Player> buildPlayerComparator(PlayerID blackSheep) {
113 Comparator<GameState.Player> coordinateComparator =
114 (p1, p2) -> p1.position().compareTo(p2.position());
115
116 Comparator<GameState.Player> idComparator =
117 (p1, p2) -> p1.id() == blackSheep ? -1 : 0;
118
119 return coordinateComparator.thenComparing(idComparator);
120 }
121
122 private GameState gameState;
123 private PlayerID playerID;
124
125 /**
126 * Display the given GameState from the point of view of the given playerID.
127 *
128 * @param gs GameState to be displayed
129 * @param pid playerID related to the view
130 */
131 public void setGameState(GameState gs, PlayerID pid) {
132 this.gameState = gs;
133 this.playerID = pid;
134 this.repaint();
135 }
136
137 /**
138 * Returns the value of the preferredSize property.
139 *
140 * @return the value of the preferredSize property
141 */
142 @Override
143 public Dimension getPreferredSize() {
144 return Grid.FRAME_DIMENSION;
145 }
146
147 /**
148 * Draw the component.
149 *
150 * @param g0 the Graphics context
151 */
152 @Override
153 protected void paintComponent(Graphics g0) {
154 Graphics2D g = (Graphics2D) g0;
155
156 if (Objects.isNull(this.gameState))
157 return;
158
159 Painter.drawImageMap(g, Lists.linearMap(Grid.CELL_POSITIONS, this.gameState.board()));
160 Painter.drawImageMap(g, Lists.linearMap(Grid.CELL_POSITIONS, this.gameState.explosions()));
161 Painter.drawImageMap(g, Lists.linearMap(Grid.SCORE_BG_POSITIONS, this.gameState.scores()));
162 Painter.drawImageMap(g, Lists.linearMap(Grid.TIME_LINE_POSITIONS, this.gameState.ticks()));
163 Painter.drawStringMap(g, Lists.traverseMaps(Lists.invertMap(Grid.SCORE_TXT_POSITIONS), this.gameState.playerScores()));
164 drawPlayers(g, Lists.sorted(this.gameState.players(), buildPlayerComparator(this.playerID)));
165 }
166
167 /**
168 * Draw the players on the graphic context.
169 *
170 * @param g the graphic context
171 * @param players the list of players to be displayed
172 */
173 private void drawPlayers(Graphics2D g, List<GameState.Player> players) {
174 for (GameState.Player p : players)
175 Painter.drawImage(g, Grid.positionForPlayer(p), p.image());
176 }
177
178}