1

最近我在使用 2D 游戏工作SurfaceView,我学到了很多关于游戏循环和一切的知识。但现在我想使用 OpenGL 制作同样的游戏。我读到那GLSurfaceView是与过去相关的类SurfaceView。但我不确定其他事情:

使用SurfaceView,我使用 Bitmap 类来加载一个图像资源,可以说是一个字符。该位图将是我Character班级的财产。对于游戏循环,我使用了不同的Thread

我是新手,OpenGL所以我想知道如何加载图像资源(我是否使用Bitmap类加载它们?),或者使用什么来代替Thread游戏循环?

4

2 回答 2

1

使用 Bitmap 类加载它们?

是的,您可以加载位图并将其用作textImage2D.

例子:

public void loadTextures(GL10 gl, Context context) {
    Log.e(LOG_TAG, "ExplosionSprite :: loadTextures");  

    mFrame = 0;

    InputStream is;
    Bitmap bitmap;
    is = context.getResources().openRawResource(DRAW_SOURCE);


    bitmap = BitmapFactory.decodeStream(is);
    try {
        is.close();
        is = null;
    } catch (IOException e) {
    }

    gl.glGenTextures(TEXTURE_COUNT, textures, 0);

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    bitmap.recycle(); 
}

在 4 个月之前,我做了同样的事情,因为性能切换到了 OpenGL ES 2D。

它有点复杂,但一段时间后似乎很容易。

我现在没有单个图像的示例,但是对于我为图像设置动画的精灵表有很好的示例。我相信您可以删除不相关的数据以使其成为一张静态图像。谷歌有足够的资源“如何”所以我会指出我用于我的目的:

链接 1

链接 2

链接 3

Cast_001_Sprite_.java

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import net.obviam.droidz.R;
import net.obviam.droidz.model.components.ESpriteDirection;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.util.Log;

public class Cast_001_Sprite_ {

    private static final String LOG_TAG = Cast_001_Sprite.class.getSimpleName();

    /** Sprite sheet definition */
    private static final int SPRITE_WIDTH = 5;
    private static final int SPRITE_HEIGHT = 4;
    private int DRAW_SOURCE = R.drawable.a1;

    private int mX = Location._1[0]; // 100;
    private int mY = Location._1[1]; // 100;


    private float mScreenWidth, mScreenHeight, wRatio, hRatio;
    private int mFrame = 0;
    private int mSwitcher = 0;
    private final static int TEXTURE_COUNT = 1; // for sprite sheet we use 1 image all the time.
    private int[] textures = new int[TEXTURE_COUNT]; // frame animation

    protected FloatBuffer vertexBuffer;

    private final static ESpriteDirection mDirection = ESpriteDirection.TOP_TO_DOWN_LEFT_TO_RIGHT;


    public float x, y, initPos, finalPos, initSpeed, currentPos;

    private ByteBuffer bb1;

    private final static int TOTAL_IMAGE_COUNT_IN_SPRITE = SPRITE_WIDTH * SPRITE_HEIGHT;

    private FloatBuffer[] floatBufferArray = new FloatBuffer[TOTAL_IMAGE_COUNT_IN_SPRITE];

    private float xOffset = 1.0f/SPRITE_WIDTH;
    private float yOffset = 1.0f/SPRITE_HEIGHT;


    float[] vertices = new float[] {
            -1.0f, -1.0f, 0.0f,
            -1.0f, 1.0f, 0.0f,
           1.0f,  -1.0f, 0.0f,
            1.0f, 1.0f, 0.0f };


    private float storage[][] = new float[TOTAL_IMAGE_COUNT_IN_SPRITE][];
    private int[] sprite_X_Indexes = new int[SPRITE_WIDTH];//{1,2,3,4}; 
    private int[] sprite_Y_Indexes = new int[SPRITE_HEIGHT];//{1,2,3,4};





    public Cast_001_Sprite_(float screenWidth, float screenHeight){

        generateSpriteIndexes();

        updateScreenData(screenWidth, screenHeight);

        int index = 0;

        switch (mDirection) {
        case TOP_TO_DOWN_LEFT_TO_RIGHT:

            for(int row = 0; row<SPRITE_HEIGHT; row++){
                for(int column = 0; column<SPRITE_WIDTH; column++){
                    storage[index] = generateTextures(column, row);
                    index++;
                }
            }
            break;
        case DOWN_TO_TOP_LEFT_TO_RIGHT:
            //TODO
            //          for(int row = spriteLength; row>0; row--){
            //              for(int column = 0; column<spriteHeight; column++){
            //                  storage[index] = generateTextures( row-1, column);
            //                  index++;
            //              }
            //          }
            break;

        default:
            break;
        }       


        // vertices buffer
        bb1 = ByteBuffer.allocateDirect(vertices.length * 4);
        bb1.order(ByteOrder.nativeOrder());
        vertexBuffer = bb1.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);

