1

我首先要说我对 OpenGL ES 真的很陌生(我昨天开始 =),但我确实有一些 Java 和其他语言的经验。

我看了很多教程,当然是 N​​ehe 的,我的工作主要是基于它。

作为测试,我开始创建一个“瓷砖生成器”,以创建一个类似塞尔达的小型游戏(只是在带纹理的正方形中移动一个花花公子会很糟糕:p)。

到目前为止,我已经实现了一个可以工作的图块生成器,我定义了一个 char map[][] 数组来存储图块所在的位置:

private char[][] map = {
            {0, 0, 20, 11, 11, 11, 11, 4, 0, 0},
            {0, 20, 16, 12, 12, 12, 12, 7, 4, 0},
            {20, 16, 17, 13, 13, 13, 13, 9, 7, 4},
            {21, 24, 18, 14, 14, 14, 14, 8, 5, 1},
            {21, 22, 25, 15, 15, 15, 15, 6, 2, 1},
            {21, 22, 23, 0, 0, 0, 0, 3, 2, 1},
            {21, 22, 23, 0, 0, 0, 0, 3, 2, 1},
            {26, 0, 0, 0, 0, 0, 0, 3, 2, 1},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
    };

它正在工作,但我对此并不满意,我确信有更好的方法来做这些事情:

1)加载纹理:

我创建了一个丑陋的数组,其中包含我想在该地图上使用的图块:

private int[] textures = {
            R.drawable.herbe, //0
            R.drawable.murdroite_haut, //1
            R.drawable.murdroite_milieu, //2
            R.drawable.murdroite_bas, //3
            R.drawable.angledroitehaut_haut, //4
            R.drawable.angledroitehaut_milieu,  //5
    };

(我故意剪了这个,我目前加载了 27 个图块)

所有这些都存储在drawable文件夹中,每一个都是一个16*16的瓦片。

然后我使用这个数组生成纹理并将它们存储在 HashMap 中以供以后使用:

int[] tmp_tex = new int[textures.length]; 
gl.glGenTextures(textures.length, tmp_tex, 0); 
texturesgen = tmp_tex; //Store the generated names in texturesgen 
for(int i=0; i < textures.length; i++)
{ 
    //Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), textures[i]);
    InputStream is = context.getResources().openRawResource(textures[i]);
    Bitmap bitmap = null;
    try {
        //BitmapFactory is an Android graphics utility for images
        bitmap = BitmapFactory.decodeStream(is);

    } finally {
        //Always clear and close
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    } 
    // Get a new texture name 
    // Load it up 
    this.textureMap.put(new Integer(textures[i]),new Integer(i)); 
    int tex = tmp_tex[i]; 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, tex); 
    //Create Nearest Filtered Texture
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

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

    bitmap.recycle();
} 

我很确定有更好的方法来处理这个问题……我只是想不通。如果有人有想法,我会全力以赴。

2)绘制瓷砖

我所做的是创建一个正方形和一个纹理贴图:

/** The initial vertex definition */
    private float vertices[] = { 
                                -1.0f, -1.0f, 0.0f,     //Bottom Left
                                1.0f, -1.0f, 0.0f,      //Bottom Right
                                -1.0f, 1.0f, 0.0f,      //Top Left
                                1.0f, 1.0f, 0.0f        //Top Right
                                                };

    private float texture[] = {         
            //Mapping coordinates for the vertices
              0.0f, 1.0f,
              1.0f, 1.0f,
              0.0f, 0.0f,
              1.0f, 0.0f

                                };

然后,在我的绘图函数中,我循环遍历地图以定义要使用的纹理(在指向并启用缓冲区之后):

for(int y = 0; y < Y; y++){
    for(int x = 0; x < X; x++){
        tile = map[y][x];
        try 
            { 
                //Get the texture from the HashMap
                int textureid = ((Integer) this.textureMap.get(new Integer(textures[tile]))).intValue(); 
                gl.glBindTexture(GL10.GL_TEXTURE_2D, this.texturesgen[textureid]); 
            }    
            catch(Exception e) 
            { 
                return; 
            }

        //Draw the vertices as triangle strip
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);            
        gl.glTranslatef(2.0f, 0.0f, 0.0f); //A square takes 2x so I move +2x before drawing the next tile
    }
    gl.glTranslatef(-(float)(2*X), -2.0f, 0.0f); //Go back to the begining of the map X-wise and move 2y down before drawing the next line
}

这很好用,我真的认为在 1000*1000 或更大的地图上,它会像地狱一样滞后(提醒一下,这是一张典型的塞尔达世界地图:http: //vgmaps.com/Atlas/SuperNES/LegendOfZelda- ALinkToThePast-LightWorld.png)。

我已经阅读了有关 Vertex Buffer Object 和 DisplayList 的内容,但我找不到一个好的教程,而且 nodoby 似乎还可以,其中一个是最好的/有更好的支持(T1 和 Nexus One 已经很久了)。

我想就是这样,我已经放了很多代码,但我认为它有帮助。

提前致谢 !

4

1 回答 1

1

有几件事:

  1. 不需要使用哈希图,只需使用向量/列表。
  2. 拥有一个包含所有图块的大纹理可能会更快/更容易。使用适当的纹理坐标来选择适当的图块。您可能需要对此处的纹理过滤稍加小心。听起来您正在做一个 2D 游戏,在这种情况下,您可能希望对图块使用最近邻过滤并将相机钳制在整数像素位置。
  3. 使用 GL_QUADS 而不是 GL_TRIANGLE_STRIP 不是更容易吗?不确定您的代码 - 您似乎没有使用“纹理”数组。
  4. 只要您不绘制不在屏幕上的图块,地图大小就不会产生任何影响。你的代码应该是这样的:

.

int minX = screenLeft / tileSize;
int minY = screenBottom / tileSize;
int maxX = screenRight / tileSize;
int maxY = screenTop / tilesSize;
for (int x = minX; x <= maxX; ++x)
{
   for (int y = minY; y < maxY; ++y)
   {
      ...
于 2010-03-15T12:02:01.327 回答