Question About Scrolling A Tilemap In C++/SDL/OpenGL

oscar.rpr
  • Question About Scrolling A Tilemap In C++/SDL/OpenGL oscar.rpr

    I been working with scrolling this week but I recently encounter a problem that I don't understand why it's happening.

    In a 2D scroller I want to scroll a tilemap pixel per pixel which gives a smooth scrolling in the game, but I encounter a weird problem, when the movement of the map corresponds with the exact size of the tile, for example, the map it's scrolling 32 pixels to the right, the map seems to jump to the next tile and not the one that corresponds correctly with the screen.

    This is the code for drawing the map:

    bool Tilemap::drawTilemap(GLfloat sizeTile, int indexTileset)
    {
        offsetX++;
        if (offsetX >= 320.f) offsetX = 320.f;
    
        GLfloat widthTilesetImage = tilesetList.at(indexTileset).getWidthImage();
        GLfloat heightTilesetImage = tilesetList.at(indexTileset).getHeightImage();
    
        int widthMap = 40 + offsetX/32;
        int heigthMap = 23;
    
    
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        glEnableClientState( GL_VERTEX_ARRAY );
        glEnableClientState( GL_TEXTURE_COORD_ARRAY );  
    
        glBindTexture( GL_TEXTURE_2D, tilesetList.at(indexTileset).getTexture() );
    
    
        for (int i = 0; i < heigthMap; i++)
        {
            int startX = offsetX/32;
    
            for (int j = 0; j < 40; j++) 
            {
                int frameIndex = layerMap[i][startX];
    
                if (frameIndex == 0)
                { 
                    continue; 
                }
    
                frameIndex -= 1;
    
                const GLfloat tileX = 0.0f + ( (sizeTile)*j);
                const GLfloat tileY = 0.0f + (sizeTile*i);
    
                const GLfloat verts[] = {
                        tileX, tileY,
                        tileX + sizeTile, tileY,
                        tileX + sizeTile, tileY + sizeTile,
                        tileX, tileY + sizeTile
                };
    
    
                const GLfloat textureWidth = (sizeTile - offsetX/widthTilesetImage) / (GLfloat)widthTilesetImage;
                const GLfloat textureHeight = sizeTile / (GLfloat)heightTilesetImage;
                const int numFramePerRow = (GLfloat)widthTilesetImage / sizeTile;
                const GLfloat textureX = ((frameIndex % numFramePerRow) * textureWidth)+offsetX/widthTilesetImage;
                const GLfloat textureY = (frameIndex / numFramePerRow ) * textureHeight;
    
                const GLfloat texVerts[] = {
                        textureX, textureY,
                        textureX + textureWidth, textureY,
                        textureX + textureWidth, textureY + textureHeight,
                        textureX, textureY + textureHeight
                };
    
                glVertexPointer(2, GL_FLOAT, 0, verts);
                glTexCoordPointer(2, GL_FLOAT, 0, texVerts);
                glDrawArrays(GL_QUADS, 0, 4);
    
                startX++;
    
            }   
        }
    
        glDisableClientState( GL_VERTEX_ARRAY );            
        glDisableClientState( GL_TEXTURE_COORD_ARRAY );
    
        return true;
    }
    

    The variable offsetX it's the one that helps me move one tile at a time the map. The variable startX indicates when it's no longer drawing one tile, so in this one start in the next column of the matrix of tiles.

    So, what could be wrong in my code?

    Thanks for the help.

  • Sorry for the late answer. I already find out the problem, I leave the new code so maybe someone will find this useful. The problem was handling the different offset in each row of the tilemap, but now it's solved.

    void Tilemap::drawTilemap(int indexTileset)
    {
        GLfloat offsetXTemp = offset.x;
    
        offsetXTemp = transformOffsetXToIntervalValues(offset.x);
    
        GLfloat variableSizeTile = 32.f;
    
        GLfloat widthTilesetImage = tilesetList.at(indexTileset).getWidthImage();
        GLfloat heightTilesetImage = tilesetList.at(indexTileset).getHeightImage();
    
        int widthMap = (1280 / (int)sizeTiles) + 1;
        int heigthMap = (int) ceil( 720.0f / sizeTiles );
    
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        glEnableClientState( GL_VERTEX_ARRAY );
        glEnableClientState( GL_TEXTURE_COORD_ARRAY );  
    
        glBindTexture( GL_TEXTURE_2D, tilesetList.at(indexTileset).getTexture() );
    
        GLfloat posXPrevious = 0.0f, posXPreviousOnTexture = 0.0f;
    
        for (int i = 0; i < heigthMap; i++)
        {
            int startX = (int)floor(offset.x/sizeTiles);
            posXPrevious = 0.0f;
    
            posXPrevious -= offsetXTemp;
            variableSizeTile = 32.f;
    
            for (int j = 0; j < widthMap; j++) 
            {
                if ( startX == widthLevelInTiles )
                {
                    break;
                }
    
                int frameIndex = layerMap[i][startX].getID();
    
                if ( frameIndex == 0 )
                { 
                    startX++;
                    variableSizeTile = 32.f;
                    posXPrevious = posXPrevious + variableSizeTile;
    
                    continue; 
                }
    
                if ( j == 0 && offsetXTemp != sizeTiles)
                {
                    posXPreviousOnTexture = offsetXTemp/widthTilesetImage;
                    variableSizeTile -= offsetXTemp;
                    posXPrevious = 0.0f;
                }
    
                else 
                { 
                    variableSizeTile = 32.f; 
                    posXPreviousOnTexture = 0.0f;
                }
    
                if ( j == 40 )
                {
                    variableSizeTile = offsetXTemp;
                }
    
                frameIndex -= 1;
    
                const GLfloat tileX = posXPrevious;
                const GLfloat tileY = sizeTiles * i;
                posXPrevious = tileX + variableSizeTile;
    
                const GLfloat verts[] = {
                        tileX, tileY,
                        tileX + variableSizeTile, tileY,
                        tileX + variableSizeTile, tileY + sizeTiles,
                        tileX, tileY + sizeTiles
                };
    
                const GLfloat textureWidth = variableSizeTile / (GLfloat)widthTilesetImage;
                const GLfloat textureHeight = sizeTiles / (GLfloat)heightTilesetImage;
                const int numFramePerRow = (int)widthTilesetImage / (int)sizeTiles;
                const GLfloat textureX = ( (frameIndex % numFramePerRow) * sizeTiles/(GLfloat)widthTilesetImage ) 
                                        + posXPreviousOnTexture;
                const GLfloat textureY = ( frameIndex / numFramePerRow ) * textureHeight;
    
                const GLfloat texVerts[] = {
                        textureX, textureY,
                        textureX + textureWidth, textureY,
                        textureX + textureWidth, textureY + textureHeight,
                        textureX, textureY + textureHeight
                };
    
                glVertexPointer(2, GL_FLOAT, 0, verts);
                glTexCoordPointer(2, GL_FLOAT, 0, texVerts);
                glDrawArrays(GL_QUADS, 0, 4);
    
                startX++;
            }   
        }
    
        glDisableClientState( GL_VERTEX_ARRAY );            
        glDisableClientState( GL_TEXTURE_COORD_ARRAY );
    }
    

