oscar.rpr
oscar.rpr

Reputation: 678

Question About An Implementation Of Parallax Scrolling In C++/SDL/OpenGL

I been working in a project with a team for a Software Engineering class and we think that using the parallax scrolling will help our game to look really nice but we are not really sure if our idea for implementation it's the correct one, so I hope that someon will give us some guidance about our plan.

First, we have three classes, Level, Tileset, Layer, the first one has two vectors of Layers and Tilesets, so our idea is load all the data from a TMX file of the first level in a vector>, but we only draw the part of the map that it's currently in camera, so inside a cycle we draw every layer, but we're not sure how defined a velocity for each layer so the parallax scrolling works like it supposed.

PD: If someone need more information, don't doubt in ask.

Upvotes: 1

Views: 2060

Answers (2)

oscar.rpr
oscar.rpr

Reputation: 678

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

Upvotes: 1

Razzupaltuff
Razzupaltuff

Reputation: 2311

Are you implementing a 2D side scrolling game where several background layers should move in a way that gives a proper impression of depth?

If so, one approach might be to define a distance from the viewer for each layer. Chose a reference point that is sufficiently far away to simulate an infinite distance for it, and compute the intersections of the view vector to that point through your layers. When the viewer moves, do the same for the new viewer position. Use the distance between the intersections of old and new reference vectors to determine the speed of the layers.

A simpler method would be to just use some controls to adjust scroll speeds (or adjust the front layer's scroll speed and the speed scales of each other layer) and play around with that until you think it looks good.

Upvotes: 0

Related Questions