SDL Text Input returning white squares - c++

I created an event class and wanted to get text with it. Unfortunately the text isn't reading correctly...
I've set it up so that all text that is gotten is output to the command line when a new key is input, but it obviously isn't working.
Here's my "EventManager" code for my update function:
void EventManager::update(){
while(SDL_PollEvent(&e)){
switch(e.type){
case SDL_QUIT:
running = false;
break;
case SDL_MOUSEBUTTONDOWN:
mousePressed = true;
break;
case SDL_KEYDOWN:
if(shouldCollectText && e.key.keysym.sym == SDLK_BACKSPACE && currentCollectedText.length() > 0){
currentCollectedText.pop_back();
}else if(shouldCollectText && e.key.keysym.sym != SDLK_BACKSPACE){
currentCollectedText += e.text.text; //The problem
std::cout << currentCollectedText << std::endl;
}
}
}
}
I followed the Lazy Foo tutorials, and I can't find the problem.
Some other things to note:
I start text input in my "main.cpp" class:
int main( int argc, char *argv[] ) {
Game *game = new Game();
game->init();
SDL_StartTextInput();
while(game->isRunning()){
game->handleEvents();
game->update();
game->render();
}
game->close();
SDL_StopTextInput();
return 0;
}
I create some of my variables in "EventManager.h":
bool shouldCollectText;
std::string currentCollectedText;
And define them in an "init()" function:
shouldCollectText = false;
currentCollectedText = "";

Your problem is that you are using the wrong event type. Take a second look at Lazy Foo's tutorial and here:
TextInputEvent
e.text.text is reserved for Text Input events and nothing else. Being SDL_Event an union of structures, overlaps may occur in the used memory. That is exactly what you see in the terminal output.
Remove the SDL_KEYDOWN event and try this instead:
case SDL_TEXTINPUT:
currentCollectedText += e.text.text;
break;
I'm not sure about std::cout << currentCollectedText << std::endl; though. It depends on when you want to get output of the text content.
If you want to use SDL_KEYDOWN you will have to access the keysym tables and maybe calculate to which letter they correspond and print those out. I would say, that approach is more complicated for what you want to achieve.
So in conclusion e.text.text will only work if e.type has the SDL_TEXTINPUT value as event. With all the other settings in your code that event should be triggered and may get the text you type in.
So your complete example could look like this:
void EventManager::update(){
while(SDL_PollEvent(&e)){
switch(e.type){
case SDL_QUIT:
running = false;
break;
case SDL_MOUSEBUTTONDOWN:
mousePressed = true;
break;
case SDL_TEXTINPUT:
if(shouldCollectText && currentCollectedText.length() > 0){
currentCollectedText.pop_back();
}else if(shouldCollectText) {
currentCollectedText += e.text.text; //The problem
std::cout << currentCollectedText << std::endl;
}
break;
default: break;
}
}
}

Related

SDL_PollEvents - Part of the code that are executed without key being pressed. Situation not desired

