GLFW input handling not working as intended - c++

So this may be a newbie question regarding GLFW, but I seem to be having an interesting issue. So I'm developing a simple input handling class using GLFW, specifically utilizing static methods to allow only requiring the inclusion of the header file to use the methods. So this is my code thus far...
InputHandler.cpp
#include "InputHandler.h"
GLFWwindow *Input::m_Window;
bool Input::isDown;
std::vector<int> Input::keyCache;
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
for (int _key = 0; _key < Input::keyCache.size(); _key++)
{
if (key == Input::keyCache[_key] && action == GLFW_PRESS || key == Input::keyCache[_key] && action == GLFW_REPEAT)
Input::isDown = true;
else
Input::isDown = false;
}
}
void Input::processInput(GLFWwindow* window)
{
m_Window = window;
}
bool Input::isKeyDown(int key)
{
keyCache.push_back(key);
glfwSetKeyCallback(m_Window, key_callback);
return isDown;
}
InputHandler.h
#pragma once
#include <GLFW\glfw3.h>
#include <vector>
class Input
{
public:
static bool isDown;
static std::vector<int> keyCache;
private:
static GLFWwindow *m_Window;
public:
static void processInput(GLFWwindow* window);
static bool isKeyDown(int key);
static bool isKeyUp(int key);
static int getMouseX();
static int getMouseY();
};
However, whenever I call the isKeyDown method, which will return true or false based on if the key is down or not, multiple times, the program seems to only respond to the last key mentioned. For example, if I use the code...
if (Input::isKeyDown(GLFW_KEY_W) || Input::isKeyDown(GLFW_KEY_Q))
std::cout << "Key is down" << std::endl;
only the Q key will trigger the statement, W does nothing. I have gone through GLFW's site multiple times, the input guide is where I learned the necessary things needed to receive the input, and it also seems that no one else has had this issue, as I have searched and searched for anything. If anyone could help, by explaining possible issues or pointing me in the right direction in terms of finding the answer myself, I would greatly appreciate it!

Alright, I figured out my issue. I was WAAAAAAAAAAAAAAAAAAAAAAAAAAY overcomplicating it. So, my issue was that the key callback was only able to ever handle one key, and it was completely unnecessary. So, my fix involved removing the key callback, the keyCache and the isDown variable, and simply changing isKeyDown to...
bool Input::isKeyDown(int key)
{
if (glfwGetKey(m_Window, key))
return true;
return false;
}
I'm sorry for how ridiculously incompetent I have shown myself to be. Well, now I know how the key callback works! xD

Related

GetAsyncKeyState constantly active

