Hey guys! I started with Solar2D 4 weeks ago and it’s been going pretty well. Now, I want to make games for windows only (no android settings, etc)- and I wrote a player movement script. It moves, except that I’d have to press the key repeatably, rather than holding it down to move.
local function move(event) -- Uses keys to move. Event is just the class that we access to use values if event.keyName == "a" then --print(event.keyName.." was pressed on "..event.phase) player.x = player.x - 5 end if event.keyName == "d" then player.x = player.x + 5 end end
I would split this into two functions: a key press checker which records whether a key is being held, and a frame listener which updates the player every frame based on which keys are recorded as being pressed:
local pressedKeys = {}
local function onKeyEvent(event)
if event.phase == "down" then
pressedKeys[event.keyName] = true
else
pressedKeys[event.keyName] = false
end
end
local function onEnterFrame(event)
if pressedKeys["a"] then
player.x = player.x - 5
end
if pressedKeys["d"] then
player.x = player.x + 5
end
end
Runtime:addEventListener( "key", onKeyEvent )
Runtime:addEventListener( "enterFrame", onEnterFrame )
Thank you so much for this, cheers!!! Quick question: What does pressedKeys[event.keyName] = true mean? Why not check for the keys? What does true mean in this context?
To clarify:
True/false in this context simply means “is held down” or “is not held down”. Checking the key presses themselves is not sufficient, as pressing a key only triggers a single key event (regardless of whether it is tapped or held down). You need to keep a record of it being pressed in your code and then clear that record when the key is released - which is what the pressedKeys table is doing.
In my example, when the “a” key is pressed on the keyboard the onKeyEvent function will be triggered with event.keyName being “a” and event.phase being “down”. So my code says: populate the pressedKeys table, using the event.keyName as the key, and true as the value.
The result would be the same as manually writing out: pressedKeys["a"] = true
Of course writing it out manually like this means it wouldn’t handle other keys, whereas using event.keyName allows it to keep track of all keys being held.
When the key is released the same function will be called, this time with phase == “up”. This in turn will set the pressedKeys value for that particular keyName to false (similar to manually coding it as pressedKeys["a"] = false)
The second part of this is the enterFrame function. This function will run every single frame, and check the current state of the key presses (as recorded in the pressedKeys table). If the key is being held during a frame, it will adjust the x position accordingly. If it’s still being held in the next frame it will adjust it again, and so on. Once the value for that key is set to false (or nil) it will stop updating the player in that direction.