Im trying to get the key input in SFML 2, in the SFML 1.6 im using
while (App.GetEvent(Event))
{
if (App.GetInput().IsKeyDown(sf::Key::Down)) { dir='d'; }
}
But i have no idea how to do this in SFML 2.
When you don't need to worry about real-time keyboard input, you can use an approach very similar to the SFML 1.6 code you provided. In your application's event processing loop, you can do something like this:
sf::Event event;
while (mWindow.pollEvent(event))
{
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Escape)
{
// Do something when Escape is pressed...
}
if (event.key.code == sf::Keyboard::W)
{
// Do something when W is pressed...
}
// And so on.
}
}
This type of input handling is nice when you must guarantee your application has focus when the user presses the key, as key events aren't generated otherwise. It is also great for when the key in question is pressed infrequently. You can check out an example of this from the SFML 2.0 tutorials here, under the section titled "The KeyPressed and KeyReleased events": http://sfml-dev.org/tutorials/2.0/window-events.php
On the other hand, you may actually need access to real-time keyboard input. To do this, use SFML 2.0's Keyboard class like this:
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
// 'W' is currently pressed, do something...
}
With real-time input, you are accessing the state of the input device at that particular point in time. This is handy because you do not have to lump all your key checks in your event processing loop. A disadvantage of this approach is since SFML is just reading the state of the keyboard, your event handling code can still execute if the application doesn't have focus, is minimized, etc. You can find a tutorial on all the real-time inputs here: http://sfml-dev.org/tutorials/2.0/window-inputs.php
Be careful in choosing the event processing vs. real-time approach. For a game example, consider a situation where a character fires a machine gun when the user holds down the space bar. If you handle the space bar in the event processing loop, the machine gun will incorrectly fire like a semi-automatic since there is a delay between sf::Event::KeyPressed events for the same key, even if the user is holding the key down. If you handle the space bar by checking with real-time keyboard input, the machine gun will fire repeatedly, as expected.
Related
I have been trying to make a GUI Blackjack game in C++ with Qt. However, I have hit a road block on my way. I made the game and the game logic last year in pure C++ (link below). I am trying to use the same code to build the GUI version of the game Github/Blackjack.
It's mostly done to the point that I have the cards showing up, adding the values of those cards, the dealer and the player set up.
In the C++ version I made a vector of all the players and added the dealer to the end of it, then using a for loop, I would iterate through the players to get them to play.
In Qt, I have created a widget with two buttons "Hit" and "Stand" for the player control.
"Hit" button is simple and connected the click event of the button with the hit member function of the player.
ctrl = new PlayerControl(nullptr, mainPlayer);
connect(ctrl->ui->hitButton, &QPushButton::clicked, [mainPlayer]{
mainPlayer->hit();
});
Code for iterating through the vector:
for (size_t i = 0; i < players.size(); i++)
{
if (i == playerPos - 1)
{
ctrl->setVisible(true);
//how to make the loop to pause here until the user presses the
//"Stand button", and then proceed with the rest of the loop?
}
else if (i == players.size() - 1)
dealerPlay();
else
computerPlay(players[i]);
}
I'll really appreciate any help. :)
I don't really understand the code you are showing or how it relates to the question in the title of your post. I'll just answer the question, which is:
How to make a for loop until a button is pressed
The answer is that you probably don't want to do that, because that would involve multi-threading or some kind of complicated concurrency mechanism. When you're writing a GUI, the main thread of your application usually sits in a loop waiting for event messages (like clicks and key presses) from the operating system. When it gets such a message, it is supposed to handle them quickly and then go back to waiting for the next message.
In Qt, you can handle these events by overriding functions in your QMainWindow class or by connecting Qt signals to slots.
So, instead of having a loop that iterates through each player and waits for them to make their move, you would have some long-living variables that keep track of the state of the game, and when you detect that a player has made a move (i.e. by clicking a button), you would update those variables, update any data shown on the screen, and then return from your event handler so you can handle the next event.
I am creating a game using EntityX library which handles Entity-Component-System model, and SFML.
Right now, I just have four basic components: position, direction, velocity and renderable, plus two systems: a movement system and a render system.
I will separate my question in two:
How can I make basic controls such as moving my character? With SFML, I can get the events this way:
sf::Event event;
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
window.close();
// other events ...
}
So I could create a ControllerSystem which targets entities having a Controller component, and give a reference to my window to the system so that it handles the events. But the only controllable entity would be my character so is that really efficient? Plus, it means I would have to loop through the events in my system to get KeyPressed events. Thus I can't for example do the condition to close the window except if I put it along with the events for the character.
Finally, when I get - wherever it is - a KeyPressed event and I want to do an action, how and where should I send this action so that it get realised? I mean, my controller system can deplace my character and a AI system could deplace a mob. I'm not going to write the deplacement twice in my systems, even if it's just changing direction and velocity. I could have more complex actions such as launching spells etc.
Coming to my second point, how to handle different spells/weapons? Suppose I have three keys A, B, C each one launching a totally different spell. In my Controller Component, when I would get an event saying one of these key has been pressed, I would want to launch the spell. But where should I have this spell "stored" in the code? Assuming the three spells must be coded differently as they have a different comportment, but there needs to a common pattern between them, no?
So shall spells be systems, or just normal classes out of the ECS model, having access on entity manager and components to create projectiles or I don't know what?
It remains quite blur to me and I can't really find specific enough tutorials. Thanks for your help.
I want to make snake game in console using c++, but I don't want to wait every "frame" for user input.
If i'll use cin or getch (), program will wait for player input every frame:
while (game)
{
c = getch (); //input
snake.move (c); //moving
draw (); //drawing
}
How to move snake and draw it in console and don't waiting for input every frame?
Is there any way to do that without multithreating?
Maybe something like put something in cin buffer in code instead of using console? Is it doable?
You can't use standard C++ because there is no guarantee that when the User presses a key, the key press will be acknowledged immediately. Many implementations wait for the Enter key to be pressed, then process the input buffer.
You will need an event driven system. You want the OS or hardware to notify your program that a key press event has occurred. In this kind of system, you would move the snake during the event handler.
Another method is to poll the switch status. When the key is released, you could move the snake.
All of the above solutions require platform or OS specific functionality.
At some point in my program, I want to wait for the user to either press [return] or [escape].
This is what I did:
while(1)
{
Sleep(100);
if( GetAsyncKeyState( VK_RETURN ) )
{
//do something
}
if( GetAsyncKeyState( VK_ESCAPE ) )
{
//do something else
}
}
But (only in the release build) after waiting for about 2 seconds, Windows says it's not responding, and it crashes.
What should I do?
Your application is a GUI subsystem application and its main thread must regularly pump its message queue. You are not doing that because you enter a tight loop looking for specific key state. Because you don't service your queue, the system concludes that your application is broken and ghosts your window.
Before we go on to how to do it right, your existing approach is broken in other ways. Suppose that the key is pressed and released during the Sleep(100). Then you miss that event. Or suppose your app is not in the foreground. Then it responds to key presses meant for other applications.
To solve the problem you simply need to let your normal message loop process and dispatch messages. When you get a WM_KEYDOWN message for the appropriate key you can react accordingly.
Using the message loop in the intended way not only fixes the behaviour you observe in the question, but also the issues I describe above.
What is the fastest way to determine a key press and also how to determine if a key is being held? It appears that window messaging is slow. Please provide an example of how to do so, and why it is faster than an alternative.
To be clear, this for a real time loop (a simulation) so I am looking for the fastest way to determine if a key has been pressed and also to check to see if it is being held.
GetAsyncKeyState() is what you're looking for. It reads the physical state of the keyboard, regardless of the input queue state. If the high-bit is set, then the key was down at the time of the call.
// Fetch tab key state.
SHORT tabKeyState = GetAsyncKeyState( VK_TAB );
// Test high bit - if set, key was down when GetAsyncKeyState was called.
if( ( 1 << 15 ) & tabKeyState )
{
// TAB key down...
}
Also, for the record, Windows is not a real-time operating system. If your application requires real-time precision, you may want to select another platform.
If you just want to poll the keyboard state so as to discover which keys are up/down as well as the shift/alt/ctrl state, just call GetKeyboardState (MSDN reference).
When I worked in a game studio, this is exactly how we got keyboard state for each frame. Should be applicable to your simulation code.
TL;DR: you can use GetAsyncKeyState for checking if a key is currently down, but for best application responsiveness to key presses and releases, you want to use the Win32 pipeline code near the bottom of my post.
GetAsyncKeyState works perfectly fine for determining if a key is currently down, but in terms of determining whether a key was first pressed or released and how many times this was done, GetAsyncKeyState misses keystrokes in a CPU-intensive application, even after storing the previous key state.
This was what I tried:
static const unsigned int NumberOfKeys = 256U;
bool previousKeyboardState[NumberOfKeys];
//Get the current state of each key as the application starts to ensure that keys held down beforehand are not processed as pressed keys.
for (unsigned int keyNum = 0U; keyNum < NumberOfKeys; ++keyNum)
{
previousKeyboardState[keyNum] = isKeyDown(keyNum);
}
//Works fine.
bool isKeyDown(int key)
{
return (GetAsyncKeyState(key) & (1 << 16));
}
//Misses key presses when application is bogged down.
bool isKeyFirstPressed(int key)
{
bool previousState = previousKeyboardState[key];
previousKeyboardState[key] = isKeyDown(key);
return (previousKeyboardState[key] && !previousState);
}
//Misses key releases when application is bogged down.
bool isKeyFirstReleased(int key)
{
bool previousState = previousKeyboardState[key];
previousKeyboardState[key] = isKeyDown(key);
return (!previousKeyboardState[key] && previousState);
}
//Example usage:
if (isKeyDown(VK_W))
{
//W key.
}
if (isKeyFirstReleased(VK_SNAPSHOT))
{
//Print screen.
}
GetKeyboardState is no good either, as it does not keep track of the number of key presses or releases. As Erik Philips said in his answer, these are unbuffered solutions, which are no good if you are e.g. writing a game. You would have to process all keystrokes faster than they are received.
Now, my code above works decently well, and may be suitable for many people, but I much prefer not to miss a single keystroke. I hate using applications that are unresponsive. I think the best solution for Win32 applications is to catch WM_KEYDOWN and WM_KEYUP messages in the pipeline and process them. What's nice is that WM_KEYDOWN also provides an auto-repeat count, which could be useful for applications that support entering text (e.g. chat, IDE's, etc.). This also adds a slight complication, which is mentioned in the WM_KEYDOWN documentation:
Because of the autorepeat feature, more than one WM_KEYDOWN message
may be posted before a WM_KEYUP message is posted. The previous key
state (bit 30) can be used to determine whether the WM_KEYDOWN message
indicates the first down transition or a repeated down transition.
There are also Windows keyboard hooks you could look into, but those are more difficult to use. They're good for receiving global key presses though.
Considering that all inter-windows communications are through windows messaging (keyboard events, mouse events, pretty much all events you can imagine), there isn't a lower level way to access the keyboard events (unless you write your own keyboard driver) that I know of.
DirectX still uses the windows keyboard messaging to provide DirectX programmers easier access to keyboard events.
Updated
My note about DirectX was not to use it, but that when Microsoft wanted to make an interface for programmers to use for real time games, they still wrote DirectX on top of the Windows Message Queue.
I would suggest taking a look at how to write a program that can read directly from the message queue. I believe there is a good example Code Project Windows Message Handling - Part 1.
Your two options are to either read from the message queue (buffered) or read directly from the keyboard state (as Bukes states) which means your own loop could techinically miss a keyboard event for any number of reasons.