Search code examples
c++sdlsdl-2

Smooth grid movement with SDL2?


I'm making a Pokemon-like game using C++ and SDL2. I'm trying to accomplish its grid movement (in which the character moves tile by tile, 32px each one).

I've accomplished the tile by tile movement, but it does not look smooth, it looks very "robotic".

Here it is what I have so far:

overflowY += deltaY * elapsedTime;
overflowX += deltaX * elapsedTime;
if (overflowX >= 32){
    _x += 32;
    overflowX = 0;
}else if (overflowX <= -32){
    _x -= 32;
    overflowX = 0;

}
if (overflowY >= 32){
    _y += 32;
    overflowY = 0;
}else if(overflowY <= -32){
   _y -= 32;
    overflowY = 0;
}

AnimatedSprite::update(elapsedTime);

deltaX is 1 or -1 (right or left) * speed, same with deltaY. My code actually works, but as I said, it does not look smooth.

Any guesses?


Solution

  • The following code is not tested, but should give an idea how to solve the issue. Keep in mind that for small elapsedTime (high framerate) the calculation with integers does not work. Then use floats or fixpoint calculation.

    class SpritePosition
    {
    public:
        enum Direction { Left, Right, Up, Down };
    
        SpritePosition(int x, int y) : _x(x), _y(y) {}
    
        void update(Direction d, float elapsedTime)
        {
            _d = d;
    
            switch(d)
            {
                case Left: _x -= _tileSize * elapsedTime; break;
                case Right: _x += _tileSize * elapsedTime; break;
                case Up: _y -= _tileSize * elapsedTime; break;
                case Down: _y -= _tileSize * elapsedTime; break;
            }
        }
    
        void update(float elapsedTime)
        {
            if((_x % _tileSize) == 0 && (_y % _tileSize) == 0)
                return;
    
            int step = _tileSize * elapsedTime;
    
            if(_d == Left)
            {
                int d = _x % _tileSize;
    
                if(step > d)
                    _x -= d;
                else
                    _x -= step;
            }                
            else if(_d == Right)
            {
                int d = tileSize - (_x % _tileSize);
    
                if(step > d)
                    _x += d;
                else
                    _x += step;
            }
            else // same for Up and Down                
        }
    
        int getX() const { return _x;}        
        int getY() const { return _y;}        
    
        int getTileX() const { return _x / _tileSize;}        
        int getTileY() const { return _y / _tileSize;}        
    
    private:
        const int _tileSize = 32;
        int _x;
        int _y;
        Direction _d;
    };