[C++/SDL2] Player not moving constantly

Hello guys

Im using SDL2 but I'm encountering an unexpected error. I have implemented the same method to move as in my old Projects, but the Player appears to be stuck...

The Player is stuck for maybe half a second, and then everything works as it should, but every time I Change direction or i start moving the Player is stuck for a short Moment. Do you have any idea what it could be?

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
#ifndef _PLAYER_HPP_
    #define _PLAYER_HPP_


#include <iostream>
#include <string>
#include "SDLGameObject.hpp"


class CPlayer : public CSDLGameObject
{
    public:
        CPlayer();

        void Load(SDL_Renderer* pRenderer, int R, int G, int B);
        void HandleInput(SDL_Event Event);
        void Update();
        void Render(SDL_Renderer* pRenderer);

        void SetPosX(float NewPosX);
        float GetPosX () { return m_PosX; }

        void SetPosY(float NewPosY);
        float GetPosY () { return m_PosY; }

        float GetWidth() { return m_Width; }
        float GetHeight() { return m_Height; }

        int GetCurrentFrame() { return m_CurrentFrame; }
        void SetMaxFrames(int NewMaxFrames);

        std::string GetName();
        void SetName(std::string Name);

        std::string GetState() { return m_State; }
        void SetState(std::string NewState);

    private:
        std::string m_Name;
        std::string m_State;

        int m_Score;

        CSprite PlayerSprite;
};


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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "Player.hpp"
#include "PlayState.hpp"


CPlayer::CPlayer() : CSDLGameObject()
{
    m_Name = "";
    m_State = "STAND_RIGHT";

    m_PosX = 200;
    m_PosY = 300;
    m_Width = 28;
    m_Height = 32;

    m_CurrentFrame = 0;
    m_CurrentRow = 0;

    m_MovingSpeed = 5;
    m_JumpingHeight = 35;

    m_Score = 0;

}

void CPlayer::Load(SDL_Renderer* pRenderer, int R, int G, int B)
{
    ObjectTexture = PlayerSprite.Load(pRenderer,"data/imgs/player/Mario.png",R,G,B);
}

void CPlayer::HandleInput(SDL_Event Event)
{
    switch (Event.type)
    {
        case SDL_KEYDOWN:
            switch (Event.key.keysym.sym)
            {
                case SDLK_a:
                    m_PosX -= m_MovingSpeed;
                    m_State = "WALKING_LEFT";
                    break;
                case SDLK_d:
                    m_PosX += m_MovingSpeed;
                    m_State = "WALKING_RIGHT";
                    break;
                case SDLK_SPACE:
                    m_PosY -= m_JumpingHeight;
                    m_State = "JUMPING";
                    break;

            }
            break;

        case SDL_KEYUP:
            switch (Event.key.keysym.sym)
            {
                case SDLK_a:
                    m_State = "STAND_LEFT";
                    break;

                case SDLK_d:
                    m_State = "STAND_RIGHT";
                    break;
            }
    }
}

void CPlayer::Update()
{
    if (m_State == "STAND_RIGHT")
    {
        m_CurrentRow = 0;
        m_CurrentFrame = 0;
    }
    else if (m_State == "STAND_LEFT")
    {
        m_CurrentRow = 1;
        m_CurrentFrame = 0;
    }
    else if (m_State == "JUMPING")
    {
        m_CurrentFrame = 1;
    }
    else if (m_State == "ACCELERATING_RIGHT")
    {

    }
    else if (m_State == "ACCELERATING_LEFT")
    {

    }
    else if (m_State == "WALKING_RIGHT")
    {
        m_CurrentRow = 0;
        if (m_CurrentFrame < 4)
        {
            m_CurrentFrame++;
        }
        else
        {
            m_CurrentFrame = 2;
        }
    }
    else if (m_State == "WALKING_LEFT")
    {
        m_CurrentRow = 1;
        if (m_CurrentFrame < 4)
        {
            m_CurrentFrame++;
        }
        else
        {
            m_CurrentFrame = 2;
        }
    }
    else if (m_State == "DYING")
    {
        m_CurrentRow = 0;
        m_CurrentFrame = 5;
    }
    else if (m_State == "SLIDING_END")
    {
        m_CurrentRow = 0;
        m_CurrentFrame = 6;

    }

    PlayerSprite.SetSourceRect(m_Width * m_CurrentRow, m_Height * m_CurrentFrame,m_Width,m_Height);
}

