SDL2 Key Repeat not working - c++

I'm trying to make a simple character that can move around a shoot bullets. My event handler currently looks like this:
while( SDL_PollEvent( &e ) != 0 ) {
if( e.type == SDL_QUIT ) {
quit = true;
} else if (e.type == SDL_KEYDOWN && e.key.repeat == 0) {
switch (e.key.keysym.sym) {
case SDLK_UP:
p->setVelY(-1);
break;
case SDLK_DOWN:
p->setVelY(1);
break;
case SDLK_LEFT:
p->setVelX(-1);
break;
case SDLK_RIGHT:
p->setVelX(1);
break;
case SDLK_SPACE:
cout << "Firing" << endl;
p->Fire();
break;
}
} else if (e.type == SDL_KEYUP && e.key.repeat == 0) {
...
The problem is that if I hold the space bar, I only want my character to fire once. Right now though, it fires once, delays for like a quarter second, and then rapidly continues to fire. From my understanding, the repeat flag was the way to avoid this problem? It isn't working currently however. I saw somewhere to use scancodes instead, but I still had the same problem. I could make a map manually, but I wanted to just use the built in way to avoid key repeats. I'm currently using SDL 2.0.5 on Ubuntu 16.04. I'm just starting with SDL, so any help is appreciated.
Edit: Still not working, but I see now that the KEYUP is happening immediately in the next frame after every KEYDOWN, but then a new KEYDOWN is triggered (while I am still holding the key), and so forth. So it just keeps rapidly doing keydown and up events. This doesn't even let me do my own mapping for key press / release... any ideas?

Related

SFML player movement

I have a problem with implementing player movement using SFML on macos.
Player movement works when i use this piece of code:
keyRight = event.type == Event::KeyPressed && event.key.code == sf::Keyboard::Right;
keyLeft = event.type == Event::KeyPressed && event.key.code == sf::Keyboard::Left;
keyUp = event.type == Event::KeyPressed && event.key.code == sf::Keyboard::Up;
keyDown = event.type == Event::KeyPressed && event.key.code == sf::Keyboard::Down;
but it won't work if I use this:
keyRight= sf::Keyboard::isKeyPressed(sf::Keyboard::Right);
keyLeft= sf::Keyboard::isKeyPressed(sf::Keyboard::Left);
keyUp= sf::Keyboard::isKeyPressed(sf::Keyboard::Up);
keyDown= sf::Keyboard::isKeyPressed(sf::Keyboard::Down);
I wanna use the second method because the first one seems to not work with diagonal movement (it just cant register two keys pressed at once.) Where am I making a mistake?
For every mac user with same issue I’ve managed to resolve mine. Since os catalina you have to re-give your compiler (or project) permissions to monitor inputs.
More of it here: https://en.sfml-dev.org/forums/index.php?topic=26395.0
You can either click it every time you change anything in your build or use event based movement.

Why is SDL2 providing event values that are incorrect?

I'm using SDL2 v2.0.9-3, 64 bit, with VS2019 C++. SDL_PollEvent returns events whose type field contains values that are incorrect. The returned values are consistent, but wrong, ALWAYS!
I'm running code that worked correctly with older versions of the library and VC compilers. I've tried building with VC2015 with the same result. I've also tried using the VCPKG version and compiling SDL2 from scratch. Always the same result.
Here's my code (with some debug output statements):
auto loop = true;
SDL_Event event;
long eventCounter = 0;
while (loop) {
while (SDL_PollEvent(&event)) {
std::wstringstream s;
s << "Event " << eventCounter++ << ", Type: 0x" << hex << event.type << std::endl;
OutputDebugString(s.str().c_str());
if (event.type == SDL_QUIT)
loop = false;
if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
loop = false;
break;
case SDLK_SPACE:
DoSomething();
break;
default:
break;
}
}
}
keydown returns 0x10002 (bigger value than SDL_LASTEVENT - should be 0x300) and keyup returns 0x3 (should be 0x301). All other events are also consistent but wrong. Any clues?
Thank you Cubic! Your response clued me in to the problem. I had both SDL1 and SDL2 installed in vcpkg, so, even though I was including the correct header files, my program apparently was getting the SDL1 library linked in! I removed SDL1 from vcpkg and the problem went away.
It would seem that they should be able to coexist in a package manager, but I guess not. Lesson learned, don't have both SDL1 and SDL2 installed in vcpkg!

How to clear event input after a key press?

When I press F, my controller fires – everything works fine. However, when F is pressed twice, it fires, and after processing the first event (200ms later), it fires again, and that's not what I want. I would like to clear all the input after the first firing.
My code is:
sf::Event event;
while (window.waitEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
else if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::F) //fire
{
controleur.Shot(45, 100); //this step during 200ms
}
}
}
Just use a variable "isShooting" to prevent your controler to shot.
void Controleur::Shot(int a, int b)
{
if (!this->isShooting)
{
this->isShooting = true;
// do stuff
}
}
And when your actions are finished , just set the variable to false, then you can shoot again.
EDIT: nevermind, i misunderstood your problem
You could use sf::Input::IsKeyDown from sf::Input to see wether your key is pressed or not when computing events.
Another way to do it is flushing your event queue after the end of Shot() with this code
// consumes all events in the queue
while (window.pollEvent(event));
But it is not a very good thing to do i think.

How do I write multiple GetAsyncKeyState with C++

My problem is where can I add this line of code:
if( GetKeyState(VK_F2) & 0x8000 )
I tried in different ways, but when I compile and run it and press the F1 or F2 key it executes all the functions. I want to call the F1 key functions when the key is pressed and F2 key when it is pressed. I am using Visual Studio 2010 Express.
Here is my code:
switch(uMsg)
{
case WM_INITDIALOG:
{
// do something here
break;
}
case WM_TIMER:
{
if( GetKeyState(VK_F1) & 0x8000 )
if( GetKeyState(VK_F2) & 0x8000 )
{
// do something here
}
break;
}
case WM_CLOSE:
{
// do something here
}
}
return 0;
SOLVED:) well my problem is solved after trying for sometime finally i got it the problem
was that little "break;" statement please look at the code its working flawless.
Thank you so very much for your time and help appreciated
case WM_TIMER:
{
if(GetKeyState(VK_F1) & 0x8000 )
{
MessageBoxA (NULL, TEXT ("This is a call from F1 key!"), TEXT("Test F1 key"), MB_OK );
}
//break; << this was the one that was giving me the problem
if(GetKeyState(VK_F2) & 0x8000 )
{
MessageBoxA (NULL, TEXT ("This is a call from F2 key!"), TEXT("Test F2 key"), MB_OK );
}
//if(GetKeyState(VK_F3) & 0x8000 ) << i can add multi VK_ keys here
break; // << should be here
}
case WM_CLOSE:
A couple points:
Are you sure you want to poll like this? Maybe you want to be responding to notifications when the user presses these keys (WM_KEYDOWN for example) instead of polling periodically? Your code has the problem that it can easily miss if you press & release F1 between WM_TIMERs.
You should probably be using GetKeyState, as Joachim Pileborg says. GetAsyncKeyState works on the state of the keyboard at the time of the call; GetKeyState works on the state of the keyboard when the current message was sent. This tends to keep things more tightly synchronized. That said, if you're polling in WM_TIMER, it probably doesn't matter so much.
You are only checking if the return value is non-zero, which is not how this function works. The return value is a bitmask. From the documentation:
If the high-order bit is 1, the key is down; otherwise, it is up.
If the low-order bit is 1, the key is toggled. A key, such as the CAPS LOCK key, is toggled if it is turned on. The key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled.
Thus, to check for F1:
if( GetKeyState(VK_F1) & 0x8000 )
{
...
}

How to identify shift/ctrl keys were pressed in the linux world (without using GL and X11/XKBlib.h) in C++?

I used to do in windows:
SHORT key1 = ::GetKeyState(VK_LSHIFT)& 0xF0;
SHORT key2 = ::GetKeyState(VK_RSHIFT)& 0xF0;
SHORT key3 = ::GetKeyState(VK_LCONTROL)& 0xF0;
SHORT key4 = ::GetKeyState(VK_RCONTROL)& 0xF0;
bShift = (key1 != 0) || (key2 != 0);
bCtrl = (key3 != 0) || (key4 != 0);
How to detect if the shift/ctrl keys were pressed in the linux world?
Without using GL(it can be pressed not in the graphic window..) or X11..
Is there something general to retrieve it directly form the OS?
Thanks,
Vladimir.
I would do this using Linux Input API. Take a look at Youarefunny's answer here to see how you can check current key state (pressed or released).
Such check may take noticeable amount of time especially if you need to call it very often. So once you determine the initial state you may monitor for changes by reading input events from device file, like this (I skipped error-checking for brevity):
#include <stdio.h>
#include <linux/input.h>
int main (int argc, char *argv[])
{
struct input_event ev;
FILE *kbd = fopen("/dev/input/by-id/usb-Dell_Dell_QuietKey_Keyboard-event-kbd", "r");
while (fread(&ev, sizeof(ev), 1, kbd) == 1)
{
if (ev.type == EV_KEY && (ev.code == KEY_LEFTSHIFT || ev.code == KEY_RIGHTSHIFT))
{
switch (ev.value)
{
case 0: printf("Shift released\n"); break;
case 1: printf("Shift pressed\n"); break;
case 2: printf("Shift repeated\n"); break;
default: break;
}
}
// similarly for KEY_LEFTCTRL, KEY_RIGHTCTRL, etc.
}
fclose(kbd);
return 0;
}
Note that reading /dev/input/* files will probably require root privileges (unless you run chmod before) since default access mode is 640 and the files belong to root.