0

I've got a KeyListener class called Keyboard which implements KeyListener's methods.

There are 4 states keys can have with it (UP, ISUP, DOWN, ISDOWN) all representing whether they're down, or they just became down.

Before every update to the Keyboard, I'd like to change all of the UPs to ISUPS, and DOWNs to ISDOWNs.

There is an Update method on the Keyboard class, but I don't know when to call it (because the addKeyListener() function seems to be magic and just works without having to call any functions [probably launches a thread])

How do I know when to call the Update method? (right before the Keyboard is about to fire events)

Here's the Keyboard class itself:

package game.input;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.HashMap;
import java.util.Map;

enum KeyStatus
{
    DOWN, ISDOWN, UP, ISUP
}

public class Keyboard implements KeyListener
{
    private Map<Character, KeyStatus> keys;

    public Keyboard()
    {
        keys = new HashMap<Character, KeyStatus>();

        for (int i = 0; i < 256; i++)
        {
            keys.put((char)i, KeyStatus.ISUP);
        }
    }

    public void update() //This should be called after every event loop (how?)
    {
        for (Map.Entry<Character, KeyStatus> ks: keys.entrySet())
        {
            if (ks.getValue() == KeyStatus.UP)
                keys.put(ks.getKey(), KeyStatus.ISUP);

            else if (ks.getValue() == KeyStatus.DOWN)
                keys.put(ks.getKey(), KeyStatus.ISDOWN);
        }
    }

    public boolean keyDown(char i)
    {
        return (keys.get(i) == KeyStatus.DOWN || keys.get(i) == KeyStatus.ISDOWN);
    }

    public boolean onKeyDown(char i)
    {
        return (keys.get(i) == KeyStatus.DOWN);
    }

    public boolean keyUp(char i)
    {
        return (keys.get(i) == KeyStatus.UP || keys.get(i) == KeyStatus.ISUP);
    }

    public boolean onKeyUp(char i)
    {
        return (keys.get(i) == KeyStatus.UP);
    }


    @Override
    public void keyPressed(KeyEvent key)
    {
        keys.put(key.getKeyChar(), KeyStatus.DOWN);
    }

    @Override
    public void keyReleased(KeyEvent key)
    {
        keys.put(key.getKeyChar(), KeyStatus.UP);
    }

    @Override
    public void keyTyped(KeyEvent key)
    {
    }

}
8
  • I'm sorry, I understand your UP and DOWN states, but what do ISUP and ISDOWN represent? They appear to be redundant. Also, have you read up on key bindings which may be better options than a KeyListener? Commented May 7, 2013 at 23:36
  • @Hovercraftfullofeels UP, DOWN = User JUST pushed the key. ISUP, ISDOWN = The key is currently down. Commented May 7, 2013 at 23:44
  • What you call UP, DOWN above then are not states but rather events. I fear that your structure is broken. What you desire is two states, what I'd call UP and DOWN, and indicating whether the key is currently up or down. You then would listen for events where the state changes. But you don't make the event a state. Commented May 7, 2013 at 23:47
  • @HovercraftFullOfEels Whilst this would make sense normally, I'm writing a game. Not every component can have access to the KeyListener. Is this not the right way to do it? (Store the current state of the keys in an array, and when you get a DOWN event, change the key in the array? [to DOWN, then after one loop to ISDOWN]) Commented May 7, 2013 at 23:52
  • OK, answer this, how long is your UP state supposed to last? When is it supposed to change from UP to ISUP and by what mechanism? What sort of Timer are you using? The answer is, it is moot. Again, your logic and structure are faulty. What you suggest is not the right way to do it, not by any means. In fact your whole problem currently is that you don't have this mechanism, and in fact you don't need it or want it. Commented May 7, 2013 at 23:54

1 Answer 1

2

The KeyListener is registered to a component, which is notified by the EventQueue when a KeyEvent of some kind occurs. The EventQueue is notified by a platform specific mechanism which is tied directly to the OS/native layer.

Swing generally uses an observer pattern when it comes to listeners. That is, you attach a listener to a component which will tell you when something happens

You shouldn't "need" to call any method to check the state of the keys. Instead, when a KeyEvent is triggered, the KeyListener will be notified (via the event chain) and fire an appropriate event through the KeyListener interface.

A KeyListener needs to be registered with some component that is visible on the screen, can obtain keyboard focus and has focus at the time the event occurred.

Take a look at How to write Key Listeners for more details.

You may also find Introduction to Event Listeners useful.

KeyListener suffers from focus issues (only the currently focusable/focused component can receive KeyEvents). It is recommend that you use Key Bindings instead.

Updated

After a round robin of disscussion where we nutted out what was the real problem, we concluded that the OP was trying to generate a masking list of keys that were currently pressed, but had been processed by the game engine, in an effort to eliminate the key-repeat from triggering more updates.

We came to the conclusion that the OP should generate a "processed" and "active" list of keys.

When a key pressed event is triggered, the keyboard handler would check to see if the key exists on in the "processed" list, if it does, the key is ignored, otherwise it is placed in the active list.

When the game engine processes the keys, it scans the "active" list, takes action and places each key on the "processed" list.

Once the key is released, it is removed from the processed list.

Sign up to request clarification or add additional context in comments.

2 Comments

I've got all of this stuff down, that's not my problem. I'm just trying to update the state of my key array to represent how long the keys have been down (UP and DOWN for when they've just been pushed, ISUP and ISDOWN for if they are currently down.)
@Mad: chat

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.