开发一个简单的小游戏可以通过使用GLSurfaceView来实现,下面我将展示一个基本的例子,一个简单的OpenGL ES 2.0小游戏,在屏幕上渲染一个可以移动的二维正方形。我们会通过触摸屏幕来移动这个正方形。
项目结构
- 布局文件:定义一个
GLSurfaceView。 - GLSurfaceView子类:设置渲染器和处理触摸事件。
- Renderer实现类:处理OpenGL ES绘制。
1. 布局文件
在res/layout/activity_main.xml中定义一个GLSurfaceView。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.opengl.GLSurfaceView
android:id="@+id/glSurfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
2. GLSurfaceView子类
在MainActivity.java中设置GLSurfaceView并处理触摸事件。
package com.example.openglesgame;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private GLSurfaceView glSurfaceView;
private MyGLRenderer renderer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
glSurfaceView = findViewById(R.id.glSurfaceView);
glSurfaceView.setEGLContextClientVersion(2);
renderer = new MyGLRenderer();
glSurfaceView.setRenderer(renderer);
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
glSurfaceView.setOnTouchListener(new GLSurfaceView.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event != null) {
final float normalizedX = (event.getX() / (float) v.getWidth()) * 2 - 1;
final float normalizedY = -((event.getY() / (float) v.getHeight()) * 2 - 1);
glSurfaceView.queueEvent(new Runnable() {
@Override
public void run() {
renderer.handleTouch(normalizedX, normalizedY);
}
});
return true;
}
return false;
}
});
}
@Override
protected void onPause() {
super.onPause();
glSurfaceView.onPause();
}
@Override
protected void onResume() {
super.onResume();
glSurfaceView.onResume();
}
}
3. Renderer实现类
在MyGLRenderer.java中实现GLSurfaceView.Renderer接口。
package com.example.openglesgame;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class MyGLRenderer implements GLSurfaceView.Renderer {
private final FloatBuffer vertexBuffer;
private final int program;
private int positionHandle;
private int colorHandle;
private int mvpMatrixHandle;
private float[] mvpMatrix = new float[16];
private float[] projectionMatrix = new float[16];
private float[] viewMatrix = new float[16];
private float[] modelMatrix = new float[16];
private float squareCoords[] = {
-0.1f, 0.1f, 0.0f, // top left
-0.1f, -0.1f, 0.0f, // bottom left
0.1f, -0.1f, 0.0f, // bottom right
0.1f, 0.1f, 0.0f }; // top right
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 };
private float[] color = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
private float squareX = 0.0f;
private float squareY = 0.0f;
public MyGLRenderer() {
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
@Override
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(program);
positionHandle = GLES20.glGetAttribLocation(program, "vPosition");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
colorHandle = GLES20.glGetUniformLocation(program, "vColor");
GLES20.glUniform4fv(colorHandle, 1, color, 0);
Matrix.setIdentityM(modelMatrix, 0);
Matrix.translateM(modelMatrix, 0, squareX, squareY, 0);
Matrix.multiplyMM(mvpMatrix, 0, viewMatrix, 0, modelMatrix, 0);
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, mvpMatrix, 0);
mvpMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
GLES20.glDisableVertexAttribArray(positionHandle);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
Matrix.setLookAtM(viewMatrix, 0, 0, 0, -5, 0, 0, 0, 0, 1, 0);
}
public void handleTouch(float normalizedX, float normalizedY) {
squareX = normalizedX;
squareY = normalizedY;
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}
代码说明
- MainActivity.java:初始化
GLSurfaceView并设置渲染器,处理触摸事件将触摸坐标传递给渲染器。 - MyGLRenderer.java:实现
Renderer接口,在onDrawFrame方法中绘制一个正方形,并根据触摸输入更新正方形的位置。
总结
这只是一个非常基本的例子,展示了如何使用GLSurfaceView和OpenGL ES 2.0在Android上进行简单的游戏开发。你可以进一步扩展这个示例,添加更多的图形、动画和交互逻辑来创建更复杂的游戏。
当前文章价值6.85元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

你可能感兴趣的文章
分类:Android
标签:glsurfaceview, renderer, 渲染
评论已关闭!