-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGamePanel.java
More file actions
300 lines (248 loc) · 9.88 KB
/
GamePanel.java
File metadata and controls
300 lines (248 loc) · 9.88 KB
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
package snakeGame;
//Imports all the libraries that are needed
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
//Creates the GamePanel class that inherits the properties of the JPanel class and uses the ActionListener interface
public class GamePanel extends JPanel implements ActionListener {
//Create final variables for the game window size
static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
//Set the size of the squares in the game
static final int UNIT_SIZE = 25;
//Amount of squares in the game panel
static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
//Sets the delay of the timer
static final int DELAY = 75;
// Initializes two arrays for the snake body's x and y coordinates
final int x[] = new int[GAME_UNITS];
final int y[] = new int[GAME_UNITS];
//Sets the other class properties
int bodyParts = 5;
int applesEaten = 0;
int appleX;
int appleY;
//Sets the direction of the snake
char direction = 'R';
//Shows if the game is running for not
boolean running = false;
//Create a Random and Timer object
Timer timer;
Random random;
//The main constructor of the class
public GamePanel() {
//Declares the random variable to an instance of the Random class
random = new Random();
//Sets the preferred size of the panel to the screen width and height.
this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
//Sets the background to black
this.setBackground(Color.black);
//Sets focusability to true to allow player input
this.setFocusable(true);
//Adds a key listener object
this.addKeyListener(new MyKeyAdapter());
//runs the start game method
startGame();
}
//Method for starting the game
public void startGame() {
//Runs the new apple method
newApple();
//sets running to true
running = true;
//declares the time with the arguments delay for the delay and the action listener
timer = new Timer(DELAY, this);
//Starts the timer
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
//The method for drawing the games visuals
public void draw(Graphics g) {
//If the game is running then this code block is executed
if (running) {
//Loops to draw the grid lines on the screen
for (int i = 0; i < SCREEN_HEIGHT / UNIT_SIZE; i++) {
g.drawLine(i * UNIT_SIZE, 0, i * UNIT_SIZE, SCREEN_HEIGHT);
g.drawLine(0, i * UNIT_SIZE, SCREEN_WIDTH, i * UNIT_SIZE);
}
//sets the color to red
g.setColor(Color.red);
//makes a square at the randomly generated X and Y coordinates for the apple with the dimensions as the unit sizes
g.fillRect(appleX, appleY, UNIT_SIZE, UNIT_SIZE);
//Loops through the snakes bodyparts
for (int i = 0; i < bodyParts; i++) {
//if i is 0 then the body part is the head
if (i == 0) {
//makes it green
g.setColor(Color.green);
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
//else it makes the reset a different shade of green
} else {
g.setColor(new Color(133, 255, 2));
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
}
}
//sets the color to red
g.setColor(Color.red);
//sets the font of the text
g.setFont(new Font("Fixedsys", Font.BOLD, 40));
//Creates a new FontMetrics object
FontMetrics metrics = getFontMetrics(g.getFont());
//Draws the string at the location of the string metrics coordinates
g.drawString("Score: " + applesEaten, (SCREEN_WIDTH - metrics.stringWidth("Score: " + applesEaten))/2, g.getFont().getSize());
} else {
//Runs the game over method is the game is not running
gameOver(g);
}
}
//Method for setting the coordinates of the new apple
public void newApple() {
//randomly generates coordinates using the unit sizes
appleX = random.nextInt((int) SCREEN_WIDTH / UNIT_SIZE) * UNIT_SIZE;
appleY = random.nextInt((int) SCREEN_HEIGHT / UNIT_SIZE) * UNIT_SIZE;
//Loops through the body parts of the snake to check if the apple spawned there
for (int i=0; i < bodyParts; i++){
if (appleX == x[i] && appleY == y[i]){
newApple();
}
}
}
//Method for moving the snake
public void move() {
//Loops through the snake body and sets the coordinates of each body part to the last bodypart
for (int i = bodyParts; i > 0; i--) {
x[i] = x[i - 1];
y[i] = y[i - 1];
}
//Sets the coordinates and direction of the head of the snake based on the value of the direction variable
switch (direction) {
case 'U':
y[0] = y[0] - UNIT_SIZE;
break;
case 'D':
y[0] = y[0] + UNIT_SIZE;
break;
case 'L':
x[0] = x[0] - UNIT_SIZE;
break;
case 'R':
x[0] = x[0] + UNIT_SIZE;
break;
}
}
//Checks if the apple is touching the head of the snake
public void checkApple() {
if ((x[0] == appleX) && y[0] == appleY){
//increases the score and body parts variable
bodyParts++;
applesEaten++;
//Runs the new apple method to spawn another apple on the grid
newApple();
}
}
public void checkCollisions() {
//check if snake head collides with body
for (int i = bodyParts; i > 0; i--){
if ((x[0] == x[i]) && (y[0] == y[i])){
running = false;
}
}
//checks if snake hits left border
if (x[0] < 0){
running = false;
}
//check if snake head touches right border
if (x[0] > SCREEN_WIDTH - UNIT_SIZE){
running = false;
}
//check if snake head touches top border
if (y[0] < 0){
running = false;
}
//checks if snake head touches bottom border
if (y[0] > SCREEN_HEIGHT - UNIT_SIZE){
running = false;
}
//Checks to see if the running is not true to stop timer
if (!running){
timer.stop();
}
}
//Method for calling game over
public void gameOver(Graphics g) {
//Game over text
g.setColor(Color.red);
//Set font
g.setFont(new Font("Fixedsys", Font.BOLD, 75));
//Create metrics object for text
FontMetrics metricsOne = getFontMetrics(g.getFont());
//Draw the string in the middle of the screen
g.drawString("GAME OVER", (SCREEN_WIDTH - metricsOne.stringWidth("GAME OVER"))/2, SCREEN_HEIGHT/2);
//Set the color to red
g.setColor(Color.red);
//Sets the font of the text
g.setFont(new Font("Fixedsys", Font.BOLD, 40));
//Make a metrics object
FontMetrics metricsTwo = getFontMetrics(g.getFont());
//Draw the string onto the board
g.drawString("Score: " + applesEaten, (SCREEN_WIDTH - metricsTwo.stringWidth("Score: " + applesEaten))/2, (SCREEN_HEIGHT/2) + g.getFont().getSize());
}
//Override the action performed method
@Override
public void actionPerformed(ActionEvent e) {
//Checks to see if running is true
if (running){
move();
checkApple();
checkCollisions();
}
//calls the repaint command to update graphics
repaint();
}
//Makes an embeded class that extends the keyadapter super class
public class MyKeyAdapter extends KeyAdapter {
//Overrides the keypressed method
@Override
public void keyPressed(KeyEvent e) {
//runs a switch statement for the e key source
switch (e.getKeyCode()){
//If the key is the left arrow
case KeyEvent.VK_LEFT:
//Check if direction is not right
if (direction != 'R'){
//sets direction to left;
direction = 'L';
}
break;
//If the key is the right arrow
case KeyEvent.VK_RIGHT:
//Checks if direction is not left
if (direction != 'L'){
//sets direction to right
direction = 'R';
}
break;
//Checks if key is up arrow
case KeyEvent.VK_UP:
//Checks if key is not down
if (direction != 'D'){
//Sets the direction to up
direction = 'U';
}
break;
//Checks if key is down arrow
case KeyEvent.VK_DOWN:
//Checks if direction is not up
if (direction != 'U'){
//Sets the direction to down
direction = 'D';
}
break;
}
}
}
}