android采用GLSurfaceView开发一个小游戏

2024-06-14 17:18 android采用GLSurfaceView开发一个小游戏已关闭评论

开发一个简单的小游戏可以通过使用GLSurfaceView来实现,下面我将展示一个基本的例子,一个简单的OpenGL ES 2.0小游戏,在屏幕上渲染一个可以移动的二维正方形。我们会通过触摸屏幕来移动这个正方形。

项目结构

  1. 布局文件:定义一个GLSurfaceView
  2. GLSurfaceView子类:设置渲染器和处理触摸事件。
  3. 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;
    }
}

代码说明

  1. MainActivity.java:初始化GLSurfaceView并设置渲染器,处理触摸事件将触摸坐标传递给渲染器。
  2. MyGLRenderer.java:实现Renderer接口,在onDrawFrame方法中绘制一个正方形,并根据触摸输入更新正方形的位置。

总结

这只是一个非常基本的例子,展示了如何使用GLSurfaceView和OpenGL ES 2.0在Android上进行简单的游戏开发。你可以进一步扩展这个示例,添加更多的图形、动画和交互逻辑来创建更复杂的游戏。

当前文章价值6.85元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://teachcourse.cn/3489.html ,谢谢支持!

资源分享

分类:Android 标签:, ,
Map接口集合方法解析 Map接口集合方法解析
Android开发之深入理解Builder设计模式 Android开发之深入理解Builder
浅谈SortedList方法使用 浅谈SortedList方法使用
python实现正则表达式获取html图片目录 python实现正则表达式获取html图

评论已关闭!