Smooth sprite movement (SDL)

Hello!
I'm making a 2D rpg game, but I have some problem with the sprite movement. The sprite movement feels choppy.
That's because I move the sprite 5 pixels per seconds. I now that I need somthing that have to do with SDL_getTicks and deltatime,
but I dont know how to use/implement it.

Here is a little part of my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
float spriteDstY;
float spriteDstX;
float speed = 5;

     while(SDL_PollEvent(&event)!= 0)
        {
            if (event.type == SDL_QUIT)
            {
                quit = true;
            }
            else if (event.type == SDL_KEYDOWN)
            {
                switch(event.key.keysym.sym)
                {
                case SDLK_UP:
                spriteDstY-=speed;
                break;
                
                case SDLK_DOWN:
                spriteDstY+=speed;
                break;

                case SDLK_RIGHT:
                spriteDstX+=speed;
                break;

                case SDLK_LEFT:
                spriteDstX-=speed;
                break;
                }
            }

        draw->drawSprite(spriteDstX,spriteDstY,optimizedPlayerSprite,screenSurface);

        SDL_UpdateWindowSurface(window);
        SDL_FreeSurface(background);
         }
Last edited on
uhm... you could make a variable that holds the time that passed ^^

I think you want to make your Game run at 60 FPS but i'll just make a Variable so that you won't get confused...

also, you might want to initialize your SpritePosition Variables, but that may just be something formal... some time ago not initialized variables didn't automatically initialize to "0"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
int FPS = 60;
int FrameStartTimeMs = 0; // will Hold the Time at the beginning of a Frame

float spriteDstY = 0.0f;
float spriteDstX = 0.0f;
float speed = 5.0 / FPS; // do NOT forget the .0 in 5.0, otherwise the Speed 
                         //be a Integer Division (5 / 60) which would equal zero(0)
while(quit != true)
{
    FrameStartTimeMs = SDL_GetTicks();

    while(SDL_PollEvent(&event)!= 0)
    {
        if (event.type == SDL_QUIT)
        {
            quit = true;
        }
        else if (event.type == SDL_KEYDOWN)
        {
            switch(event.key.keysym.sym)
            {
            case SDLK_UP:
                spriteDstY-=speed;
            break;
               
            case SDLK_DOWN:
                spriteDstY+=speed;
            break;

            case SDLK_RIGHT:
                spriteDstX+=speed;
            break;

            case SDLK_LEFT:
                spriteDstX-=speed;
            break;
            }
        }
        draw->drawSprite(spriteDstX,spriteDstY,optimizedPlayerSprite,screenSurface);

        SDL_UpdateWindowSurface(window);
        SDL_FreeSurface(background);
    }

    // does nothing until the Time of 1 Frame is over
    while(SDL_GetTicks() - FrameStartTimeMs < 1000/FPS); 
}


I hope I was able to help you ^^
Last edited on
1
2
    // does nothing until the Time of 1 Frame is over
    while(SDL_GetTicks() - FrameStartTimeMs < 1000/FPS);


FWIW, you should really consider sleeping rather than doing a dead spin.

Dead spins consume 100% CPU time which will make other processes on the system crawl, and will drain batteries on portable computers.
@Gamer2015

Thanks ^^ It works a little bit better, but it still feels a bit choppy. However do you know how I could make my game so it can handle mulitple key inputs at the same time. Because right now I can only handle one key at the time, and that makes the game feel a bit choppy.


@Disch
Dead spins consume 100% CPU time which will make other processes on the system crawl, and will drain batteries on portable computers.

Thanks, I'll keep that in mind :D
To accept multiple key inputs try changing your switch in your else if(event.type == SDL_KEYDOWN) to if statements. All of them. Not if-else if, just all if statements.
@twiggystardust

Thanks!! It works... but not perfect. Because the sprite stops when I push down an another key before it starts to move again. So every time I want the sprite to move in an another direction it stops.
Oh I forgot a part. Make 4 bool variables, one for each key. Set them all to false, then in the function you have if a certain key is pushed then set its bool to true. (If you do this you will need a key released function to return the variables to false.) Then make a function to update the x and y if the bool for that key is true. Hope that helps.
@twiggystardust

Thanks again... it's much better, but still the sprite stop for one second before it change direction.

Here is a part of my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

bool up = false;
bool down = false;
bool left = false;
bool right = false;
float spriteDstX = 0.0f;
float spriteDstY = 0.0f;
int FPS = 60;
int FrameStartTimeMs = 0;
float speed = 400.0 / FPS;

while(quit != true)
{
    FrameStartTimeMs = SDL_GetTicks();

 while(SDL_PollEvent(&event)!= 0)
        {
            if (event.type == SDL_QUIT)
            {
                quit = true;
            }
            else if (event.type == SDL_KEYDOWN)
            {

                //****************************************************
                if (event.key.keysym.sym == SDLK_UP)
                {
                    up = true;
                }
                if (event.key.keysym.sym == SDLK_DOWN)
                {
                    down = true;
                }
                if (event.key.keysym.sym == SDLK_LEFT)
                {
                    left = true;
                }
                if (event.key.keysym.sym == SDLK_RIGHT)
                {
                    right = true;
                }
             }

                //****************************************************
            else if (event.type == SDL_KEYUP)
            {
                if (event.key.keysym.sym == SDLK_UP)
                {
                    up = false;
                }
                if (event.key.keysym.sym == SDLK_DOWN)
                {
                    down = false;
                }
                if (event.key.keysym.sym == SDLK_LEFT)
                {
                    left = false;
                }
                if (event.key.keysym.sym == SDLK_RIGHT)
                {
                    right = false;
                }
            }

              //****************************************************

                if (up == true)
                {
                    spriteDstY-=speed;
                }

                if (down == true)
                {
                    spriteDstY+=speed;
                }

                if (left == true)
                {
                    spriteDstX-=speed;
                }

                if (right == true)
                {
                    spriteDstX+=speed;
                }
}
draw->drawSprite(spriteDstX,spriteDstY,optimizedPlayerSprite,screenSurface);
SDL_UpdateWindowSurface(window);
while(SDL_GetTicks() - FrameStartTimeMs < 1000/FPS);
}
Last edited on
Try taking out the FPS stuff maybe...you really shouldn't need it with the method I gave you. Just make sure your main update isn't more than 60 per second. I honestly can't think of anything else it would be at the moment.
Topic archived. No new replies allowed.