1 |
package com.androidside.demo.tetris; |
---|
2 |
|
---|
3 |
import android.content.Context; |
---|
4 |
import android.graphics.Canvas; |
---|
5 |
import android.graphics.Paint; |
---|
6 |
import android.graphics.Rect; |
---|
7 |
import android.graphics.RectF; |
---|
8 |
import android.os.Bundle; |
---|
9 |
import android.util.AttributeSet; |
---|
10 |
import android.util.Log; |
---|
11 |
import android.view.View; |
---|
12 |
|
---|
13 |
public class BoardView extends View { |
---|
14 |
|
---|
15 |
static int squareLength; // square ���ш린 (in pixel) |
---|
16 |
|
---|
17 |
static int COLS = Tetris4Android.COLS; // columns |
---|
18 |
static int ROWS = Tetris4Android.ROWS; // rows |
---|
19 |
|
---|
20 |
int colors[]; |
---|
21 |
|
---|
22 |
Rect rectClient = new Rect(); // �ъ� 媛������㈃ �� Rect rectBoard = new Rect(); // ������ ���由ъ� ����� |
---|
23 |
|
---|
24 |
// ��� �댁� |
---|
25 |
byte boardPrev[][]; // 吏�� ��� �댁� |
---|
26 |
byte boardCurr[][]; // ��� (蹂�꼍 �� ��� �댁� |
---|
27 |
|
---|
28 |
Square pieceCurr[] = new Square[4]; // �����釉�� |
---|
29 |
|
---|
30 |
private byte mode = READY; // ��� 寃������� |
---|
31 |
|
---|
32 |
public static final byte PAUSE = 0; // �쇱� 以�� |
---|
33 |
public static final byte READY = 1; // 寃�� ��� ��以�� ��� |
---|
34 |
public static final byte RUNNING = 2; // 寃�� 吏�� 以� public static final byte END = 3; // 寃�� 醫���� |
---|
35 |
public BoardView(Context context) { |
---|
36 |
super(context); |
---|
37 |
init(); |
---|
38 |
} |
---|
39 |
|
---|
40 |
public BoardView(Context context, AttributeSet attrs, int defStyle) { |
---|
41 |
super(context, attrs, defStyle); |
---|
42 |
init(); |
---|
43 |
} |
---|
44 |
|
---|
45 |
public BoardView(Context context, AttributeSet attrs) { |
---|
46 |
super(context, attrs); |
---|
47 |
init(); |
---|
48 |
} |
---|
49 |
|
---|
50 |
/** |
---|
51 |
* �대���� �ъ���� 媛�� �댁������ 珥�린 �ㅼ� |
---|
52 |
*/ |
---|
53 |
void init() { |
---|
54 |
|
---|
55 |
colors = new int[8]; // �대���� �ъ���� ����ㅼ� 吏�����. |
---|
56 |
|
---|
57 |
colors[0] = 0xff000060; // 諛곌꼍�� |
---|
58 |
// 釉����� �ъ���� ��� |
---|
59 |
colors[1] = 0xffff0000; // red |
---|
60 |
colors[2] = 0xff00c800; // green |
---|
61 |
colors[3] = 0xff00c8ff; // light blue |
---|
62 |
colors[4] = 0xffffff00; // yellow |
---|
63 |
colors[5] = 0xffff9600; // orange |
---|
64 |
colors[6] = 0xffd200f0; // purple |
---|
65 |
colors[7] = 0xff2800f0; // dark bluer |
---|
66 |
|
---|
67 |
// ��� ������ 怨듦���������. |
---|
68 |
boardPrev = new byte[Tetris4Android.COLS][Tetris4Android.ROWS + 4]; |
---|
69 |
boardCurr = new byte[Tetris4Android.COLS][Tetris4Android.ROWS + 4]; |
---|
70 |
|
---|
71 |
// fillBoard(); |
---|
72 |
showAllBlocks(); |
---|
73 |
// cleanBoard(); |
---|
74 |
} |
---|
75 |
|
---|
76 |
/* ��������媛������吏������린 ��� ����몄� */ |
---|
77 |
private void fillBoard() { |
---|
78 |
for (int r = 0; r < ROWS; r++) { |
---|
79 |
for (int c = 0; c < COLS; c++) { |
---|
80 |
boardCurr[c][r] = (byte) (((r + c) % (colors.length - 1)) + 1); |
---|
81 |
} |
---|
82 |
} |
---|
83 |
} |
---|
84 |
|
---|
85 |
public byte getMode() { |
---|
86 |
return mode; |
---|
87 |
} |
---|
88 |
|
---|
89 |
public void setMode(byte mode) { |
---|
90 |
this.mode = mode; |
---|
91 |
} |
---|
92 |
|
---|
93 |
/* 紐⑤� 釉���������� ��㈃��異����以�� */ |
---|
94 |
private void showAllBlocks() { |
---|
95 |
for (int i = 0; i <= 6; i++) { |
---|
96 |
newBlock(i); |
---|
97 |
moveCurrentPiece(0, (6 - i) * 3, false); |
---|
98 |
} |
---|
99 |
} |
---|
100 |
|
---|
101 |
/* ��� 紐⑤� �댁���吏��怨������釉����珥�린����� 寃�� ��� ��以�� �④��대�. */ |
---|
102 |
void cleanBoard() { |
---|
103 |
for (int c = 0; c < COLS; c++) { |
---|
104 |
for (int r = 0; r < ROWS; r++) { |
---|
105 |
boardPrev[c][r] = -1; |
---|
106 |
boardCurr[c][r] = 0; |
---|
107 |
} |
---|
108 |
} |
---|
109 |
|
---|
110 |
pieceCurr = new Square[4]; |
---|
111 |
} |
---|
112 |
|
---|
113 |
@Override |
---|
114 |
protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
---|
115 |
super.onSizeChanged(w, h, oldw, oldh); |
---|
116 |
|
---|
117 |
// 二쇱�吏���㈃ �����諛���쇰� �ㅼ� �ъ��������怨�����. |
---|
118 |
int width = w / COLS; |
---|
119 |
int height = h / ROWS; |
---|
120 |
|
---|
121 |
squareLength = Math.min(width, height); |
---|
122 |
|
---|
123 |
rectClient = new Rect(0, 0, w, h); |
---|
124 |
|
---|
125 |
int xoffset = (w - squareLength * COLS) / 2; |
---|
126 |
int yoffset = (h - squareLength * ROWS) / 2; |
---|
127 |
|
---|
128 |
rectBoard = new Rect( |
---|
129 |
xoffset, yoffset, |
---|
130 |
xoffset + squareLength * COLS, yoffset + squareLength * ROWS); |
---|
131 |
|
---|
132 |
Log.v(Tetris4Android.TAG, " SQUARE LEN = " + squareLength); |
---|
133 |
Log.v(Tetris4Android.TAG, "CLIENT RECT (" + rectClient.left + "," + rectClient.top + ")-(" + rectClient.right + "," + rectClient.bottom + ")"); |
---|
134 |
Log.v(Tetris4Android.TAG, " BOARD RECT (" + rectBoard.left + "," + rectBoard.top + ")-(" + rectBoard.right + "," + rectBoard.bottom + ")"); |
---|
135 |
} |
---|
136 |
|
---|
137 |
/* |
---|
138 |
* 蹂�꼍 �������� 蹂�꼍 �����濡���릿�� ���� ��꺼吏������吏��щ���������. |
---|
139 |
*/ |
---|
140 |
private boolean moveBlocks(Square from[], Square to[]) { |
---|
141 |
|
---|
142 |
outerlabel: |
---|
143 |
|
---|
144 |
for (int i = 0; i < to.length; i++) { |
---|
145 |
|
---|
146 |
if (!to[i].isInBounds()) { |
---|
147 |
return false; |
---|
148 |
} |
---|
149 |
|
---|
150 |
if (boardCurr[to[i].getX()][to[i].getY()] != 0) { |
---|
151 |
|
---|
152 |
for (int j = 0; j < from.length; j++) |
---|
153 |
{ |
---|
154 |
if (to[i].isEqual(from[j])) { |
---|
155 |
continue outerlabel; |
---|
156 |
} |
---|
157 |
} |
---|
158 |
return false; |
---|
159 |
} |
---|
160 |
} |
---|
161 |
|
---|
162 |
// blank old piece |
---|
163 |
for (int i = 0; i < from.length; i++) |
---|
164 |
{ |
---|
165 |
if (from[i].isInBounds()) { |
---|
166 |
boardCurr[from[i].getX()][from[i].getY()] = 0; |
---|
167 |
boardPrev[from[i].getX()][from[i].getY()] = -1; |
---|
168 |
} |
---|
169 |
} |
---|
170 |
|
---|
171 |
for (int i = 0; i < to.length; i++) |
---|
172 |
{ |
---|
173 |
boardCurr[to[i].getX()][to[i].getY()] = to[i].getColor(); |
---|
174 |
} |
---|
175 |
|
---|
176 |
return true; |
---|
177 |
} |
---|
178 |
|
---|
179 |
/* |
---|
180 |
* �����釉����������. 留��, �����釉��������������硫� * (怨듦���苑�李�寃쎌�) false 瑜�諛�����. |
---|
181 |
*/ |
---|
182 |
protected boolean newBlock() { |
---|
183 |
|
---|
184 |
// �����釉���대�濡� 湲곗〈���������諛�� ����쇰� 吏�����. |
---|
185 |
Square old[] = new Square[4]; |
---|
186 |
old[0] = old[1] = old[2] = old[3] = new Square(-1, -1, (byte) 0); |
---|
187 |
|
---|
188 |
// �����紐⑥���媛���ㅻ�濡����. |
---|
189 |
int blockType = (int) (Math.random() * 7); |
---|
190 |
|
---|
191 |
// 釉����������. |
---|
192 |
newBlock(blockType); |
---|
193 |
|
---|
194 |
// �����釉�����대����. |
---|
195 |
// 留��, �대����ㅽ����硫���㈃ 以�� ����������釉���������� ����� // �대� �ㅻⅨ 釉����議댁���� 寃쎌�) false 瑜�諛�����. |
---|
196 |
return moveBlocks(old, pieceCurr); |
---|
197 |
|
---|
198 |
} |
---|
199 |
|
---|
200 |
/* |
---|
201 |
* ��㈃ 以�� �����吏��������������釉����������. �����釉���������釉���쇰� 吏�����. |
---|
202 |
*/ |
---|
203 |
private void newBlock(int type) { |
---|
204 |
|
---|
205 |
int m = COLS / 2; |
---|
206 |
|
---|
207 |
switch (type) { |
---|
208 |
case 0: |
---|
209 |
// #### |
---|
210 |
pieceCurr[0] = new Square(m - 1, 0, (byte) 1); |
---|
211 |
pieceCurr[1] = new Square(m - 2, 0, (byte) 1); |
---|
212 |
pieceCurr[2] = new Square(m, 0, (byte) 1); |
---|
213 |
pieceCurr[3] = new Square(m + 1, 0, (byte) 1); |
---|
214 |
break; |
---|
215 |
|
---|
216 |
case 1: |
---|
217 |
// ### |
---|
218 |
// # |
---|
219 |
pieceCurr[0] = new Square(m, 0, (byte) 5); |
---|
220 |
pieceCurr[1] = new Square(m, 1, (byte) 5); |
---|
221 |
pieceCurr[2] = new Square(m - 1, 0, (byte) 5); |
---|
222 |
pieceCurr[3] = new Square(m + 1, 0, (byte) 5); |
---|
223 |
break; |
---|
224 |
|
---|
225 |
case 2: |
---|
226 |
// ## |
---|
227 |
// ## |
---|
228 |
pieceCurr[0] = new Square(m, 0, (byte) 2); |
---|
229 |
pieceCurr[1] = new Square(m - 1, 1, (byte) 2); |
---|
230 |
pieceCurr[2] = new Square(m, 1, (byte) 2); |
---|
231 |
pieceCurr[3] = new Square(m + 1, 0, (byte) 2); |
---|
232 |
break; |
---|
233 |
|
---|
234 |
case 3: |
---|
235 |
// ## |
---|
236 |
// ## |
---|
237 |
pieceCurr[0] = new Square(m, 0, (byte) 7); |
---|
238 |
pieceCurr[1] = new Square(m + 1, 1, (byte) 7); |
---|
239 |
pieceCurr[2] = new Square(m, 1, (byte) 7); |
---|
240 |
pieceCurr[3] = new Square(m - 1, 0, (byte) 7); |
---|
241 |
break; |
---|
242 |
|
---|
243 |
case 4: |
---|
244 |
// ## |
---|
245 |
// ## |
---|
246 |
pieceCurr[0] = new Square(m - 1, 1, (byte) 3); |
---|
247 |
pieceCurr[1] = new Square(m, 1, (byte) 3); |
---|
248 |
pieceCurr[2] = new Square(m - 1, 0, (byte) 3); |
---|
249 |
pieceCurr[3] = new Square(m, 0, (byte) 3); |
---|
250 |
|
---|
251 |
break; |
---|
252 |
|
---|
253 |
case 5: |
---|
254 |
// # |
---|
255 |
// ### |
---|
256 |
pieceCurr[0] = new Square(m, 1, (byte) 6); |
---|
257 |
pieceCurr[1] = new Square(m - 1, 1, (byte) 6); |
---|
258 |
pieceCurr[2] = new Square(m + 1, 1, (byte) 6); |
---|
259 |
pieceCurr[3] = new Square(m + 1, 0, (byte) 6); |
---|
260 |
break; |
---|
261 |
|
---|
262 |
case 6: |
---|
263 |
// # |
---|
264 |
// ### |
---|
265 |
pieceCurr[0] = new Square(m, 1, (byte) 4); |
---|
266 |
pieceCurr[1] = new Square(m + 1, 1, (byte) 4); |
---|
267 |
pieceCurr[2] = new Square(m - 1, 1, (byte) 4); |
---|
268 |
pieceCurr[3] = new Square(m - 1, 0, (byte) 4); |
---|
269 |
break; |
---|
270 |
} |
---|
271 |
} |
---|
272 |
|
---|
273 |
/** |
---|
274 |
* �����釉�����대����. |
---|
275 |
* |
---|
276 |
* @param byx |
---|
277 |
* ��� �대� 蹂�� |
---|
278 |
* @param byy |
---|
279 |
* ��� �대� 蹂�� |
---|
280 |
* @param rotate |
---|
281 |
* ��� �щ� |
---|
282 |
* |
---|
283 |
* @return �대� 媛����寃쎌� true, 洹몃�吏�紐삵� 寃쎌� false |
---|
284 |
*/ |
---|
285 |
synchronized boolean moveCurrentPiece(int byx, int byy, boolean rotate) { |
---|
286 |
|
---|
287 |
Square newpos[] = new Square[4]; |
---|
288 |
|
---|
289 |
for (int i = 0; i < 4; i++) { |
---|
290 |
if (rotate) { |
---|
291 |
int dx = pieceCurr[i].getX() - pieceCurr[0].getX(); |
---|
292 |
int dy = pieceCurr[i].getY() - pieceCurr[0].getY(); |
---|
293 |
|
---|
294 |
newpos[i] = new Square(pieceCurr[0].getX() + dy, pieceCurr[0].getY() - dx, pieceCurr[i].getColor()); |
---|
295 |
|
---|
296 |
} else { |
---|
297 |
newpos[i] = new Square(pieceCurr[i].getX() + byx, pieceCurr[i].getY() + byy, pieceCurr[i].getColor()); |
---|
298 |
} |
---|
299 |
} |
---|
300 |
|
---|
301 |
if (!moveBlocks(pieceCurr, newpos)) |
---|
302 |
return false; |
---|
303 |
|
---|
304 |
pieceCurr = newpos; |
---|
305 |
|
---|
306 |
return true; |
---|
307 |
} |
---|
308 |
|
---|
309 |
/** |
---|
310 |
* ��㈃��洹몃━��遺���대�. |
---|
311 |
*/ |
---|
312 |
@Override |
---|
313 |
protected void onDraw(Canvas canvas) { |
---|
314 |
super.onDraw(canvas); |
---|
315 |
|
---|
316 |
Log.v(Tetris4Android.TAG, "DRAWING BOARD"); |
---|
317 |
|
---|
318 |
Paint p = new Paint(); |
---|
319 |
|
---|
320 |
p.setColor(0xffffffff); |
---|
321 |
canvas.drawRect(rectClient, p); |
---|
322 |
|
---|
323 |
p.setColor(colors[0] & 0xe0ffffff); |
---|
324 |
canvas.drawRect(rectBoard, p); |
---|
325 |
|
---|
326 |
for (int c = 0; c < COLS; c++) { |
---|
327 |
for (int r = 0; r < ROWS; r++) { |
---|
328 |
{ |
---|
329 |
p.setColor(colors[boardCurr[c][r]]); |
---|
330 |
|
---|
331 |
// Log.v(Tetris4Android.TAG4LOG, |
---|
332 |
// "("+rectSquare.left+","+rectSquare.top+")-("+rectSquare.right+","+rectSquare.bottom+") COLOR = " |
---|
333 |
// + colors[boardCurr[c][r]]); |
---|
334 |
|
---|
335 |
// RoundRect |
---|
336 |
{ |
---|
337 |
RectF rectSquare = new RectF( |
---|
338 |
rectBoard.left + squareLength * c, rectBoard.top + squareLength * r |
---|
339 |
, rectBoard.left + squareLength * (c + 1) - 1, rectBoard.top + squareLength * (r + 1) - 1 |
---|
340 |
); |
---|
341 |
canvas.drawRoundRect(rectSquare, 4F, 4F, p); |
---|
342 |
} |
---|
343 |
// // BasicRect |
---|
344 |
// { |
---|
345 |
// Rect rectSquare = new Rect( |
---|
346 |
// rectBoard.left + squareLength * c, rectBoard.top + squareLength * r |
---|
347 |
// , rectBoard.left + squareLength * (c + 1) - 1, rectBoard.top + squareLength * (r + 1) - 1 |
---|
348 |
// ); |
---|
349 |
// canvas.drawRect(rectSquare, p); |
---|
350 |
// } |
---|
351 |
boardPrev[c][r] = boardCurr[c][r]; |
---|
352 |
} |
---|
353 |
} |
---|
354 |
} |
---|
355 |
} |
---|
356 |
|
---|
357 |
/* 梨��吏��쇱������硫�吏���� */ |
---|
358 |
void removeCompleteLines() { |
---|
359 |
|
---|
360 |
for (int r = ROWS - 1; r >= 0; r--) { |
---|
361 |
int c; |
---|
362 |
for (c = 0; c < COLS; c++) { |
---|
363 |
if (boardCurr[c][r] <= 0) // 鍮�怨듦������硫� ���댄�蹂����媛����. |
---|
364 |
break; |
---|
365 |
} |
---|
366 |
|
---|
367 |
// 梨��議��硫�.. |
---|
368 |
if (c == COLS) { |
---|
369 |
for (int k = r; k > 0; k--) { |
---|
370 |
for (int l = 0; l < COLS; l++) { |
---|
371 |
boardCurr[l][k] = boardCurr[l][k - 1]; |
---|
372 |
} |
---|
373 |
} |
---|
374 |
// ��� ��以�� �щ�媛��誘��, �ㅼ� �����以�� 寃�����. |
---|
375 |
r++; |
---|
376 |
} |
---|
377 |
} |
---|
378 |
} |
---|
379 |
|
---|
380 |
/* ��������瑜�����������濡����. �닿���restoreState() ����� �대(�댁� ���. */ |
---|
381 |
public Bundle saveState() { |
---|
382 |
|
---|
383 |
Bundle map = new Bundle(); |
---|
384 |
|
---|
385 |
byte board[] = new byte[COLS * ROWS]; |
---|
386 |
for (int c = 0; c < COLS; c++) { |
---|
387 |
for (int r = 0; r < ROWS; r++) { |
---|
388 |
board[r * COLS + c] = boardCurr[c][r]; |
---|
389 |
} |
---|
390 |
} |
---|
391 |
|
---|
392 |
map.putByte("mode", mode); |
---|
393 |
map.putByteArray("boardCurr", board); |
---|
394 |
|
---|
395 |
return map; |
---|
396 |
} |
---|
397 |
|
---|
398 |
/* ��������瑜�蹂듭����. �닿���saveState() ����� �대(�댁� ���. */ |
---|
399 |
public void restoreState(Bundle map) { |
---|
400 |
|
---|
401 |
setMode(PAUSE); |
---|
402 |
|
---|
403 |
byte board[]; |
---|
404 |
board = map.getByteArray("boardCurr"); |
---|
405 |
|
---|
406 |
for (int c = 0; c < COLS; c++) { |
---|
407 |
for (int r = 0; r < ROWS; r++) { |
---|
408 |
boardCurr[c][r] = board[r * COLS + c]; |
---|
409 |
} |
---|
410 |
} |
---|
411 |
|
---|
412 |
setMode(map.getByte("mode")); |
---|
413 |
} |
---|
414 |
} |
---|