Listening for key input in wxErlang

344 Views Asked by At

I'm trying to make a small game in Erlang, using wxErlang. My main function is a loop and I need to check if a specific key has been pressed at the start of the loop (up, down, left, right...). Most of the solutions I've found online use a global handler function for events, which is not what I'm looking for in this case. Is there any way to do this?

2

There are 2 best solutions below

0
On

I don't know much about wxErlang but there is way how to collect messages which arrive in a certain interval. It uses an after clause of the receive expression.

collect() ->
    collect([]).

collect(Acc) ->
    receive
        {my_msg, _} = Msg ->
            collect([Msg|Acc])
    after 0 ->
        lists:reverse(Acc)
    end.

main() ->
    ...,
    _ = collect(),    % clean message box or previous loop
    ...,
    Msgs = collect(), % messages arrived after last collect/0
    ...
0
On

Events come into the main receive loop as messages in the form of records:

-record(wx, {    id   :: integer(),         %% Integer Identity of object.
                 obj  :: wx:wx_object(),    %% Object reference that was used in the connect call.
             userData :: term(),            %% User data specified in the connect call.
                event :: event()            %% The event record
        }).

Here is the event you should place into the main receive loop of your code:

%%%
%% Event for Keyboard button press
%

     #wx{ id = _ , event = #wxKey{ type = key_down , 
                                keyCode = integer()}
                                                                }) ->

% Your code where something happens

loop(State);

As for what should the integer() be?

%from wx.hrl
-define(WXK_LEFT, 314).
-define(WXK_UP, 315).
-define(WXK_RIGHT, 316).
-define(WXK_DOWN, 317).

The keyCode integer will be one of these 4, or its macro equivalent.

Some Background

The specific event you are interested in is the wxKey Event:

-record(wxKey,   {type :: wxKeyEventType(), %% Callback event: {@link wxKeyEvent}
                     x :: integer(),
                     y :: integer(),
               keyCode :: integer(),
           controlDown :: boolean(),
             shiftDown :: boolean(),
               altDown :: boolean(),
              metaDown :: boolean(),
              scanCode :: boolean(),
               uniChar :: integer(),
               rawCode :: integer(),
              rawFlags :: integer()}).

When key events come in, you additionally have these values to add to that tuple and pattern match against. This give you the ability to really hone in on the exact event you are interested. The record generated will have the values equivalent to its type. That is, not all Key events have all of the above values. You can change that initial 'type=' to one of the 4 below.

-type wxKeyEventType() :: char                 %% #wx{ event = #wxKey{ type = char } }
                        | char_hook            %% #wx{ event = #wxKey{ type = char_hook } }
                        | key_down             %% #wx{ event = #wxKey{ type = key_down } }
                        | key_up.              %% #wx{ event = #wxKey{ type = key_up } }

Realize you have quite a bit of command over what can happen.