0

伙计们,我再次需要你的帮助:)

MainRenderer.java:

package com.example.galaga2d;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ByteOrder;
import java.util.Random;
import java.util.Vector;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;

public class MainRenderer implements Renderer {
    Random rand = new Random();
    float chance = 0.0f;
    private Context context;

    public Ship playerShip = new Ship();

    Vector<Asteroid> asteroidVector = new Vector<Asteroid>();

    public MainRenderer(Context context) {
        this.context = context;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //! TEXTURES
        playerShip.loadGLTexture(gl, this.context);

        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_ONE, GL10.GL_SRC_COLOR);
        //gl.glShadeModel(GL10.GL_SMOOTH);
        //! TEXTURES

        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    }


    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        gl.glLoadIdentity();


        chance = rand.nextFloat() * (100.0f - 1.0f) + 1.0f;

        if (chance <= 4.0f) {
            asteroidVector.addElement(new Asteroid());
        }


        if (playerShip.life != 0) {

            playerShip.draw(gl);

            gl.glLoadIdentity();

            for (int i = 0; i < asteroidVector.size(); i++) {
                if(asteroidVector.elementAt(i).textured == 0) {
                    asteroidVector.elementAt(i).loadGLTexture(gl,  this.context);
                    asteroidVector.elementAt(i).textured |= 1;
                    //gl.glLoadIdentity();
                } else {
                    asteroidVector.elementAt(i).textured &= ~1;
                }

            }

            for (int i = 0; i < asteroidVector.size(); i++) {
                asteroidVector.elementAt(i).collisionCheck();
                asteroidVector.elementAt(i).draw(gl);
                if (asteroidVector.elementAt(i).Y > 480.0f) {
                    asteroidVector.remove(i);
                }

                gl.glLoadIdentity();
            }

        } else {
            gl.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
        }


    }



    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrthof(0, width, height, 0, 1, -1);
        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

// --------------------------------------------------------------------------------

    class Ship {
        public int life = 3;                    // Количество жизней игрока

        public FloatBuffer ShipVertexBuffer;    // Vertex буффер
        public FloatBuffer ShipTextureBuffer;   // Texture буффер

        public float X = 100.0f;                // Начальные координаты игрока по X
        public float Y = 300.0f;                // Начальные координаты игрока по Y

        //! TEXTURES
        private int[] textures = new int[1];
        //! TEXTURES

        public float ShipVerticles[] = {        // Вертикли прямоугольника - корабль
            0, 0,
            0, 30,
            30, 0,
            30, 30
        };

        //! TEXTURES
        public float ShipTextures[] = {         // Разметка наложения текстуры, соответствует
                0.0f, 0.0f,                     // разметке вертиклей
                0.0f, 1.0f,
                1.0f, 0.0f,
                1.0f, 1.0f
            };
        //! TEXTURES

        public Ship() {
            //! Буффер вертексов
            ByteBuffer bb = ByteBuffer.allocateDirect(36);
            bb.order(ByteOrder.nativeOrder());
            ShipVertexBuffer = bb.asFloatBuffer();
            ShipVertexBuffer.put(ShipVerticles);
            ShipVertexBuffer.position(0);

            //! TEXTURES
            bb = ByteBuffer.allocateDirect(ShipTextures.length * 4);
            bb.order(ByteOrder.nativeOrder());
            ShipTextureBuffer = bb.asFloatBuffer();
            ShipTextureBuffer.put(ShipTextures);
            ShipTextureBuffer.position(0);
            //! TEXTURES
        }

        public void loadGLTexture(GL10 gl, Context context) {
            // loading texture
            Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
                    R.drawable.ship);

            // generate one texture pointer
            gl.glGenTextures(1, textures, 0);
            // ...and bind it to our array
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

            // create nearest filtered texture
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

            // Use Android GLUtils to specify a two-dimensional texture image from our bitmap 
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            // Clean up
            bitmap.recycle();
        }

        public void draw(GL10 gl) {
            //! TEXTURE
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            //! TEXTURE

            gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
            gl.glTranslatef(playerShip.X, playerShip.Y, 0.0f);
            gl.glVertexPointer(2, GL10.GL_FLOAT, 0, ShipVertexBuffer);

            //! TEXTURE         
            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, ShipTextureBuffer);
            //! TEXTURE         

            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

            //! TEXTURE             
            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            //! TEXTURE 
        }

    }

    class Asteroid {
        private float colorR = rand.nextFloat()* (1.0f - 0.3f) + 0.3f;
        private float colorG = rand.nextFloat()* (1.0f - 0.3f) + 0.3f;
        private float colorB = rand.nextFloat()* (1.0f - 0.3f) + 0.3f;

        private float X = rand.nextFloat() * (300.0f - 1.0f) + 1.0f;
        private float Y = -30.0f;

        private float size = rand.nextFloat() * (30.0f - 20.0f) + 20.0f;

        private float speed = rand.nextFloat() * (10.0f - 1.0f) + 1.0f;

        private int collision = 0;

        private int textured = 0;

        private FloatBuffer AsteroidVertexBuffer;
        private FloatBuffer AsteroidTextureBuffer;

        //! TEXTURES
        private int[] textures = new int[1];
        //! TEXTURES

        public float AsteroidVerticles[] = {
                0, 0,       // лево низ
                0, size,        // лево вверх
                size, 0,        // право низ
                size, size      // право вверх
            };

        //! TEXTURES
        public float AsteroidTextures[] = {
                0.0f, 0.0f,
                0.0f, 1.0f,
                1.0f, 0.0f,
                1.0f, 1.0f
            };
        //! TEXTURES

        public Asteroid() {


            ByteBuffer bb = ByteBuffer.allocateDirect(36);
            bb.order(ByteOrder.nativeOrder());
            AsteroidVertexBuffer = bb.asFloatBuffer();
            AsteroidVertexBuffer.put(AsteroidVerticles);
            AsteroidVertexBuffer.position(0);

            //! TEXTURES
            bb = ByteBuffer.allocateDirect(AsteroidTextures.length * 4);
            bb.order(ByteOrder.nativeOrder());
            AsteroidTextureBuffer = bb.asFloatBuffer();
            AsteroidTextureBuffer.put(AsteroidTextures);
            AsteroidTextureBuffer.position(0);
            //! TEXTURES
        }

        public void collisionCheck() {
            float result = (float)Math.sqrt(Math.pow((playerShip.X-X), 2)+Math.pow((playerShip.Y-Y), 2));

            if (result < size)
            {
                if(collision == 0)
                {
                    playerShip.life = playerShip.life - 1;
                    collision |= 1;
                }
            } else {
                collision &= ~1;
            }
        }

        public void loadGLTexture(GL10 gl, Context context) {
            // loading texture
            Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
                    R.drawable.asteroid);

            // generate one texture pointer
            gl.glGenTextures(1, textures, 0);
            // ...and bind it to our array
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

            // create nearest filtered texture
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

            // Use Android GLUtils to specify a two-dimensional texture image from our bitmap 
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            // Clean up
            bitmap.recycle();
        }

        public void draw(GL10 gl) {
            Y += speed;
            //! TEXTURE
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            //! TEXTURE

            gl.glColor4f(colorR, colorG, colorB, 1.0f);

            gl.glTranslatef(X, Y, 0.0f);
            gl.glVertexPointer(2, GL10.GL_FLOAT, 0, AsteroidVertexBuffer);

            //! TEXTURE         
            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, AsteroidTextureBuffer);
            //! TEXTURE         

            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

            //! TEXTURE             
            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            //! TEXTURE 
        }

    }

