GLFW Keyboard Input Registers As Multiple Clicks - opengl

In my current LWJGL application I am using the GLFW window input handler which I have set up a class to handle called Keyboard.java which extends GLFWKeyCallback. I have correctly set up my keyboard input class but when I click on a key if i do not click if fast enough (very quickly) then it registers as multiple clicks. I have presented some documentation below:
Keyboard Class
public class Keyboard extends GLFWKeyCallback {
//Variables
public static boolean keys[] = new boolean[65536];
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
keys[key] = action == GLFW_PRESS;
}
}
Implementation
public static void handleInput() {
if (Keyboard.keys[GLFW_KEY_SPACE]) {
System.out.println("Space");
glfwPollEvents();
}
}
The above method is implemented in the main game loop and is called once a frame.
Result
Initialised LWJGL Version: 3.1.2 build 29
Space
Space
Space
Space
The above: "Space" should be outputted every time that I click space but when I click it relatively fast, Then i get the above result of many "spaces".
Conclusion: Is it possible for a click of space to be registered only once no matter how long you hold it. Thanks

In your handleInput() function, you are testing to see if Keyboard.keys[GLFW_KEY_SPACE] is true, and if it is, you execute the statement. The problem is that this test only becomes false when you stop hitting space, which could take seconds to happen.
My suggestion: once you tested for Keyboard.keys[GLFW_KEY_SPACE], make it false.
public static void handleInput() {
if (Keyboard.keys[GLFW_KEY_SPACE]) {
Keyboard.keys[GLFW_KEY_SPACE] = false;
System.out.println("Space");
glfwPollEvents();
}
}

Related

C++: Instantiate same object as one of many types depending on variable

I am programming an LED Cube I have designed. The cube has a "pause" button and a "play/next" button. Unless the cube is paused, it will cycle through all of the different effects (animations) I've made for it. If you press the pause button, the cube will no longer transition between effects and will instead repeat the current effect. Pressing the 'play/next' button will unset the pause feature and will advance to the next effect immediately.
Some of these effects are pretty complex and require a large number of variables to be kept between frames of animation. In order to easily destroy all of these variables at a moment's notice (like when the next button is pressed), I'm instantiating the current animation as an object and destroying it when the effect is complete or the skip button is pressed.
I'm trying to set my main loop up as follows:
void loop() {
//create an effect object
switch(effectIndex){
case 0:
EF_GROWFRAME effect;
break;
case 1:
EF_RANDOMFILL effect;
break;
}
bool proceed;
do{
//returns false until the effect has completed
proceed=effect.step();
//push this cube update and wait for it to display
cube.update();
cube.waitForFrame();
}
while ((!proceed)&&(!skipflag));
//skipflag is set true during a timer interrupt if the skip button is freshly pressed
skipflag=false;
cube.clearPattern();
if (play) effectIndex++;
if (effectIndex=effectCount) effectIndex=0;
}
That fails because of my conflicting definitions of effect though. You can probably see what I'm going for, so what's the proper way to approach this?
This is a use case for polymorphism.
Define a base class, Animation that defines a shared interface and have your various animation types derive from it. For example:
class Animation {
public:
virtual ~Animation() {
// any generic cleanup shared by all animation types
}
virtual bool step() = 0;
};
class AnimationA : public Animation {
public:
bool step() override {
// logic for this type of animation
}
};
class AnimationB : public Animation {
public:
bool step() override {
// logic for this type of animation
}
};
void loop() {
std::unique_ptr<Animation> effect;
switch (effectIndex) {
case 0:
effect = std::make_unique<AnimationA>();
break;
case 1:
effect = std::make_unique<AnimationB>();
break;
}
//...
}
Live Demo
Since it seems like this may be an embedded environment, you could avoid the dynamic memory allocation from my first example by factoring your animation playing logic out into a separate function:
void playAnimation(Animation& effect) {
bool proceed;
do{
//returns false until the effect has completed
proceed=effect.step();
//push this cube update and wait for it to display
cube.update();
cube.waitForFrame();
} while (!proceed && !skipFlag);
//skipflag is set true during a timer interrupt if the skip button is freshly pressed
skipflag=false;
cube.clearPattern();
}
void loop() {
switch (effectIndex) {
case 0:
{
AnimationA effect;
playAnimation(effect);
break;
}
case 1:
{
AnimationB effect;
playAnimation(effect);
break;
}
}
if (play) effectIndex++;
if (effectIndex == effectCount) effectIndex=0;
}
Live Demo

