Override a current button?

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
xpali2
Prole
Posts: 38
Joined: Thu Apr 05, 2018 4:47 pm

Override a current button?

Post by xpali2 »

So below is the code for my project's character animation and move function. When I press the d key the character moves right and the animation follows. When you hold the d key and then the a key the character moves to the left. When I try the same but press the a key first the character doesn't switch directions after I press and hold d too. Is there a way of fixing this without drifting too far from my original data structure? I also would like to know how to make the move function so that the character can move both right and up at the same time(e.g) so that it moves laterally.
Oh and btw, the arms and body are animated separately so the character can run and slash his sword at the same time. (if you were wondering)

Thanks for having a look,

xpali2

edit: I already seem to know that this is due to the order of draw statements in player_draw() but would like to keep the function this way

Code: Select all

local frameTime = 0
local frameArmTime = 0

function player_load()
  idle = love.graphics.newImage("Player/KnightlyIdle.png")
  unarmedRun = love.graphics.newImage("Player/Knightlyunarmedrunningcycle.png")
  armedRun = love.graphics.newImage("Player/Knightlyarmedruncycle.png")
  verticalRun = love.graphics.newImage("Player/KnightlyFrontandBackRunAnimation.png")
  attackblockArms = love.graphics.newImage("Player/Knightlyattackandblockarms.png")
  player = {
    Animations = {
  idleQuads = {
    love.graphics.newQuad(0, 0, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(32, 0, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(64, 0, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(96, 0, 32, 32, idle:getDimensions())
  },
  idleArmQuads = {
    love.graphics.newQuad(0, 64, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(32, 64, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(64, 64, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(96, 64, 32, 32, idle:getDimensions())
  },
  idleArmedQuads = {
    love.graphics.newQuad(0, 32, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(32, 32, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(64, 32, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(96, 32, 32, 32, idle:getDimensions())
  },
  idleArmedArmQuads= {
    love.graphics.newQuad(0, 96, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(32, 96, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(64, 96, 32, 32, idle:getDimensions()),
    love.graphics.newQuad(96, 96, 32, 32, idle:getDimensions())
  },
  runQuads = {
    love.graphics.newQuad(0, 0, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(32, 0, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(64, 0, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(96, 0, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(0, 32, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(32, 32, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(64, 32, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(96, 32, 32, 32, unarmedRun:getDimensions())
  },
  runQuadsArms = {
    love.graphics.newQuad(0, 64, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(32, 64, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(64, 64, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(96, 64, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(0, 96, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(32, 96, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(64, 96, 32, 32, unarmedRun:getDimensions()),
    love.graphics.newQuad(96, 96, 32, 32, unarmedRun:getDimensions())
  },
  armedRunQuads = {
    love.graphics.newQuad(0, 0, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(32, 0, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(64, 0, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(96, 0, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(0, 32, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(32, 32, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(64, 32, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(96, 32, 32, 32, armedRun:getDimensions())
  },
  armedRunQuadsArms = {
    love.graphics.newQuad(0, 64, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(32, 64, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(64, 64, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(96, 64, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(0, 96, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(32, 96, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(64, 96, 32, 32, armedRun:getDimensions()),
    love.graphics.newQuad(96, 96, 32, 32, armedRun:getDimensions())
  },
  vRunQuadsDown = {
    love.graphics.newQuad(0, 0, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(32, 0, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(64, 0, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(96, 0, 32, 32, verticalRun:getDimensions())
  },
  vRunQuadsUp = {
    love.graphics.newQuad(0, 64, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(32, 64, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(64, 64, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(96, 64, 32, 32, verticalRun:getDimensions())
  },
  vArmedRunQuadsDown = {
    love.graphics.newQuad(0, 32, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(32, 32, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(64, 32, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(96, 32, 32, 32, verticalRun:getDimensions())  
  },
  vArmedRunQuadsUp = {
    love.graphics.newQuad(0, 96, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(32, 96, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(64, 96, 32, 32, verticalRun:getDimensions()),
    love.graphics.newQuad(96, 96, 32, 32, verticalRun:getDimensions())
  },
  blockArms = {
    love.graphics.newQuad(0, 32, 32, 32, attackblockArms:getDimensions()),
    love.graphics.newQuad(32, 32, 32, 32, attackblockArms:getDimensions()),
    love.graphics.newQuad(64, 32, 32, 32, attackblockArms:getDimensions()),
    love.graphics.newQuad(96, 32, 32, 32, attackblockArms:getDimensions())
  },
  attackArms = {
    love.graphics.newQuad(0, 0, 32, 32, attackblockArms:getDimensions()),
    love.graphics.newQuad(32, 0, 32, 32, attackblockArms:getDimensions()),
    love.graphics.newQuad(64, 0, 32, 32, attackblockArms:getDimensions()),
    love.graphics.newQuad(96, 0, 32, 32, attackblockArms:getDimensions())
  },
 },
currentQuad = 1,
currentArmQuad = 1,
x = 400,
y = 300,
xoffset = 16,
yoffset = 16,
hp = 100,
dmg = 25,
status = "idle",
armStatus = "idle",
isArmed = false,
yscale = 1,
xscale = 1,
speed = 75
}
end

function player_draw()
  if player.status == "idle" then
  love.graphics.draw(idle, player.Animations.idleQuads[player.currentQuad], player.x - player.xoffset, player.y - player.yoffset, 0, player.xscale, player.yscale)
  love.graphics.draw(idle, player.Animations.idleArmQuads[player.currentArmQuad], player.x - player.xoffset, player.y - player.yoffset, 0, player.xscale, player.yscale)
  
elseif player.status == "runleft" then
  love.graphics.draw(unarmedRun, player.Animations.runQuads[player.currentQuad], player.x - player.xoffset, player.y - player.yoffset, 0, player.xscale, player.yscale)
  love.graphics.draw(unarmedRun, player.Animations.runQuadsArms[player.currentArmQuad], player.x - player.xoffset, player.y - player.yoffset, 0, player.xscale, player.yscale)
  
elseif player.status == "runright" then
  love.graphics.draw(unarmedRun, player.Animations.runQuads[player.currentQuad], player.x - player.xoffset, player.y - player.yoffset, 0, player.xscale, player.yscale)
  love.graphics.draw(unarmedRun, player.Animations.runQuadsArms[player.currentArmQuad], player.x - player.xoffset, player.y - player.yoffset, 0, player.xscale, player.yscale)
  end
end

function player_update(dt)
  
  if love.keyboard.isDown("a") then
    player.x = player.x - player.speed * dt
  
  elseif love.keyboard.isDown("d") then
    player.x = player.x + player.speed * dt
  end
  
if love.keyboard.isDown("a") then
   if player.isArmed == false then
    player.status = "runleft"
    player.xscale = -1
    player.xoffset = -16
   elseif player.isArmed == true then
    player.status = "runleftarmed"
    player.xscale = -1
    player.xoffset = -16
  end

elseif love.keyboard.isDown("w") then
  
elseif love.keyboard.isDown("s") then
  
elseif love.keyboard.isDown("d") then
   if player.isArmed == false then
    player.status = "runright"
    player.xscale = 1
    player.xoffset = 16
   elseif player.isArmed == true then
    player.status = "runrightarmed"
    player.xscale = 1
    player.xoffset = 16
   end
  else player.status = "idle"
end
  
  if player.status == "runleft" then
     frameTime = frameTime + dt
  for i, v in pairs(player.Animations.runQuads) do
    if frameTime > 0.1 then
      player.currentQuad = player.currentQuad + 1
      frameTime = 0
    elseif player.currentQuad > 8 then
      player.currentQuad = 1
      end
    end
  end
  
  if player.status == "runleft" then
    frameArmTime = frameArmTime + dt
    for i, v in pairs(player.Animations.runQuadsArms) do
      if frameArmTime > 0.1 then
      player.currentArmQuad = player.currentArmQuad + 1
      frameArmTime = 0
    elseif player.currentArmQuad > 8 then
     player.currentArmQuad = 1
    end
  end
end

if player.status == "runright" then
  frameTime = frameTime + dt
  for i, v in pairs(player.Animations.runQuads) do
    if frameTime > 0.1 then
      player.currentQuad = player.currentQuad + 1
      frameTime = 0
    elseif player.currentQuad > 8 then
      player.currentQuad = 1
    end
  end
end

if player.status == "runright" then
  frameArmTime = frameArmTime + dt
  for i, v in pairs(player.Animations.runQuadsArms) do
      if frameArmTime > 0.1 then
        player.currentArmQuad = player.currentArmQuad + 1
        frameArmTime = 0
      elseif player.currentArmQuad > 8 then
        player.currentArmQuad = 1
      end
    end
  end
  

  
  if player.status == "idle" then
     frameTime = frameTime + dt
  for i, v in pairs(player.Animations.idleQuads) do
  if frameTime > 0.5 then
    player.currentQuad = player.currentQuad + 1
    frameTime = 0
  elseif player.currentQuad > 4 then
    player.currentQuad = 1
   end
  end
end

  if player.status == "idle" then
     frameArmTime = frameArmTime + dt
  for i, v in pairs(player.Animations.idleArmQuads) do
    if frameArmTime > 0.5 then
     player.currentArmQuad = player.currentArmQuad + 1
    frameArmTime = 0
  elseif player.currentArmQuad > 4 then
    player.currentArmQuad = 1
    end
   end
  end
end

function player_keypressed(key)
end

function player_mousepressed(x, y, button)
end
User avatar
ArchAngel075
Party member
Posts: 319
Joined: Mon Jun 24, 2013 5:16 am

Re: Override a current button?

Post by ArchAngel075 »

Its due to the elseif from what i see.
If you have all keys in their own if...then blocks then they will not exclude.

assume w is down
assume a is down

Code: Select all

--psuedocode
if w is down
	--do stuff W
elseif a is down
	--do stuff a
end
here if w is true, then we never evaluate a etc.

but if we do

Code: Select all

--psuedocode
if w is down
	--do stuff W
end
if a is down
	--do stuff a
end
then w does not prevent a from being evaluated.
Though mind the last evaluated key is overrides state :

Code: Select all

--psuedocode
if a is down
	--make state a
end
if d is down
	--make state d
end
here the state is d if a and d is down. you can choose to select which is more preferred between the two by using if...elseif
ie :

Code: Select all

--psuedocode
if a is down
	--make state a
elseif d is down
	--make state d
end
if w is down
	--make state w 
elseif s is down
	--make state s
end
here we select d and s to win if they are down alongside their opposites.

If you want to use the latest key pressed, then you need to track onKeyPress states and have logic that prefers the latest of the keys.
ie if a is pressed, the d and then w but not s. we prefer d between a and d and we prefer w between w (s is not pressed)

Hope this makes sense.
This is my attempt at explaining, perhaps someone else can do better? I tend to miss communicate haha.
xpali2
Prole
Posts: 38
Joined: Thu Apr 05, 2018 4:47 pm

Re: Override a current button?

Post by xpali2 »

ArchAngel075 wrote: Thu Nov 08, 2018 6:55 pm Its due to the elseif from what i see.
If you have all keys in their own if...then blocks then they will not exclude.

assume w is down
assume a is down

Code: Select all

--psuedocode
if w is down
	--do stuff W
elseif a is down
	--do stuff a
end
here if w is true, then we never evaluate a etc.

but if we do

Code: Select all

--psuedocode
if w is down
	--do stuff W
end
if a is down
	--do stuff a
end
then w does not prevent a from being evaluated.
Though mind the last evaluated key is overrides state :

Code: Select all

--psuedocode
if a is down
	--make state a
end
if d is down
	--make state d
end
here the state is d if a and d is down. you can choose to select which is more preferred between the two by using if...elseif
ie :

Code: Select all

--psuedocode
if a is down
	--make state a
elseif d is down
	--make state d
end
if w is down
	--make state w 
elseif s is down
	--make state s
end
here we select d and s to win if they are down alongside their opposites.

If you want to use the latest key pressed, then you need to track onKeyPress states and have logic that prefers the latest of the keys.
ie if a is pressed, the d and then w but not s. we prefer d between a and d and we prefer w between w (s is not pressed)

Hope this makes sense.
This is my attempt at explaining, perhaps someone else can do better? I tend to miss communicate haha.
Thanks that solved one of the issues. But now if you hold both the a and d key for example the character stops moving. Can I make it so that if two buttons across from each other are pressed that it goes with the most recently held button? Really appreciate it.
edit: Nevermind just noticed you actually did go into that point. Though I still don't really understand how to make it happen.
Last edited by xpali2 on Thu Nov 08, 2018 8:07 pm, edited 1 time in total.
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Re: Override a current button?

Post by pgimeno »

If you want your character to keep moving when both keys are pressed, but to remember the last key pressed, the idea is as follows: you need a movement state; when both left and right are off, you set it to "none" (or "stopped" or "idle" or "standing" or whatever you prefer), and when one key goes from off to on, you set it to "left" or "right" as appropriate. Then your movement code will react to that state, rather than to the keys directly.

To detect when a key is pressed, you can use either the love.keypressed / love.keyreleased events, or keep the last seen state of each key in a variable, so that you can check the last state and the current one.

For example:

Code: Select all

local movementState = "none"
local currentLeft = false
local currentRight = false

function love.update(dt)
  local previousLeft = currentLeft
  local previousRight = currentRight
  currentLeft = love.keyboard.isScancodeDown("a")
  currentRight = love.keyboard.isScancodeDown("d")

  if currentLeft == false and currentRight == false then
    movementState = "none"
  elseif previousLeft == false and currentLeft == true then
    movementState = "left"
  elseif previousRight == false and currentRight == true then
    movementState = "right"
  end

  if movementState == "left" then
    -- update player to move left
  elseif movementState == "right" then
    -- update player to move right
  end

...
You can also keep a separate up/down state and handle the vertical movement separately, so your character can move diagonally.

Note I used love.keyboard.isScancodeDown rather than isDown. That way your game can reach the French market too :)
xpali2
Prole
Posts: 38
Joined: Thu Apr 05, 2018 4:47 pm

Re: Override a current button?

Post by xpali2 »

pgimeno wrote: Thu Nov 08, 2018 7:55 pm If you want your character to keep moving when both keys are pressed, but to remember the last key pressed, the idea is as follows: you need a movement state; when both left and right are off, you set it to "none" (or "stopped" or "idle" or "standing" or whatever you prefer), and when one key goes from off to on, you set it to "left" or "right" as appropriate. Then your movement code will react to that state, rather than to the keys directly.

To detect when a key is pressed, you can use either the love.keypressed / love.keyreleased events, or keep the last seen state of each key in a variable, so that you can check the last state and the current one.

For example:

Code: Select all

local movementState = "none"
local currentLeft = false
local currentRight = false

function love.update(dt)
  local previousLeft = currentLeft
  local previousRight = currentRight
  currentLeft = love.keyboard.isScancodeDown("a")
  currentRight = love.keyboard.isScancodeDown("d")

  if currentLeft == false and currentRight == false then
    movementState = "none"
  elseif previousLeft == false and currentLeft == true then
    movementState = "left"
  elseif previousRight == false and currentRight == true then
    movementState = "right"
  end

  if movementState == "left" then
    -- update player to move left
  elseif movementState == "right" then
    -- update player to move right
  end

...
You can also keep a separate up/down state and handle the vertical movement separately, so your character can move diagonally.

Note I used love.keyboard.isScancodeDown rather than isDown. That way your game can reach the French market too :)
Interesting, and I can place a similar system over the code(since slightly changed) I have now? Thanks for the love.isScancodeDown tip, will do ;).
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Re: Override a current button?

Post by pgimeno »

xpali2 wrote: Thu Nov 08, 2018 8:15 pm Interesting, and I can place a similar system over the code(since slightly changed) I have now?
Pretty much. Add that as a prefix, and just replace 'love.keyboard.isDown("a")' with 'movementState == "left"' and so on. I haven't examined your code in detail, but from a cursory read, it looks like that will do.
Post Reply

Who is online

Users browsing this forum: No registered users and 21 guests