Computer Science Canada

Advanced Input - Keyboard and Mouse Events (Not Simple States)

Author:  Zren [ Tue Sep 13, 2011 9:45 pm ]
Post subject:  Advanced Input - Keyboard and Mouse Events (Not Simple States)

Advanced Input and Input Events (In.tu)


The built in modules for input (Input / Mouse) revolve around the state of the input. Is the key being pressed? Is the person pressing the mouse button down? When people really want to know when someone releases the mouseButton (mouse click) or limit creating a new box to when you just press the key down and not for the entire duration you're holding it. This module will simplify that process for you. It can also manage all the regular "pressed" events for you in a single place. So you won'thave to hassle yourself with input variable containers for every program. Especially usefull as you need to set up twice the variables in order to get the last state of the input object to tell if the states have changed, a requirement to tell events from simple states.


How To Use It
Put the file in the same folder as your project. Then put this at the top of your program:
Turing:

import In


You then need to call: In.Initialize() in it's appropriate place. If you're managing your own windows, make sure to open your own window(s) first before calling this procedure. Calling it beforehand will end up opening a second window (the default running window) as the input initialization requires a window to be open when calling it's functions.

You will need to place In.Update() in your main program loop, or wherever you require input to be updating.

Call the functions pertaining to input events when desired.
Turing:

if In.MouseDown () then
    ...
end if


Here's an example of the module in action:
Turing:

import In

% The run code
var fpsDelay : int
proc setFPS (n : int)
    fpsDelay := 1000 div n
end setFPS
setFPS (60)

proc charLine (s : string, f : function f2 (c : char) : boolean)
    put s ..
    for c : char
        if f (c) then
            put c, "" ..
        end if
    end for
    put ""
end charLine

% Make sure to open your windows first!
var window := Window.Open ("graphics:640;480,nobuttonbar,offscreenonly")

% The initilization code requires a window to exist. Opening your own window
% afterwards will result in an extra window (the default run window).
In.Initialize()

loop
    In.Update ()
    exit when In.KeyDown (KEY_ESC)

    cls
    put "ESC to Exit",skip
    put "Mouse: (", In.mouse.x, ",", In.mouse.y, ") ", In.mouse.b
    put "    Up: ", In.MouseUp ()
    put "    Pressed: ", In.MousePressed ()
    put "    Down: ", In.MouseDown ()
    put "    DoubleClick: ", In.DoubleClick (500)
    put "    Last Up: ", Time.Elapsed - In.mouseLast.lastUp

    put "Keyboard: "
    charLine ("    Down: ", In.KeyDown)
    charLine ("    Pressed: ", In.KeyPressed)
    charLine ("    Up: ", In.KeyUp)

    View.Update
    delay (fpsDelay)
end loop
Window.Close (window)


How It Works
Basically whenever it updates, it takes the state currently remembered and moves it to the ___Last variables. The function calls to check if an event has taken place will then check the current state versus the last state. DoubleClick and DoubleType events have a little more attached. Every time a key is released or a mouse button is clicked, it remembers the time. Then you can do math when the the ___Up event is fired again, and check the difference in time.

Download

Author:  Zren [ Sun Mar 25, 2012 9:39 pm ]
Post subject:  Re: Advanced Input - Keyboard and Mouse Events (Not Simple States)

Version 2


Long ago I started a Gui module built on this module. I ran into a roadblock when trying to get the special characters found when using SHIFT. It requires using the input buffer provided with getchar and hasch but that would lose functionality for KeyUp and KeyPressed as there's no way to detect when the key is lifted through an event (if there was, then this entire module would be moot). So I decided to create a central area to check the buffer. Due to it's nature, you would need to centralize all your input somewhere as it reads from the buffer. Thus, this module now stores it, and let's you check what's being fired this cycle with In.KeyFired(char). I've also added a similar In.charsLastFired array. Advantages to using KeyFired instead are:


  • Holding a key will use fire repetitively per OS settings.
  • Possible to check for special characters.


While lookups might be faster with a full array char of boolean. Iterating through the collection will be a constant speed of max iterations (256). While not a huge performance guzzler, I considered storing the buffer into a flexible array. So I might do a version 3 later. Right now, any speed loss of resizing the array as it pulls from the buffer is probably dwarfed by the charsFiredCheck := charsEmpty copy ... probably.

Test

While only containing a a minimal change, it's probably best to readd the whole thing. Here's the updated test example of the module in action:
Turing:

import In

% The run code
var fpsDelay : int
proc setFPS (n : int)
    fpsDelay := 1000 div n
end setFPS
setFPS (60)

proc charLine (s : string, f : function f2 (c : char) : boolean)
    put s ..
    for c : char
        if f (c) then
            put c, "" ..
        end if
    end for
    put ""
end charLine

% Make sure to open your windows first!
var window := Window.Open ("graphics:640;480,nobuttonbar,offscreenonly")

% The initilization code requires a window to exist. Opening your own window
% afterwards will result in an extra window (the default run window).
In.Initialize ()

loop
    In.Update ()
    exit when In.KeyFired (KEY_ESC)

    cls
    put "ESC to Exit", skip
    put "Mouse: (", In.mouse.x, ",", In.mouse.y, ") ", In.mouse.b
    put "    Up: ", In.MouseUp ()
    put "    Pressed: ", In.MousePressed ()
    put "    Down: ", In.MouseDown ()
    put "    DoubleClick: ", In.DoubleClick (500)
    put "    Last Up: ", Time.Elapsed - In.mouseLast.lastUp

    put "Keyboard: "
    charLine ("    Fired: ", In.KeyFired)
    charLine ("    Down: ", In.KeyDown)
    charLine ("    Pressed: ", In.KeyPressed)
    charLine ("    Up: ", In.KeyUp)

    View.Update
    delay (fpsDelay)
end loop
Window.Close (window)



GitHub

The file is on GitHub (along with a few other modules). You can view the latest version here: https://github.com/Zren/TuringAltModules/blob/master/Modules/In.tu


Download

A code frozen version can be downloaded below.


: