SDL help movement not working correctly

I am following a tutorial and this guy had 1000 case statements for movement but i simplified it but cant get it to work correctly. if i tap wasd it will move but if i hold was or d it will stay in that position, but if i still hold down a key and move my mouse the box will move which i dont know why. also it looks like a paint program, the background is black and the square is white and when it moves it creates a white trail.

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
#include <SDL.h>
#include <string>

//left off on Tutorial 4

int main(int argc, char* argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Surface *screen;
    SDL_Surface *image;
    image = SDL_DisplayFormat(SDL_LoadBMP("Test.bmp"));
    screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
    bool running = true;
    const int FPS = 30;
    Uint32 start;
    SDL_Rect rect;
    rect.x = 10;
    rect.y = 10;
    rect.w = 20;
    rect.h = 20;
    Uint32 color = SDL_MapRGB(screen->format, 255, 255, 255);
    Uint8 *keyStates = SDL_GetKeyState(NULL);

    while(running)
    {
        start = SDL_GetTicks();
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    running = false;
                    break;
            }

            if(keyStates[SDLK_w])
            {
                rect.y -= 5;
            }
            if(keyStates[SDLK_a])
            {
                rect.x -= 5;
            }
            if(keyStates[SDLK_s])
            {
                rect.y += 5;
            }
            if(keyStates[SDLK_d])
            {
                rect.x += 5;
            }


            SDL_FillRect(screen, &rect, color);
            SDL_BlitSurface(image, NULL, screen, NULL);
            SDL_Flip(screen);
            if(1000/FPS>SDL_GetTicks()-start)
            {
                SDL_Delay(1000/FPS-(SDL_GetTicks()-start));
            }
        }
    }
    SDL_FreeSurface(image);
    SDL_Quit();
}


bump
Your while loop only runs when you get an event (like a mouse movement, or key press change) so your rectangle will only move when events are being processed, rather than every frame.
ok so how do i fix this?
Place line 37-61 outside the event loop.
awesome thanks, now i have a problem, I have an image and it is a pinkish color and when i move it, it makes a pink trail and its not supposed too, so what is the problem? I would post this on the SDL forums but it wont let me create an account for some reason. but thanks for the help from anyone who can help me.

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
#include <SDL.h>
#include <string>

//left off on Tutorial 4

int main(int argc, char *argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Surface *screen;
    SDL_Surface *image;
    image = SDL_LoadBMP("Test.bmp");
    screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
    bool running = true;
    Uint8 *keyStates = SDL_GetKeyState(0);

    //Offsetting the bmp image
    SDL_Rect offset;

    offset.x = 0;
    offset.y = 0;

    while(running)
    {
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    running = false;
                    break;
            }
        }
        if(keyStates[SDLK_w])
        {
            offset.y -= 1;
        }
        if(keyStates[SDLK_a])
        {
            offset.x -= 1;
        }
        if(keyStates[SDLK_s])
        {
            offset.y += 1;
        }
        if(keyStates[SDLK_d])
        {
            offset.x += 1;
        }
        if((keyStates[SDLK_s]) && (offset.y == 500))
        {
            offset.y -= 1;
        }
        if((keyStates[SDLK_d]) && (offset.x == 700))
        {
            offset.x -= 1;
        }
        //We are blitting image, NULL, telling what we are blitting image to
        //
        SDL_BlitSurface(image, NULL, screen, &offset);
        SDL_Flip(screen);
    }
}
Last edited on
You should be clearing the screen every time you draw. Otherwise you will be drawing on top of whatever garbage data is in the video buffer (which is typically going to be the previous frame).

This can be accomplished with SDL_FillRect:

1
2
// do this every frame before you start any drawing
SDL_FillRect( your_surface, nullptr, your_desired_color );
Awesome thanks it works :D now my image moves quite fast and i dont want it too, how do i slow it down? i tried changing the offset.y -= 1; to 0.001 but it has no effect. Also how would i accomplish some simple gravity so i could make the image jump?
You don't want to just alter the speed like that. What's happening is the program is just running as fast as it can. If you tweak the speed to be the way you want... it may run fine on your computer, but when you try it on another computer it will run at a different speed (ie: slower computers will run slower, etc).

Typically in these kinds of games, you want to upload the logic only X times per second (60 times per second is typical) then draw one scene.

You can regulate this 60 FPS by periodically checking the time (SDL_GetTicks), and sleeping (SDL_Delay) until it's time to run another frame.

"Good" framerate regulation can get be a moderately complex topic that I won't get into here. But that's the basic idea.
ah i see, ok i'll look into that but im trying to gwet my player to jump which isnt going well i cant hget him to jump, here is my code

jump code

1
2
3
4
5
6
7
8
9
10
11
if(keyStates[SDLK_SPACE])
        {
            for(int i = 0; i < 1; i++)
            {
                offset.y -= 6;
            }
            for(int i = 0; i < 1; i++)
            {
                offset.y += 6;
            }
        }