        for(int i=0; i<TOTAL_IMAGE_COUNT_IN_SPRITE; i++){
            bb1 = ByteBuffer.allocateDirect(storage[i].length * 4);
            bb1.order(ByteOrder.nativeOrder());
            FloatBuffer textureBuffer = bb1.asFloatBuffer();
            textureBuffer.put(storage[i]);
            textureBuffer.position(0);

            floatBufferArray[i] = textureBuffer;
        }
    }

    private void generateSpriteIndexes() {      

        for(int indexX = 0; indexX<SPRITE_WIDTH; indexX++){
            sprite_X_Indexes[indexX] = indexX+1;
        }

        for(int indexY = 0; indexY<SPRITE_HEIGHT; indexY++){
            sprite_Y_Indexes[indexY] = indexY+1;
        }
    }

    public void updateScreenData(float screenWidth, float screenHeight){
        // takes screen Height and Width
        this.mScreenWidth = (screenWidth > 0) ? screenWidth : 1f;
        this.mScreenHeight = screenHeight;
        wRatio = 10f/mScreenWidth;
        hRatio = mScreenHeight/10f;
        addExplosion(mX,mY);
    }


    public void addExplosion(float x, float y) {        
        this.x = x;
        this.y = y;
        this.initPos = y;
    }


    /**
     * Generates texture by location
     * 
     * @param texture - fill current texture
     * @param placeX - image place in sprite scale X
     * @param placeY - image place in sprite scale Y
     * @return 
     */
    private float[] generateTextures(int placeX, int placeY) {

        float texture[] = new float[8];

        /*
        V1 _____ V3 
          |     |
          |     |
        V2|_____|V4 
         */
        //StringBuffer buff = new StringBuffer();

        /** V1 */   
        texture[0] = (placeX == 0)?0.0f : xOffset*sprite_X_Indexes[placeX-1];  
        texture[1] = yOffset*sprite_Y_Indexes[placeY];

        /** V2 */
        texture[2] = (placeX == 0)?0.0f : xOffset*sprite_X_Indexes[placeX-1];
        texture[3] = (placeY == 0)?0.0f : yOffset*sprite_Y_Indexes[placeY-1];

        /** V3 */
        texture[4] = xOffset*sprite_X_Indexes[placeX];
        texture[5] = yOffset*sprite_Y_Indexes[placeY];

        /** V4 */
        texture[6] = xOffset*sprite_X_Indexes[placeX];
        texture[7] = (placeY == 0)?0.0f : yOffset*sprite_Y_Indexes[placeY-1];


        return texture;

    }


    private void update() {
        if(mSwitcher == 1){
            mFrame = ++mFrame % TOTAL_IMAGE_COUNT_IN_SPRITE;
            mSwitcher = 0;
            // Log.e(LOG_TAG, "DevQuestSpriteBase :: " + mFrame);   
        }
        else{
            mSwitcher++; 
        }   
    }

    public void reset(){
        mFrame = 0;
    }


    public void loadTextures(GL10 gl, Context context) {
        Log.e(LOG_TAG, "ExplosionSprite :: loadTextures");  

        mFrame = 0;

        InputStream is;
        Bitmap bitmap;
        is = context.getResources().openRawResource(DRAW_SOURCE);


        bitmap = BitmapFactory.decodeStream(is);
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }

        gl.glGenTextures(TEXTURE_COUNT, textures, 0);

        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

        bitmap.recycle(); 

    }

    public void draw(GL10 gl){
//      if(mFrame == TOTAL_IMAGE_COUNT_IN_SPRITE - 1){
//          return;
//      }

        gl.glPushMatrix();
        try {
            float transx =  + (wRatio * x);
            float transy =  + (mScreenHeight*wRatio) - (wRatio * y) - 1/hRatio;

            // Log.e(LOG_TAG, "transx: " + transx + "; transy: " + transy + "; sprite.x: "+  sprite.x + "; sprite.y: " + sprite.y);  

            gl.glTranslatef(transx, transy, 0.0f);

            //###########  draw ##############

            gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, floatBufferArray[mFrame]);

            update();

            gl.glColor4f(1f, 1f, 1f, 0.2f);

            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

            //###############################

        } catch (NullPointerException e) {
        }
        gl.glPopMatrix();           
    }
} 

