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?
-
Maybe will be better if you show current version(with global handler) or describe expected result or example as it implement in wxwidets or another library. – Jun 18 '16 at 16:36
-
Do you mean checking if a key is pressed _now_ or checking if the key has _just_ been pressed? – VZ. Jun 18 '16 at 21:50
-
I don't think it matters that much for me, but checking if a certain key has been pressed since the last time the loop ran would probably be easier to work with. Checking if it's pressed now would be fine though, it's just a continous loop and it runs fast enough that I think it wouldn't matter. – Muibadorei Jun 19 '16 at 01:39
2 Answers
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
...

- 26,174
- 5
- 52
- 73
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.

- 71
- 4