SDL_KEYDOWN Not Recognizing Some Keystrokes (A-Z, 0-9 & Space) - c++

I'm rewriting some SDL things for practice from my Linux/Codeblocks setup to my Win7/VisStudio setup and I've hit an odd road block. SDL recognizes some keystrokes but not others. It reads the arrow keys, shift, alt, ctrl and a handful of others but it doesn't recognize a majority of keys, a-z 0-9, Space among others.
Neither:
SDL_GetScancodeName(event->key.keysym.scancode)
nor
SDL_GetKeyName(event->key.keysym.sym)
print any response from the problematic keys with a printf but responds fine for the working keys.
I double checked that my keyboard was set to English and I also tried a USB keyboard as opposed to my usual PS2 board just in case for some reason those were interfering but no result.
I've tried to find similar questions but I can't seem to find any that have specific keystroke problems like this.
Visual Studio 2017. SDL2, using libsdl.org's Dev libs. x86 if it matters.
EDIT:
I treated the symptoms but not the fever. If anyone could help I would like to have a better understanding for what went wrong and some better solutions.
I was trying to detect when no keys were being pressed, my original code was to follow:
if (e.type == SDL_KEYDOWN)
with an:
else
for when no keys were pressed. This worked fine except for the problem keys.
I'm curious as to why this only affected some keys and possibly an alternative to detecting when no keys are pressed.
Here's an excerpt of the code I was using:
while (SDL_PollEvent(&e) != 0)
{
if (e.type == SDL_KEYDOWN)
{
switch (e.key.keysym.sym)
{
case SDLK_UP:
keyPressed = "Up";
printf("Keypress test: Up\n");
break;
case SDLK_SPACE:
keyPressed = "Space";
printf("Keypress test: Space\n");
break;
default:
break;
}
}
else
{
keyPressed = "None";
}
}
With the else I can correctly return the string keyPressed for SDLK_UP but not SDLK_SPACE. In this case both printf in the switch occur so I definitely step into it but the else seems to overwrite the string. Removing the else makes both work perfectly but then I can't detect when no keys are pressed.
I assume there is just something about SDLK_SPACE A-Z and 0-9 that I don't understand that causes the program to step into the else.
I quickly made a git to post the code:
https://github.com/TorsvikVonClemson/AloeFoil00
It should display 5 shapes and a test rectangle. One for no key presses, on for each arrow key and the rect while pressing space.
Apologies if its sloppy, I haven't quite figured how to post straight from VS17.

Although this is a question from four years ago, I still want to provide my answer to help others in need.
// In your main loop
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
std::cout << "I want quit game\n"; // Working
break;
case SDLK_p:
std::cout << "I want pause game\n"; // Not working
break;
default:
break;
}
}
break;
case SDL_TEXTINPUT:
std::cout << event.text.text;
break;
default:
break;
}
}
If you check event type SDL_TEXTINPUT, you will find 0-9, a-z, etc. just go into case SDL_TEXTINPUT.
The soluction is SDL_StopTextInput, It's obvious:
// In your main loop
SDL_StopTextInput(); // Stop text input first.
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
std::cout << "I want quit game\n"; // Working
break;
case SDLK_p:
std::cout << "I want pause game\n"; // Working now🎉🎉🎉
break;
default:
break;
}
}
break;
case SDL_TEXTINPUT:
std::cout << event.text.text; // bye bye text input event 🎃
break;
default:
break;
}
}
If you want to reopen text input, just use SDL_StartTextInput.
Thanks #HolyBlackCat comment :)

Related

How do i make the program accept the second input before the first one while keeping the delay?

If i press A then B quickly, i would like the program to display
Case B before
Case A while still keeping the delay on Case A
but no matter how i do it after pressing A then B the program still waits 2 seconds for Case A to finish.
What should i do?
Also i apologize for my poor english skills.
if (_kbhit()){
switch (getch()){
case 'a':
Sleep(2000);
cout << "AAAAA";
break;
case 'b':
cout << "BBBBB";
break;
}
}

The input keys for Linux aren't manageable, how can I go around it in C++?

I am trying to follow a snake tutorial game using C++. However, it seems they were using some windows libraries and in my case I am compiling it on Linux. The problem is in my Input() method, I tried changing it with a recommended code I found on here, but that did not quite worked for me. Is there a way to go around this or any recommendation? Thanks.
#include <iostream>
#include <stdio.h>
#include <ncurses.h>
#include <unistd.h>
.....
//Get the key input inorder to move the snake around
void Input() {
//Tried this from the stackoverlow recommendations, did not work for my situation
if (getch() == '\033') {
getch();
switch(getch()) { // the real value
case 'A':
// code for arrow up
direction = UP;
break;
case 'B':
// code for arrow down
direction = DOWN;
break;
case 'C':
// code for arrow right
direction = RIGHT;
break;
case 'D':
// code for arrow left
direction = LEFT;
break;
case 'Q':
gameOver = true;
break;
default:
break;
}
}
}
.....
The issue I am having with is that linux does not accept the kbhit() which what the snake game tutorial was using, so I tried to modify it with what I have above, however it does not move the snake.
This case 'A': expects capital letter to be typed. Which is not the case :) normally. So:
switch(getch()) { // the real value
case 'A': // either capital
case 'a': // or low case
// code for arrow up
direction = UP;
break;

SDL_KEYDOWN not working, got code 771 instead

Here is my code:
void MainGame::ProcessInput()
{SDL_Event Evnt;
while (SDL_PollEvent(&Evnt));
{switch(Evnt.type)
{case SDL_QUIT: {_GameState = GameState::EXIT;}
break;
case SDL_MOUSEMOTION: {}
break;
case SDL_KEYDOWN: {_InputManager.PressedKey(Evnt.key.keysym.scancode);}
break;
case SDL_KEYUP: {_InputManager.ReleasedKey(Evnt.key.keysym.scancode);}
break;
case 771: {std::cout << "Info1 = " << Evnt.key.keysym.scancode << std::endl;
_InputManager.PressedKey(Evnt.key.keysym.scancode); }
break;
}
}
}
So in this code, if I push up, down, left and right arrows, KEYDOWN is working properly. If I hit any letters on my keyboard, it will only return code 771. Here I made a test including 771 in my switch. When I hit letters, it does go to 771 and print a silly number like 30445778. And this number change every time I re-run the program. Man what's going on here?!? please help me
The problem you are facing is an additional ; after your while condition. Citing SDL wiki, your code should be written as follows:
while (1) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
/* handle your event here */
}
/* do some other stuff here -- draw your app, etc. */
}
Note that there's no semicolon after while.
However, although the code you've written does not do what you want it to do, it's still correct from C++ point of view.
This line:
while (SDL_PollEvent(&Evnt));
will enter a loop that will iterate up until the point SDL_PollEvent returns 0, while doing nothing.
After that, your switch statement will only run once, processing the last polled event (disregarding its type). In the same time, your switch statement is not ready to handle most of the event types.

