import java.util.Random; |
|
import com.nttdocomo.ui.Canvas; |
import com.nttdocomo.ui.Display; |
import com.nttdocomo.ui.Font; |
import com.nttdocomo.ui.Graphics; |
import com.nttdocomo.ui.IApplication; |
|
public class TemplateAppli extends IApplication implements Runnable { |
|
int FIELD_WIDTH = 12; |
int FIELD_HEIGHT = 22; |
|
int[][][] pattern = { |
{ |
{0, 1, 0}, |
{0, 1, 0}, |
{0, 1, 0} |
}, { |
{0, 1, 0}, |
{0, 1, 1}, |
{0, 0, 0} |
} |
}; |
|
int mode = 0; // ゲーム内の状態を表すモード(0:落下開始、1:落下中、2:着地) |
int score = 0; |
int totalLines = 0; |
Thread thread; |
Random random = new Random(); |
StringBuffer keyBuffer = new StringBuffer(); |
int[][] field = new int[FIELD_HEIGHT][FIELD_WIDTH]; |
int[][] next = new int[pattern[0].length][pattern[0].length]; |
|
Canvas canvas; |
|
public void start() { |
canvas = new Canvas() { |
public void paint(Graphics g) { |
// このメソッドは利用しないので実装する必要はない |
} |
|
public void processEvent(int type, int param) { |
// 落下中でかつ先行入力が2つ未満の場合のみキー入力を受け付ける |
if (mode == 1 && keyBuffer.length() < 2) { |
if (type == Display.KEY_PRESSED_EVENT) { |
if (param == Display.KEY_DOWN) { |
keyBuffer.append('D'); |
} else if (param == Display.KEY_UP) { |
keyBuffer.append('U'); |
} else if (param == Display.KEY_LEFT) { |
keyBuffer.append('L'); |
} else if (param == Display.KEY_RIGHT) { |
keyBuffer.append('R'); |
} else { |
keyBuffer.append('A'); |
} |
} |
} |
} |
}; |
Display.setCurrent(canvas); |
thread = new Thread(this); |
thread.start(); |
} |
|
public void resume() { |
// このイベントは利用しないので実装する必要はない |
} |
|
public void run() { |
int x = 0; |
int y = 0; |
int count = 0; |
int prevKey = '0'; |
initField(); |
int[][] current = new int[pattern[0].length][pattern[0].length]; |
copy(pattern[Math.abs(random.nextInt() % pattern.length)], next); |
char keyKind = 'N'; // 'N' はどれにも該当しないキーを表す |
int keyRepeat = 0; |
Graphics g = canvas.getGraphics(); |
while (true) { |
if (mode == 0) { |
if (keyBuffer.length() > 0) { |
keyBuffer.delete(0, keyBuffer.length() - 1); |
} |
copy(next, current); |
copy(pattern[Math.abs(random.nextInt() % pattern.length)], next); |
int rotateCount = Math.abs(random.nextInt() % 4); |
for (int i = 0; i < rotateCount; i++) { |
rotate(next); |
} |
x = FIELD_WIDTH / 2 - (int)Math.sqrt(pattern[0].length); |
y = 0; |
// ゲーム終了判定 |
if (isHit(x, y, current)) { |
initField(); |
score = 0; |
totalLines = 0; |
} |
mode = 1; |
count = 0; |
keyRepeat = 0; |
} else if (mode == 1) { |
boolean fix = false; |
if (count != 0) { |
char key = 'N'; // 'N' は何も押していないことを表す |
if (count % 20 == 0) { |
if (!(keyBuffer.length() > 0 && keyBuffer.charAt(0) == 'D')) { |
keyBuffer.insert(0, 'D'); |
} |
} else { |
int keyState = canvas.getKeypadState(); |
if (keyState == 1 << Display.KEY_DOWN) { |
if (keyKind == 'D') { |
if (keyRepeat++ > 3) { |
keyBuffer.append('D'); |
} |
} else { |
keyKind = 'D'; |
keyRepeat = 0; |
} |
} else if (keyState == 1 << Display.KEY_UP) { |
if (keyKind == 'U') { |
if (keyRepeat++ > 3) { |
keyBuffer.append('U'); |
} |
} else { |
keyKind = 'U'; |
keyRepeat = 0; |
} |
} else if (keyState == 1 << Display.KEY_LEFT) { |
if (keyKind == 'L') { |
if (keyRepeat++ > 3) { |
keyBuffer.append('L'); |
} |
} else { |
keyKind = 'L'; |
keyRepeat = 0; |
} |
} else if (keyState == 1 << Display.KEY_RIGHT) { |
if (keyKind == 'R') { |
if (keyRepeat++ > 3) { |
keyBuffer.append('R'); |
} |
} else { |
keyKind = 'R'; |
keyRepeat = 0; |
} |
} else if (keyState != 0){ |
if (keyKind == 'A') { |
if (keyRepeat++ > 3) { |
keyBuffer.append('A'); |
} |
} else { |
keyKind = 'A'; |
keyRepeat = 0; |
} |
} else { |
keyKind = 'N'; |
keyRepeat = 0; |
} |
} |
if (keyBuffer.length() > 0) { |
key = keyBuffer.charAt(0); |
keyBuffer.deleteCharAt(0); |
if (key == 'L') { |
x--; |
} else if (key == 'R') { |
x++; |
} else if (key == 'D') { |
y++; |
} else if (key == 'A') { |
rotate(current); |
} else if (key == 'U') { |
while (!isHit(x, y, current)) { |
y++; |
} |
} |
if (isHit(x, y, current)) { |
if (key == 'L') { |
x++; |
} else if (key == 'R') { |
x--; |
} else if (key == 'A') { |
if (prevKey == 'L') { |
if (!isHit(x + 1, y, current)) { |
x++; |
} else { |
rotate(current); |
rotate(current); |
rotate(current); |
} |
} else if (prevKey == 'R') { |
if (!isHit(x - 1, y, current)) { |
x--; |
} else { |
rotate(current); |
rotate(current); |
rotate(current); |
} |
} |
} else if (key == 'D' || key == 'U') { |
y--; |
fix = true; |
} |
} |
if (key == 'L' || key == 'R') { |
prevKey = key; |
} |
} |
} |
|
for (int i = 0; i < FIELD_HEIGHT; i++) { |
for (int j = 0; j < FIELD_WIDTH; j++) { |
if (field[i][j] == 1) { |
field[i][j] = 0; |
} |
} |
} |
|
for (int i = 0; i < current.length; i++) { |
for (int j = 0; j < current[i].length; j++) { |
if (current[i][j] == 1) { |
field[y + i][x + j] = 1; |
if (fix) { |
field[y + i][x + j] = 2; |
} |
} |
} |
} |
|
g.lock(); |
|
// メインフィールドを描画 |
drawBlocks(g); |
|
// 次に出現するブロックを描画 |
drawNext(g); |
|
// 得点と消去したライン数を描画 |
drawScore(g); |
|
g.unlock(true); |
|
if (fix) { |
mode = 2; |
} |
if (count == 0) { |
sleep(150); |
} else { |
sleep(50); |
} |
count++; |
} else if (mode == 2) { |
// 一列揃ったかどうかを判定する |
int[] eraseLines = new int[pattern[0].length]; |
int index = 0; |
for (int i = 0; i < FIELD_HEIGHT; i++) { |
boolean complete = true; |
for (int j = 1; j < FIELD_WIDTH - 1; j++) { |
if (field[i][j] != 2) { |
complete = false; |
break; |
} |
} |
if (complete) { |
eraseLines[index++] = i; |
} |
} |
if (index != 0) { |
for (int i = 0; i < 5; i++) { |
for (int j = 0; j < index; j++) { |
for (int k = 1; k < FIELD_WIDTH - 1; k++) { |
field[eraseLines[j]][k] = i % 2 == 0 ? 0 : 2; |
} |
} |
g.lock(); |
// メインフィールドを描画 |
drawBlocks(g); |
g.unlock(true); |
sleep(150); |
} |
for (int i = 0; i < index; i++) { |
for (int j = eraseLines[i] - 1; j > 0; j--) { |
field[j + 1] = field[j]; |
field[j] = new int[FIELD_WIDTH]; |
field[j][0] = field[j][FIELD_WIDTH - 1] = -1; |
} |
} |
score += index * index * 10; |
totalLines += index; |
} |
mode = 0; |
} |
} |
} |
|
void copy(int[][] src, int[][] dest) { |
for (int i = 0; i < src.length; i++) { |
System.arraycopy(src[i], 0, dest[i], 0, src[i].length); |
} |
} |
|
void rotate(int[][] omino) { |
int[][] temp = new int[omino[0].length][omino[0].length]; |
temp[0][2] = omino[0][0]; |
temp[1][2] = omino[0][1]; |
temp[2][2] = omino[0][2]; |
temp[0][1] = omino[1][0]; |
temp[1][1] = omino[1][1]; |
temp[2][1] = omino[1][2]; |
temp[0][0] = omino[2][0]; |
temp[1][0] = omino[2][1]; |
temp[2][0] = omino[2][2]; |
for (int i = 0; i < omino.length; i++) { |
System.arraycopy(temp[i], 0, omino[i], 0, temp[i].length); |
} |
} |
|
boolean isHit(int x, int y, int[][] omino) { |
for (int i = 0; i < omino.length; i++) { |
for (int j = 0; j < omino[i].length; j++) { |
if (omino[i][j] == 1) { |
if (field[y + i][x + j] == -1 || field[y + i][x + j] == 2) { |
return true; |
} |
} |
} |
} |
return false; |
} |
|
void initField() { |
for (int i = 0; i < FIELD_HEIGHT; i++) { |
for (int j = 0; j < FIELD_WIDTH; j++) { |
if (j == 0 || j == FIELD_WIDTH - 1) { |
field[i][j] = -1; |
} else if (i == FIELD_HEIGHT - 1) { |
field[i][j] = -1; |
} else { |
field[i][j] = 0; |
} |
} |
} |
for (int i = 1; i < FIELD_WIDTH - 1; i++) { |
field[FIELD_HEIGHT - 1][i] = -1; |
} |
for (int i = 0; i < FIELD_HEIGHT; i++) { |
field[i][0] = -1; |
field[i][FIELD_WIDTH - 1] = -1; |
} |
} |
|
void drawBlocks(Graphics g) { |
int blockSize = canvas.getHeight() / (FIELD_HEIGHT + 2); |
for (int i = 0; i < FIELD_HEIGHT; i++) { |
for (int j = 0; j < FIELD_WIDTH; j++) { |
if (field[i][j] == -1) { |
g.setColor(Graphics.getColorOfName(Graphics.GRAY)); |
g.fillRect(j * blockSize, i * blockSize, blockSize, blockSize); |
} else if (field[i][j] == 1) { |
g.setColor(Graphics.getColorOfName(Graphics.RED)); |
g.fillRect(j * blockSize, i * blockSize, blockSize, blockSize); |
} else if (field[i][j] == 2) { |
g.setColor(Graphics.getColorOfName(Graphics.BLUE)); |
g.fillRect(j * blockSize, i * blockSize, blockSize, blockSize); |
} else { |
g.setColor(Graphics.getColorOfName(Graphics.BLACK)); |
g.fillRect(j * blockSize, i * blockSize, blockSize, blockSize); |
} |
} |
} |
} |
|
void drawNext(Graphics g) { |
int ominoSize = pattern[0].length; |
int blockSize = canvas.getHeight() / (FIELD_HEIGHT + 2); |
for (int i = 0; i < ominoSize; i++) { |
for (int j = 0; j < ominoSize; j++) { |
if (next[i][j] == 1) { |
g.setColor(Graphics.getColorOfName(Graphics.RED)); |
g.fillRect((FIELD_WIDTH + j + 1) * blockSize, (i + 1) * blockSize, blockSize, blockSize); |
} else { |
g.setColor(Graphics.getColorOfName(Graphics.WHITE)); |
g.fillRect((FIELD_WIDTH + j + 1) * blockSize, (i + 1) * blockSize, blockSize, blockSize); |
} |
} |
} |
} |
|
void drawScore(Graphics g) { |
int blockSize = canvas.getHeight() / (FIELD_HEIGHT + 2); |
int fontHeight = Font.getDefaultFont().getHeight(); |
int offx = (FIELD_WIDTH + 1) * blockSize; |
int offy = (FIELD_HEIGHT) * blockSize - fontHeight * 2; |
g.setColor(Graphics.getColorOfName(Graphics.WHITE)); |
g.fillRect(offx, offy, canvas.getWidth() - offx, fontHeight * 2); |
g.setColor(Graphics.getColorOfName(Graphics.BLACK)); |
g.drawString("Line:" + totalLines, offx, offy + fontHeight); |
g.drawString("Score:" + score, offx, offy + fontHeight * 2); |
} |
|
void sleep(long millis) { |
try { |
Thread.sleep(millis); |
} catch (InterruptedException e) { |
// 例外は発生しない |
} |
} |
|
} |