1
\$\begingroup\$

I'm trying to use SDL2 and Modern OpenGL to make a 2D rpg. The problem is, I have no idea how to render a tile map. I'm using the Tiled map editor to create maps. I have a vague idea of how to parse the maps using this (https://github.com/andrewrk/tmxparser) tmx parser. I try to parse the maps using said parser, but then I run into the problem of how to actually get the tile maps to appear on screen, when using a spritebatch class. How would I go about rendering these maps using modern OpenGL?

\$\endgroup\$
3
  • \$\begingroup\$ Welcome to the site. This question is both broad and open-ended; there are lots of things to learn and there's no real ending to the process. Because of that, this type of question is considered to be outside this site's scope. However, if you want to learn details of some specific aspect of rendering tiles, there is a strong chance you will find helpful details by searching here. But that will only work after you let google find you an initial tutorial elsewhere. Good luck. \$\endgroup\$ Jul 9, 2015 at 13:45
  • \$\begingroup\$ Do you actually want to use raw opengl or do you want to use SDL2's drawing system? You could use SDL as just a window and input manager and do all the drawing yourself or you can use SDL's surfacing system and let it handle drawing shapes on the screen. What is it that you want to use? OpenGL has no concept of sprite batches. \$\endgroup\$
    – Honeybunch
    Jul 9, 2015 at 20:10
  • \$\begingroup\$ I want to use raw openGL. I built a spritebatch using it, and it works for individual sprites, but things start to get hazy when I try using it with any sort of tile map. I can't think of anyway so get OpenGL to draw any sort tile map at all, with or without the SpriteBatch. \$\endgroup\$ Jul 10, 2015 at 14:46

2 Answers 2

2
\$\begingroup\$

You'd draw a tile map in OpenGL the same way you'd draw a sprite that has multiple frames in a single texture; by adjusting the texture coordinates such that you only drew a portion of the texture onto the quad that represents the tile.

A rough way to do it would be to create a mesh of quads/triangles that represents your tile map; each tile's world coordinates would be equal to the tile's X,Y index in the grid * the size of the tile (make sure to use orthographic projection!);

Then, each tile's UV coordinates into the master tiles texture would be something like;

(1 / tiles across) * textureXindex

So if your texture had four tiles across (same thing in an ortho projection) and you wanted tile #2;

textureWidth = 1 / 4;

textureWidth * 2 = 0.5 (left texture U coordinate)

the above value (0.5) + textureWidth (right texture U coordinate)

Same for the Y/V coordinate. You could also calculate the tile width by dividing the total width of the tile texture in pixels by the width of a tile in pixels, which will give you the same decimal value as the 1/4 calculation above.

In order to convert a single-number tile index into an X, Y value within the tile map, divide it by the number of columns to get the Y, then mod (%) it by the number of columns to get the X.

So if your tile map is 4x4, and your index is 13;

13 / 4 = 3
13 % 4 = 1

So your tile coordinates are 1, 3.

\$\endgroup\$
2
  • \$\begingroup\$ Ahh, okay, I see what you are saying! The one question I have about this is, how would I index the tile sheet to get a specific tile? \$\endgroup\$ Jul 11, 2015 at 3:42
  • \$\begingroup\$ You can convert an index into an X,Y lookup by dividing it by the number of columns to get the Y, then mod (%) it by the number of columns to get the X. \$\endgroup\$
    – Sandalfoot
    Jul 13, 2015 at 18:31
2
\$\begingroup\$

tilesheet

Here is an example with a very simple tile/sprite sheet. Each tile is 32x32 and the red line marks the left and the upper corner of each tile.

You always want to use sheets like this when rendering tiles. Switching textures is much more expensive than drawing a bunch of vertices.

You can either index it either by using a 2D vector or just a number. To index it via a vector you would get the minimum position (assuming the origin is in the top left of the image) and maximum position as such (this is some kind of pseudocode):

sheetPrediv = (1 / sheetWidth, 1 / sheetHeight);
minPos = (x * spriteWidth, y * spriteHeight) * sheetPrediv;
maxPos = (x * spriteWidth + spriteWidth, y * spriteHeight + spriteHeight) * sheetPrediv;

sheetPrediv could be contained in some class that also contains your OpenGL texture handle, since it only needs to be calculated when the texture is loaded and can then be stored.

Another way to index the sheet is by a number. Imagine that each cell has a number; the top-left cell is 0, the top-middle cell is 1 and so on, when it gets to the last cell on the current line it keeps going on the next line.

Numbered sheet

Now you can get the minimum and maximum position of the tile (once again, assuming the origin is in the top-left) in a different way:

sheetPrediv = (1 / sheetWidth, 1 / sheetHeight);
minPos = ((index % sheetColumns) * spriteWidth, floor(index / sheetColumns) * spriteHeight) * sheetPrediv;
maxPos = minPos + (spriteWidth, spriteHeight) * sheetPrediv;

There are tons of other ways to get the index, doing it the way I've don it here are just two examples. If your origin is somewhere else (like in the bottom-left) you'll have to modify these formulas a bit. I'll leave that as an exercise.

So, now you have the texels for drawing. So bind the texture and send the texels to your shader. Alternatively you send the index to your shader and to do all the calculations there.

Remember to mark an answer for your question

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .