SFML player movement - sfml

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.

Related

How to get persistent input in SDL2 c++

So I noticed that when getting input with SDL_GetKeyboardState(NULL), when holding a specific button, it is going to first write outlets say a, and after 1 second its gonna continue aaaaaaaa normally. I want to when I hold the button a that it automatically goes aaaaaa.
Here is a video if you don't understand my poor explanations:
https://streamable.com/oub0w3
There is a delay between it writes out first a, and writing out aaaaa about 1 second. How can I change that? (I want there to be no delay)
Here is my code:
while (gameRunning) {
SDL_Event event;
const Uint8* keystates = SDL_GetKeyboardState(NULL);
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
gameRunning = false;
}
if (keystates[SDL_SCANCODE_W]) {
entities[0].setY(entities[0].getY() - 1);
}
if (keystates[SDL_SCANCODE_S]) {
entities[0].setY(entities[0].getY() + 1);
}
if (keystates[SDL_SCANCODE_A]) {
entities[0].setX(entities[0].getX() - 1);
}
if (keystates[SDL_SCANCODE_D]) {
entities[0].setX(entities[0].getX() + 1);
}
}
You're misusing SDL_GetKeyboardState(nullptr).
It should be used in the main loop, not in the event loop:
while (gameRunning)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
gameRunning = false;
}
const std::uint8_t *keystates = SDL_GetKeyboardState(nullptr);
if (keystates[SDL_SCANCODE_W])
entities[0].setY(entities[0].getY() - 1);
if (keystates[SDL_SCANCODE_S])
entities[0].setY(entities[0].getY() + 1);
// An so on...
}
If you want the repetition to start immediately, you need to make your own implementation of the repeating letters.
The additional "a" characters you receive as events are (I assume) generated by the operating system, so unless you have some settings on your OS you can change to make repetition start immediately, you need your program to do it.
(I am assuming SDL is not the one generating these characters, which could be a possibility)
To do this, you would make a system check the amount of time elapsed and kept track of how long keys are being pressed, and outputting "key" events that it generated itself, much like the OS is doing.

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!

SDL2 Key Repeat not working

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?

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 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.