Tags
c++ opengl sdl side-scroller tilemap
Related questions and answers
  • ); glEnableClientState(GL_VERTEX_ARRAY); // Point them to the objects arrays if (Objects[i].textured) glTexCoordPointer(2, GL_FLOAT, 0, Objects[i].TexCoords...); // Set The Color Of The Model ( NEW ) // ORIGINAL DRAWING CODE //Draw the model as an interpolation between the two frames glBegin(GL_TRIANGLES); for(int i = 0; i..., 0.0f, 1.0f); glScalef(scale, scale, scale); // Loop through the objects for (int i = 0; i &lt; numObjects; i++) { // Enable texture coordiantes, normals

  • _TRIANGLES, m_nNumIndices, GL_UNSIGNED_INT, ((char*)NULL + 0) ); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY... ) return; glBindBuffer( GL_ARRAY_BUFFER, m_nVboId ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_nVboIdIndex ); glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY... in the shader code) for( int n = 0; n &lt; vShaderArgs.size(); n ++) glBindAttribLocation( m_nProgramId, n, vShaderArgs[n].sFieldName.c_str() ); // Create and bind to a vertex array object, which

  • ); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glLoadIdentity(); ...here is my image loading function... SDL_Surface *loadImage (const char *filename, bool alpha = true) { SDL_Surface...I am making a game using OpenGL, with SDL_Image employed to load the textures. When drawn on screen, there's no alpha -- in an exact square around the opaque contents of the texture, black is drawn... = SDL_DisplayFormat(zoomedImage); SDL_FreeSurface(zoomedImage); } return optimizedImage; } ...here is the code I actually use to create the GL texture... GLuint thisIsMyTexture

  • (GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glNormalPointer(GL_FLOAT, 0, indices); glTexCoordPointer(2, GL_FLOAT, sizeof(float)*3, indices); glVertexPointer(3, GL...); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glNormalPointer(GL_FLOAT, 0, &normals[0]); glTexCoordPointer(2, GL_FLOAT, 0, &textCoords[0... at the same time: glBegin(GL_TRIANGLES); for(int i = 0; i &lt; numTriangles; i++) { MD2Triangle* triangle = triangles + i; for(int j = 0; j &lt; 3; j++) { MD2Vertex* v1

  • I'm using vertex array to draw 2d geometry, but I can't achieve smoothness. This is the code I'm using: glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glColorPointer(4, GL_UNSIGNED_BYTE, 0, shared_colors); glVertexPointer(3, GL_FLOAT, 0, shared_vertex); glDrawArrays(GL_LINES, 0, shared_counter); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisable(GL_BLEND); Some advice?

  • zbd.SampleDesc.Count = 1; // no multi-sampling zbd.Format = DXGI_FORMAT_D32_FLOAT; // one 32-bit float per pixel zbd.BindFlags = D3D10_BIND_DEPTH_STENCIL; // texture is to be used as a depth...(&dsvd, sizeof(dsvd)); dsvd.Format = DXGI_FORMAT_D32_FLOAT; // one 32-bit float per pixel dsvd.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D; // depth buffer is a 2D texture device->...(); }; #endif If I call Init() from game.cpp, the code works fine, if I call cube->init(), just as this function is entered (not when the other one is left), the device pointer suddenly has an address

  • ; float current_time, old_time, interpol; int type, current_frame, next_frame; }; struct md2_glcmd_t { float s; float t; int index; }; #define MD2_IDENT (('2'&lt;&lt;24) + ('P'&lt;&lt;16...[m_MD2Header.framesize * i]; vec3_t* Vertices = &m_Vertices[m_MD2Header.num_xyz * i]; int* Normals = &m_Normals[m_MD2Header.num_xyz * i]; for(int vertex = 0; vertex &lt..._Commands; while(int i = *(Commands++)) { if(i &lt; 0) { glBegin(GL_TRIANGLE_FAN); i = -i; } else

  • is identified, so that's all good. I'm writing the game in C++ with OpenGl/GLFW The drawing function is: int win_width; int win_height; glfwGetWindowSize(&win_width, &win_height); float win... a = 0; a &lt; (int)groups.size(); a++) { if(groups[a].type == "prop") { //Code for rotation glPopMatrix(); glPushMatrix(); float x,y,z; x = y = z = 0; int...++) { glBegin(GL_POLYGON); for(int c = 0; c &lt; (int)groups[a].faces[b].vertices.size(); c++) { vertexIndex = groups[a].faces[b].vertices[c]; glVertex3d

  • (mats.mvHandle,1,GL_FALSE,glm::value_ptr(mats.modelViewMatrix)); //bind to vertex array object glBindVertexArray(vaoHandle); //render scene glDrawArrays(GL_TRIANGLES, 0, 240*3 ); //do post-processing... is the init code for the FBO and it's texture: glGenTextures(1,&fboimg); glBindTexture(GL_TEXTURE_2D,fboimg); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D

Data information