Wednesday, 16 September 2015

Some thoughts about SDL texture and sprite z-index

...and a solution ("painters solution").

I've read and heard that SDL don't have any real z-index when it comes to render image on screen,
the last drawn image/sprite/texture has the highest z-index. That got me thinking of a way to correct it.

In a X,Y,Z graphics environment we can correct the z-index like this:
The bigger the number of y-pos is = the bigger the z-index is
or in other words: z-index = y-pos + spriteHeight;
(In most cases you need to add sprite height to y-pos to get the real y-pos, and your sprites need to be cropped/trimmed from unnecessary transparent height so the bottom of the sprites are accurate)



Some pseudo code to explain solution:
if(object.A.pos.y > object.B.pos.y)
{
  redraw(object.B);
  redraw(object.A);
}
else if(object.A.pos.y < object.B.pos.y)
{
  redraw(object.A);
  redraw(object.B);
}


Final coding (c++):
This is what I ended up doing: basically comparing 2 vectors and redraw textures in right order.
Here's my code, I run it last/at the bottom in my gameloop render function,
but surely this can/should be included to the default render function as a permanent part:
/////////////////////////////////////////////////////////////////////////////////////////////////////
//A little sorter-helper function
bool howToSort(int i, int j) { return i < j; }

/////////////////////////////////////////////////////////////////////////////////////////////////////
//A function to get z-index from object, defined in a header file
//It's made out from a getPosition.getY() function and a class member int m_objHeight
int getZindex() { return getPosition().getY() + m_objHeight; }

/////////////////////////////////////////////////////////////////////////////////////////////////////
//Redraw objects to correct the z-index of all screen objects/sprites/textures
//The parameter is a vector of GameObjects (class that makes up the objects) 
void RedrawObjectZindex(const std::vector<GameObject*> &objects)
{
    //Declare a vector of integers to hold all objects z-indexes
    std::vector<int> v_zindex;
    
    for(int i=0; i < objects.size(); i++)
    { 
        //In my case I omit the background image object, it's always going to have the highest zindex, 
        //(largest height+ypos), so I avoid it. (Its textureID=background)
        //objID() is a function that gets the objects textureID
        if(objects[i]->objID() !="background") 
        {
             //Add each objects z-index to the v_zindex vector
             v_zindex.push_back(objects[i]->getZindex());
        }
    }
 
    //Sort the vector from lowest to highest zindex
    sort( v_zindex.begin(), v_zindex.end(), howToSort );

    //Now we redraw objects in correct order by comparing the sorted z-indexes 
    //with objects ypos+height. By drawing the lowest first (smallest value) and
    //highest last (biggest value), we correct the zindex and "depth" is achieved.
    for(int i=0; i < v_zindex.size(); i++)
    {
        for(int j=0; j < objects.size(); j++)
        {
            if(v_zindex[i] == objects[j]->getZindex())
            {
                 //draw() is a function that draws textures to screen
                 objects[j]->draw();
            }   
        }  
    }
    //Clean up this vector
    v_zindex.clear();
}

No comments:

Post a Comment

Please, no foul language, trolling, keep it clean. Thanx.