full 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
#include <SDL.h>
#include <string>

//left off on Tutorial 4

int main(int argc, char *argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Surface *screen;
    SDL_Surface *image;
    image = SDL_LoadBMP("Test.bmp");
    screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
    bool running = true;
    Uint8 *keyStates = SDL_GetKeyState(0);
    Uint32 color = SDL_MapRGB(screen->format, 0, 255, 255);

    //Create Rectangle
    SDL_Rect rect;

    rect.x = 10;
    rect.y = 10;
    rect.w = 20;
    rect.h = 20;

    //Offsetting the bmp image
    SDL_Rect offset;

    offset.x = 0;
    offset.y = 570;

    while(running)
    {
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    running = false;
                    break;
            }
        }

        if(keyStates[SDLK_w])
        {
            //offset.y -= 1;
        }
        if(keyStates[SDLK_a])
        {
            offset.x -= 1;
        }
        if(keyStates[SDLK_s])
        {
            //offset.y += 1;
        }
        if(keyStates[SDLK_d])
        {
            offset.x += 1;
        }
        if((keyStates[SDLK_s]) && (offset.y == 570))
        {
            offset.y -= 1;
        }
        if((keyStates[SDLK_d]) && (offset.x == 770))
        {
            offset.x -= 1;
        }
        if(keyStates[SDLK_SPACE])
        {
            for(int i = 0; i < 1; i++)
            {
                offset.y -= 6;
            }
            for(int i = 0; i < 1; i++)
            {
                offset.y += 6;
            }
        }
        //We are blitting image, NULL, telling what we are blitting image to
        SDL_FillRect(screen, &rect, color);
        SDL_FillRect(screen, NULL, 0);
        SDL_BlitSurface(image, NULL, screen, &offset);
        SDL_Flip(screen);
    }

    SDL_FreeSurface(image);
    SDL_Quit();
}
Last edited on
Those for loops are canceling each other out. Try just adjusting the y value once in the key press handler, you'll then need to apply gravity every frame. You should also check the y value of the player and only apply gravity if its y is less then the ground.
Can i see the code for that? Im a visual person i need to see it.
Maybe something like this
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
    offset.x = 0;
    offset.y = 570;
	
    int gravity = 1;
	
    while(running)
    {
    ...
	if(keyStates[SDLK_SPACE])
        {
            offset.y -= 6;            
        }
		
	if(offset.y < 570)
	    offset,y += gravity;
			
        //We are blitting image, NULL, telling what we are blitting image to
        SDL_FillRect(screen, &rect, color);
        SDL_FillRect(screen, NULL, 0);
        SDL_BlitSurface(image, NULL, screen, &offset);
        SDL_Flip(screen);
    }

    SDL_FreeSurface(image);
    SDL_Quit();
}
Last edited on
haha lol thats cool :D but if i hold space he keeps jumping how can i make it so that when he reaches a certain height he stops and goes back down? Also i made a FPS thing and my player still moves too fast.

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
91
92
93
94
95
96
97
98
99
100
#include <SDL.h>
#include <string>

int main(int argc, char *argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);

    //Creating the screen and the image
    SDL_Surface *screen;
    SDL_Surface *image;
    image = SDL_LoadBMP("Test.bmp");
    screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);


    bool running = true;
    const int FPS = 30;
    Uint32 start;

    //Create Rectangle
    SDL_Rect rect;

    rect.x = 10;
    rect.y = 10;
    rect.w = 32;
    rect.h = 32;


    Uint8 *keyStates = SDL_GetKeyState(0);
    Uint32 RectColor = SDL_MapRGB(screen->format, 234, 0, 45);
    Uint32 ScreenColor = SDL_MapRGB(screen->format, 25, 23, 90);

    //Offsetting the bmp image
    SDL_Rect offset;

    offset.x = 0;
    offset.y = 570;

    int gravity = 1;

    while(running)
    {
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    running = false;
                    break;
            }
        }

        if(keyStates[SDLK_w])
        {
            //offset.y -= 1;
        }
        if(keyStates[SDLK_a])
        {
            offset.x -= 1;
        }
        if(keyStates[SDLK_s])
        {
            //offset.y += 1;
        }
        if(keyStates[SDLK_d])
        {
            offset.x += 1;
        }
        if((keyStates[SDLK_s]) && (offset.y == 570))
        {
            offset.y -= 1;
        }
        if((keyStates[SDLK_d]) && (offset.x == 770))
        {
            offset.x -= 1;
        }
        if(keyStates[SDLK_SPACE])
        {
            offset.y -= 2;
        }

		if(offset.y < 570)
		{
                     offset.y += gravity;
		}

        //We are blitting image, NULL, telling what we are blitting image to
        SDL_FillRect(screen, NULL, ScreenColor);
        SDL_FillRect(screen, &rect, RectColor);
        SDL_BlitSurface(image, NULL, screen, &offset);
        SDL_Flip(screen);
        if(1000/FPS>SDL_GetTicks()-start)
        {
            SDL_Delay(1000/FPS-(SDL_GetTicks()-start));
        }
    }

    SDL_FreeSurface(image);
    SDL_Quit();
}
Last edited on
Never mind i fixed the jumping too high part but how do i make it so i cant hold the spacebar? also player is still mving too fast.
Last edited on
You could change the FPS constant to make the game run slower but that will not solve the problem when you have different things moving at different speeds.