I am trying to make an autoclicker to mess around with getkeystate and key pressing functions in VS and c++, for some odd reason it will never stop clicking once it is initially clicked. I looked over my code and couldn't find anything wrong with it, i know the issue is gonna be something stupidly small. Heres my code:
#include <iostream>
#include <Windows.h>
using namespace std;
bool click = false;
int x = 0, y = 0, cps;
void gui()
{
cout << "Enter desired clicks per second: ";
cin >> cps;
}
void clicked()
{
while (1)
{
if (GetAsyncKeyState(VK_LBUTTON)) // Left mbutton
{
click = true;
}
else
{
click = false;
}
if (click == true)
{
mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
Sleep(1000 / cps);
}
if (click == false)
{
continue;
}
}
}
int main()
{
gui();
clicked();
}```
You maybe missed to read the documentation about return value of GetAsyncKeyState.
The return value of GetAsyncKeyState is zero for the following cases:
The current desktop is not the active desktop
The foreground thread belongs to another process and the desktop does not allow the hook or the journal record.
And,if the most significant bit is set , the key is down.
So, for checking up, you need to check, if the most significant bit is reset.
[Sorry, I am writing the answer on mobile. So, could not provide source code.]

Application (sometimes) crashes on PlaySound()

I'm writing a game where player picks coins. Picking a coin there is supposed to be a sound, I use PlaySound to play *.wav file. It works. But sometimes (7/10 attempts) app just crushes. I have no idea why sometimes is works and sometimes it doesn't.
The interesting thing is when I run the app in debug mode it works perfectly
What can cause the problem and how can it be fixed?
And also can you recommend another way to play wav? (As simple as that (Using one-two functions))
I've tried to use PlaySoundA, sndPlaySound all of the variations - the same result
tried to read wav directly from file and save it in memory - the same result
//This sample checks if there a coin on the right
void Player::step_right() {
if (check_right()) {
sndPlaySound(TEXT("D:\\projects\\s.wav"), SND_FILENAME | SND_ASYNC);
//PlaySoundA(TEXT("D:\\projects\\s.wav"), nullptr, SND_FILENAME | SND_ASYNC);
//sndPlaySound(buffer, SND_MEMORY || SND_ASYNC);
netWorth++;
steps+=10;
}
cur->X++;
}
upd:
I use MinGW
Console output after crush: Process finished with exit code -1073741819 (0xC0000005)
Here is the Player class specification:
class Player {
private:
Point* cur; // Current coords
Point post; // Last coords
int steps; // Remaining steps
int netWorth; // Picked coins
void (Player::*m[4])(); // Array of movement functions pointers
// Movement
void step_right();
void step_left();
void step_up();
void step_down();
// Coins checking
bool check_right();
bool check_left();
bool check_up();
bool check_down();
public:
Player();
Point* Getcur() { return cur; }
void Move(void (Player::*t)());
bool isOutofSteps();
auto ReturnSomeArray() { return m; }
int GetNet(); //Networth
void display_player_info();
};
I also have Action_Listener class which has
map<int, void (Player::*)()> m;
Depending on a keycode I send a function pointer to void Player::Move(void (Player::*t)())
here:
if (m.find(event) != m.end() && !player->isOutofSteps()) {
void (Player::*t)() = m[event];
player->Move(t);
unsigned int (Drawer::*y)() = drawhandlers[event];
drawer->Draw_Hero(y);
player->display_player_info();
} else if(player->isOutofSteps()){
terminal_print(2, 2, "You're out of steps");
return;
}
Move function:
void Player ::Move(void (Player::*t)()) {
post = *cur;
(this->*t)();
steps--;
}

How to make a loading screen state transition to game level state?

I am trying to make my basic loading screen transition over to game level screen. So what i wanted to do is, once the loading screen is active (or has appeared onscreen), I want at this point to start loading my game state. What it is doing at the moment is loading everything at the start, and this does take a while.
So currently my project starts off with a main menu. Then when i press enter, its starts the loading screen. I have my manual state change using keypresses like so:
void Game::update()
{
static bool enterPreviouslyPressed = false;
static bool escapePreviousPressed = false;
const Uint8 *keys = SDL_GetKeyboardState(NULL);
if (keys[::SDL_SCANCODE_ESCAPE] && !escapePreviousPressed && typeid(*fsm->getState()) == typeid(GameState))
{
fsm->setState(menuState);
}
else if (keys[::SDL_SCANCODE_RETURN] && !enterPreviouslyPressed && typeid(*fsm->getState()) == typeid(MainMenuState))
{
fsm->setState(loadingState);
}
else if ((keys[::SDL_SCANCODE_RETURN] && !enterPreviouslyPressed) && typeid(*fsm->getState()) == typeid(LoadScreenState))
{
fsm->setState(gameState);
}
else if (keys[::SDL_SCANCODE_ESCAPE] && !escapePreviousPressed && typeid(*fsm->getState()) == typeid(MainMenuState))
{
exit(0);
}
enterPreviouslyPressed = keys[::SDL_SCANCODE_RETURN] != 0;
escapePreviousPressed = keys[::SDL_SCANCODE_ESCAPE] != 0;
fsm->update();
}
I did this to initially does this so i could change states manually to check that everything works. I was wondering if there was an easy(ish) way, like boolean flags for example or another simpler way to do this. I wasn't able find any tutorials online so wondering if someone knows the best solution as to how to do this. I did see a question on here, kindda similar but I wasn't sure if it answered my question as the person did this in threads which I am not familiar with how to implement. Apologies if I dont seem to have the logic correct - so please advise otherwise.
Looks fairly standard, except I would simplify it by keeping two keyboard state variables declared as class variables, like:
const Uint8 *curKeys = SDL_GetKeyboardState(NULL), *prevKeys;
// ...
void Game::update() {
prevKeys = curKeys;
curKeys = = SDL_GetKeyboardState(NULL);
//and so then compare curKeys to prevkeys
//and ditch the booleans
// ...
}

SFML - Rendering a character when the key is pressed?

So I've got this program that is supposed to imitate a console (with a little coding help from this user):
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
sf::Color fontColor;
sf::Font mainFont;
sf::Clock myClock;
bool showCursor = true;
void LoadFont() {
mainFont.loadFromFile("dos.ttf");
fontColor.r = 0;
fontColor.g = 203;
fontColor.b = 0;
}
int main() {
sf::RenderWindow wnd(sf::VideoMode(1366, 768), "SFML Console");
wnd.setSize(sf::Vector2u(1366, 768));
LoadFont();
sf::Text myTxt;
myTxt.setColor(fontColor);
myTxt.setString("System Module:");
myTxt.setFont(mainFont);
myTxt.setCharacterSize(18);
myTxt.setStyle(sf::Text::Regular);
myTxt.setPosition(0, 0);
while(wnd.isOpen()) {
sf::Event myEvent;
while (wnd.pollEvent(myEvent)) {
if (myEvent.type == sf::Event::Closed) {
wnd.close();
}
if (myEvent.type == sf::Event::KeyPressed) {
if (myEvent.key.code == sf::Keyboard::Escape) {
wnd.close();
}
}
}
wnd.clear();
if (myClock.getElapsedTime() >= sf::milliseconds(500)) {
myClock.restart();
showCursor = !showCursor;
if(showCursor == true) {
myTxt.setString("System Module:_");
} else {
myTxt.setString("System Module:");
}
}
wnd.draw(myTxt);
wnd.display();
}
}
I need to be able to let the user type a key on the keyboard, and then render that key on the screen. I'm thinking about using an std::vector of sf::Keyboard::Key, and use a while loop to check what the key is (looping through the std::vector<sf::Keyboard::Key>) without using a whole bunch of if statements, but I don't exactly know how to handle that yet, so I'd like to know if there is an easier way to accomplish my main goal. Suggestions? Comments?
Thank you for your time,
~Mike
SFML has a nice feature for this, sf::Event::TextEntered (tutorial). That is typically what you want and it avoids you to do crazy things to interpret the text entered by the user.
Stock your text entered by adding every character into a sf::String (rather than std::string, it may deal better with sfml's unicode types ~ not sure, but that would need a little check) which is then the perfect type for sf::Text::setString !
Don't hesitate to look at the docs, it has further documentation in every classes' page.
Example:
sf::String userInput;
// ...
while( wnd.pollEvent(event))
{
if(event.type == sf::Event::TextEntered)
{
/* Choose one of the 2 following, and note that the insert method
may be more efficient, as it avoids creating a new string by
concatenating and then copying into userInput.
*/
// userInput += event.text.unicode;
userInput.insert(userInput.getSize(), event.text.unicode);
}
else if(event.type == sf::Event::KeyPressed)
{
if(event.key.code == sf::Keyboard::BackSpace) // delete the last character
{
userInput.erase(userInput.getSize() - 1);
}
}
}

Exiting glutFullScreen()

I don't understand why when I press 'f' it enters into fullscreen but does not exit out of full screen. In the beginning of this method I have set bool fullscreen = false;
Here is the code for my toggle:
case 'f': //toggle screenmode
if(!fullscreen){
glutFullScreen();
fullscreen = true;
} else if(fullscreen){
glutReshapeWindow(1200, 900);
glutPositionWindow(0,0);
fullscreen = false;
}
break;
at the top of this method I have set bool fullscreen = false;
Every time you press a key, GLUT will call your keyboard handler. And at the top of your keyboard handler, you create a bool variable named fullscreen and set its value to false. This happens regardless of whether you're in full-screen mode or not. Every time you press a key, this will happen.
If you want to retain a boolean variable that actually tracks whether you're currently fullscreen, then you need to use a global. And you need to not set it at the start of the function. You set it once when you create the window, and you only set it again when you change the fullscreen status of the window.
To restore the original window size
... switch the calling order of ReshapeWindow and PositionWindow to
glutPositionWindow(0,0);
glutReshapeWindow(1200, 900);
Otherwise it will go back to windowed mode, but not adapt to the window size you specified!
The problem is not in the code you posted above as according to glutFullScreen specification the window should exit fullscreen mode once glutReshapeWindow or glutPositionWindow is being called.
at the top of this method I have set bool fullscreen = false;
I bet you set this inside the same function (not as a global variable) rendering the variable always being false when you press f
Instead of defining the bool at the beginning of the method, you have to define a global variable. Otherwise each time that method is called, it will set the fullscreen bool to 0, and think that it's not in fullscreen mode. Also, you may want to take not of euphrat's answer, he makes a valid point about the method organization.
Try this:
case 'f': //toggle screenmode
fullScreen = !fullScreen;
if (fullScreen) {
glutFullScreen();
} else {
glutReshapeWindow(1200, 900);
glutPositionWindow(0,0);
}
break;
While it might not answer the question directly, I found it an excellent place to post a go-to full-screen and exit source code.
Switch and restore full screen with <GL/glut.h>
myGame.c
...
glutSpecialFunc(handleSpecial);
void handleSpecial(int key, int x, int y) {
oglHandleFullScreen(key, x, y);
}
...
If you are looking forward to responding to a keyboard event instead (glutKeyboardFunc), make sure to change the signature of the below oglHandleFullScreen to (unsigned char key, int x, int y).
fullscreen.h
void oglHandleFullScreen(int key, int x, int y);
void oglWindowed(int positionX, int positionY, int width, int height);
void oglFullScreen();
fullscreen.c
#include <GL/glut.h>
#include "fullscreen.h"
int isFullScreen = 0;
int previousPosition[2] = { 0, 0 };
int previousSize[2] = { 100, 100 };
void oglHandleFullScreen(int key, int x, int y) {
if (key != GLUT_KEY_F11) { // Respond to F11 key (glutSpecialFunc).
return;
}
if (isFullScreen) {
oglWindowed(previousPosition[0], previousPosition[1],
previousSize[0], previousSize[1]);
} else {
previousPosition[0] = glutGet(GLUT_WINDOW_X);
previousPosition[1] = glutGet(GLUT_WINDOW_Y);
previousSize[0] = glutGet(GLUT_WINDOW_WIDTH);
previousSize[1] = glutGet(GLUT_WINDOW_HEIGHT);
oglFullScreen();
}
isFullScreen = !isFullScreen;
}
void oglWindowed(int positionX, int positionY, int width, int height) {
glutReshapeWindow(width, height);
glutPositionWindow(positionX, positionY);
}
void oglFullScreen() {
glutFullScreen();
}
In this case, you may want to add a static keyword before the bool to make this variable initialized only once.
A safer approach would be to make fullscreen global, since static local variables may be implemented differently across compilers and c++ standards.
Edit to add code snippet:
static bool fullscreen = false;
This should fix the problem of initializing the variable every call to the function, and by c++11 standard should be thread-safe
(Many compilers may say otherwise. Visual Studio only supported this feature of c++11 in VS2015 according to another question's accepted answer: Is static init thread-safe with VC2010?)
Better option may be using a global variable (Wrapping into a class is not good for this purpose).
Edit: Also, despite being simple in syntax, this c++11 feature is costly when called frequently.(See Cost of thread-safe local static variable initialization in C++11?)
(A key down is not that frequent as drawing vertices at high FPS, though... Do NOT use this when performance-critical...)