2010-03-15 16 views
1

Je vais commencer par dire que je suis vraiment nouveau à OpenGL ES (j'ai commencé hier =), mais j'ai une certaine expérience de Java et d'autres langues.Meilleure façon de générer des tuiles

J'ai regardé beaucoup de tutoriels, bien sûr ceux de Nehe et mon travail est principalement basé sur cela. Comme test, j'ai commencé à créer un "générateur de tuiles" afin de créer un petit jeu ressemblant à Zelda (déplacer un mec dans un carré texturé serait génial: p).

Jusqu'à présent, j'ai réalisé un générateur de tuiles de travail, je définis une carte de char [] [] de tableau pour stocker la tuile Wich est:

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} 
    }; 

Il travaille, mais je ne suis pas satisfait, Je suis sûr qu'il ya une Beter façon de faire les choses:

1) Textures Chargement:

Je crée un tableau regardant laid contenant les tuiles que je veux utiliser sur cette carte:

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 
    }; 

(je CUTTED exprès, je charge actuellement 27 tuiles)

Toutes les thèses sont stockés dans le dossier drawable, chacun est une tuile 16 * 16.

J'utilise ensuite ce tableau pour générer les textures et les stocker dans une table de hachage pour une utilisation ultérieure:

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(); 
} 

Je suis tout à fait sûr qu'il ya une meilleure façon de gérer ... Je viens juste étais incapable de le comprendre. Si quelqu'un a une idée, je suis tout ouïe.

2) Dessin des tuiles

Ce que je faisais était de créer un carré et une seule carte de texture:

/** 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 

           }; 

Puis, dans ma fonction de tirage au sort, la boucle I à la carte pour définir la texture à utiliser (après pointant et en permettant aux tampons):

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 
} 

Cela fonctionne très bien par je pense vraiment que sur un 1000 * 10 00 ou plus carte, il sera en retard (comme un rappel, il s'agit d'une carte du monde typique de Zelda: http://vgmaps.com/Atlas/SuperNES/LegendOfZelda-ALinkToThePast-LightWorld.png). J'ai lu des choses à propos de Vertex Buffer Object et DisplayList mais je n'ai pas trouvé un bon tutoriel et nodoby semble être OK sur lequel on est le meilleur/a le meilleur support (T1 et Nexus One sont loin) .

Je pense que c'est ça, j'ai mis beaucoup de code mais je pense que ça aide.

Merci d'avance!

Répondre

1

Quelques choses:

  1. Il n'y a pas besoin d'utiliser un hashmap, il suffit d'utiliser un vecteur/liste.
  2. Il peut être plus rapide/plus facile d'avoir une grande texture qui contient toutes vos tuiles. Utilisez les coordonnées de texture appropriées pour sélectionner la tuile appropriée. Vous devrez peut-être faire attention au filtrage des textures ici. Il semble que vous fassiez un jeu 2D auquel cas vous voudrez probablement utiliser le filtrage du plus proche voisin pour les tuiles et fixer la caméra à des emplacements de pixels entiers.
  3. Ne serait-il pas plus facile d'utiliser GL_QUADS plutôt que GL_TRIANGLE_STRIP. Vous n'êtes pas sûr de votre code, vous ne semblez pas utiliser le tableau 'texture'.
  4. La taille de la carte ne devrait pas faire de différence, tant que vous ne dessinez pas de tuiles qui ne sont pas à l'écran. Votre code devrait être quelque chose comme:

.

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