-
Notifications
You must be signed in to change notification settings - Fork 30
/
Board.java
177 lines (154 loc) · 6.31 KB
/
Board.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
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.*;
public class Board extends JPanel implements ActionListener, KeyListener {
// controls the delay between each tick in ms
private final int DELAY = 25;
// controls the size of the board
public static final int TILE_SIZE = 50;
public static final int ROWS = 12;
public static final int COLUMNS = 18;
// controls how many coins appear on the board
public static final int NUM_COINS = 5;
// suppress serialization warning
private static final long serialVersionUID = 490905409104883233L;
// keep a reference to the timer object that triggers actionPerformed() in
// case we need access to it in another method
private Timer timer;
// objects that appear on the game board
private Player player;
private ArrayList<Coin> coins;
public Board() {
// set the game board size
setPreferredSize(new Dimension(TILE_SIZE * COLUMNS, TILE_SIZE * ROWS));
// set the game board background color
setBackground(new Color(232, 232, 232));
// initialize the game state
player = new Player();
coins = populateCoins();
// this timer will call the actionPerformed() method every DELAY ms
timer = new Timer(DELAY, this);
timer.start();
}
@Override
public void actionPerformed(ActionEvent e) {
// this method is called by the timer every DELAY ms.
// use this space to update the state of your game or animation
// before the graphics are redrawn.
// prevent the player from disappearing off the board
player.tick();
// give the player points for collecting coins
collectCoins();
// calling repaint() will trigger paintComponent() to run again,
// which will refresh/redraw the graphics.
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// when calling g.drawImage() we can use "this" for the ImageObserver
// because Component implements the ImageObserver interface, and JPanel
// extends from Component. So "this" Board instance, as a Component, can
// react to imageUpdate() events triggered by g.drawImage()
// draw our graphics.
drawBackground(g);
drawScore(g);
for (Coin coin : coins) {
coin.draw(g, this);
}
player.draw(g, this);
// this smooths out animations on some systems
Toolkit.getDefaultToolkit().sync();
}
@Override
public void keyTyped(KeyEvent e) {
// this is not used but must be defined as part of the KeyListener interface
}
@Override
public void keyPressed(KeyEvent e) {
// react to key down events
player.keyPressed(e);
}
@Override
public void keyReleased(KeyEvent e) {
// react to key up events
}
private void drawBackground(Graphics g) {
// draw a checkered background
g.setColor(new Color(214, 214, 214));
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
// only color every other tile
if ((row + col) % 2 == 1) {
// draw a square tile at the current row/column position
g.fillRect(
col * TILE_SIZE,
row * TILE_SIZE,
TILE_SIZE,
TILE_SIZE
);
}
}
}
}
private void drawScore(Graphics g) {
// set the text to be displayed
String text = "$" + player.getScore();
// we need to cast the Graphics to Graphics2D to draw nicer text
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(
RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
// set the text color and font
g2d.setColor(new Color(30, 201, 139));
g2d.setFont(new Font("Lato", Font.BOLD, 25));
// draw the score in the bottom center of the screen
// https://stackoverflow.com/a/27740330/4655368
FontMetrics metrics = g2d.getFontMetrics(g2d.getFont());
// the text will be contained within this rectangle.
// here I've sized it to be the entire bottom row of board tiles
Rectangle rect = new Rectangle(0, TILE_SIZE * (ROWS - 1), TILE_SIZE * COLUMNS, TILE_SIZE);
// determine the x coordinate for the text
int x = rect.x + (rect.width - metrics.stringWidth(text)) / 2;
// determine the y coordinate for the text
// (note we add the ascent, as in java 2d 0 is top of the screen)
int y = rect.y + ((rect.height - metrics.getHeight()) / 2) + metrics.getAscent();
// draw the string
g2d.drawString(text, x, y);
}
private ArrayList<Coin> populateCoins() {
ArrayList<Coin> coinList = new ArrayList<>();
Random rand = new Random();
// create the given number of coins in random positions on the board.
// note that there is not check here to prevent two coins from occupying the same
// spot, nor to prevent coins from spawning in the same spot as the player
for (int i = 0; i < NUM_COINS; i++) {
int coinX = rand.nextInt(COLUMNS);
int coinY = rand.nextInt(ROWS);
coinList.add(new Coin(coinX, coinY));
}
return coinList;
}
private void collectCoins() {
// allow player to pickup coins
ArrayList<Coin> collectedCoins = new ArrayList<>();
for (Coin coin : coins) {
// if the player is on the same tile as a coin, collect it
if (player.getPos().equals(coin.getPos())) {
// give the player some points for picking this up
player.addScore(100);
collectedCoins.add(coin);
}
}
// remove collected coins from the board
coins.removeAll(collectedCoins);
}
}