I am making a game in Matlab (a sort of space invaders shooter) The graphics are all on one figure and just generated with multiple plots, I am aware that matlab is not meant for such things, which makes it particularly fun to show classmates. for the key inputs I am currently using:
f = figure(1)
set(f, 'KeyPressFcn', @(x,y)disp(get(f,'CurrentCharacter')));
a = get(f,'CurrentCharacter');
if a=='w' %move up..
if a=='d' %move right..
if a=='2' %switch to weapon 2..
This works perfectly but each time a key is pressed it is displayed on the console, causing unwanted lag.
I tried:
f = figure(1)
set(f, 'KeyPressFcn');
a = get(f,'CurrentCharacter');
but it displays "string -or- function handle -or- cell array" each time a key is pressed.
How do I identify a Key Press and store it into a variable without having anything pop up on the console? I would also prefer not having to make second function, as everything is kept cleanly in one .m file at the moment.
Thanks!
As the author of a few popular games on MATLAB Central, I can give you an idea of how to do this properly in MATLAB. I cannot guarantee my way is not the most optimal, but this is the best solution I have come up with after thinking about this problem for years. Firstly, there are a few principles that I usually follow when writing up games:
Use 'CurrentKey' in favour of 'CurrentCharacter', since the former recognizes more keys that are not classified as 'characters'.
You may also need a 'KeyReleaseFcn' since this is a shoot'em'up. Usually you would like the aircraft to keep moving when you hold down a key, and stop when you release the key; you don't want to press and release a key repeatedly in order for the aircraft to keep moving. How it works is: when the player presses down 'w', we invoke KeyPressedFcn once, in which we set a flag variable 'w_status' to true; when the player releases 'w', invoke KeyReleasedFcn once, and set the flag to flase. In the main loop of the game, repeatedly check if 'w_status' is true. If so, then move aircraft up by one step, otherwise don't update the position.
If you want to keep everything in one file, try to implement KeyPressFcn and KeyReleaseFcn as nested functions. It is better than squeezing all the code in to a one-liner.
Avoid hard coded key names in if-else clauses. You may later want to allow the user to reassign the keys, so it is a better idea to keep the key names in an array which you can modify.
So the entire game will look like this:
function MainGame()
KeyStatus = false(1,6); % Suppose you are using 6 keys in the game
KeyNames = {'w', 'a','s', 'd', 'j', 'k'};
KEY.UP = 1;
KEY.DOWN = 2;
KEY.LEFT = 3;
KEY.RIGHT = 4;
KEY.BULLET = 5;
KEY.BOMB = 6;
...
gameWin = figure(..., 'KeyPressFcn', @MyKeyDown, 'KeyReleaseFcn', @MyKeyUp)
...
% Main game loop
while GameNotOver
if KeyStatus(KEY.UP) % If left key is pressed
player.y = player.y - ystep;
end
if KeyStatus(KEY.LEFT) % If left key is pressed
player.x = player.x - xstep;
end
if KeyStatus(KEY.RIGHT) % If left key is pressed
%..
end
%...
end
% Nested callbacks...
function MyKeyDown(hObject, event, handles)
key = get(hObject,'CurrentKey');
% e.g., If 'd' and 'j' are already held down, and key == 's'is
% pressed now
% then KeyStatus == [0, 0, 0, 1, 1, 0] initially
% strcmp(key, KeyNames) -> [0, 0, 1, 0, 0, 0, 0]
% strcmp(key, KeyNames) | KeyStatus -> [0, 0, 1, 1, 1, 0]
KeyStatus = (strcmp(key, KeyNames) | KeyStatus);
end
function MyKeyUp(hObject, event, handles)
key = get(hObject,'CurrentKey');
% e.g., If 'd', 'j' and 's' are already held down, and key == 's'is
% released now
% then KeyStatus == [0, 0, 1, 1, 1, 0] initially
% strcmp(key, KeyNames) -> [0, 0, 1, 0, 0, 0]
% ~strcmp(key, KeyNames) -> [1, 1, 0, 1, 1, 1]
% ~strcmp(key, KeyNames) & KeyStatus -> [0, 0, 0, 1, 1, 0]
KeyStatus = (~strcmp(key, KeyNames) & KeyStatus);
end
end
Notice that the callbacks make use of a 'dictionary' KeyNames to eliminate the need of any if-else clauses. This way, regardless of the number of keys to use and what they are actually used for, these two functions can be plugged into ANY game without any modification.
To see how this idea works in real life, you can check out my games on MATLAB Central:
http://www.mathworks.com/matlabcentral/fileexchange/authors/111235
There is one space shooting game 'Stellaria' there. However, it was written back in the day when I did not know about nested functions, so the code was split into many small function files and might be very hard to read. Please Use with caution.