先ほどのサンプルをベースに、簡単なゲームを作ってみます。
ソースはこちらで公開しています。
https://github.com/matsushima-terunao/android_ringmuns
apk はこちら。
https://github.com/matsushima-terunao/android_ringmuns/raw/master/Ringmuns/bin/Ringmuns.apk
操作方法
Start ボタンを押してゲームスタート
< > ボタン、左右のフリック、スワイプで地面を回転
v ボタン、下へのフリック、スワイプでピースを下へ移動
* ボタン、タップでピースを入れ替え
同じピースが縦横ななめ3つ並ぶと消えます。
MainActivity.java
画面をタッチしたときの処理 OnTouchEvent() が追加されています。
package com.example.ringmuns;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
public static MainActivity activity;
private MyView view;
private static final int FP = LinearLayout.LayoutParams.FILL_PARENT;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); activity = this;
this.view = new MyView(this);
((LinearLayout)findViewById(R.id.layout)).addView(this.view, new LinearLayout.LayoutParams(FP, FP));
findViewById(R.id.buttonLeft).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
GameMain.keyLeft = true;
}
});
findViewById(R.id.buttonRight).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
GameMain.keyRight = true;
}
});
findViewById(R.id.buttonDown).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
GameMain.keyDown = true;
}
});
findViewById(R.id.buttonFlip).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
GameMain.keyFlip = true;
}
});
findViewById(R.id.buttonStart).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
GameMain.keyStart = true;
}
});
}
@Override
protected void onResume() {
super.onResume();
view.onResume();
}
@Override
protected void onPause() {
super.onPause();
view.onPause();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
GameMain.mouseLeft = (MotionEvent.ACTION_DOWN == event.getAction());
case MotionEvent.ACTION_MOVE:
GameMain.mouseTime = event.getEventTime();
GameMain.mouseX = (int)(event.getX() * 30 / view.getWidth());
GameMain.mouseY = (int)(event.getY() * 30 / view.getWidth());
break;
}
return true;
}
}
MyView.java
今までと大きく変わりません。
package com.example.ringmuns;
import android.content.Context;
import android.opengl.GLSurfaceView;
public class MyView extends GLSurfaceView {
public MyRenderer renderer;
public MyView(Context context) {
super(context);
renderer = new MyRenderer();
setRenderer(renderer); }
}
MyRenderer.java
今までと大きく変わりません。
package com.example.ringmuns;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;
public class MyRenderer implements Renderer {
private GameMain controller = new GameMain();
private int width, height;
public static float perspectiveFovy = 45, perspectiveNearZ = 1, perspectiveFarZ = 100;
public static float lookAtEyeX = 0, lookAtEyeY = 0, lookAtEyeZ = 0;
public static float lookAtCenterX = 0, lookAtCenterY = -0.35f, lookAtCenterZ = -1;
public static float lookAtUpperX = 0, lookAtUpperY = 1, lookAtUpperZ = 0;
public static float translateX = 0, translateY = 0, translateZ = -50;
public static float rotateX = 0, rotateY = 0, rotateZ = 0;
public static boolean isLightPosition = true;
public static float[] lightPosition = {-20.0f, 20.0f, 100.0f, 1.0f};
public static boolean isLightAmbient = true;
public static float[] lightAmbient = {0.5f, 0.5f, 0.5f, 1.0f};
public static boolean isLightDiffuse = true;
public static float[] lightDiffuse = {1.0f, 1.0f, 1.0f, 1.0f};
public static boolean isLightSpecular = true;
public static float[] lightSpecular = {1.0f, 1.0f, 1.0f, 1.0f};
public static float[] lightZero = {0, 0, 0, 0};
public static boolean planeNormal = false;
public static boolean vertexNormal = true;
public static volatile boolean optionChanged = false;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); if (isLightPosition) {
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPosition, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, isLightAmbient ? lightAmbient : lightZero, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, isLightDiffuse ? lightDiffuse : lightZero, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, isLightSpecular ? lightSpecular : lightZero, 0); gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); }
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
this.width = width;
this.height = height;
gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); GLU.gluPerspective(gl, perspectiveFovy, (float)width / height, perspectiveNearZ, perspectiveFarZ); // 視野の設定
gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); GLU.gluLookAt(gl, lookAtEyeX, lookAtEyeY, lookAtEyeZ, lookAtCenterX, lookAtCenterY, lookAtCenterZ, lookAtUpperX, lookAtUpperY, lookAtUpperZ); }
@Override
public void onDrawFrame(GL10 gl) {
controller.proc();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); if (optionChanged) {
optionChanged = false;
gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); GLU.gluPerspective(gl, perspectiveFovy, (float)width / height, perspectiveNearZ, perspectiveFarZ); // 視野の設定
gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); GLU.gluLookAt(gl, lookAtEyeX, lookAtEyeY, lookAtEyeZ, lookAtCenterX, lookAtCenterY, lookAtCenterZ, lookAtUpperX, lookAtUpperY, lookAtUpperZ); if (isLightPosition) {
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPosition, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, isLightAmbient ? lightAmbient : lightZero, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, isLightDiffuse ? lightDiffuse : lightZero, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, isLightSpecular ? lightSpecular : lightZero, 0); gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); } else {
gl.glDisable(GL10.GL_LIGHTING); gl.glDisable(GL10.GL_LIGHT0); }
}
controller.draw(gl);
}
}
MyModel.java
プリミティブの頂点の持ち方を変え、色も持てるようにしました。
package com.example.ringmuns;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
public class MyModel {
private static final float[][] vertices = {
{
-0.8f,-0.8f, 0.8f, 0.8f,-0.8f, 0.8f, -0.8f,0.8f, 0.8f, 0.8f,0.8f, 0.8f,
0.8f,-0.8f,-0.8f, -0.8f,-0.8f,-0.8f, 0.8f,0.8f,-0.8f, -0.8f,0.8f,-0.8f,
}, {
0,1.2f,0, -1,0,1, 1,0,1, 1,0,-1, -1,0,-1, 0,-1.2f,0,
}, {
-1.0f,1.2f,0, -1.0f,-1.2f,0, 1.0f,-1.2f,0, 1.0f,1.2f,0,
-0.6f,0.7f, 0.5f, -0.6f,-0.7f, 0.5f, 0.6f,-0.7f, 0.5f, 0.6f,0.7f, 0.5f,
-0.6f,0.7f,-0.5f, -0.6f,-0.7f,-0.5f, 0.6f,-0.7f,-0.5f, 0.6f,0.7f,-0.5f,
}, {
-0.6f,1.0f,-0.6f, -0.6f,1.0f,0.6f, 0.6f,1.0f,0.6f, 0.6f,1.0f,-0.6f,
-1.0f,0.5f,-1.0f, -1.0f,0.5f,1.0f, 1.0f,0.5f,1.0f, 1.0f,0.5f,-1.0f,
0.0f,-1.2f,0.0f,
}, {
-0.6f, 1.0f,-0.6f, -0.6f, 1.0f,0.6f, 0.6f, 1.0f,0.6f, 0.6f, 1.0f,-0.6f,
-1.0f, 0.0f,-1.0f, -1.0f, 0.0f,1.0f, 1.0f, 0.0f,1.0f, 1.0f, 0.0f,-1.0f,
-0.6f,-1.0f,-0.6f, -0.6f,-1.0f,0.6f, 0.6f,-1.0f,0.6f, 0.6f,-1.0f,-0.6f,
}, { 0,0.6f,0, -0.5f,0,0.5f, 0.5f,0,0.5f, 0.5f,0,-0.5f, -0.5f,0,-0.5f, 0,-0.6f,0,
}, { 0,0,0,
3 * GameMain.WIDTH * (float)Math.sin(2 * Math.PI * 0.5 / 7), 0, 3 * GameMain.WIDTH * (float)Math.cos(2 * Math.PI * 0.5 / 7),
3 * GameMain.WIDTH * (float)Math.sin(2 * Math.PI * 1.5 / 7), 0, 3 * GameMain.WIDTH * (float)Math.cos(2 * Math.PI * 1.5 / 7),
3 * GameMain.WIDTH * (float)Math.sin(2 * Math.PI * 2.5 / 7), 0, 3 * GameMain.WIDTH * (float)Math.cos(2 * Math.PI * 2.5 / 7),
3 * GameMain.WIDTH * (float)Math.sin(2 * Math.PI * 3.5 / 7), 0, 3 * GameMain.WIDTH * (float)Math.cos(2 * Math.PI * 3.5 / 7),
3 * GameMain.WIDTH * (float)Math.sin(2 * Math.PI * 4.5 / 7), 0, 3 * GameMain.WIDTH * (float)Math.cos(2 * Math.PI * 4.5 / 7),
3 * GameMain.WIDTH * (float)Math.sin(2 * Math.PI * 5.5 / 7), 0, 3 * GameMain.WIDTH * (float)Math.cos(2 * Math.PI * 5.5 / 7),
3 * GameMain.WIDTH * (float)Math.sin(2 * Math.PI * 6.5 / 7), 0, 3 * GameMain.WIDTH * (float)Math.cos(2 * Math.PI * 6.5 / 7),
}
};
private static final int[][][] points = {
{{0,1,2,3}, {4,5,6,7}, {5,0,7,2}, {1,4,3,6}, {2,3,7,6}, {5,4,0,1}},
{{0,1,2}, {0,2,3}, {0,3,4}, {0,4,1}, {1,5,2}, {2,5,3}, {3,5,4}, {4,5,1}},
{{0,4,3,7}, {1,5,0,4}, {2,6,1,5}, {3,7,2,6}, {4,5,7,6}, {3,11,0,8}, {0,8,1,9}, {1,9,2,10}, {2,10,3,11}, {9,8,10,11}},
{{0,1,3,2}, {0,4,1,5}, {1,5,2,6}, {2,6,3,7}, {3,7,0,4}, {4,8,5}, {5,8,6}, {6,8,7}, {7,8,4}},
{{0,1,3,2}, {0,4,1,5}, {1,5,2,6}, {2,6,3,7}, {3,7,0,4}, {4,8,5,9}, {5,9,6,10}, {6,10,7,11}, {7,11,4,8}},
{{0,1,2}, {0,2,3}, {0,3,4}, {0,4,1}, {1,5,2}, {2,5,3}, {3,5,4}, {4,5,1}}, {{0,1,2}, {0,2,3}, {0,3,4}, {0,4,5}, {0,5,6}, {0,6,7}, {0,7,1}}, };
private static final float[][][] colors = {
{{0.5f,0,0,1}},
{{0,0.5f,0,1}},
{{0,0,0.5f,1}},
{{0.5f,0,0.5f,1}},
{{0,0.5f,0.5f,1}},
{{1,1,0,1}}, {{0.5f,0,0,1}, {0.5f,0.5f,0,1}, {0,0.5f,0,1}, {0,0.5f,0.5f,1}, {0,0,0.5f,1}, {0.5f,0,0.5f,1}, {0.5f,0.5f,0.5f,1}}, };
private static FloatBuffer[] vertexBuffer = new FloatBuffer[vertices.length];
private static float[][] normalVectors = new float[vertices.length][];
public static final int KIND_DROP_CNT = 5;
public static final int KIND_FLUSH = 5;
public static final int KIND_FLOOR = 6;
public int kind;
public boolean deleted;
public float x, y, z;
public float b;
{
for (int k = 0; k < vertices.length; ++ k) {
int vert_cnt = 0;
for (int p = 0; p < points[k].length; ++ p) {
vert_cnt += points[k][p].length;
}
ByteBuffer buf = ByteBuffer.allocateDirect(vert_cnt * 3 * 4);
buf.order(ByteOrder.nativeOrder());
vertexBuffer[k] = buf.asFloatBuffer();
normalVectors[k] = new float[points[k].length * 3];
for (int p = 0; p < points[k].length; ++ p) {
for (int v = 0; v < points[k][p].length; ++ v) {
vertexBuffer[k].put(vertices[k][points[k][p][v] * 3 + 0]);
vertexBuffer[k].put(vertices[k][points[k][p][v] * 3 + 1]);
vertexBuffer[k].put(vertices[k][points[k][p][v] * 3 + 2]);
}
float vx1 = vertices[k][points[k][p][1] * 3 + 0] - vertices[k][points[k][p][0] * 3 + 0];
float vx2 = vertices[k][points[k][p][2] * 3 + 0] - vertices[k][points[k][p][0] * 3 + 0];
float vy1 = vertices[k][points[k][p][1] * 3 + 1] - vertices[k][points[k][p][0] * 3 + 1];
float vy2 = vertices[k][points[k][p][2] * 3 + 1] - vertices[k][points[k][p][0] * 3 + 1];
float vz1 = vertices[k][points[k][p][1] * 3 + 2] - vertices[k][points[k][p][0] * 3 + 2];
float vz2 = vertices[k][points[k][p][2] * 3 + 2] - vertices[k][points[k][p][0] * 3 + 2];
float nx = vy1 * vz2 - vy2 * vz1;
float ny = vz1 * vx2 - vz2 * vx1;
float nz = vx1 * vy2 - vx2 * vy1;
float nr = (float)Math.sqrt(nx * nx + ny * ny + nz * nz);
normalVectors[k][p * 3 + 0] = nx / nr;
normalVectors[k][p * 3 + 1] = ny / nr;
normalVectors[k][p * 3 + 2] = nz / nr;
}
vertexBuffer[k].position(0);
}
}
public void draw(GL10 gl) {
gl.glPushMatrix();
gl.glTranslatef(x + MyRenderer.translateX, y + MyRenderer.translateY, z + MyRenderer.translateZ); gl.glRotatef(MyRenderer.rotateX, 1, 0, 0); gl.glRotatef(b + MyRenderer.rotateY, 0, 1, 0); gl.glRotatef(MyRenderer.rotateZ, 0, 0, 1); gl.glFrontFace(GL10.GL_CCW); gl.glEnable(GL10.GL_CULL_FACE); gl.glCullFace(GL10.GL_BACK); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer[kind]); if (MyRenderer.vertexNormal) {
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); gl.glNormalPointer(GL10.GL_FLOAT, 0, vertexBuffer[kind]); } else {
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); }
int point = 0;
for (int p = 0; p < points[kind].length; ++ p) {
if (p < colors[kind].length) {
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT_AND_DIFFUSE, colors[kind][p], 0);
}
if (MyRenderer.planeNormal) {
gl.glNormal3f(normalVectors[kind][p * 3 + 0], normalVectors[kind][p * 3 + 1], normalVectors[kind][p * 3 + 2]); }
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, point, points[kind][p].length); point += points[kind][p].length;
}
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisable(GL10.GL_CULL_FACE); gl.glPopMatrix();
}
}
GameMain.java
ゲーム本体の処理です。
package com.example.ringmuns;
import javax.microedition.khronos.opengles.GL10;
import android.os.Handler;
import android.widget.TextView;
public class GameMain {
private static final long TOUCH_TIME = 300;
private static final float TOUCH_DISTANCE = 1;
public static final int COLS = 7;
public static final int ROWS = 15;
public static final float WIDTH = 2.5f;
enum State {
GAME_OVER,
DROPPING,
DROPPED,
JUDGING,
JUDGED,
}
private State state = State.GAME_OVER;
private long stateTime = 0;
private int judgeCount;
private int score;
private int speed;
public static boolean keyLeft, keyRight, keyDown, keyFlip, keyStart;
public static boolean mouseLeft, mouseLeftPrev;
public static long mouseTime, mouseLeftDownTime;
public static int mouseXLeftDown, mouseYLeftDown, mouseXPrev, mouseYPrev, mouseX, mouseY;
private MyModel[][] models = new MyModel[COLS][ROWS];
private MyModel[] dropModels = new MyModel[3];
private MyModel[] nextModels = new MyModel[3];
private MyModel floor;
private int dropCount;
private int dropX;
private float dropY;
Handler handler = new Handler();
public GameMain() {
floor = new MyModel();
floor.kind = MyModel.KIND_FLOOR;
floor.y = -ROWS * WIDTH + WIDTH / 4;
}
public void proc() {
try {
long curTime = System.currentTimeMillis();
int dx = 0, dy = 0;
boolean flip = false;
if (keyLeft) {
keyLeft = false;
dx = -1;
}
if (keyRight) {
keyRight = false;
dx = 1;
}
if (keyDown) {
keyDown = false;
dy = 1;
}
if (keyFlip) {
keyFlip = false;
flip = true;
}
if (mouseLeft) {
if (!mouseLeftPrev) {
mouseLeftDownTime = mouseTime;
mouseXLeftDown = mouseXPrev = mouseX;
mouseYLeftDown = mouseYPrev = mouseY;
}
} else { if (mouseLeftPrev) {
if (mouseTime - mouseLeftDownTime < TOUCH_TIME
&& Math.abs(mouseX - mouseXLeftDown) < TOUCH_DISTANCE
&& Math.abs(mouseY - mouseYLeftDown) < TOUCH_DISTANCE) {
flip = true;
}
}
}
if ((mouseLeft && mouseLeftPrev) || (!mouseLeft && mouseLeftPrev)) {
if (Math.abs(mouseX - mouseXLeftDown) >= Math.abs(mouseY - mouseYLeftDown)) {
int x = (mouseX - mouseXLeftDown) / 3;
if (mouseTime - mouseLeftDownTime < TOUCH_TIME) {
x = (0 == x ? 0 : x > 0 ? 1 : -1);
}
dx = -(x - (mouseXPrev - mouseXLeftDown) / 3);
mouseX = mouseXLeftDown + x * 3;
} else {
int y = mouseY - mouseYLeftDown;
if (mouseTime - mouseLeftDownTime < TOUCH_TIME) {
y = (0 == y ? 0 : y > 0 ? 1 : -1);
}
dy = y - (mouseYPrev - mouseYLeftDown);
mouseY = mouseYLeftDown + y;
}
}
mouseLeftPrev = mouseLeft;
mouseXPrev = mouseX;
mouseYPrev = mouseY;
float dropYPrev = dropY;
for (int i = 0; i < dy; ++ i) {
if (State.DROPPING == state) { dropYPrev = dropY;
dropY = (curTime - stateTime) / speed;
if (dropY > dropYPrev + 1) {
dropY = dropYPrev + 1;
}
if ((dropY + 2 >= ROWS - 1) || (null != models[dropX][(int)dropY + 2 + 1])) {
dropY = (float)(int)dropY;
state = State.DROPPED; stateTime = curTime;
} else {
stateTime -= speed;
}
} else if (State.DROPPED == state) { stateTime = curTime - 1000;
break;
}
}
for (int i = 0; i < Math.abs(dx); ++ i) {
if ((State.DROPPING == state) || (State.DROPPED == state)) { if (null != models[(dropX + COLS + (dx >= 0 ? 1 : -1)) % COLS][(int)dropY + 2]) {
break;
}
}
dropX = (dropX + COLS + (dx >= 0 ? 1 : -1)) % COLS;
}
if (flip) {
MyModel model = dropModels[2];
dropModels[2] = dropModels[1];
dropModels[1] = dropModels[0];
dropModels[0] = model;
}
switch (state) {
case GAME_OVER: if (keyStart) {
state = State.DROPPING; stateTime = curTime;
mouseLeft = mouseLeftPrev = false;
score = 0;
speed = 1000;
dropCount = 1;
dropX = 0;
dropY = 0;
models = new MyModel[COLS][ROWS];
for (int i = 0; i < 3; ++ i) {
dropModels[i] = new MyModel();
dropModels[i].kind = (int)(Math.random() * MyModel.KIND_DROP_CNT);
dropModels[i].b = i * 50;
nextModels[i] = new MyModel();
nextModels[i].kind = (int)(Math.random() * MyModel.KIND_DROP_CNT);
}
}
break;
case DROPPING: dropY = (curTime - stateTime) / speed;
if (dropY > dropYPrev + 1) {
dropY = dropYPrev + 1;
}
if ((dropY + 2 >= ROWS - 1) || (null != models[dropX][(int)dropY + 2 + 1])) {
dropY = (float)(int)dropY;
state = State.DROPPED; stateTime = curTime;
}
break;
case DROPPED: if (stateTime + 1000 > curTime) {
if ((dropY + 2 >= ROWS - 1) || (null != models[dropX][(int)dropY + 2 + 1])) {
} else {
state = State.DROPPING; stateTime = curTime - (long)(dropY * speed);
}
} else {
System.out.println("d4:" + dropY);
for (int i = 0; i < 3; ++ i) {
models[dropX][(int)dropY + i] = dropModels[i];
dropModels[i] = null;
}
state = State.JUDGING; stateTime = curTime - 500;
judgeCount = 1;
}
break;
case JUDGING: if (stateTime + 500 > curTime) {
break;
}
int deleteCnt = 0;
if ((null != models[dropX][(int)dropY]) && (MyModel.KIND_FLUSH == models[dropX][(int)dropY].kind)) {
if (dropY + 2 + 1 >= ROWS) {
deleteCnt = 100;
} else {
int kind = models[dropX][(int)dropY + 2 + 1].kind;
for (int x = 0; x < COLS; ++ x) {
for (int y = 0; y < ROWS; ++ y) {
if ((null != models[x][y]) && (kind == models[x][y].kind)) {
models[x][y].deleted = true;
++ deleteCnt;
}
}
}
}
} else {
final int[] dirs = {1,0, 0,1, 1,1, -1,1}; for (int d = 0; d < dirs.length; d += 2) {
for (int x = 0; x < COLS; ++ x) {
for (int y = 0; y < ROWS; ++ y) {
int x1 = (x + COLS + dirs[d] * 1) % COLS;
int x2 = (x + COLS + dirs[d] * 2) % COLS;
int y1 = y + dirs[d + 1] * 1;
int y2 = y + dirs[d + 1] * 2;
if (y2 < ROWS
&& null != models[x][y]
&& null != models[x1][y1]
&& null != models[x2][y2]
&& models[x][y].kind == models[x1][y1].kind
&& models[x][y].kind == models[x2][y2].kind) {
deleteCnt += 3;
models[x][y].deleted = true;
models[x1][y1].deleted = true;
models[x2][y2].deleted = true;
}
}
}
}
}
if (deleteCnt > 0) {
for (int x = 0; x < COLS; ++ x) {
for (int y = 0; y < ROWS; ++ y) {
if ((null != models[x][y]) && (models[x][y].deleted)) {
models[x][y].kind = MyModel.KIND_FLUSH;
}
}
}
state = State.JUDGED; stateTime = curTime;
} else {
for (int x = 0; x < COLS; ++ x) {
if (null != models[x][2]) {
state = State.GAME_OVER; return;
}
}
++ dropCount;
boolean flush = (0 == dropCount % 100);
for (int i = 0; i < 3; ++ i) {
dropModels[i] = nextModels[i];
dropModels[i].b = i * 50;
nextModels[i] = new MyModel();
nextModels[i].kind = (flush ? MyModel.KIND_FLUSH : (int)(Math.random() * MyModel.KIND_DROP_CNT));
}
state = State.DROPPING; stateTime = curTime;
mouseLeft = mouseLeftPrev = false;
dropY = 0;
}
score += deleteCnt * 100 * judgeCount;
speed = Math.max(100, 1000 - score / 100);
final String textScore = "" + score; handler.post(new Runnable() {
@Override
public void run() {
((TextView)MainActivity.activity.findViewById(R.id.textView1)).setText(textScore);
}
});
break;
case JUDGED: if (stateTime + 500 > curTime) {
break;
}
for (int x = 0; x < COLS; ++ x) {
for (int y = ROWS - 1; y >= 0; ) {
if (null == models[x][y]) {
break;
} else if (MyModel.KIND_FLUSH != models[x][y].kind) {
-- y;
} else {
for (int i = y; i >= 1; -- i) {
models[x][i] = models[x][i - 1];
}
models[x][0] = null;
}
}
}
state = State.JUDGING; stateTime += 500;
++ judgeCount;
break;
}
keyLeft = keyRight = keyDown = keyFlip = keyStart = false;
} catch (RuntimeException e) {
System.out.println(e.toString());
e.printStackTrace(System.out);
throw e;
}
}
private long drawTime = System.currentTimeMillis();
public void draw(GL10 gl) {
floor.b = -360f * dropX / COLS;
floor.draw(gl);
for (int x = 0; x < COLS; ++ x) {
float tx = (float)Math.sin(2 * Math.PI * (x - dropX) / COLS) * WIDTH * 2;
float tz = (float)Math.cos(2 * Math.PI * (x - dropX) / COLS) * WIDTH * 2;
for (int y = 0; y < ROWS; ++ y) {
if (null != models[x][y]) {
models[x][y].x = tx;
models[x][y].y = -y * WIDTH;
models[x][y].z = tz;
models[x][y].b += floor.b;
models[x][y].draw(gl);
models[x][y].b -= floor.b;
}
}
}
long bTime = System.currentTimeMillis();
float vb = (bTime - drawTime) * 360f / 2000f;
drawTime = bTime;
for (int i = 0; i < 3; ++ i) {
if (null != dropModels[i]) {
dropModels[i].x = 0;
dropModels[i].y = -(dropY + i) * WIDTH;
dropModels[i].z = WIDTH * 2;
dropModels[i].b += vb;
dropModels[i].b += floor.b;
dropModels[i].draw(gl);
dropModels[i].b -= floor.b;
}
}
for (int i = 0; i < 3; ++ i) {
if (null != nextModels[i]) {
nextModels[i].x = WIDTH * 4;
nextModels[i].y = -i * WIDTH;
nextModels[i].z = 0;
nextModels[i].b = 0;
nextModels[i].draw(gl);
}
}
}
}
activity_main.xml
特に大きく変わりません。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="0dp"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.ringmuns.MainActivity" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="0dp"
android:layout_marginLeft="34dp"
android:layout_marginTop="21dp"
android:orientation="vertical"
android:padding="0dp" >
<LinearLayout
android:id="@+id/layout"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical" >
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="@+id/textView2"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_weight="0" />
<Button
android:id="@+id/buttonStart"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:text="start" />
<TextView
android:id="@+id/TextView01"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_weight="0" />
<Button
android:id="@+id/buttonLeft"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text="<" />
<Button
android:id="@+id/buttonDown"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text="v" />
<Button
android:id="@+id/buttonFlip"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text="*" />
<Button
android:id="@+id/buttonRight"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text=">" />
</LinearLayout>
<LinearLayout
android:id="@+id/optionLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
</RelativeLayout>
← 1-4. Android で OpenGL その2
↑ 一覧