void CPlayer::Render(SDL_Renderer* pRenderer)
{
    PlayerSprite.SetDestinationRect(m_PosX,m_PosY,m_Width,m_Height);
    PlayerSprite.Render(pRenderer);
}

void CPlayer::SetPosX(float NewPosX)
{
    m_PosX = NewPosX;
}

void CPlayer::SetPosY(float NewPosY)
{
    m_PosY = NewPosY;
}


std::string CPlayer::GetName()
{
    return m_Name;
}

void CPlayer::SetName(std::string Name)
{
    m_Name = Name;
}

void CPlayer::SetMaxFrames(int NewMaxFrames)
{
    m_MaxFrames = NewMaxFrames;
}
I wonder why u set the position at a KeyDown Event
1
2
3
4
5
6
7
8
9
10
11
12
                case SDLK_a:
                    m_PosX -= m_MovingSpeed; // here
                    m_State = "WALKING_LEFT";
                    break;
                case SDLK_d:
                    m_PosX += m_MovingSpeed; // here
                    m_State = "WALKING_RIGHT";
                    break;
                case SDLK_SPACE:
                    m_PosY -= m_JumpingHeight; // here
                    m_State = "JUMPING";
                    break;


Also i don't understand your "State-Methods" for Walking, what should happen here?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    else if (m_State == "WALKING_RIGHT")
    {
        m_CurrentRow = 0;
        if (m_CurrentFrame < 4)
        {
            m_CurrentFrame++;
        }
        else
        {
            m_CurrentFrame = 2;
        }
    }
    else if (m_State == "WALKING_LEFT")
    {
        m_CurrentRow = 1;
        if (m_CurrentFrame < 4)
        {
            m_CurrentFrame++;
        }
        else
        {
            m_CurrentFrame = 2;
        }
    }


I think you want your player to move in them but you don't actually increase the Position (i think)
I also don't understand the meaning of CurrentFrame and CurrentRow, what purpose do they serve?

Furthermore i don't understand why u change the SourceRect, don't you want to change the DestRect to render your player at the new position?
PlayerSprite.SetSourceRect(m_Width * m_CurrentRow, m_Height * m_CurrentFrame,m_Width,m_Height);

I am sorry, but I can't read your code :<
Last edited on
Alright... xddd

So I've still gotta work on that... the currentframe and currentrow are only to set the Frame of the spritesheet im currently at... My states are defined and made for the spritesheet im using. With the Animation everythings doing fine.

But to your first Point: Why shouldnt i set the Position when a key is down? what would you suggest?
You probably don't want to rely on repeated key events. It's more for typing text and other GUI actions. It's the same behavior you have when typing text in your web browser. When you press a key the letter will be typed, but there is a small delay before the letter starts repeating rapidly. Without the delay you would have to be too careful with how long you hold the key down to avoid repeated letters.

You probably should update the player's position in the Update() function instead.
Last edited on
Well, i think Peter87 answered your question perfectly.

A KeyDown event is not an event where the key is down, it is an event where the Key State changes from Pressed to not Pressed and after some time there is an auto-repeat of the KeyDown event, so it is exactly as Peter87 said.
Last edited on
Hmm ist not the first question hes answered perfectly ;)

It wont work with booleans, if I say for example
1
2
3
4
5
// In the HandleInput-function
case SDLK_d:
    m_FaceRight = true;
    //setstate
    break;

1
2
3
4
5
//In the Update-function
if (m_FaceRight == true)
{
    m_PosX += MOVEMENT_SPEED;
}

