SDL poll event inverting w with z and viceversa - c++

I'm doing a simple camera movement with the WASD keys:
switch (k) {
case SDLK_w:
this->up = true;
break;
case SDLK_s:
this->down = true;
break;
case SDLK_a:
this->left = true;
break;
case SDLK_d:
this->right = true;
break;
default:
break;
}
It's pretty self explanatory. But when I press w it simply doesn't detect that button pressing. If I press a or d or s it works. The cool thing about it is that if I just change SDLK_w to any other button (let's say SDLK_q) keeping the same exact code, it just works. It's not an issue of how I handle this->up because even if I print something on the screen inside the case SDLK_w: and I press w it doesn't print anything.
PS: obviously my w key is not broken otherwise I would have had trouble writing this post doWn.
What's wrong with w?

It could depend on the type of keyboard you are using, actually your W and Z key could be inversed depending on your keyboard layout. I recommand you try ALT+SHIFT.

Do not use SDLK_w for this as it gives you whatever key actually gives you a W letter, whereas what you want is the key that you'd expect at the W position regardless of the layout, you do this by using scancodes, in this case SDL_SCANCODE_W.

Related

SDL2 - Keyboard events for character movement have unexpected behavior

I'm currently working on a small game and recently tried to introduce smoother movements for the player using velocity variables: when a key is pressed, the velocity is increased in the appropriate direction; and, when the same key is released, the velocity goes back to 0. However, when moving on the y axis, the character won't stop moving as it should when the key is released, which is weird considering everything works as intended when moving on the x axis.
Here's the function responsible for keyboard events:
void Game::processEvent(){
switch(Engine::Instance().event.type){
case SDL_KEYDOWN:
switch(Engine::Instance().event.key.keysym.sym){
case SDLK_LEFT: Entities[0]->vx=-0.0001f; break; //Entities is a vector filled with pointers to objects like enemies, the player etc..
case SDLK_RIGHT: Entities[0]->vx=0.0001f; break; //This is how velocity is set
case SDLK_UP: Entities[0]->vy=-0.0001f; break;
case SDLK_DOWN: Entities[0]->vy=0.0001f; break;
}
break;
case SDL_KEYUP:
switch(Engine::Instance().event.key.keysym.sym){ //Reset velocity in a direction only if the player was previously moving in that direction
case SDLK_LEFT: if(Entities[0]->vx>0) Entities[0]->vx=0.0f; break;
case SDLK_RIGHT: if(Entities[0]->vx<0) Entities[0]->vx=0.0f; break;
case SDLK_UP: if(Entities[0]->vy<0) Entities[0]->vy=0.0f; break;
case SDLK_DOWN: if (Entities[0]->vy>0) Entities[0]->vy=0.0f; break;
}
break;
default:
break;
}
}
And the function used to update objects' position:
void Entity::updatePos(){
x += vx; //Velocity is added to the sprite's coords
y += vy;
dstrect = {static_cast<int>(x*800), static_cast<int>(y*800), static_cast<int>(w*800), static_ cast<int>(h*800)}; //Workaround to make sprites' coords and dimensions always relative to the screen, not great I know XD that's why x and y are floats between 0 and 1.
}
I've been scratching my head for a while as to why vy isn't reset properly when vx is. Any idea?
EDIT: Removing the 'if' statements before setting the velocity to 0 solved the problem, guess it was unnecessary in the first place.
Which give us instead:
case SDL_KEYUP:
switch(Engine::Instance().event.key.keysym.sym){
case SDLK_LEFT: Entities[0]->vx=0; break;
case SDLK_RIGHT: Entities[0]->vx=0; break;
case SDLK_UP: Entities[0]->vy=0; break;
case SDLK_DOWN: Entities[0]->vy=0; break;
default: break;
(I can't flag this as the answer yet, sorry 'bout that)

How to take multiple key input in wxwidgets?

As I am making a game in Wxwidgets. The place where i am stuck is to jump Mario and take the input when the Mario is jumping in the air. Let me make you clear - When an player press space to jump vertical
the loop to jump Mario will run but when the player presses the "d" key to move forward while jumping it should jump forward.... i also need your help to take two input at the same time like in game when we press shift and "w" the player will walk faster but when we press only "w" key the player will walk slow..
void MyFrame :: OnChar(wxKeyEvent& event){
wxChar uc = event.GetUnicodeKey();
switch ( uc )
{
case 97:
tempx = x;
x = x - 5;
Check(x);
FindGround(x);
CheckForNextMove(x,y,CurrentGroundX,CurrentGroundY,PreviousGroundX,PreviousGroundY,NextGroundX,NextGroundY);
Refresh();
break;
case 100:
tempx =x;
x = x + 5;
Check(x);
FindGround(x);
CheckForNextMove(x,y,CurrentGroundX,CurrentGroundY,PreviousGroundX,PreviousGroundY,NextGroundX,NextGroundY);
Refresh();
break;
case 32:
tempy = y;
for(int i=0;i<=10;i++){
check = true;
tempx = x;
Sleep(1);
y=y-7;
x=x+5;
Check(x);
FindGround(x);
CheckForNextMove(x,y,CurrentGroundX,CurrentGroundY,PreviousGroundX,PreviousGroundY,NextGroundX,NextGroundY);
Update();
Refresh();
}
for(int j=0;j<=10;j++){
check = true;
tempx = x;
Sleep(1);
y=y+7;
x=x+5;
Check(x);
FindGround(x);
CheckForNextMove(x,y,CurrentGroundX,CurrentGroundY,PreviousGroundX,PreviousGroundY,NextGroundX,NextGroundY);
Update();
Refresh();
if(stop){ stop = false; break; }
}
check = false;
Update();
Refresh();
break;
}
event.Skip();
}
here is the code where pressing space bar will make mario to jump in parabolic path but i wanted to make it more professional. I want mario to jump in parabolic when we press two key at the same time i.e. (when I press vertical jump key and right motion key then it will have to jump in right direction in parabolic path.
You need to change your program control flow to only remember that a key was pressed or released in wxEVT_KEY_{DOWN,UP} handlers instead of trying to do everything in wxEVT_CHAR handler.
Also, you definitely shouldn't ever have any calls to Sleep() or long-running loops in the event handlers, so whenever you think about putting them there, you can be sure that you're doing something wrong.

OpenGL:How to make "Feet" go up and down?

I'm writing code that draws a polygon and gives it two feet, walks from the right until it gets to the middle, does a flip, and then lands and walks to the left. I'm having a lot of trouble figuring out how to animate his feet. All I want to do is make one go up, then come down, then the other go up, and then come down. I know all I have to do is change the Y values of his feet, but I can't figure out how.
My professor talks about key frames a lot, but wouldn't every step that my "Polyman" would take be a key frame leading to infinite amount of cases? Here is my timer function...
void TimerFunction(int value) //float plx = 7.0, ply=-3.0, linet=0.00;
{
switch(frame)
{
case 1:
dx-=0.15;
plx-=0.15; //dx=polygon, plx = one foot, pl2x = other foot
pl2x-=0.15;
if(dx<=0.0)
{
plx=0.0; //this case makes polyman walk to the middle
dx=0.0;
pl2x=0.0;
frame=2;
}
break;
case 2:
dxt+=0.05;
if (dxt<=-0.00) //this is a triangle I translate over polyman appearing as if he's opening his mouth
{
dxt=0.00;
frame=3;
}
break;
case 3:
dy+=0.2;
theta+=10.0;
thetat+=10.0;
dyt+=0.2; //this is the flip with polyman's mouth open
ply+=0.2;
pl2y+=0.2;
linet2+=10.0;
linet+=10.0;
if(dy>5.0 || theta>360.00)
{
dy=5.0;
dyt=5.0;
ply=5.0;
pl2y=5.0;
linet2=0.0;
theta=0.0;
thetat=0.0;
linet=0.0;
frame=4;
}
break;
case 4:
dy-=0.2;
dyt-=0.2;
ply-=0.2;
pl2y-=0.2;
if(dy<=-3.0) //this is polyman coming back down to earth
{
dy=-3.0;
dyt=-3.0;
ply=-3.0;
pl2y=-3.0;
frame=5;
}
break;
case 5:
dxt-=0.2;
if (dxt<-3)
{ //this is the triangle slowly translating left appearing as if he's closing his mouth
dxt-=3.0;
}
if (dxt<=-8)
{
dxt = -8;
frame = 6;
}
break;
case 6:
dx-= 0.15;
plx-= 0.15;
pl2x-=0.15; //this is polyman walking off the stage to the left
if(dx<=-8.0)
{
dx=-8.0;
plx=-8.0;
pl2x=-8.0;
}
break;
}
glutPostRedisplay();
glutTimerFunc(30, TimerFunction, 1);
}
All variables that are used in my timerfunction are global. Thanks for your time! If you need any more of my code just ask and i'll append.

SDL collision handling

I have an instance where a SDL_Rect is inside of a big SDL_Rect and i need it to make it so it cannot leave that rect but can still move. The movement of the little rect needs to be like board game movement where you click the button once and it moves a certain cords here is my code:
if( event.type == SDL_KEYDOWN) {
switch( event.key.keysym.sym ) {
case SDLK_UP:
yVel -= 10;
if (!check_collision(box,Cont))
{
std::cout<<"in the water"<<std::endl;
box.y -= yVel - 10;
}
break;
case SDLK_DOWN:
if (!check_collision(box,Cont))
{
std::cout<<"in the water"<<std::endl;
box.y -= yVel + 20;
}
else
{
yVel += 10;
}
break;
case SDLK_LEFT:
xVel -= 10;
if (!check_collision(box,Cont))
{
std::cout<<"in the water"<<std::endl;
}
break;
case SDLK_RIGHT:
xVel += 10;
if (!check_collision(box,Cont))
{
std::cout<<"in the water"<<std::endl;
}
break;
case SDLK_1:
return 2;
break;
}
}
You have inconsistencies in your SDLK_DOWN and the rest of your inputs - no velocity change happens if there are no collisions.
Your input code is changing coordinates, it shouldn't be like that. Make your input code manage the "intent", and have a game loop apply velocity to the object and to the collision detection.
Also, your collision checks should check if I'm at position and I move of delta, will I collide? If I do collide, what's the collision reaction? Do you want the entity to "slide" on collisions or simply stop as soon as a collision is detected?
Considering you are doing a board game, you shouldn't even have to do collision detection. Represent your board as a graph of possible positions your unit can be, translate mouse clicks into board coordinates and calculate the shortest path (use the A* algorithm) between your current position and your destination; invalid clicks (out of bounds) shouldn't translate into movement commands.

180 to -180 motion in opengl c++?

i'm using a glutTimerFunc(...) to achieve motion of robot arm, my problem is left side 0 degree to 90 is easily done,
when i try 0 to -90 degree, the arm is not stoping? i tried various methods, but all falied, can you suggest better options?
here's my timer function, void myTimerFunc(int var)
{
switch(var)
{
case 1: if(shoulder>=90)
stop=1;
if(!stop)
{
shoulder = (shoulder + 5);
glutPostRedisplay();
glutTimerFunc(100,myTimerFunc,1);
break;
}
if(shoulder<=0)
stop1=1;
if(!stop1)
{
shoulder = (shoulder - 5);
glutPostRedisplay();
glutTimerFunc(100,myTimerFunc,1);
break;
}
case 2: if(shoulder>=360)
stop2=1;
if(!stop2)
{
shoulder = (shoulder - 5);
glutPostRedisplay();
glutTimerFunc(100,myTimerFunc,2);
break;
}
// here robot arm is not stopping...........
if(shoulder<=270)
stop2 = 0;
stop3 = 1;
if(!stop3)
{
shoulder = (shoulder + 5);
glutPostRedisplay();
glutTimerFunc(100,myTimerFunc,2);
break;
}
default:break;
}
}
i'm calling this from keyboard function.......
void keyboard (unsigned char key, int x, int y)
{
switch (key)
{
case 's':
glutTimerFunc(100,myTimerFunc,1);
break;
glutTimerFunc(100,myTimerFunc,2);
break;
Looks to me like you're confused about how to treat angles. Are you using a [0, 360] scale for a full circle or [-180, +180]? I see a check against 270 in your code, but your prose mentions -90. Yes, they're "the same", but if it's not working perhaps some confusion has crept into your code.
If you're going with [-180, +180], with zero degrees as the neutral position for your robot arm, perhaps you can take advantage of symmetry and use the absolute value function. You only have to code it once that way. If it's successful for [0, +90] it'll also work for [-90, 0] as well.
It also seems to me that you're not taking advantage of object-oriented thinking. This method has motion and timing and graphical refresh all in the same method. Writing smaller methods and unit testing each one to be sure that it works is a better approach. It's called "decomposition". The moment you say "it's a big method", it suggests to me that perhaps it's too big and needs to be refactored.