My program has to quit when I press ESC key. Even not pressing the key, my program exit automatically after some seconds of execution. No errors or notable exceptions found during the execution and the code seems to be correct.
void pollE(bool& _isRunning, build *actionBuild,finance *money,squareId* slotId,squareId map[][MAP_SLOTS_H]) {
while (SDL_PollEvent(&event)) {
// MOUSE
switch (event.button.button) {
case SDL_BUTTON_LEFT:
if (event.button.state == SDL_RELEASED) {
actionBuild->construct(ID_CASA, map);
}
if (event.button.state == SDL_PRESSED) {
}
break;
case SDL_BUTTON_RIGHT:
if (event.button.state == SDL_RELEASED) {
// test
debugPrintMap(map);
}
if (event.button.state == SDL_PRESSED) {
}
break;
}
// KEYBOARD
switch (event.key.keysym.sym) { // ---------------------------- HERE
case SDLK_ESCAPE: // ------------------------------------------ HERE
_isRunning = false; // ------------------- to stop mainLoop()
break;
case SDLK_SPACE:
break;
default:
break;
}
}
The function is called here:
void mainLoop() {
(...)
while (isRunning == true) {
dealWithEvents->pollE(isRunning,actionBuild,money,slotId,map);
preDraw();
draw();
afterDrawEffects();
draw();
(...)
}
(...)
}

Enter and Exit menu using enum and switch sfml

In my game right now I am trying to make a menu you can access when you press 'q', but currently I am having some issues. I think it switches to the CompScreen view and then back to the currentroom view quickly, I may be wrong. I am getting the cout CompMenu, HELP, and hello readings so I know it is running through the programs, but when I press q I remain in the same spot, nothing happening.
EventManager.h
#ifndef EventManager_h
#define EventManager_h
#endif /* EventManager_h */
int windowWidth = 5000;//width of window
int windowHeight = 5000;//height of window
sf::View leveltwo(sf::FloatRect(x, y, 5000, 5000));
sf::View start(sf::FloatRect(0, 0, 2500, 1500));
sf::View ComputerScreen(sf::FloatRect(50000, 50000, 5000, 5000));
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight ), "Awesome Game" );
Character player("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Sprites/Player.png");
bool InMenu = false;
enum Levels{
StartRoom, LevelTwo
};
Levels room = StartRoom;
int currentroom;
void WhatRoom(int TheLevel){
switch (room){
case StartRoom:
currentroom = 1;
window.setView(start);
if (TheLevel == 2){
room = LevelTwo;
}
break;
case LevelTwo:
currentroom = 2;
window.setView(leveltwo);
break;
}
};
enum States{
compmenu, mainmenu, NoMenu
};
States menu = NoMenu;
void CompMenu(){
window.setView(ComputerScreen);
cout << "HELP";
InMenu = true;
}
void WhatMenu(int TheMenu){
switch (menu){
case compmenu:
cout << "CompMenu";
CompMenu();
break;
case mainmenu:
break;
case NoMenu:
if (TheMenu == 2){
menu = compmenu;
}
break;
if (TheMenu == 3){
menu = mainmenu;
}
break;
}
}
main.cpp (inside int main)
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q) and InMenu == false){
WhatMenu(2);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q) and InMenu == true){
InMenu = false;
WhatRoom(currentroom);
cout << "hello";
}
If you have any questions or need to see more of the code let me know. Thanks.
I think you've missed else after first if block so it may be executed immediately because InMenu may be changed to true at that point:
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q) and InMenu == true){
Also you should handle the situation when key is pressed for a long time (to react only when it enters pressed state) and get rid of all the global variables because they are already creating quite a mess.

How to Capture Key combination ALT+CTRL+INSERT using preTranslate message in C++

I want to capture key combinations like ALT+CTRL+INSERT using preTranslateMessage() in C++ as shown in below code. I could not get what I am expecting. I tried doing logical code changes. It doesnt seems to be the best solution.Also,using Keyboard Accelerators may solve my problem.But I could not exactly figure out how to do process.
Please anyone suggest me some possible solution..
BOOL BMWView::PreTranslateMessage(MSG* pMsg)
{
//static int k_ctrlPressed,k_altPressed,k_insertPressed = 0;
static int keylog_var = 0;
if (pMsg->message == WM_KEYUP )
{
switch (pMsg->wParam)
{
case VK_CONTROL: if(keylog_var==0) keylog_var = 1; else keylog_var = 0;
break;
case VK_MENU: if(keylog_var==1) keylog_var = 2; else keylog_var = 0;
break;
case VK_INSERT: if(keylog_var==2) keylog_var = 3; else keylog_var = 0;
break;
default: keylog_var = 0;
break;
}
//Switch case is replaced with below if statement
if(keylog_var == 3)
{
keylog_var = 0;
// Set mode
CWnd *pWnd = (CWnd *)this;
pWnd->PostMessage(ID_ENTRY, 0L, 0L);
}
}
return BView::PreTranslateMessage(pMsg);
Simple. Capture a ALT+CTRL+INSERT with GetKeyState and test pMsg for a VK_INSERT.
BOOL CTestView::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message==WM_KEYDOWN)
{
BOOL bCtrl=::GetKeyState(VK_CONTROL)&0x8000;
BOOL bShift=::GetKeyState(VK_SHIFT)&0x8000;
BOOL bAlt=::GetKeyState(VK_MENU)&0x8000;
switch(pMsg->wParam)
{
case VK_INSERT :
if( bCtrl && bAlt )
{
MessageBox(" Ctrl+Alt+INSERT ", " ",MB_OK);
}
break;
}
}
return CView::PreTranslateMessage(pMsg);
}