// --------------------------------------------------------------------------------

}

每一帧都偶然画出小行星:

chance = rand.nextFloat() * (100.0f - 1.0f) + 1.0f;

if (chance <= 4.0f) {
    asteroidVector.addElement(new Asteroid());
}

这意味着我们需要为我们每秒绘制的所有新对象加载纹理,但我们不需要多次为一个对象加载纹理,并且我添加标志来检查对象是否纹理化:

    for (int i = 0; i < asteroidVector.size(); i++) {
        if(asteroidVector.elementAt(i).textured == 0) {
            asteroidVector.elementAt(i).loadGLTexture(gl,  this.context);
            asteroidVector.elementAt(i).textured |= 1;
            //gl.glLoadIdentity();
        } else {
            asteroidVector.elementAt(i).textured &= ~1;
        }

    }

在对象创建和纹理化后,如果他越过屏幕边框,我们需要将其删除,所以我这样做:

        for (int i = 0; i < asteroidVector.size(); i++) {
            asteroidVector.elementAt(i).collisionCheck();
            asteroidVector.elementAt(i).draw(gl);
   //! THIS
            if (asteroidVector.elementAt(i).Y > 480.0f) {
                asteroidVector.remove(i);
            }
   //! THIS
            gl.glLoadIdentity();
        }

但这还不够,因为 tuxture 缓冲区没有清除,并且在应用程序运行 10-20 秒后,我看到一些滞后和低 fps。

问题是 - 我如何清除纹理缓冲区或内存?修复滞后和低帧率?

4

1 回答 1

0

我想你可以这样做,但话说回来,你不应该让自己陷入你真正需要的情况。

就目前而言,您正在为曾经构建的每个对象创建一个新的纹理对象(并且永远不会释放它!)Asteroid,这绝对没有必要 - 解决这个问题的好方法是为所有Asteroid实例使用共享纹理对象.

在静态函数(调用一次)中,只需将图像资源解码为原始像素数据 -> glGenTextures-> glBindTexture->glTexParam...调用 -> GLUtils.TexImage2D-> 释放(客户端)解码的原始像素数据并将纹理 ID(由 给出glGenTextures)存储到类中的静态变量Asteroid。完成此操作后,您可以在渲染阶段(即。 )绑定到这个共享draw纹理对象,然后像往常一样继续。

如前所述,从不调用glDeleteTextures是您问题的第二部分,尽管现在您(希望)为您的Asteroid实例使用共享纹理对象,它变得不那么重要了。

(此外,即使是顶点/texcoord 缓冲区也可以在实例之间共享,只要它们相同:P)

于 2013-08-22T08:45:44.913 回答