1
\$\begingroup\$

Whats the best way to be rendering the locations of objects in box2D in such a way that there no stuttering on movement beyond 8-directions. I'm looking to have object strictly snap to the pixels but still keep objects moving smoothly without jittering.

every game loop iteration calls an Update() method on all GameObjects which rounds the objects position in the Physics world to a corresponding pixel coordinate and scaled up.

destRect.x = std::floor(getX() * scale);
destRect.y = std::floor(getY() * scale);

drawn to the screen afterward in GameObject::Draw()

SDL_RenderCopy(targetRenderer, objectTexture, &srcRect, &destRect);

this works fine and positions the object perfectly on the screen--too perfectly.

Moving straight in any direction is smooth and doesn't stutter. I quickly wrote the following code to fix jittering on diagonals (45 degrees) by ensuring that each row/column has only one pixel drawn on it. This makes 8-way movement smooth.

if (IsMoving())
    {
        // Which direction is the object traveling
        float angleAbs = std::abs(GetAngleDegrees());
        if (angleAbs <= 135 && angleAbs >= 45)
        {
            CurrentCol = CurrentColY = NULL;
    
            // set y to floored object->x in scaled pixels
            destRect.y = std::floor(getY() * scale);
    
            // has this row been rendered to yet?
            if (CurrentRow == std::floor(getY()))
            {
                destRect.x = CurrentRowX;
            }
            else
            {
                CurrentRow = std::floor(getY());
                destRect.x = CurrentRowX = std::floor(getX() * scale);
            }
        }
        else
        {
            CurrentRow = CurrentRowX = NULL;
    
            // set y to floored object->x in scaled pixels
            destRect.x = std::floor(getX() * scale);
    
            // has this column been rendered to yet?
            if (CurrentCol == std::floor(getX()))
            {
                destRect.y = CurrentColY;
            }
            else
            {
                CurrentCol = std::floor(getX());
                destRect.y = CurrentColY = std::floor(getY() * scale);
            }
        }
    }
    else 
    {    
        // update any changes made to the coordinates
        destRect.x = std::floor(getX() * scale);
        destRect.y = std::floor(getY() * scale);
    }

This code tries to smooths out other angles that objects might move in (jumping forward, for, example, forms a parabola like shape) but doesn't look smooth when speed up to normal frame rates. The motion doesn't render seamlessly.

I think I'm rendering the locations of the objects almost too precisely, making the objects movement (ironically) pixelated and mechanical, but I'm lost on how to make pixel perfect motion on varied angles seem--or at lease give the illusion of--smooth "realistic" motion.

I'm looking for advice on how to approach this problem and find a working solution rather than make it work with my engine directly--all the same, the code for my game engine can be found on GitHub here if it helps.

\$\endgroup\$

You must log in to answer this question.

Browse other questions tagged .