SDL 2.0 Keyboard Handling

I am writing a very simple sample program that simply shows you "a key is pressed or not" only once, the key pressed event is triggered whenever i press any number of keys (either i press one key, two keys or more), while the key is released event is triggered when an SDL_KEYUP event is occurred while the number of keys pressed is only 1 key, this example works perfectly on arrow keys, however for the other keys whenever i press multiple keys and release only one of them a "Key is released" message is triggered followed by "a key is pressed", i failed to locate the problem with this.
my Code:
#include <iostream>
#include <SDL2/SDL.h>
using namespace std;
SDL_Event input;
int main(int argc, const char * argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
int y = 0;
int z = 0;
int w = 0;
bool key = false;
const Uint8 *state = SDL_GetKeyboardState(NULL);
while (1){
w = 0;
SDL_PollEvent(&input);
//check for events generated
switch (input.type) {
case SDL_KEYDOWN:
key = true;
break;
case SDL_KEYUP:
key = false;
break;
default:
break;
}
// Check for no. of keys pressed using ASCII code
for (y = 48;y<=127;y++)
if(state[y] == 1)
w++;
// Display the messages
if (key && z==0 )
{
cout << "Key is Pressed" << endl;
z = 1;
}
else if (!key && w < 1 && z==1)
{
cout << "Key is released" << endl;
z = 0;
}
}
return 0;
}
The problem was with the initialization of the for loop, SDL 2 does not use the same ASCII enumerations for characters thus my code tend to ignore the code enumerations outside the (48-127) range after changing the code to:
for (y = 0;y<=127;y++)
if(state[y] == 1)
w++;
the problem is solved

SDL 2 Space keydown not detected but Space keyup works fine

