1 package erland.game.tetris;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import erland.game.GameEnvironmentInterface;
22 import erland.game.FpsCounter;
23 import erland.game.GamePanelInterface;
24
25 import java.awt.event.KeyAdapter;
26 import java.awt.event.KeyEvent;
27 import java.awt.event.KeyListener;
28 import java.awt.*;
29
30 public class TetrisMain implements GamePanelInterface {
31 private GameEnvironmentInterface environment;
32 private boolean bQuit;
33 private boolean cheatMode;
34 private KeyListener keyListener;
35 private FpsCounter fps;
36 /*** Container representing the game logo */
37 protected BlockContainerData titleContainer;
38 /*** Container representing the next block */
39 protected BlockContainerData previewContainer;
40
41 /*** Size of the squares */
42 protected int squareSize;
43
44 /*** Horizontal drawing offset */
45 protected int offsetX;
46 /*** Vertical drawing offset */
47 protected int offsetY;
48 /*** Number of pixels between squares */
49 protected int spaceBetweenSquares;
50 /*** Counter to handle blinking of text when game is completed or GAME OVER has occurred */
51 protected int endBlink;
52 /*** Speed of blinking text */
53 protected final int END_BLINK_SPEED=10;
54 /*** Object representing the tetris data model */
55 private TetrisModelInterface model;
56
57 public TetrisMain(TetrisModelInterface model) {
58 this.model = model;
59 }
60 public boolean isExit() {
61 return bQuit;
62 }
63
64 public void setCheatmode(boolean enable) {
65 cheatMode = enable;
66 }
67
68 public void exit() {
69 environment.getScreenHandler().getContainer().removeKeyListener(keyListener);
70 }
71
72 public void init(GameEnvironmentInterface environment) {
73 this.environment = environment;
74 bQuit = false;
75 cheatMode = false;
76
77 keyListener = new KeyAdapter() {
78 public void keyPressed(KeyEvent e) {
79 if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
80 bQuit = true;
81 }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
82 model.moveLeft();
83 }else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
84 model.moveRight();
85 }else if(e.getKeyCode() == KeyEvent.VK_UP) {
86 model.rotate();
87 }else if(e.getKeyCode() == KeyEvent.VK_DOWN) {
88 model.moveDown();
89 }else if(e.getKeyCode()==e.VK_SPACE) {
90 newGame();
91 }
92 }
93 };
94 environment.getScreenHandler().getContainer().setCursor(null);
95 environment.getScreenHandler().getContainer().requestFocus();
96 environment.getScreenHandler().getContainer().addKeyListener(keyListener);
97 environment.getScreenHandler().getContainer().setBackground(Color.black);
98 fps = new FpsCounter(60);
99
100 previewContainer = new BlockContainerData(4,2);
101 titleContainer = new BlockContainerData(34,5);
102 titleContainer.clear();
103 makeTitle(titleContainer);
104 this.offsetX = 20;
105 this.offsetY = 20;
106 this.squareSize = 13;
107 this.spaceBetweenSquares = 1;
108 init();
109 model.init(environment);
110 }
111
112 /***
113 * Initialize a new game
114 */
115 protected void init()
116 {
117 endBlink=0;
118 }
119
120 /***
121 * Start a new game, this will only succeed if there is not a game already running
122 */
123 public void newGame()
124 {
125 if(model.isEnd() || !model.isStarted()) {
126 model.startGame();
127 }
128 }
129
130 /***
131 * Draw the tetris logo in the specied BlockMatrix
132 * @param m The BlockMatrix to draw the logo in
133 */
134 protected void makeTitle(BlockMatrix m) {
135
136
137
138
139
140
141 Color c = Color.red;
142
143 m.setUsed(6,0,c);
144 m.setUsed(7,0,c);
145 m.setUsed(8,0,c);
146 m.setUsed(9,0,c);
147 m.setUsed(10,0,c);
148 m.setUsed(6,1,c);
149 m.setUsed(6,2,c);
150 m.setUsed(7,2,c);
151 m.setUsed(8,2,c);
152 m.setUsed(9,2,c);
153 m.setUsed(6,3,c);
154 m.setUsed(6,4,c);
155 m.setUsed(7,4,c);
156 m.setUsed(8,4,c);
157 m.setUsed(9,4,c);
158 m.setUsed(10,4,c);
159
160 m.setUsed(12,0,c);
161 m.setUsed(13,0,c);
162 m.setUsed(14,0,c);
163 m.setUsed(15,0,c);
164 m.setUsed(16,0,c);
165 m.setUsed(14,1,c);
166 m.setUsed(14,2,c);
167 m.setUsed(14,3,c);
168 m.setUsed(14,4,c);
169
170 m.setUsed(18,0,c);
171 m.setUsed(18,1,c);
172 m.setUsed(18,2,c);
173 m.setUsed(18,3,c);
174 m.setUsed(18,4,c);
175 m.setUsed(19,0,c);
176 m.setUsed(20,0,c);
177 m.setUsed(21,0,c);
178 m.setUsed(22,1,c);
179 m.setUsed(19,2,c);
180 m.setUsed(20,2,c);
181 m.setUsed(21,2,c);
182 m.setUsed(21,3,c);
183 m.setUsed(22,4,c);
184
185 m.setUsed(25,0,c);
186 m.setUsed(25,1,c);
187 m.setUsed(25,2,c);
188 m.setUsed(25,3,c);
189 m.setUsed(25,4,c);
190
191 m.setUsed(30,0,c);
192 m.setUsed(31,0,c);
193 m.setUsed(32,0,c);
194 m.setUsed(33,0,c);
195 m.setUsed(29,1,c);
196 m.setUsed(30,2,c);
197 m.setUsed(31,2,c);
198 m.setUsed(32,2,c);
199 m.setUsed(33,3,c);
200 m.setUsed(29,4,c);
201 m.setUsed(30,4,c);
202 m.setUsed(31,4,c);
203 m.setUsed(32,4,c);
204 }
205
206 public void update() {
207 fps.update();
208 model.update();
209 }
210
211 public void draw() {
212 Graphics g = environment.getScreenHandler().getCurrentGraphics();
213 g.setColor(Color.black);
214 g.clearRect(0,0,640,480);
215 if(cheatMode) {
216 fps.draw(g,Color.white,10,10);
217 }
218 BlockContainerData mainContainer1 = model.getMainContainer();
219 int rightColumnX = offsetX + mainContainer1.getWidth()*(squareSize+spaceBetweenSquares)+10;
220 int rightColumnX2 = 640-(offsetX + mainContainer1.getWidth()*(squareSize+spaceBetweenSquares) + 60);
221 int rightColumnY = offsetY;
222 drawContainer(g,mainContainer1,offsetX,offsetY, squareSize,spaceBetweenSquares,1,Color.blue,Color.darkGray);
223 if(model.isMultiplayer()) {
224 if(model.isOpponentConnected()) {
225 drawContainer(g,model.getOpponentMainContainer(),640-(mainContainer1.getWidth()*(squareSize+spaceBetweenSquares)+offsetX),offsetY, squareSize,spaceBetweenSquares,1,Color.blue,Color.darkGray);
226 }else {
227 drawContainer(g,model.getOpponentMainContainer(),640-(mainContainer1.getWidth()*(squareSize+spaceBetweenSquares)+offsetX),offsetY, squareSize,spaceBetweenSquares,1,Color.darkGray,Color.darkGray);
228 }
229 }
230 updatePreviewContainer();
231 drawContainer(g,previewContainer,offsetX + mainContainer1.getWidth()*(squareSize+spaceBetweenSquares)+10,rightColumnY, squareSize, spaceBetweenSquares,1,Color.blue,Color.darkGray);
232 drawContainer(g,titleContainer,rightColumnX,
233 offsetY + mainContainer1.getHeight()*(squareSize+spaceBetweenSquares)-titleContainer.getHeight()*(squareSize/2+spaceBetweenSquares)-20,squareSize/2,spaceBetweenSquares,0,Color.blue,Color.black);
234 g.drawString("by Erland Isaksson",rightColumnX+147,offsetY + mainContainer1.getHeight()*(squareSize+spaceBetweenSquares));
235 rightColumnY += offsetY+previewContainer.getHeight()*(squareSize+spaceBetweenSquares)+20;
236 g.setColor(Color.white);
237 g.drawString("LEVEL: "+model.getLevel(),rightColumnX, rightColumnY);
238 if(model.isMultiplayer()) {
239 g.drawString("LEVEL: "+model.getOpponentLevel(),rightColumnX2, rightColumnY);
240 }
241 rightColumnY+=20;
242 g.drawString("HIGHSCORE:",rightColumnX+100, rightColumnY);
243 g.drawString(model.getHighScore(),rightColumnX+120,rightColumnY+20);
244 g.drawString("SCORE:",rightColumnX,rightColumnY);
245 if(model.isMultiplayer()) {
246 g.drawString("SCORE:",rightColumnX2,rightColumnY);
247 }
248 rightColumnY+=20;
249 g.drawString(model.getScore(),rightColumnX,rightColumnY);
250 if(model.isMultiplayer()) {
251 g.drawString(model.getOpponentScore(),rightColumnX2,rightColumnY);
252 }
253 rightColumnY+=20;
254 if(model.isEnd()) {
255 if(endBlink<END_BLINK_SPEED) {
256 if(!model.isCompleted()) {
257 g.drawString("GAME OVER", rightColumnX,rightColumnY);
258 rightColumnY+=20;
259 if(!model.isStarted()) {
260 rightColumnY+=20;
261 if(!model.isMultiplayer() || model.isOpponentConnected()) {
262 g.drawString("Press space for new game", rightColumnX, rightColumnY);
263 }else {
264 g.drawString("Press space or wait for opponent", rightColumnX, rightColumnY);
265 }
266 rightColumnY+=20;
267 }
268 }else {
269 g.drawString("* CONGRATULATIONS *", rightColumnX, rightColumnY);
270 rightColumnY+=20;
271 g.drawString(" You have finished ", rightColumnX, rightColumnY);
272 rightColumnY+=20;
273 g.drawString(" the game ", rightColumnX, rightColumnY);
274 rightColumnY+=20;
275 if(!model.isStarted()) {
276 rightColumnY+=20;
277 if(!model.isMultiplayer() || model.isOpponentConnected()) {
278 g.drawString("Press space for new game", rightColumnX, rightColumnY);
279 }else {
280 g.drawString("Press space or wait for opponent", rightColumnX, rightColumnY);
281 }
282 rightColumnY+=20;
283 }
284
285 }
286 endBlink++;
287 }else {
288 if(endBlink<(2*END_BLINK_SPEED)) {
289 endBlink++;
290 }else {
291 endBlink=0;
292 }
293 }
294 }else if(!model.isStarted()) {
295 if(endBlink<END_BLINK_SPEED) {
296 if(!model.isMultiplayer() || model.isOpponentConnected()) {
297 g.drawString("Press space for new game",rightColumnX, rightColumnY);
298 }else {
299 g.drawString("Press space or wait for opponent",rightColumnX, rightColumnY);
300 }
301 rightColumnY+=20;
302 endBlink++;
303 }else {
304 if(endBlink<(2*END_BLINK_SPEED)) {
305 endBlink++;
306 }else {
307 endBlink=0;
308 }
309 }
310 }
311 }
312
313 /***
314 * Draw all grapics in a specific BlockMatrix
315 * @param g The Graphics object to draw on
316 * @param m The BlockMatix object to draw
317 * @param offsetX The horisontal drawing offset
318 * @param offsetY The vertical drawing offset
319 * @param squareSize The size of each square in pixels
320 * @param spaceBetweenSquares Number of pixels between each square
321 * @param borderSize The size in pixels of the border around the drawn area
322 * @param borderColor The color of the border
323 * @param gridColor The color of the grid
324 */
325 protected void drawContainer(Graphics g, BlockMatrix m, int offsetX, int offsetY, int squareSize, int spaceBetweenSquares, int borderSize, Color borderColor, Color gridColor)
326 {
327
328 if(borderSize>=0) {
329 g.setColor(borderColor);
330 g.fillRect(offsetX, offsetY, borderSize, (squareSize+spaceBetweenSquares)*m.getHeight()-spaceBetweenSquares+borderSize);
331 g.fillRect(offsetX, offsetY, (squareSize+spaceBetweenSquares)*m.getWidth()-spaceBetweenSquares+borderSize, borderSize);
332 g.fillRect(offsetX+borderSize+(squareSize+spaceBetweenSquares)*m.getWidth()-spaceBetweenSquares, offsetY,borderSize,(squareSize+spaceBetweenSquares)*m.getHeight()-spaceBetweenSquares+borderSize*2);
333 g.fillRect(offsetX, offsetY+borderSize+(squareSize+spaceBetweenSquares)*m.getHeight()-spaceBetweenSquares,(squareSize+spaceBetweenSquares)*m.getWidth()-spaceBetweenSquares+borderSize*2,borderSize);
334 }
335 if(spaceBetweenSquares>0) {
336 g.setColor(gridColor);
337 for(int x=1;x<m.getWidth();x++) {
338 g.fillRect(offsetX + borderSize + x*(squareSize+spaceBetweenSquares)-spaceBetweenSquares,
339 offsetY + borderSize,
340 spaceBetweenSquares,
341 m.getHeight()*(squareSize+spaceBetweenSquares)-spaceBetweenSquares);
342 }
343 for(int y=1;y<m.getHeight();y++) {
344 g.fillRect(offsetX + borderSize,
345 offsetY + borderSize + y*(squareSize+spaceBetweenSquares)-spaceBetweenSquares,
346 m.getWidth()*(squareSize+spaceBetweenSquares)-spaceBetweenSquares,
347 spaceBetweenSquares);
348 }
349 }
350 for(int x=0;x<m.getWidth();x++) {
351 for(int y=0;y<m.getHeight();y++) {
352 if(m.isUsed(x,y)) {
353 g.setColor(m.getColor(x,y));
354 g.fillRect(offsetX +borderSize+ x*(squareSize+spaceBetweenSquares),offsetY +borderSize+ y*(squareSize+spaceBetweenSquares),squareSize, squareSize);
355 }
356 }
357 }
358 }
359 protected void updatePreviewContainer() {
360 previewContainer.clear();
361 Block b = model.getNextBlock();
362 if(b!=null) {
363 b.init(1,0,0);
364 b.moveDown(previewContainer);
365 }
366 }
367 }