-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathRacer.java
227 lines (201 loc) · 5.9 KB
/
Racer.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
import javax.swing.*;
/**
* uses the GameArena APIs to implement a simple top down racing game.
*
* The graphical output of the game is provided as a Swing component,
* so that it can be added into any Swing application, just like a JButton etc.
*
* To allow users to control the game as they see fit, start(), stop() and update()
* methods are provided. start() should be used to create a new game, stop() to terminate
* a running game, and update() should be called in a loop to update gameplay and graphics
*
* Simple example of use:
*
* <pre>
*
* JFrame window = new JFrame();
* Racer r = new Racer();
* window.setTitle("Racer");
* window.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
* window.setContentPane(r.getPanel());
* window.setVisible(true);
*
* r.start();
*
* while(r.isPlaying())
* r.update();
*
* </pre>
*
* @author Joe Finney (joe@comp.lancs.ac.uk)
*/
public class Racer
{
public static final double PLAYER_SPEED = 5;
public static final int ROAD_SEGMENT_WIDTH = 160;
public static final int ROAD_SEGMENT_HEIGHT= 10;
public static final int ROAD_CURVE_SPEED = 5;
public static final int SCREEN_WIDTH = 800;
public static final int SCREEN_HEIGHT = 600;
private GameArena arena;
private Car player;
private RoadSegment[] road = new RoadSegment[SCREEN_HEIGHT / ROAD_SEGMENT_HEIGHT + 1];
private double currentRoadX = SCREEN_WIDTH/2;
private double speed = 2.0;
private boolean playing = false;
private int score = 0;
/**
* Creates a new instance of the Racer racing game.
*/
public Racer()
{
arena = new GameArena(SCREEN_WIDTH, SCREEN_HEIGHT, false);
}
/**
* Provides a Swing component in which the Racer game runs.
* This component can be added to a Swing panel to display the game on screen.
*
* @return A Swing component for this game.
*/
public JComponent getPanel()
{
return arena.getPanel();
}
/**
* Provides the player's current score in the game.
* @return The player's current score.
*/
public int getScore()
{
return score;
}
/**
* Starts a new game, if the game is not alreayd running.
*/
public void start()
{
if(!playing)
{
// Create the player's car
player = new Car(SCREEN_WIDTH/2, SCREEN_HEIGHT - 150, arena);
// Create the initial road layout
for (int s = road.length-1; s >= 0 ; s--)
{
road[s] = nextRoadSegment();
road[s].setYPosition(s*ROAD_SEGMENT_HEIGHT);
}
score = 0;
playing = true;
}
}
/**
* Stops a currently running game.
*/
public void stop()
{
if(playing)
{
playing = false;
arena.exit();
}
}
/**
* Determines if the game is currently being played.
*
* @return false if the game has not been started or on game over, true if the game is actively running.
*/
public boolean isPlaying()
{
return playing;
}
/**
* Updates the game state to allow the road and player character to move on the screen.
*
* This method should be called in a loop (once per frame) to advance gameplay in response to time
* and user input. The method uses the GameArena pause() method to ensure the game runs at a constant speed.
*/
public void update()
{
if(playing)
{
score++;
double speed = 0;
if (arena.leftPressed())
speed -= PLAYER_SPEED;
if (arena.rightPressed())
speed += PLAYER_SPEED;
player.setXSpeed(speed);
player.move();
for (int i=0; i<road.length; i++)
{
if (road[i] != null)
road[i].move();
}
// Recycle any segments that have crolled off screen...
recycleRoadSegments();
if (hasCrashed())
stop();
}
arena.pause();
}
/**
* Provides a randomly generated, thin slice of road.
* This method is used periodically to create new road on the screen in front of the player's car.
*
* @return A new randomly generated RoadSegment
*/
private RoadSegment nextRoadSegment()
{
currentRoadX += Math.random() * 2 * ROAD_CURVE_SPEED - ROAD_CURVE_SPEED;
RoadSegment s = new RoadSegment(currentRoadX, -ROAD_SEGMENT_HEIGHT, ROAD_SEGMENT_WIDTH, ROAD_SEGMENT_HEIGHT, arena);
s.setYSpeed(speed);
return s;
}
/**
* Removes any parts of road that have scrolled off the bottom of the screen.
*/
private void recycleRoadSegments()
{
for (int i=0; i<road.length; i++)
{
if (road[i].getYPosition() > SCREEN_HEIGHT)
{
double y = road[i].getYPosition();
road[i].remove();
road[i] = nextRoadSegment();
road[i].setYPosition(y - SCREEN_HEIGHT - ROAD_SEGMENT_HEIGHT);
}
}
}
/**
* Determines if the player has crased (driven off road)
*
* @return true is the player is touching the kerb/grass, false otherwise.
*/
private boolean hasCrashed()
{
for (int i=0; i<road.length; i++)
{
if (player.isTouching(road[i]))
return true;
}
return false;
}
/**
* A simple example of usage
*
* @param args unused.
*/
public static void main(String[] args)
{
JFrame window = new JFrame();
Racer r = new Racer();
window.setTitle("Racer");
window.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
window.setContentPane(r.getPanel());
window.setVisible(true);
r.start();
while(r.isPlaying())
r.update();
}
}