Лучший способ генерировать плитки

1

Начну с того, что я ДЕЙСТВИТЕЛЬНО новичок в OpenGL ES (я начал вчера =), но у меня есть опыт Java и других языков.

Я просмотрел много учебников, конечно, Nehe, и моя работа в основном основана на этом.

В качестве теста я начал создавать "генератор плитки", чтобы создать небольшую игру, похожую на Zelda (просто перемещение чувака в текстурированном квадрате было бы awsome: 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 фрагментов)

Все тезисы хранятся в папке с возможностью рисования, каждая из которых представляет собой плиту 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

                                };

Затем в моей функции draw я просматриваю карту, чтобы определить используемую текстуру (после указания и включения буферов):

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 и DisplayList, но я не смог найти хороший учебник, и nodoby, похоже, в порядке, так как один из них лучший/имеет лучшую поддержку (T1 и Nexus One отныне).

Я думаю, что это, я поместил много кода, но я думаю, что это помогает.

Спасибо заранее!

Теги:
opengl-es
textures
tiles

1 ответ

1

Несколько вещей:

  • Нет необходимости использовать хэш-карту, просто используйте вектор/список.
  • Быстрее/проще иметь одну большую текстуру, содержащую все ваши плитки. Используйте соответствующие координаты текстуры, чтобы выбрать подходящую плитку. Возможно, вам придется немного позаботиться о фильтрации текстур здесь. Похоже, вы делаете 2D-игру, и в этом случае вы, вероятно, захотите использовать фильтрацию ближайшего соседа для фрагментов и закрепить камеру в целых пиксельных местоположениях.
  • Не было бы проще использовать GL_QUADS, а не GL_TRIANGLE_STRIP. Не уверен в вашем коде - вы, кажется, не используете массив текстуры.
  • Размер карты не должен иметь никакого значения, если вы не рисуете фрагменты, которые не отображаются на экране. Ваш код должен выглядеть примерно так:

.

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)
   {
      ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню