This repository was archived by the owner on Jun 15, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGameMapView.java
319 lines (272 loc) · 9.62 KB
/
GameMapView.java
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.HashSet;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/**
* This is the view where the game is actually playable.
* Note that the first paint will be animated.
*/
public class GameMapView extends JPanel {
private static final long serialVersionUID = -8221311233615840987L;
public static final int WIDTH = 695;//Cell.DIST_TO_CORNER*2 * (GameMap.CELL_COLS-6);
public static final int HEIGHT = 650;//Cell.DIST_TO_EDGE*2 * (GameMap.CELL_ROWS+2);
private GameMap map;
private int index = 0; // used for animation
private Cell selected = null;
private Cell rightClicked = null;
private JPopupMenu popup = new JPopupMenu("Options");
private JMenuItem moveItem = new JMenuItem("Move");
private JMenuItem attackItem = new JMenuItem("Attack");
private JMenuItem skipItem = new JMenuItem("Skip Turn");
private ActionListener al;
private ArrayList<Player> players;
private Player playerTurn; //current player in control
private int movesRemaining; //current players moves
public GameMapView(GameMap m, ArrayList<Player> players) {
super(true); // double buffered
this.map = m;
this.players = players;
this.playerTurn = players.get(0);
this.movesRemaining = 1;
this.add(popup);
System.out.println("Loaded " + map.getName() + " (" + map.getCells().size() + " cells)");
Timer t = new Timer(10, new ActionListener() { // 1000ms / 10ms pf = 100fps
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
t.setInitialDelay(0);
t.start();
al = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//selected should never be null at this point
BasicWars o = ((BasicWars)getParent());
if (e.getSource().equals(skipItem)) {
//remove highlights for valid moves
for (Cell c : map.getCells())
c.setValidMove(false);
// deselect after attack
selected.setSelected(null);
selected = null;
nextPlayerTurn(o);
o.showSelected(null);
} else if (selected.getUnit().getPlayer() != playerTurn) {
o.showMessage("Player "+playerTurn.getNumber()+", are you trying to cheat?\nYou can't control a unit that you don't own!");
} else {
if (e.getSource().equals(moveItem)) {
// check if valid move
if (!canMoveToCell(selected, rightClicked)) {
o.showMessage("You can't move there, you're just a " + selected.getUnit().getType()+"! Surely you know the rules of battle?");
return;
}
// one less move available
movesRemaining--;
Unit u = selected.getUnit();
selected.setUnit(null);
for (Cell c : map.getCells())
c.setValidMove(false);
//TODO animate movement
rightClicked.setUnit(u);
selected.setSelected(null);
selected = rightClicked;
rightClicked = null;
o.showTurn(playerTurn, movesRemaining);
if (selected == null) // DEBUG
System.out.println("OMG: selected == null");
for (Cell c : getValidAttacks(selected))
c.setValidAttack(true);
selected.setSelected(o); //ensure color is correct
} else if (e.getSource().equals(attackItem)) {
Unit attacker = selected.getUnit();
Unit victim = rightClicked.getUnit();
//TODO animate attack
int damage = victim.attackedBy(attacker);
String overlayString = damage + " damage!";
if (victim.isDead()) {
rightClicked.setUnit(null);
overlayString += "\nVictim is dead.";
}
o.showOverlay(overlayString, rightClicked.getX(), rightClicked.getY());
//remove highlights for valid moves
for (Cell c : map.getCells())
c.setValidMove(false);
// deselect after attack
selected.setSelected(null);
selected = null;
o.showSelected(null);
//check if game over
if (!o.isGameOver()) {
nextPlayerTurn(o);
}
}
}
}
};
moveItem.addActionListener(al);
attackItem.addActionListener(al);
skipItem.addActionListener(al);
popup.add(moveItem);
popup.add(attackItem);
popup.addSeparator();
popup.add(skipItem);
this.addMouseListener(new MouseListener() {
@Override
public void mousePressed(MouseEvent e) {
ArrayList<Cell> cells = map.getCells();
BasicWars o = ((BasicWars)getParent());
if (SwingUtilities.isLeftMouseButton(e)) {
Cell clicked = null;
for (Cell c : cells) {
if (c.contains(e.getPoint())) {
//System.out.println("Cell " + cells.indexOf(c) + " selected!");
clicked = c;
break;
}
}
HashSet<Cell> validCells;
if (movesRemaining > 0)
validCells = getValidMoves(clicked);
else
validCells = getValidAttacks(clicked);
//System.out.println("Valid cells: " + validMoves.size()); //debug
for (Cell c : cells)
if (c.equals(clicked)) {
selected = c.setSelected(o);
} else {
c.setSelected(null);
if (validCells.contains(c) && clicked.getUnit().getPlayer() == playerTurn)
c.setValidMove(true);
else
c.setValidMove(false);
}
} else if (SwingUtilities.isRightMouseButton(e)) {
if (selected != null) {
for (Cell c : cells)
if (c.contains(e.getPoint())) {
rightClicked = c;
//System.out.println("Cell " + cells.indexOf(c) + " right-clicked!");
boolean isEmptyCell = (c.getUnit() == null);
boolean canMove = movesRemaining > 0;
boolean validMove = getValidMoves(selected).contains(rightClicked);
boolean validAttack = getValidAttacks(selected).contains(rightClicked) && !c.equals(selected);
moveItem.setEnabled(isEmptyCell && canMove && validMove);
attackItem.setEnabled(!isEmptyCell && validAttack);
popup.show(e.getComponent(), rightClicked.getX(), rightClicked.getY());
break;
}
}
}
}
@Override
public void mouseEntered(MouseEvent e) { }
@Override
public void mouseExited(MouseEvent e) { }
@Override
public void mouseClicked(MouseEvent e) { } // mousePressed is more responsive
@Override
public void mouseReleased(MouseEvent e) { }
});
}
@Override
public void paintComponent(Graphics graphics) {
if (isMapLoaded() || index == 0) {
Graphics2D g = (Graphics2D)graphics;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(BasicWars.BG_COLOR);
g.fillRect(0, 0, WIDTH, HEIGHT);
}
}
@Override
public void paintChildren(Graphics g) {
ArrayList<Cell> cells = map.getCells();
if (isMapLoaded()) {
for (Cell c : cells)
c.paintCell(g);
return;
}
cells.get(index+0).paintCell(g);
cells.get(index+1).paintCell(g);
cells.get(index+2).paintCell(g);
cells.get(index+3).paintCell(g);
cells.get(index+4).paintCell(g);
index += 5; // load 5 at a time
//cells.get(index+5).paintCell(g);
//cells.get(index+6).paintCell(g);
//cells.get(index+7).paintCell(g);
//cells.get(index+8).paintCell(g);
//cells.get(index+9).paintCell(g);
//index += 10; // load 10 at a time
}
public boolean isMapLoaded() {
return index+1 > map.getCells().size();
}
public Player getPlayerTurn() { return playerTurn; }
public int getMovesRemaining() { return movesRemaining; }
public Cell getSelected() { return selected; }
private void nextPlayerTurn(BasicWars o) {
int i = players.indexOf(playerTurn);
i++;
if (i < players.size())
playerTurn = players.get(i);
else
playerTurn = players.get(0);
this.movesRemaining = 1;
o.showTurn(playerTurn, movesRemaining);
}
/**
* @param c The center cell
* @return set of cells that are <= radius from c
*/
private HashSet<Cell> getValidMoves(Cell c) {
HashSet<Cell> set = new HashSet<Cell>(10);
if (c != null && c.getUnit() != null) {
addAdj(c, c, set, 1, c.getUnit().getMaxMoves(), false);
} //else return empty set
return set;
}
private HashSet<Cell> getValidAttacks(Cell c) {
HashSet<Cell> set = new HashSet<Cell>(10);
if (c != null && c.getUnit() != null) {
addAdj(c, c, set, 1, c.getUnit().getMaxAttackDist(), true);
} //else return empty set
return set;
}
private void addAdj(Cell start, Cell cur, HashSet<Cell> set, int i, int max, boolean attack) {
if (cur == null || i > max)
return;
for (Cell adj : cur.getAdjacentCells()) {
if (adj != null && (attack || canMoveToCell(start, adj)))
set.add(adj); // attacks are not limited by cell type
addAdj(start, adj, set, i+1, max, attack);
}
}
private boolean canMoveToCell(Cell from, Cell to) {
boolean validMove = false;
if (from == null || to == null)
return false;
switch (from.getUnit().getType()) {
case SOLDIER: //water yes, swamp no
validMove = (to.getType() != Cell.Type.SWAMP);
break;
case TANK: // water no, swamp yes
validMove = (to.getType() != Cell.Type.WATER);
break;
case PLANE: // only fly over water/swamp, must land on earth
validMove = (to.getType() == Cell.Type.EARTH);
break;
}
return validMove;
}
}