SFML button triggers twice

I'm using SFML to write game and I got small problem with my button. Here is function I use to check if button is clicked:
bool InputManager::isSpriteClicked(sf::Sprite object, sf::Mouse::Button button, sf::RenderWindow &window) {
if (sf::Mouse::isButtonPressed(button)) {
sf::IntRect rect(object.getPosition().x, object.getPosition().y,
object.getGlobalBounds().width, object.getGlobalBounds().height);
if (rect.contains(sf::Mouse::getPosition(window))) {
return true;
}
}
return false;
}
It works almost fine, yet sometimes once I press this button, action is trigerred twice, like I double click it, even tho I didnt even release it yet. I tried to involve sf::Event::MouseButtonReleased but It actually wasnt helping too. What I want to achieve is of course just 1 action per 1 button press/release/whatever.
Here is example of my GameLoop if its needed
void GameState::handleUserInput() {
sf::Event evnt;
while (this->m_data->window.pollEvent(evnt)) {
if (this->m_data->input.isSpriteClicked(this->m_rollButton, sf::Mouse::Left, this->m_data->window)) {
m_gameEngine.startTurn(m_gameStatusBox);
}
}
void GameState::update(sf::Time dt) {
m_gameEngine.getActivePlayer().move(dt);
}
void GameState::draw() {
this->m_data->window.display();
}
Short answer:
if (event.type == sf::Event::MouseButtonPressed)
Long story By the way, it's second link in google....
You're mixing two different approaches to manage user input
Input by events: used to manage those things that happen once and you want to be notified
Real time input: basically, poll repeatedly for input status (in this case, the mouse)
The general rule:
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
// WHILE the left mouse button is being pressed, do something
if (event.type == sf::Event::MouseButtonPressed)
// WHEN the left mouse button has been pressed, do something
If you want to learn more, i recommend you to read this chapter (or better, the whole book) about SFML game dev.

UWP GetAsyncKeyState() from a separate thread

I am using the "DirectX 11 and XAML App (Universal Window)" template in vs2015. I want to get user's keystroke in every frame. So I tried to put GetAsyncKeyState() inside of the render-loop. The render-loop is running in a separate thread:
auto workItemHandler = ref new WorkItemHandler([this](IAsyncAction ^ action)
{
// Calculate the updated frame and render once per vertical blanking interval.
while (action->Status == AsyncStatus::Started)
{
critical_section::scoped_lock lock(m_criticalSection);
Update();
m_sceneRenderer->OnKeyDown();
if (Render())
{
m_deviceResources->Present();
}
}
});
// Run task on a dedicated high priority background thread.
m_renderLoopWorker = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced);
m_sceneRenderer->OnKeyDown() is where I put GetAsyncKeyState(). But whenever I put m_sceneRenderer->OnKeyDown() inside the while loop, all the DirectX content will not be rendered. Also, m_renderLoopWorker will be nullptr and throw an exception when I close the application.
// Sample3DSceneRenderer.h, truncated
namespace UWP_DX11_XAML_
{
class Sample3DSceneRenderer
{
Sample3DSceneRenderer(Windows::UI::Core::CoreWindow^ window);
void OnKeyDown();
Platform::Agile<Windows::UI::Core::CoreWindow^> m_window;
}
}
// Sample3DSceneRenderer.cpp, truncated
UWP_DX11_XAML_::Sample3DSceneRenderer::Sample3DSceneRenderer(
Windows::UI::Core::CoreWindow^ window):
m_window(window)
{
}
void UWP_DX11_XAML_::Sample3DSceneRenderer::OnKeyDown()
{
m_window.Get()->GetAsyncKeyState(Windows::System::VirtualKey::Control);
}
Calling other member functions of m_window can cause the same problem.
You may wish to setup a dedicated input thread using CreateCoreIndependentInputSource(CoreInputDeviceTypes::Mouse | CoreInputDeviceTypes::Touch | CoreInputDeviceTypes::Pen);
There's a sample here which demonstrates this option: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/LowLatencyInput
I also found these similar articles which discuss optimizing for low input latency.
https://learn.microsoft.com/en-us/windows/uwp/gaming/optimize-performance-for-windows-store-direct3d-11-apps-with-coredispatcher
https://blogs.windows.com/buildingapps/2013/12/18/optimizing-directx-apps-for-low-latency-input-and-longer-battery-life/#JPGhHjXExbySmTf7.97

