If I understand you correctly, the units of the velocity are in pixels, then.
Well, euhm, yeah, you coded it like that :)
A quick tour through your own code:
if (e.jaxis.value < -CONTROLLER_DEAD_ZONE)
{
pVelX = -1;
Here you set speed to 1 unit (there are other places too, I just picked one at random).
playerBase.x+= pVelX;
if(playerBase.x < 0 || (playerBase.x + playerBase.w > 1024)) {
playerBase.x-= pVelX;
}
Here you update position with 1 unit velocity, and then compare against a well-known horizontal screen-width. From this I concluded you work in pixel units.
[I added the curly brackets here. I used to program like you, leaving them out if you could, but I found it was too confusing and error-prone, so I switched to always including them.]
There is nothing wrong with using pixels as unit of position and velocity. The biggest problem is that you can't display a pixel at (for example) position 34.6, it has to be either 34 or 35, ie units, with SDL2 (without GPU, but I'll come to that later).
In your case, you feel the player character is running too fast. That can be solved in 3 ways
- Reduce speed to some fraction (what I proposed), by far the simplest.
- Enlarge the size of the playing area. Instead of 1024 we could use 2048 as width. It takes longer for the player character to reach the other side with the current speed. Unfortunately, that does not come with a new monitor that is, say, twice as wide and high. The answer to that is that you scale the bigger playing area back to your current screensize. However, 2048 wide at speed 1 is equivalent to 1024 at speed 0.5, so this is just another form of "reduce speed".
- Update the position of the player character less often. If you skip updating the position 50% of the time (ie call "movePlayer" once every 2 iterations), the player character moves 1 pixel every 2 iterations, instead of 1 pixel every iteration. It thus seems to move twice as slow. This solution is however not so flexible. It works well enough for simple cases like 50% or 75%, but imagine you want 7/12th speed, so update position every 7 out of 12 iterations. This gets horribly complicated, while changing speed to a fraction can manage the same thing easily.
That is why you can't have a decimal speed.
As you will find out, "cannot" hardly exists in software. If you want it badly enough, almost anything can be done. The normal breaking point is "it's a bad idea to want this", because you yourself won't be able to understand what happens, or why.
For fractional speed however, you're well within safety limits, it just takes a simple conversion.
int posX = ...;
int posY = ...;
int velX = ...; // Assign units
int velY = ...;
...
posX += velX;
posY += velY;
...
SDL_Rect dst_rect;
dst_rect.x = posX;
dst_rect.y = posY;
dst_rect.w = ...
dst_rect.h = ...
SDL_BlitSurface(this->image, nullptr, this->surface, &dst_rect);
Your current code likely mostly looks like this. You have an integer posX/Y, and an integer velX/Y, you update position with the velocity, and then blit the player character image to the window surface. As you can see, SDL_Rect is the data structure to give the position at the screen. Its definition is described at https://wiki.libsdl.org/SDL_Rect
As you can see, "x" and "y" of SDL_Rect are "int", SDL_BlitSurface can only handle unit positions, not fractions.
That's not a problem, we can still have floating point speeds and positions:
double posX = ...;
double posY = ...;
double velX = ...; // Assign fractions
double velY = ...;
...
posX += velX;
posY += velY;
...
SDL_Rect dst_rect;
dst_rect.x = posX; // <-- here, double to int conversion takes place, it rounds towards zero.
dst_rect.y = posY;
dst_rect.w = ...
dst_rect.h = ...
SDL_BlitSurface(this->image, nullptr, this->surface, &dst_rect);
I only changed the type of position and velocities. (There is also "float" as type. It is also a floating point, but it's smaller and computes slightly faster. neither is relevant for your application currently.) Not shown is that you should also assign a fraction to the speed, or it has no effect.
You can compile this, and it will work. Now you may wonder, what if posX == 34.6, what happens then? The answer is that the C++ compiler converts your double posX value to an SDL_Rect integer x coordinate by rounding towards zero. 34.6 becomes 34, -1.999 becomes -1. If you want 'normal' rounding instead, for positive numbers, add 0.5, ie "dst_rect.x = posX + 0.5;". 34.6 + 0.5 = 35.1, which rounded towards zero, becomes 35. For negative numbers, this trick likely fails (if you like math puzzles, it can be fun to figure out such things), but since your positions are non-negative anyway, it doesn't matter much.
How can I use the GPU? Does SDL 2 have functions for that?
The GPU is a graphics monster, It can draw filled triangles incredibly quickly. It can draw 'pixels' at every position, including at fractional positions. Your screen however cannot display such pixels directly, so the GPU uses a trick known as anti-aliasing to do it. Basically, it splits your pixel at 34.6 in two parts, and draws 0.4 part of it at position 34, and 0.6 part of it at position 35. Our eyes and brain then merge both pixels again, and we perceive it as a single pixel again.
SDL2 does have GPU support, and I think it already uses the GPU internally, for its better performance. I started looking at how to use the GPU with SDL2 myself a few days ago, and while I found a tutorial for it ( http://lazyfoo.net/tutorials/SDL/index.php lesson 7 and further), I am not so happy with it, and decided not to use it myself.
For you, I'd advice to stick with SDL2 as you have it now. Given the kind of questions and problems you post here, switching to a GPU is a not-smart move. You'll get loads of additional problems, and no useful benefit from it, since you can easily use fractional positions and speeds with your current program, as I showed above.
Instead, try to slow the character down a bit, then extend the program so it becomes a fun game :)