it will never move. Should I go with SDL_GetKeyboardState() and SDL_PumpEvents?
Last edited on
I don't understand why it will not work with booleans.
Well, it works nice here...
I'll just dump all code, i don't care for error checking at 1:20 am, I'm sorry

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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

SDL_Texture* loadFromFile(const std::string& Path, SDL_Renderer* pRenderer)
{
    // don't care bout error checking now
    SDL_Surface* tempSurface = IMG_Load(Path.c_str());

    return SDL_CreateTextureFromSurface(pRenderer, tempSurface);
}

template <typename T>
class Vector2
{
public:
    T x;
    T y;
};

class Player
{
public:
    Player( SDL_Renderer* pRenderer ) { mpRenderer = pRenderer; }

    void SetTexture(const std::string& Path) { mpTexture = loadFromFile(Path, mpRenderer); }

    void Render() { SDL_RenderCopy(mpRenderer, mpTexture, NULL, &GetRenderRect()); }

    Vector2<float> Pos;
    Vector2<float> Size;

private:
    const SDL_Rect& GetRenderRect()
    {
        mRenderRect.x = Pos.x;
        mRenderRect.y = Pos.y;
        mRenderRect.w = Size.x;
        mRenderRect.h = Size.y;
        return mRenderRect;
    }

    SDL_Renderer* mpRenderer;
    SDL_Texture* mpTexture;
    SDL_Rect mRenderRect;
};

int main(int argc, char* argv[])
{
    std::cout << "Test 1" << std::endl;
    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window* pWindow = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);

    SDL_Renderer *pRenderer = SDL_CreateRenderer( pWindow, -1, SDL_RENDERER_ACCELERATED );
    SDL_SetRenderDrawColor( pRenderer, 0xFF, 0x00, 0x00, 0xFF );

    IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);

    char Buttons = 0;
    enum { BUTTON_RIGHT = 0x01, BUTTON_LEFT = 0x02 };

    Player player(pRenderer);
    player.SetTexture("white.png");
    player.Pos.x = 50;
    player.Pos.y = 50;
    player.Size.x = 50;
    player.Size.y = 50;

    std::cout << "Test 1" << std::endl;

    float Velocity = 50 * 1.0/60;

    SDL_Event Event;

    int Time = SDL_GetTicks();

    bool quit = false;
    while(!quit)
    {
        while(SDL_PollEvent(&Event) != 0)
        {
            if(Event.type == SDL_QUIT)
            {
                quit = true;
            }
            if (Event.type == SDL_KEYDOWN)
            {
                switch(Event.key.keysym.sym)
                {
                    case SDLK_a: Buttons |= (BUTTON_LEFT);
                        break;
                    case SDLK_d: Buttons |= (BUTTON_RIGHT);
                        break;

                    default:
                        break;
                }
            }
            else if(Event.type == SDL_KEYUP)
            {
                switch(Event.key.keysym.sym)
                {
                    case SDLK_a: Buttons &= ~(BUTTON_LEFT);
                        break;
                    case SDLK_d: Buttons &= ~(BUTTON_RIGHT);
                        break;

                    default:
                        break;
                }
            }
        }

        if(Buttons & BUTTON_RIGHT)
        {
            player.Pos.x += Velocity;
        }
        if(Buttons & BUTTON_LEFT)
        {
            player.Pos.x -= Velocity;
        }

        SDL_RenderClear( pRenderer );

        player.Render();

        SDL_RenderPresent( pRenderer );
        while(SDL_GetTicks() - Time < 1000.0/60);
        Time = SDL_GetTicks();
    }


    return 0;
}


I hope that helps, I don't know where your Problem is and why it doesn't move in your case
Last edited on
Wow thanks for the code! I didnt apply the changes on anything, thats why the bool didnt work... But I fixed that and now it works without being stuck :DD

Thanks guys
I'm glad i could help :)

no Problem
Topic archived. No new replies allowed.