Hey so I'm working on a project/2d game and I'm having some odd behavior from SDL which I'm sure is probably something I'm not understanding. The function ProcessKeys is called and works fine for all the key press downs except SDLK_SPACE and I cannot for the life of me figure out why.
What is even more bizarre is that the SDL_KEYUP switch of SDLK_SPACE works great. I tried using some debugging code to print out which key is being pressed and when you press space down nothing registers. Every other key on the keyboard registers in my debug statement at the top of the SDL_KEYDOWN case.
If anyone can see what is going on I would really appreciate it.
And if you need to see where its being called let me know.
SDLKeyboard::KeyState SDLKeyboard::ProcessKeys(SDL_Event * event)
{
switch(event->type)
{
/* Look for a keypress */
case SDL_KEYDOWN:
{
std::cout << "Key currently pressed" << event->key.keysym.sym << std::endl;
/* Check the SDLKey values and move change the coords */
switch(event->key.keysym.sym)
{
case SDLK_LEFT:
{ // rotate the ship left
c.setIsTurningLeft(true);
return this->keystate = LeftPressed;
// add code when user presses left
break;
}
case SDLK_RIGHT:
{
// rotate the ship right
c.setIsTurningRight(true);
return this->keystate = RightPressed;
// add code when user presses right
break;
}
case SDLK_UP:
{
// accleration
c.setIsAccelerating(true);
return this->keystate = UpPressed;
// add code when user presses up
break;
}
case SDLK_SPACE:
{
// shoot
c.setIsShooting(true);
std::cout << "keystate = " << this->keystate;
return this->keystate = SpacePressed;
// add code when user presses space
break;
}
default:
{
return this->keystate = NotPressed;
break;
}
}
break;
}
/* We must also use the SDL_KEYUP events to zero the x */
/* and y velocity variables. But we must also be */
/* careful not to zero the velocities when we shouldn't*/
case SDL_KEYUP:
{
std::cout << "Key currently pressed" << event->key.keysym.sym << std::endl;
switch(event->key.keysym.sym)
{
case SDLK_LEFT:
{ /* We check to make sure the ship is moving */
/* to the left. If it is then we zero the */
/* velocity. If the ship is moving to the */
/* right then the right key is still press */
/* so we don't touch the velocity */
c.setIsTurningLeft(false);
return this->keystate = LeftReleased;
// code to do things when left isn't pushed anymore but still moving left
break;
}
case SDLK_RIGHT:
{ // code to do things when right isn't pushed anymore but still moving right
c.setIsTurningRight(false);
return this->keystate = RightReleased;
break;
}
case SDLK_UP:
{ // code to do things when up isn't pushed anymore but still moving up
c.setIsAccelerating(false);
return this->keystate = UpReleased;
break;
}
case SDLK_SPACE:
{ // accleration
c.setIsShooting(false);
return this->keystate = SpaceReleased;
// add code when user presses up
break;
}
default:
break;
}
break;
}
default:
{
return this->keystate = NotPressed;
break;
}
}
}
EDIT:
Here is the example requested. The other thing that I've noticed is the latency in response isn't that great. Like if you press a key sometimes the console doesn't print the corresponding key. Probably has to do with the issue I'm having with the space as well.
void GUI::TakeInput(SDL_Event *e)
{
while (SDL_PollEvent(e))
OnEvent(e);
}
void SDLEvent::OnEvent(SDL_Event * event)
{
switch(event->type)
{
case SDL_KEYDOWN:
{
OnKeyDown(event->key.keysym.sym);
break;
}
case SDL_KEYUP:
{
OnKeyUp(event->key.keysym.sym);
break;
}
case SDL_MOUSEMOTION:
{
OnMouseMove(event->motion.x,event->motion.y);
break;
}
case SDL_MOUSEBUTTONDOWN:
{
OnMouseButtonDown(event->button.button, event->button.x,event->button.y);
break;
}
case SDL_MOUSEBUTTONUP:
{
OnMouseButtonUp(event->button.button, event->button.x,event->button.y);
break;
}
case SDL_QUIT: {
OnExit();
break;
}
case SDL_SYSWMEVENT: {
//Ignore
break;
}
case SDL_WINDOWEVENT_RESIZED: {
OnResize();
break;
}
case SDL_WINDOWEVENT_EXPOSED: {
OnExpose();
break;
}
default: {
OnUser(event->user.type,event->user.code,event->user.data1,event->user.data2);
break;
}
}
}
void GUI::Play()
{
Uint32 start_ticks = SDL_GetTicks();
TakeInput(this->setup->GetEvent());
this->keyboard->ProcessKeys(this->setup->GetEvent());
this->setup->RenderBegin();
this->ship->drawBackBuffer();
this->ship->renderSprite();
Uint32 end_ticks = SDL_GetTicks();
int sleep_delay = (1000 / 60) - (end_ticks-start_ticks);
if (sleep_delay > 0) {
SDL_Delay(sleep_delay);
}
}
If you are only writing event->key.keysym.sym on the console, you should know that the spacebar key produces an almost invisible character.
Try this instead:
std::cout << "<" << event->key.keysym.sym << ">"
So you can see whataver invisible character printed between angle brackets.