cvWaitkey for for increasing values

I have a program written in c++ with opencv which should calculate a disparity map. Now I want to play around with the values wihin a while loop looking like this:
while(true) {
cv::StereoSGBM disparity(minDISP,numDISP,SADWindowSize, disparitySmoothness1, disparitySmoothness2);
cv::Mat disparityMap, disparityNorm;
disparity(undistortedLeft[1], undistortedRight[1], disparityMap);
disparityMap*=(1/16.0);
cv::normalize(disparityMap, disparityNorm, 0,255, cv::NORM_MINMAX, CV_8U);
cv::imshow("disparityMap", disparityNorm);
key = cv::waitKey(0);
switch(char(key)) {
case 'n': numDISP+=16;
case 'm': minDISP+=1;
case 's': SADWindowSize+=2;
case 'q': break;
}
}
key is declared as char key;
the problem I have now is the following.
If I press n everything is working well, if I press m the program increases n and s as well. The same if I press s. If I press q nothing is happening.
I also tried it using if else statements and it was the same result.
Is this because of key saves the buttons pressed before in any way?
Maybe someone of you can help me with this.
Maybe there is a trouble with the syntax of switch-case. Did you leave intentionally break statement in the end of each case?
switch(char(key))
{
case 'n':
numDISP+=16;
break;
case 'm':
minDISP+=1;
break;
case 's':
SADWindowSize+=2;
break;
case 'q':
// do nothing
break;
}
to work on all systems you have not only use break statement but also to do this:
int key;
key = waitKey() & 255;
Note that I am not using waitKey(0) since it gives 0 ms to draw your image. In practice waitKey will take time to draw it still.

simple cross-platform c++ GUI console -- how to?

I'm writing a game and I'm wound up in needing a console for simple text input; filenames and simple values.
Using SDL, my console looks the following at it's simplest:
class Console
{
public:
typedef std::list<String> InputList;
enum Result
{
NOTHING = 0,
ENTERED,
ESCAPED
};
static const String& GetInput() { return input; }
static Result Query(SDLKey lastKey)
{
if(lastResult == ENTERED || lastResult == ESCAPED)
{
input.clear();
}
switch (lastKey)
{
case SDLK_a:
case SDLK_b:
case SDLK_c:
case SDLK_d:
case SDLK_e:
case SDLK_f:
case SDLK_g:
case SDLK_h:
case SDLK_i:
case SDLK_j:
case SDLK_k:
case SDLK_l:
case SDLK_m:
case SDLK_n:
case SDLK_o:
case SDLK_p:
case SDLK_q:
case SDLK_r:
case SDLK_s:
case SDLK_t:
case SDLK_u:
case SDLK_v:
case SDLK_w:
case SDLK_x:
case SDLK_y:
case SDLK_z:
case SDLK_0:
case SDLK_1:
case SDLK_2:
case SDLK_3:
case SDLK_4:
case SDLK_5:
case SDLK_6:
case SDLK_7:
case SDLK_8:
case SDLK_9:
case SDLK_SLASH:
case SDLK_BACKSLASH:
case SDLK_PERIOD:
case SDLK_COMMA:
case SDLK_SPACE:
case SDLK_UNDERSCORE:
case SDLK_MINUS:
input += static_cast<char> (lastKey);
lastResult = NOTHING;
break;
case SDLK_RETURN:
lastResult = ENTERED;
break;
case SDLK_ESCAPE:
lastResult = ESCAPED;
break;
}
return lastResult;
}
protected:
static Result lastResult;
static String input;
};
This would be called from the application's main event loop, if the console is active and the last event was a keypress, then the result of the input is processed at a state where it's necessary.
Of course, it looks incredibly awkward... What's a better way to implement a simple console that can be easily rendered in my game's window? (Not going anywhere near to highly unportable solutions like having to reroute std::cout or writing code to bring up a UNIX console etc.)
One suggestion I would offer is to use if statements instead of a switch in this case:
if(lastKey == SDLK_RETURN)
lastResult = ENTERED;
else if(lastKey == SDLK_ESCAPE)
lastResult = ESCAPED;
else if(lastKey >= SDLK_SPACE && lastKey <= SDLK_z)
{
input += static_cast<char> (lastKey);
lastResult = NOTHING;
}
I took some liberties and included some characters that you didn't have in your code above, such as the ampersand, quotes, parentheses, brackets, etc. If you don't want those keys, you can add a few more if statements to break it down a bit more.
This assumes that the enum for the keys doesn't change a lot. If it does change a lot you may be better off with what you had.