13002

Problems with single-tap and press-and-hold with LWJGL

I've been researching a way to use LWJGL for my input system. I'm having problems detecting if it is a single-press or a press-and-hold. The event fires twice when I tap, instead of just once.

while(Keyboard.next()) { if(Keyboard.getEventKeyState()) { if(Keyboard.isRepeatEvent()) { //Key held. doAction(Keyboard.getEventKey(), true, false); } else { //Key pressed doAction(Keyboard.getEventKey(), false, false); } } else { //Fired when key is released. doAction(Keyboard.getEventKey(), false, true); } }

Edit: I've both resolved the issue and modified this. Here you go, a modified version. (Dammit, Teamviewer..)

/** * Updates all mouse info, keys bound, and performs actions. */ public static void tick() { mouseButtons[0] = Mouse.isButtonDown(0); mouseButtons[1] = Mouse.isButtonDown(1); mousePos[0] = Mouse.getX(); mousePos[1] = Mouse.getY(); while(Keyboard.next()) { doAction(0, false); if(Keyboard.getEventKeyState()) { if(!Keyboard.isRepeatEvent()) { doAction(Keyboard.getEventKey(), false); } } else { doAction(Keyboard.getEventKey(), true); } } while(Mouse.next()) { } } /** * Does the associated action for each key. Called automatically from tick. * @param key The key to check & perform associated action */ public static void doAction(int key, boolean ifReleased) { if(mouseButtons[0]) { } if(mouseButtons[1]) { } if(key == 2 & !ifReleased) { System.out.println("a"); } if(Keyboard.isKeyDown(3)) { System.out.println("b"); } }

Answer1:

I know it's been awhile since this question was asked, but I came up with a solution myself. My InputHelper lets you determine if a key or mouse button is pressed, released, or held down, and can be accessed from anyother class without initializing and sharing the same instance of it.

It works by having 2 arrays, 1 for mouse events, 1 for keyboard events, that each store one enum value for each key. If there is a button or key event, when updated, the update function sets the value in the appropriate array for that button/key to a certain enum. Then, the next time it is updated, it sets all the key and button events to no event, and repeats the process, handling any new events.

/* * Handles mouse and keyboard input and stores values for keys * down, released, or pressed, that can be accessed from anywhere. * * To update the input helper, add this line into the main draw loop: * InputHelper.update(); * * Use as so (can be used from anywhere): * InputHelper.isKeyDown(Keyboard.KEY_SPACE); */ import java.util.ArrayList; import org.lwjgl.input.*; /** * * @author Jocopa3 */ public class InputHelper { private static InputHelper input = new InputHelper(); //Singleton class instance private enum EventState { NONE,PRESSED,DOWN,RELEASED; } private ArrayList<EventState> mouseEvents; private ArrayList<EventState> keyboardEvents; public InputHelper(){ //Mouse initialization mouseEvents = new ArrayList<EventState>(); //Add mouse events to Array list for(int i = 0; i < Mouse.getButtonCount(); i++) { mouseEvents.add(EventState.NONE); } //Keyboard initialization keyboardEvents = new ArrayList<EventState>(); //Add keyboard events to Array list for(int i = 0; i < Keyboard.KEYBOARD_SIZE; i++) { keyboardEvents.add(EventState.NONE); } } private void Update(){ resetKeys(); //clear Keyboard events //Set Key down events (more accurate than using repeat-event method) for(int i = 0; i < Keyboard.KEYBOARD_SIZE;; i++){ if(Keyboard.isKeyDown(i)) keyboardEvents.set(i, EventState.DOWN); } while(Keyboard.next()){ //Handle all Keyboard events int key = Keyboard.getEventKey(); if(key<0) continue; //Ignore no events if(Keyboard.getEventKeyState()){ if(!Keyboard.isRepeatEvent()){ keyboardEvents.set(key, EventState.PRESSED); } }else{ keyboardEvents.set(key, EventState.RELEASED); } } resetMouse(); //clear Mouse events //Set Mouse down events for(int i = 0; i < Mouse.getButtonCount(); i++){ if(Mouse.isButtonDown(i)) mouseEvents.set(i, EventState.DOWN); } while (Mouse.next()){ //Handle all Mouse events int button = Mouse.getEventButton(); if(button<0) continue; //Ignore no events if (Mouse.getEventButtonState()) { mouseEvents.set(button, EventState.PRESSED); }else { mouseEvents.set(button, EventState.RELEASED); } } } //Set all Keyboard events to false private void resetKeys(){ for(int i = 0; i < Keyboard.KEYBOARD_SIZE;; i++) { keyboardEvents.set(i, EventState.NONE); } } //Set all Mouse events to false private void resetMouse(){ for(int i = 0; i < Mouse.getButtonCount(); i++) { mouseEvents.set(i, EventState.NONE); } } //Non-static version of methods (Only used in the singleton instance) private boolean KeyDown(int key){ return keyboardEvents.get(key)==EventState.DOWN; } private boolean KeyPressed(int key){ return keyboardEvents.get(key)==EventState.PRESSED; } private boolean KeyReleased(int key){ return keyboardEvents.get(key)==EventState.RELEASED; } private boolean MouseButtonDown(int key){ return mouseEvents.get(key)==EventState.DOWN; } private boolean MouseButtonPressed(int key){ return mouseEvents.get(key)==EventState.PRESSED; } private boolean MouseButtonReleased(int key){ return mouseEvents.get(key)==EventState.RELEASED; } //Static version of methods (called from anywhere, return singleton instance value) public static boolean isKeyDown(int key){ return input.KeyDown(key); } public static boolean isKeyPressed(int key){ return input.KeyPressed(key); } public static boolean isKeyReleased(int key){ return input.KeyReleased(key); } public static boolean isButtonDown(int key){ return input.MouseButtonDown(key); } public static boolean isButtonPressed(int key){ return input.MouseButtonPressed(key); } public static boolean isButtonReleased(int key){ return input.MouseButtonReleased(key); } public static void update(){ input.Update(); } }

It has to be updated every frame manually, so your main draw loop you should add the line InputHelper.update(); like this:

while(!Display.isCloseRequested()) { InputHelper.update(); //Should go before other code that uses the inputs //Rest of code here }

Once you have it setup to update every frame, you can use it anywhere you need to determine input states for Mouse or Key buttons as so:

//Mouse test if(InputHelper.isButtonPressed(0)) System.out.println("Left Mouse button pressed"); if(InputHelper.isButtonDown(0)) System.out.println("Left Mouse button down"); if(InputHelper.isButtonReleased(0)) System.out.println("Left Mouse button released"); //Keyboard Test if(InputHelper.isKeyPressed(Keyboard.KEY_SPACE)) System.out.println("Space key pressed"); if(InputHelper.isKeyDown(Keyboard.KEY_SPACE)) System.out.println("Space key down"); if(InputHelper.isKeyReleased(Keyboard.KEY_SPACE)) System.out.println("Space key released");

Recommend

  • how to move 3d object in XNA?
  • Java: Index out of bounds
  • Use Keyboard.IsKeyDown in C# console application
  • How to save one click if key is pressed?
  • calling a fragment from fragment
  • to implement a spinner in angular2+
  • MVC - @Html.CheckBoxFor
  • Doctrine2 bulk import try to work with another entity
  • Passing “get” parameters doesn't work, parameter not visible in the link
  • Reading a file into a multidimensional array
  • Unable to get column index with table.getColumn method using custom table Model
  • System.InvalidCastException: Specified cast is not valid
  • App restarts from wrong activity
  • How can I extract results of aggregate queries in slick?
  • OOP Javascript - Is “get property” method necessary?
  • Declaring variable dynamically in VB.net
  • Transactional Create with Validation in ServiceStack Redis Client
  • Hardware Accelerated Image Scaling in windows using C++
  • How to avoid particles glitching together in an elastic particle collision simulator?
  • Jetty Server not starting: Unable to establish loopback connection
  • Recording logins for password protected directories
  • Splitting given String into two variables - php
  • PHP - How to update data to MySQL when click a radio button
  • Submit form in a displaytag pagination
  • Check if a string to interpolate provides expected placeholders
  • sending/ receiving email in Java
  • Can I have the cursor start on a particular column by default in jqgrid's edit mode?
  • Timeout for blocking function call, i.e., how to stop waiting for user input after X seconds?
  • Rearranging Cells in UITableView Bug & Saving Changes
  • Circular dependency while pushing http interceptor
  • Linker errors when using intrinsic function via function pointer
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • Proper folder structure for lots of source files
  • Suggestions to manage Login/Logout transitions
  • How get height of the a view with gone visibility and height defined as wrap_content in xml?
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • How does Linux kernel interrupt the application?
  • Bitwise OR returns boolean when one of operands is nil
  • Sorting a 2D array using the second column C++
  • java string with new operator and a literal