DevQuest1Activity.java

public class DevQuest1Activity extends Activity {
private DevQuestGLSurfaceView mGLView;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    mGLView = new DevQuestGLSurfaceView(this);
    setContentView(mGLView);
}

@Override
protected void onPause() {
    super.onPause();
    mGLView.onPause();
}

@Override
protected void onResume() {
    super.onResume();
    mGLView.onResume();
}
}

DevQuestGLRenderer.java

public class DevQuestGLRenderer implements GLSurfaceView.Renderer {

private static final String LOG_TAG = "Fess";//DevQuestGLRenderer.class.getSimpleName();

private Context context;
private float ratio;
private int screenWidth, screenHeight;


public Cast_001_Sprite Cast_001_Sprite;


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

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig confid) {
    gl.glEnable(GL10.GL_TEXTURE_2D);
    gl.glShadeModel(GL10.GL_SMOOTH);
    gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    gl.glClearDepthf(1.0f);
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
    gl.glEnable(GL10.GL_BLEND);
    gl.glDisable(GL10.GL_DEPTH_TEST);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, /*GL10.GL_REPLACE*/ GL10.GL_MODULATE);  


}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {

    Log.e(LOG_TAG, "onSurfaceChanged"); 

    // prevent 0 divise
    if(height == 0) { height=1;}
    screenWidth = width; screenHeight = height;
    ratio = (float) width/height;
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glOrthof(0, width, 0, height, -10f, 10f);
    gl.glViewport(0, 0, screenWidth, screenHeight);

    Cast_001_Sprite = new Cast_001_Sprite(width, height);

    Cast_001_Sprite.loadTextures(gl, context);      
}

@Override
public void onDrawFrame(GL10 gl) {

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();

    gl.glPushMatrix();
    gl.glScalef((screenWidth)/10, (screenHeight*ratio)/10, 1.0f);

    Cast_001_Sprite.draw(gl);

    gl.glPopMatrix();
}   
}

DevQuestGLSurfaceView.java

 public class DevQuestGLSurfaceView extends GLSurfaceView {
 private DevQuestGLRenderer mRenderer;

  private int count = 0;

  public DevQuestGLSurfaceView(Context context) {
    super(context);
    mRenderer = new DevQuestGLRenderer(context);
    setRenderer(mRenderer);
  }

 @Override
  public boolean onTouchEvent(MotionEvent event) {

   return true;
  }
}

ESpriteDirection.java

public enum ESpriteDirection {
 TOP_TO_DOWN_LEFT_TO_RIGHT,
 DOWN_TO_TOP_LEFT_TO_RIGHT,
 TOP_TO_DOWN_RIGHT_TO_LEFT,
 DOWN_TO_TOP_RIGHT_TO_LEFT
}

这是我使用的图像:

在此处输入图像描述

于 2013-09-13T17:38:18.880 回答
0

使用此代码加载您的图像..

public static int loadTexture(Context context, int resourceId) {
        final int[] textureObjectIds = new int[1];
        glGenTextures(1, textureObjectIds, 0);

        if (textureObjectIds[0] == 0) {
            if (LoggerConfig.ON) {
                Log.w(TAG, "Could not generate a new OpenGL texture object.");
            }
            return 0;
        } 

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;

        // Read in the resource
        final Bitmap bitmap = BitmapFactory.decodeResource(
            context.getResources(), resourceId, options);

        if (bitmap == null) {
            if (LoggerConfig.ON) {
                Log.w(TAG, "Resource ID " + resourceId + " could not be decoded.");
            }

            glDeleteTextures(1, textureObjectIds, 0);
            return 0;
        } 
        // Bind to the texture in OpenGL
        glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);

        // Set filtering: a default must be set, or the texture will be
        // black.
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        // Load the bitmap into the bound texture.
        texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);

        // Note: Following code may cause an error to be reported in the
        // ADB log as follows: E/IMGSRV(20095): :0: HardwareMipGen:
        // Failed to generate texture mipmap levels (error=3)
        // No OpenGL error will be encountered (glGetError() will return
        // 0). If this happens, just squash the source image to be
        // square. It will look the same because of texture coordinates,
        // and mipmap generation will work.

        glGenerateMipmap(GL_TEXTURE_2D);

        // Recycle the bitmap, since its data has been loaded into
        // OpenGL.
        bitmap.recycle();

        // Unbind from the texture.
        glBindTexture(GL_TEXTURE_2D, 0);

        return textureObjectIds[0];
    }
于 2014-03-27T09:02:06.883 回答