35. OpenGL Tiling Engine

Well due to a request, here is a tiling example for you all.

To tile in OpenGL, it is not that easy to merge or combine textures to create a simple 2D tiling game.
It is easier for us to draw a bunch of quads that take up the space of the world in which we want
to tile and assign different textures to those quads according to what is in our map file.

Here is the example of a map file that I am using for this tutorial, which is integrated into the code:

int cMap[10][10] = { //our map
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};

Now if you don’t like storing this in your program, you can just as easily store all of this in a file and loadit in when you need it.

So now that we have our ‘map’, we want to load in our two textures for our two states, 1 or 0, which will beeither grass or dirt in the case of the textures I have created.

I am setting 1 to be dirt, and 0 will be grass.

So as this is building on from the texturing tutorial, we need to create another variable to hold our other texture, as we already setup the first texture in the first tutorial.
GLuint texture2; //the array for our second texture

Now that we have our textures, we need to load them in, do this just like you did in the texturing tutorial:

    //Load our texture
    texture = LoadTexture(“texture.raw”, 256, 256);
    texture2 = LoadTexture(“texture2.raw”, 256, 256);

    glutMainLoop ();

    //Free our texture
    FreeTexture(texture);
    FreeTexture(texture2);

So now that we have our map, and our textures, we need to now draw it all. I am creating a method called drawTiles(). This method will be called in the display function and takes no parameters.

void drawTiles (void) { //our function to draw the tiles
First thing we want to do is start looping through the height of the map, the value of 10 here is specific
to this application. If you have a bigger or smaller map, change this value as you need.
for (int i = 0; i < 10; i++) //loop through the height of the map
{
Then we will want to loop through the width of the map, just as I said above, the value 10 is specific
to this tutorial.
for (int j = 0; j < 10; j++) //loop through the width of the map
{
Now here is where the main part of our tiling takes place, we need to check if the map value at the
current [i][j] position is either a 0 or a 1. If it is a 0, then we bind the grass texture to the quad
that we are about to draw.
if (cMap[i][j] == 0) //if the map at this position contains a 0
{
glBindTexture( GL_TEXTURE_2D, texture ); //bind our grass texture to our shape
}
Else we automatically assign it to dirt. If you have more than two states, you will need to make several if statements,
and if you do not want a default, then you will remove the else and replace it with an if.
else //otherwise
{
glBindTexture( GL_TEXTURE_2D, texture2 ); //bind our dirt texture to our shape
}

The rest of the code draws a quad at the current i, j position we are at.
Drawing a quad should be simple for you at this stage. So I will not explain it.
glPushMatrix(); //push the matrix so that our translations only affect this tile
glTranslatef(j, -i, 0); //translate the tile to where it should belong

glBegin (GL_QUADS); //begin drawing our quads
glTexCoord2d(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0); //with our vertices we have to assign a texcoord

glTexCoord2d(1.0, 0.0);
glVertex3f(1.0, 0.0, 0.0); //so that our texture has some points to draw to

glTexCoord2d(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);

glTexCoord2d(0.0, 1.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glPopMatrix(); //pop the matrix
} //end first loop
} //end second loop
}

And there we have it, you can now create a 2D tiled map for use with a game. Simple wasn’t it? 🙂
If you have any questions, email me at swiftless@gmail.com

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.

   

#include <GL/gl.h>
#include <GL/glut.h>
#include <windows.h>
#include <stdio.h>

GLuint texture; //the array for our texture
GLuint texture2; //the array for our second texture

int cMap[10][10] = { //our map
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};

//function to load the RAW file

GLuint LoadTexture( const char * filename, int width, int height )
{
    GLuint texture;
    unsigned char * data;
    FILE * file;

    //The following code will read in our RAW file
    file = fopen( filename, “rb” );
    if ( file == NULL ) return 0;
    data = (unsigned char *)malloc( width * height * 3 );
    fread( data, width * height * 3, 1, file );
    fclose( file );

    glGenTextures( 1, &texture )
    glBindTexture( GL_TEXTURE_2D, texture );
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, 
GL_MODULATE
 ); //set texture environment parameters

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
GL_LINEAR
 );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR
 );

    //Here we are setting the parameter to repeat the texture 
instead of clamping the texture

    //to the edge of our shape. 
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
GL_REPEAT
 );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
GL_REPEAT
 );

    //Generate the texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, 
GL_RGB,
 GL_UNSIGNED_BYTE, data);
    free( data ); //free the texture
    return texture; //return whether it was successfull
}

void FreeTexture( GLuint texture )
{
  glDeleteTextures( 1, &texture );
}

void drawTiles (void) { //our function to draw the tiles
    for (int i = 0; i < 10; i++) //loop through the height of the map
    {
        for (int j = 0; j < 10; j++) //loop through the width of the map
        {
            if (cMap[i][j] == 0) //if the map at this position contains a 0
            {
                glBindTexture( GL_TEXTURE_2D, texture ); //bind our grass texture to our shape
            }
            else //otherwise
            {
                glBindTexture( GL_TEXTURE_2D, texture2 ); //bind our dirt texture to our shape
            }
            
            glPushMatrix(); //push the matrix so that our translations only affect
 this tile

                glTranslatef(j, i, 0); //translate the tile to where it should belong

                glBegin (GL_QUADS); //begin drawing our quads
                    glTexCoord2d(0.0, 0.0);
                    glVertex3f(0.0, 0.0, 0.0); //with our vertices we have to assign a texcoord

                    glTexCoord2d(1.0, 0.0);
                    glVertex3f(1.0, 0.0, 0.0); //so that our texture has some points to draw to

                    glTexCoord2d(1.0, 1.0);
                    glVertex3f(1.0, 1.0, 0.0);

                    glTexCoord2d(0.0, 1.0);
                    glVertex3f(0.0, 1.0, 0.0);
                glEnd();
            glPopMatrix(); //pop the matrix
        } //end first loop
    } //end second loop
}

void display (void) {
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glEnable( GL_TEXTURE_2D );
    glTranslatef(5, 4, 20); //translate back a bit to view the map correctly

    drawTiles(); //draw our tiles
    glutSwapBuffers();
}
void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glMatrixMode (GL_MODELVIEW);
}

int main (int argc, char **argv) {
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE);
    glutInitWindowSize (500, 500);
    glutInitWindowPosition (100, 100);
    glutCreateWindow (“A basic OpenGL Window);
    glutDisplayFunc (display);
    glutIdleFunc (display);
    glutReshapeFunc (reshape);

    //Load our texture
    texture = LoadTexture(“texture.raw”, 256, 256);
    texture2 = LoadTexture(“texture2.raw”, 256, 256);

    glutMainLoop ();

    //Free our texture
    FreeTexture(texture);
    FreeTexture(texture2);

    return 0;
}

Download Texture(.RAW file)

Download the second Texture (.RAW file)

  • March 25, 2010
  • 15