A better way is to store the x y position in a floating point data type instead. That way you can move things in whatever speed you want. You only need to convert the positions to integers when you draw them.

If you don't want the speed of the jump to be constant you should probably keep track of the velocity of the player. Gravity should affect the y velocity and the y velocity should affect the y position.
1
2
velocity.y += gravity;
position.y += velocity.y;
.

To make the player jump you just set the y velocity to some negative constant. You don't want the player to be able to jump in the air so you will have to check that the person is on the ground before applying the velocity. Not sure exactly what way is best but I guess one way is to calculate the players distance from the ground.

If you don't want the player to repeatedly jump up and down when holding the space bar you could let the SDL_KEYDOWN event trigger the start of the jump. That way the player will only jump when the spacebar is pressed down.

Do you want holding the spacebar to affect the hight of the jump, like how the Mario games work? To implement that you could have a flag that is initially false. When the jump starts you set it to true. If the spacebar is down, the flag is true and the y velocity is negative (meaning the player is not falling) you subtract a small constant (smaller than the gravity constant) from the y velocity, otherwise you set the flag to false.
Ok i fixed the player so when you hold down spacebar he doesnt hover but i still have the speed issue. I have an FPS thing in my code but its not working!! D:

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <SDL.h>
#include <string>

int main(int argc, char *argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);

    //Creating the screen and the image
    SDL_Surface *screen;
    SDL_Surface *image;
    image = SDL_LoadBMP("Test.bmp");
    screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
    SDL_WM_SetCaption("Simple Game", NULL);//Keep in main


    bool running = true;
    const int FPS = 30;
    Uint32 start;

    //Create Rectangle
    SDL_Rect rect;

    rect.x = 40;
    rect.y = 40;
    rect.w = 32;
    rect.h = 32;


    Uint8 *keyStates = SDL_GetKeyState(0);
    Uint32 RectColor = SDL_MapRGB(screen->format, 234, 0, 45);
    Uint32 ScreenColor = SDL_MapRGB(screen->format, 25, 23, 90);

    //Offsetting the bmp image
    SDL_Rect offset;

    offset.x = 0;
    offset.y = 570;

    int gravity = 1;

    while(running)//Keep this and everything in it in main
    {
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    running = false;
                    break;
            }
        }

        if(keyStates[SDLK_w])
        {
            //offset.y -= 1;
        }
        if(keyStates[SDLK_a])
        {
            offset.x -= 1;
        }
        if(keyStates[SDLK_s])
        {
            //offset.y += 1;
        }
        if(keyStates[SDLK_d])
        {
            offset.x += 1;
        }
        if((keyStates[SDLK_s]) && (offset.y == 570))
        {
            offset.y -= 1;
        }
        if((keyStates[SDLK_d]) && (offset.x == 770))
        {
            offset.x -= 1;
        }
        if(offset.y == rect.y)
        {
            offset.x -= 1;
        }

        if(keyStates[SDLK_SPACE])
        {
            offset.y -= 2;
        }
	if(offset.y < 570)
	{
              offset.y += gravity;
	}
	if(offset.y < 500)
	{
	       offset.y += gravity;
               keyStates[SDLK_SPACE] = SDL_RELEASED;
	}
        //We are blitting image, NULL, telling what we are blitting image to
        SDL_FillRect(screen, NULL, ScreenColor);
        SDL_FillRect(screen, &rect, RectColor);
        SDL_BlitSurface(image, NULL, screen, &offset);
        SDL_Flip(screen);
        if(1000/FPS>SDL_GetTicks()-start)
        {
            SDL_Delay(1000/FPS-(SDL_GetTicks()-start));
        }
    }

    SDL_FreeSurface(image);//Keep in main
    SDL_Quit();// Keep in main
}
Last edited on
bump
You need to update your start variable every frame to check how long it takes to complete that frame (which you were doing in your first post).

Add start = SDL_GetTicks() at the start of your while loop
Last edited on
ah i see ok, awesome thanks. No what if i want to make the player image collide with the red box at the top left corner? how would i make it collide without saying dont collide with the boxes position in case it moves?
Topic archived. No new replies allowed.