• Advertisement

2D Tiled SDL 2D Tilemap Glitch

Recommended Posts

I have a simple openGL engine using SDL working. I'm not using any SDL_Image stuff, its all just openGL. I've made 2d tilemap levels with a .txt file before by reading in the characters and using a switch statement to assign them to various textures and using their position in the file to render them. This method works fine and produces no graphical glitches.

Then I made a .tmx map in Tiled and used TmxParser to read the file into my program, and I'm able to render the map properly to the screen, but when I move up and down these black lines start to appear between the tiles.

The map loads in fine at first, its only once I start moving the camera around that it happens, and its only when the camera moves up or down.

I made a video to show exactly what I'm seeing, I see a lot of these type of issues when searching google but nothing that matches whats happening to me.

" rel="external">

I'm not even sure if this is a problem with the code or what it could be so I don't know of any code to include.

This problem also happened to me when I was using Unity and importing a Tiled map with Tiled2Unity. In unity there were long horizontal line glitches on the tilemap, and now its happening to me again in c++, is this something to do with Tiled?

Has anyone encountered this before or know a solution?

Any help would be greatly appreciated, I feel stuck on this issue.

 

Share this post


Link to post
Share on other sites
Advertisement

  // Iterate through the tile layers.

    for (int i = 0; i < map->GetNumTileLayers(); ++i)
    {
        printf("                                    \n");
        printf("====================================\n");
        printf("Layer : %02d/%s \n", i, map->GetTileLayer(i)->GetName().c_str());
        printf("====================================\n");

 

        // Get a layer.
        const Tmx::TileLayer *tileLayer = map->GetTileLayer(i);

        for (int y = 0; y < tileLayer->GetHeight(); ++y)
        {
            for (int x = 0; x < tileLayer->GetWidth(); ++x)
            {
                //Flip y axis to convert from tiled format, tiled starts top left, we start bottom left
                glm::vec4 destRect(x * tileWidth, (tileLayer->GetHeight() * tileHeight) - (y * tileHeight)/* + (y * 1)*/, tileWidth, tileHeight);

                if (tileLayer->GetTileTilesetIndex(x, y) == -1)
                {
                    //printf("........    \n");
                }
                else
                {
                    // Get the tile's id and gid.
                    int tileId = tileLayer->GetTileId(x, y);
                    int tileGid = tileLayer->GetTileGid(x, y);
                    //printf("tileId:%d id:%03d gid:(%03d) firstGid:%03d", tileId, tileLayer->GetTileId(x, y), tileLayer->GetTileGid(x, y), map->FindTileset(tileGid)->GetFirstGid());
                    //int tileGid = tileLayer->GetTileGid(x, y);

                    // Find a tileset for that id.
                    const Tmx::Tileset *tileset = map->FindTileset(tileGid);

                    std::string imagePath = "x";

                    if (tileset->GetImage() != nullptr) {
                        imagePath = tileset->GetImage()->GetSource();
                    }
                    else {
                        SPH::fatalError("Could not find tileset source image.");
                    }

                    SPH::GLTexture texture = SPH::ResourceManager::getTexture(imagePath);

                    //printf("%s\n", tileset->GetImage()->GetSource().c_str());

                    SPH::TileSheet tileSheet;
                    tileSheet.init(texture, glm::ivec4(tileset->GetImage()->GetWidth() / tileWidth,
                        tileset->GetImage()->GetHeight() / tileHeight,
                        tileWidth, tileHeight));

                    m_spriteBatches[0].render(destRect, tileSheet.getUVs(tileId), texture.id, 1.0f, whiteColor);
 

Sprite.h

Sprite.cpp

Level.cpp

SpriteBatch.h

SpriteBatch.cpp

TileSheet.h

I think what you're saying is I'm using floating point numbers in my tileSheet.getUVs, is that correct? If I changed them to ints it would be fine? Or floating point numbers in my destRect?

Edited by Grumn Gaming

Share this post


Link to post
Share on other sites

Yep, that's exactly it. You should "floor" (i.e. round toward negative infinity; note that this is not quite the same as truncation) every position before drawing there. Otherwise some go to the right and some go to the left, and what you end up with is a mess.

Edited by JulieMaru-chan

Share this post


Link to post
Share on other sites

Floor doesn't change anything.

 

glm::vec4 destRect(x * tileWidth, (tileLayer->GetHeight() * tileHeight) - (y * tileHeight), tileWidth, tileHeight);

printf("Dest Rect: x: %f, y: %f, width: %.5f, height: %.5f\n", destRect.x, destRect.y, destRect.z, destRect.w);

x and y are already ints, tileWidth and tileHeight are ints, and tileLayer->GetHeight() returns an int.

There are no floats anywhere in my destRect coords, I did a printf on the destRect to confirm nothing changed when I added floor.

The printf result looks like this:

Dest Rect: x: 736.000000, y: 32.000000, width: 32.000000, height: 32.000000

Where does floating point precision come in here?

Share this post


Link to post
Share on other sites

that may be the case, however, you are using some kind of camera somewhere that has floating points as its position.  what framework are you using?  SDL?  SFML?

ultimately underneath that framework is OpenGL.  And you may be giving the tile positions in "ints" (although it is a float hence the xxx.00000), but the transform done by the camera the location on screen ends up being in floats with actual values past the decimal.

I used SFML before in my life.  Look into using a sf::VertexArray (or whatever it is called) to do a mass tilemap drawing.  It is more efficient and will clean up those problems.  If you are using SDL then someone else may be able to help you.

 

Share this post


Link to post
Share on other sites

Yes I’m using sdl but not for the rendering code, that is all OpenGL, but this gives me a place to start messing around with it, thank you. Maybe I need to make the tranform that holds my camera position from a glm::vec4 to a glm::ivec4 Or floor() the x and y positions in the camera class

Edited by Grumn

Share this post


Link to post
Share on other sites

Thank you djsteffey and juliemaru! The problem was 100% floating point precision and it was fixed by adding floor to the camera update code!

 

glm::vec3 translate(std::floor(-_position.x + _screenWidth/2), std::floor(-_position.y + _screenHeight/2), 0.0f);
_cameraMatrix = glm::translate(_orthoMatrix, translate);

 

Works perfectly now, I can't believe it, thank you so much!

 

Here is the end result:

Ive never thought something so bad looked so good,

 

Edited by Grumn Gaming

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By sergio2k18
      Hi all
      this is my first post on this forum.
      First of all i want to say you that i've searched many posts on this forum about this specific argument, without success, so i write another one....
      Im a beginner.
      I want use GPU geometry clipmaps algorithm to visualize virtual inifinte terrains. 
      I already tried to use vertex texture fetch with a single sampler2D with success.
       
      Readed many papers about the argument and all speak about the fact that EVERY level of a geometry clipmap, has its own texture. What means this exactly? i have to 
      upload on graphic card a sampler2DArray?
      With a single sampler2D is conceptually simple. Creating a vbo and ibo on cpu (the vbo contains only the positions on X-Z plane, not the heights)
      and upload on GPU the texture containing the elevations. In vertex shader i sample, for every vertex, the relative height to te uv coordinate.
      But i can't imagine how can i reproduce various 2d footprint for every level of the clipmap. The only way i can imagine is follow:
      Upload the finer texture on GPU (entire heightmap). Create on CPU, and for each level of clipmap, the 2D footprints of entire clipmap.
      So in CPU i create all clipmap levels in terms of X-Z plane. In vertex shader sampling these values is simple using vertex texture fetch.
      So, how can i to sample a sampler2DArray in vertex shader, instead of upload a sampler2D of entire clipmap?
       
       
      Sorry for my VERY bad english, i hope i have been clear.
       
    • By mangine
      Hello. I am developing a civ 6 clone set in space and I have a few issues. I am using Lua for the logic and UI of the game and c++ directx 12 for the graphics. I need a way to send information between Lua and c++ occasionally and was wondering what is the best and most flexible (and hopefully fast) way to do this. Don't forget that I also need to send things from c++ back to Lua. I know of a lua extension called "LuaBridge" on github but it is a little old and I am worried that it will not work with directx 12. Has anybody done something similar and knows a good method of sending data back and forth? I am aware that Lua is used more and more in the industry and surely plenty of AAA game programmers know the answer to this. I want a good solution that will hopefully still be viable code in a couple of years...
    • By owenjr
      Hi there.
      I'm pretty new to this and I don't know if it has been asked before, but here I go.
      I'm developing a game using SFML and C++.
      I would like to use the "Tiled" tool to load maps into my game but I don't actually find any tutorial or guide on how to exaclty use it (I know that I have to read an XML file and stuff). I just step into diverse projects that make all a mess. 
      Anyone knows where can I find good information to make my map loader by myself?
      Thanks in advantage!!
  • Advertisement