Optimal way for wasd movement, no diagonals?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Eglaios
Prole
Posts: 36
Joined: Mon May 03, 2021 8:45 pm

Optimal way for wasd movement, no diagonals?

Post by Eglaios »

I want to make a sprite move using wasd on a 2d environment, but without diagonals.

For this, I need more than a basic if-else due to priority : if I press "right" while "up" is already down, I'd want the sprite to go right, though depending on which keytest runs first, "right" is likely to be ignored, returning "up" instead, which is a problem.

So I thought about something like this :

Code: Select all

local last_direction
local directions = {"w","a","s","d"}

function love.keypressed(k)
 for i, key in pairs(directions) do
  if k == key then
   last_direction = key
   break
  end
 end
end

function love.update(dt)
 if love.keyboard.isDown(directions) then
  if love.keyboard.isDown(last_direction) then
   move(last_direction)
  else
   --Test other keys in case last_direction got released while another one was still down
   if love.keyboard.isDown("w") then
    move("w")
   end
   --Run test for each other directions as well
  end
 end
end

function move(key)
 --Move the sprite towards key's direction
end
Didn't verify the syntax, but it's pretty much about registering the last direction input so it gets priorized, this being followed by an if-else keytest in case the last key got released while another one was still down.

So would this be good enough for a non-diagonal 2d control? Would there be a better way? If not, could I change anything to improve this code?


Thanks once more to anyone who will take the time to answer!
Currently working on game music...
User avatar
darkfrei
Party member
Posts: 1169
Joined: Sat Feb 08, 2020 11:09 pm

Re: Optimal way for wasd movement, no diagonals?

Post by darkfrei »

Normally it's enough to make something like:
if up then move_up()
elseif down then move_down()
elseif left then move_left()
elseif right then move_right()
else move_as_before() end
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Optimal way for wasd movement, no diagonals?

Post by pgimeno »

That might work, though I'd be careful to clean last_direction when no movement key is pressed. It still favours one direction over the others when three keys are pressed and the direction key is released, though; to do it 100% right you'd need to add the movement keys to a table. But that's a minor thing.

Also, note that the position of WASD varies depending on the keyboard language. For example, the equivalent of WASD on French keyboards is ZQSD, and it's very difficult for a French to play a game with WASD controls. To avoid problems, always use the second argument of love.keypressed instead of the first, and isScancodeDown instead of isDown.

And better use ipairs instead of pairs in this case.
User avatar
milon
Party member
Posts: 472
Joined: Thu Jan 18, 2018 9:14 pm

Re: Optimal way for wasd movement, no diagonals?

Post by milon »

Eglaios wrote: Sun Sep 12, 2021 9:07 pm I want to make a sprite move using wasd on a 2d environment, but without diagonals.

For this, I need more than a basic if-else due to priority : if I press "right" while "up" is already down, I'd want the sprite to go right, though depending on which keytest runs first, "right" is likely to be ignored, returning "up" instead, which is a problem.
I actually just posted a sample Love at https://love2d.org/forums/viewtopic.php?f=4&t=91962 for input handling. It reacts as you've requested - the latest input key takes precedence over the others, using love.keypressed(). If you're pressing Up and then press Right, the sprite will start moving Right. If you then release Right, the sprite will stop (you didn't re-press Up). I'm not sure if that's exactly the behavior you want or not, but it's a starter. It also doesn't use giant IF blocks for keyboard input. But it does use ugly IF blocks for handling swipe gestures for touch input - I'm new at that, lol. :)

EDIT - The movement is a little jerky because of using love.keypressed(). I don't code action games like platformers (so far) so it's irrelevant to me, but I believe this could be improved by setting a variable in the input handler (like keys.last maybe), and use love.update() to check if the key/scancode is still down (love.keyboard.isDown or love.keyboard.isScancodeDown).
Any code samples/ideas by me should be considered Public Domain (no attribution needed) license unless otherwise stated.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 50 guests