Working with Windows mouse event states in c++ VS2012 - 13

I am working on a GameEngine Project and my framework is as follows I have an Engine Class that is a base class that creates a window and setups up an open GL context and handles windows message events. From this I have a derived class that is a Game class. Some functions are purely virtual. My project is too large to post here so I will show code segments that are relevant.
I am working within these two classes and the task I am trying to achieve is to make an object fade in and out of view with a left mouse click. The position of the mouse cursor is irrelevant. This can easily be done by changing the alpha value from 1.0f to 0.0f. The object is initially visible and when the first mouse click & release operation happens I need it to fade out. Then the next time the mouse button is pressed & released I need it to fade back into view to full opacity. I am stuck at this point.
This is the section of my Engine::messageHandler() that is of importance
Engine::MessageHandler( unsigned uMsg, WPARAM wParam, LPARAM lParam ) {
switch( uMsg ) {
// ... Irrelevant Code Here
case WM_LBUTTONDOW: {
m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTON] = true;
mouseInput(); // purely virtual - implemented by Game class
return true;
}
case WM_LBUTTONUP: {
m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTOM] = false;
mouseInput(); // purely virtual - implemented by Game class
return true;
}
// ... More Irrelevant Code Here
default {
return false;
}
}
} // messageHandler
It is in my Game::mouseInput() function where I need to change the alpha value of my rendered object with a mouse click & release operation.
void Game::mouseInput() {
} // mouseInput
And I have tried if statements & while loops to no avail.
I was able to get the object to fade by an incremental amount each time as I continued to clicking the left mouse button. The code looked something like this
Game::mouseInput {
static glm::vec4 sliceColor = m_pSliceFade->getColor();
if ( m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTON] == true ) {
sliceColor.a -= 0.05f;
m_pSliceFade->setColor( sliceColor );
}
} // mouseInput
However, this is not the behavior I want or need. I am struggling here because each time we go into the Engine::messageHandler() for both mouse down & up events my purely virtual Game::mouseInput() is being called. I guess I am having writers block because I can not seem to figure out how to continuously change the alpha value after each click & release event and then reverse the direction of the alpha value on the following click & release event within this framework. Initially all mouse buttons bool tracking variables are set to false by default on initialization.
Any kind of suggestions or help would be supportive and helpful. Thank you kindly in advance.

LWUIT List works terribly slow

I've faced with the well-known problem in LWUIT. My list component with the checkbox renderer scrolls very slow. If to test my application on emulator it runs quite smoothly (nevertheless I see CPU utilization splashes up to 60% during scroll action), but if to run it on mobile phone it takes a couple of seconds between focus movements.
There's a code of renderer:
public class CheckBoxMultiselectRenderer extends CheckBox implements ListCellRenderer {
public CheckBoxMultiselectRenderer() {
super("");
}
//override
public void repaint() {
}
public Component getListCellRendererComponent(List list, Object value,
int index,boolean isSelected) {
Location loc = (Location)value;
setText(loc.getLocationName());
setFocus(isSelected);
setSelected(loc.isSelected());
return this;
}
public Component getListFocusComponent(List list) {
setText("");
setFocus(true);
getStyle().setBgTransparency(Consts.BG_TRANSPARENCY);
return this;
}
}
that's the code of my form containing the list:
protected void createMarkup() {
Form form = getForm();
form.setLayout(new BorderLayout());
form.setScrollable(false);
Label title = new Label("Choose location zone:");
title.getStyle().setMargin(5, 5, 0, 0);
title.getStyle().setBgTransparency(Consts.BG_TRANSPARENCY);
title.setAlignment(Component.CENTER);
form.addComponent(BorderLayout.NORTH, title);
list = new List(StateKeeper.getLocationsAsList());
list.setFixedSelection(List.FIXED_NONE_CYCLIC);
// list.setSmoothScrolling(true);
list.getStyle().setBgTransparency(0);
list.setListCellRenderer(new CheckBoxMultiselectRenderer());
list.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
// List l = (List)ae.getSource();
// l.requestFocus();
// l.setHandlesInput(true);
Location selItem = (Location)list.getSelectedItem();
selItem.setSelected(!selItem.isSelected());
}
});
form.addComponent(BorderLayout.CENTER, list);
}
I would be very thankful for any help!
We must be so carefull building lwuit List. If we have made something wrong they can work worse than expected. I recommend you to take a look on this
LWUIT Blog ListRender
You can also rewrite your paint method. You list's speed will be increased.