Thread: Design opinion: keyboard input

  1. #1
    The larch
    Join Date
    May 2006
    Posts
    3,573

    Design opinion: keyboard input

    While I probably won't be writing any games any time soon, I thought I'd try to implement a (crude) keyboard input system (out of theoretical interest).

    Its idea is to separate scanning for keyboard input from processing it. (I hope this is a worthy goal and I have indeed achieved this?)

    The KeyboardReader keeps a list of EventWatchers which call the process() method of a previously registered EventHandler and pass it some information via a KeyboardEvent object.

    The usage looks like this (using Allegro):
    Code:
    int main() {
        init();
    
        GameManager game; //derived from EventHandler
        Object obj(SCREEN_W/2, SCREEN_H/2, 40); //also from EventHander
    
        KeyboardReader kb;
        kb.attach(&game, KeyboardReader::KeyDown, GameManager::GAME_OVER, KEY_ESC);
        kb.attach(&game, KeyboardReader::KeyDown, GameManager::GAME_OVER, KEY_SPACE);
        kb.attach(&game, KeyboardReader::KeyUp, GameManager::GAME_OVER, KEY_ENTER);
        kb.attach(&game, KeyboardReader::KeyDown, GameManager::DRAW_BLUE, KEY_B);
        kb.attach(&game, KeyboardReader::KeyDown, GameManager::DRAW_GREEN, KEY_G);
        kb.attach(&game, KeyboardReader::KeyUp, GameManager::DRAW_RED, KEY_B);
        kb.attach(&game, KeyboardReader::KeyUp, GameManager::DRAW_RED, KEY_G);
        kb.attach(&obj, KeyboardReader::KeyHeld, Object::LEFT, KEY_LEFT);
        kb.attach(&obj, KeyboardReader::KeyHeld, Object::RIGHT, KEY_RIGHT);
        kb.attach(&obj, KeyboardReader::KeyHeld, Object::UP, KEY_UP);
        kb.attach(&obj, KeyboardReader::KeyHeld, Object::DOWN, KEY_DOWN);
    
        BITMAP* buffer = create_bitmap(SCREEN_W, SCREEN_H);
    
        while (!game.over()) {
            kb.run_scan();
    
            game.draw_background(buffer);
            obj.draw(buffer);
            vsync();
            blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
        }
        destroy_bitmap(buffer);
    
        deinit();
        return 0;
    }
    END_OF_MAIN()
    Any criticism or suggestions?

    (I'll attach the source files. Since there's a limit of 5 files, the rest will follow in the next post.)
    Last edited by anon; 10-14-2007 at 09:19 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The rest of the files
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You may want to consider a function where you can set a range of keys to the same function.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Quote Originally Posted by matsp View Post
    You may want to consider a function where you can set a range of keys to the same function.
    I'm not sure I follow you entirely. All the different messages for one recipient end up in a single function.

    The prototype of KeyboardReader::attach specifies:
    - the object who will be notified (any class as long as it inherits from EventHandler and implements the abstract process() method);
    - the kind of event to be notified of (enum, currently for key held, key pressed and key released);
    - the ID of the event by which the handler can recognize the event (one idea is that the eventual handler doesn't care what the particular KEY is, and several keys can be associated with the same ID)
    - the keyboard key to watch.

    An overload of the attach() method might be added to specify a range of keys that are to be watched (e.g 0...9) of a particular event.

    One thing that bothers me a little, is that while the event-watchers already know which particular event was triggered, when this information reaches the handler, it will have to find this out again in a switch or if-else chain. For example, in my example GameManager implements process() like that:
    Code:
        void process(const KeyboardEvent& event)
        {
            if (event.get_id() == GAME_OVER) {
                is_over = true;
            }
            else { //else missing in attachment by mistake
                colour = event.get_id();
            }
        }
    I don't think this is a place to worry about performance, though, and this function would be called very seldom after all. There should be many ways to optimize the work of the KeyboardReader and EventWatchers, but as this should be a "black box", this could be done any time.

    Another thing that might cause problems would be a scenario, where one EventHandler destroys another EventHandler in its process() method, leading to bad things if the other handler needs to be notified of an event. Currently this is something that one simply must not do. One must let the input loop run to the end.

    There are other questions, such as: if an EventHandler has associated one ID with several keys which are pressed simultaneously, should it be notified of all these, or once per unique ID in an input loop? But I guess this is an internal implementation issue.

    I am also thinking that the current KeyboardReader (with a changed name) could be extended to process other kind of input (such as mouse), as the process would be practically the same. Or should that be a different object?

    Anyway, the general idea is that the logic of tracing input is localized in one place, and the eventhandler does not need to know about this process (as it is an API-specific thing). I hope I'm moving in the right direction and not just overcomplicating simple things?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help using inline assembly for keyboard input
    By sleventeen in forum C Programming
    Replies: 7
    Last Post: 05-10-2009, 01:31 AM
  2. Keyboard Input
    By CaliJoe in forum C++ Programming
    Replies: 3
    Last Post: 05-08-2009, 09:51 AM
  3. problem with keyboard input
    By fighter92 in forum Game Programming
    Replies: 6
    Last Post: 03-20-2009, 09:41 AM
  4. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  5. Keyboard Input
    By Unregistered in forum C++ Programming
    Replies: 5
    Last Post: 07-29-2002, 11:41 AM