-
Notifications
You must be signed in to change notification settings - Fork 0
/
Game.java
229 lines (199 loc) · 7.62 KB
/
Game.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
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
/**
* The Game class is used to generate the objects used in the Pong game,
* while also controlling what happens during each pass through the "game loop,"
* which here is implemented as the Game class's act() method.
*
* One object of the Game class is generated at compile time. This object also
* serves as the playing field itself.
*
* @author bcanada
* @version 2014.11.10
*/
public class Game extends World
{
/* FIELDS */
// Composition (has-a) relationships with basic game elements
private Paddle paddle1; // game has paddle (for player 1)
private CPUPaddle paddle2; // game has paddle (for player 2)
private Ball ball; // game has ball
private Boundary topBoundary; // game has topBoundary
private Boundary bottomBoundary; // game has bottomBoundary
private Score playerScoreDisplay; // game has playerScoreDisplay
private Score cpuScoreDisplay; // game has cpuScoreDisplay
// score variables (for the numerical value of the score)
private int playerScore;
private int cpuScore;
// 1-D array of GreenfootImage objects for scoreboard
private GreenfootImage[] scoreNumber = new GreenfootImage[12];
// sound objects
private GreenfootSound lowBlip;
private GreenfootSound highBlip;
private GreenfootSound longBeep;
// enum for game state
private static Status gameStatus; // game has status (NOT_PLAYING, PLAYING, or GAME_OVER;
// see the Status enum under "Other classes")
// constants (adjust as needed)
public static final int GAME_WIDTH = 640;
public static final int GAME_HEIGHT = 480;
public static final int MAX_SCORE = 3;
/* CONSTRUCTORS */
/**
* Constructor for objects of class Game.
*
*/
public Game()
{
// Create a new world with 640x480 cells with a cell size of 1x1 pixels
// (and set the value of the 4th parameter, 'bounded', to false, so that
// we can allow objects like the ball and the top/bottom boundaries
// to exist off-screen)
super( GAME_WIDTH, GAME_HEIGHT, 1, false );
// set the initial game status to NOT_PLAYING
// TODO: I should incorporate a title screen or display instructions here
gameStatus = Status.NOT_PLAYING;
// instantiate the paddle and ball objects
paddle1 = new Paddle();
paddle2 = new CPUPaddle();
ball = new Ball();
topBoundary = new Boundary();
bottomBoundary = new Boundary();
// instantiate the scoreboard objects
playerScoreDisplay = new Score();
cpuScoreDisplay = new Score();
// instantiate the game sound effect objects
lowBlip = new GreenfootSound("pong1.mp3");
highBlip = new GreenfootSound("pong3.mp3");
longBeep = new GreenfootSound("pong6.mp3");
// initialize scores to zero
playerScore = 0;
cpuScore = 0;
// set up scoreboard
for ( int imageIndex = 0; imageIndex < 12; imageIndex++ )
{
String imageFilename = imageIndex + ".png";
scoreNumber[imageIndex] = new GreenfootImage( imageFilename );
} // end for loop
// place the objects (coordinates refer to the CENTER point of each object, not the upper left corner)
addObject( paddle1, (int)( 0.05*GAME_WIDTH ), ( GAME_HEIGHT / 2 ) );
addObject( paddle2, (int)( 0.95*GAME_WIDTH ), ( GAME_HEIGHT / 2 ) );
addObject( ball, ( GAME_WIDTH/2 ), ( GAME_HEIGHT / 2 ) );
// place the scoreboard objects in the middle of each half
addObject( playerScoreDisplay, (int)(0.25*GAME_WIDTH), (int)(0.15*GAME_HEIGHT) );
addObject( cpuScoreDisplay, (int)(0.75*GAME_WIDTH), (int)(0.15*GAME_HEIGHT) );
// place the top and bottom boundaries just off screen
addObject( topBoundary, ( GAME_WIDTH / 2 ), 0 - topBoundary.getImage().getHeight()/2 );
addObject( bottomBoundary, ( GAME_WIDTH / 2 ), GAME_HEIGHT + bottomBoundary.getImage().getHeight()/2 );
} // end Game constructor
/* DEFINE METHODS */
/**
* In the Game class, the act() method serves as the game loop for the
* overall game. (Keep in mind that all actors still have an act() method, which
* defines what each actor object specifically does during the game loop.)
*/
public void act()
{
/*
* the game status determines what happens during each pass through the
* game loop
*/
if ( gameStatus == Status.NOT_PLAYING )
{
if ( Greenfoot.isKeyDown( "space" ) )
{
gameStatus = Status.PLAYING;
} // end if
}
else if ( gameStatus == Status.PLAYING )
{
// end the game when one player reaches the maximum score
if ( playerScore == MAX_SCORE || cpuScore == MAX_SCORE )
{
gameStatus = Status.GAME_OVER;
} // end if
}
else if ( gameStatus == Status.GAME_OVER )
{
System.out.println( "Game over!" );
Greenfoot.stop();
} // end multiway if/else
} // end method act
/**
* Allows other objects to know the current state of the game
*/
public Status getGameStatus()
{
return gameStatus;
} // end method getGameStatus
/**
* Allows other objects to "see" the ball (more accurately, allows other objects
* to have a reference to the ball object created here in the Game class)
*
* @return a copy of the reference to the game ball object
*/
public Ball getBall()
{
return ball;
}
/**
* Allows other objects to "see" the player's paddle
*
* @return a copy of the reference to the player's paddle object
*/
public Paddle getPaddle()
{
return paddle1;
}
/**
* Allows other objects to "see" the CPU's paddle
*
* @return a copy of the reference to the CPU paddle object
*/
public CPUPaddle getCPUPaddle()
{
return paddle2;
}
/**
* Used to increment score for the indicated player
*
* @param playerNumber 1 = player, 2 = CPU
*/
public void updateScore( int playerNumber )
{
switch ( playerNumber )
{
case 1:
playerScore++;
playerScoreDisplay.setImage( scoreNumber[playerScore] );
break;
case 2:
cpuScore++;
cpuScoreDisplay.setImage( scoreNumber[cpuScore] );
break;
default:
break;
} // end switch
System.out.printf( "Player Score: %d\tCPU Score: %d\n", playerScore, cpuScore );
} // end method updateScore
/**
* Plays the low blip sound (when the ball makes contact with a top or bottom boundary)
*/
public void playLowBlip()
{
lowBlip.play();
} // end method playLowBlip
/**
* Plays the high blip sound (when the ball makes contact with a paddle)
*/
public void playHighBlip()
{
highBlip.play();
} // end method playHighBlip
/**
* Plays the long beep sound (when the ball exits the screen and a point is scored)
*/
public void playLongBeep()
{
longBeep.play();
} // end method playLongBeep
} // end class Game