I haven't used anim8, so I don't know how it works, but I think this is the same case as before, but this time with the animations instead of the fonts.
When you go diagonally, the problem is that you're creating many more animations. For example, if you press W and D, first this code executes:
Code: Select all
if love.keyboard.isDown("w") then
player.body:setY(player.body:getY() - player.speed * dt)
if player.andandoW ~= true then -- and not player.andandoA == true and no$
player.animation = anim8.newAnimation(player.grid('1-9',9), 0.1)
player.andandoD = false
player.andandoA = false
player.andandoS = false
player.andandoW = true
player.parado = false
end
end
andandoW is initially false, and this code sets it to true. It also sets andandoD to false. Then this code executes:
Code: Select all
if love.keyboard.isDown("d") then
player.body:setX(player.body:getX() + player.speed * dt)
if player.andandoD ~= true then
player.animation = anim8.newAnimation(player.grid('1-9',12), 0.1)
player.andandoD = true
player.andandoA = false
player.andandoS = false
player.andandoW = false
player.parado = false
end
end
But now andandoD is false (because you set it to false when pressing W), and the animation is created again, and also andandoW is set to false again. In the next frame, both animations will be created again, and so on. You are creating animations at a very high rate, and the garbage collector can not cope with that speed of object creation.
This is also the reason why your player isn't animated when you go diagonally. The animation frame is reset to zero every screen frame, because you're re-creating the animation every time.
Instead of calling newAnimation every time, prepare each animation in variables in advance, and then assign it to player.animation to change the animation. I don't know if you will need to reset the frame to the first too (using gotoFrame, I suppose), because as I said, I haven't used anim8.
Note that the program, as it appears in GitHub, won't work when you pack it into a .love file, because of a mismatch in upper-case and lower-case filenames. In Libraries/libraries.lua, in the first line, you have:
Code: Select all
anim8 = require('libraries/anim8-master/anim8')
However, the folder is called Libraries, with upper case. Similarly, in main.lua line 10, you have:
Code: Select all
require('Load_Sprites/Load-sprites')
However, the file is called load-sprites, with lower case. These problems are also visible in Linux (which is my system) and MacOS because the filesystems are case-sensitive.
Another note: Instead of using love.keyboard.isDown, use
love.keyboard.isScancodeDown. That will allow people with different keyboard layouts to play, For example, in a French keyboard, WASD becomes ZQSD.
Now, you ask how to organize the animations. Here's my advice.
Do not set the animation when pressing keys. Instead, place each key state in a local variable, and use that to change the animation state. That animation state is the only thing that needs to be in the player object. To update the position, store the new position into local variables as well.
Code: Select all
player.animState = ""
local playerGrid = anim8.newGrid(64, 64, player.image:getWidth(), player.image:getHeight()) -- 13 x 21
local playerAnimations = {}
playerAnimations["stopped"] = anim8.newAnimation(playerGrid('1-7',3), 0.1)
playerAnimations["walk left"] = anim8.newAnimation(playerGrid('1-9',10), 0.1)
playerAnimations["walk right"] = anim8.newAnimation(playerGrid('1-9',12), 0.1)
playerAnimations["walk up"] = anim8.newAnimation(playerGrid('1-9',9), 0.1)
playerAnimations["walk down"] = anim8.newAnimation(playerGrid('1-9',11), 0.1)
-- If you don't have animations for the diagonals, you can use this:
playerAnimations["walk up left"] = playerAnimations["walk left"]
playerAnimations["walk up right"] = playerAnimations["walk right"]
playerAnimations["walk down left"] = playerAnimations["walk left"]
playerAnimations["walk down right"] = playerAnimations["walk right"]
player.animation = playerAnimations["stopped"]
function playerUpdate(dt)
if gameState == 0 then
return
end
local andandoW = love.keyboard.isScancodeDown("w")
local andandoA = love.keyboard.isScancodeDown("a")
local andandoS = love.keyboard.isScancodeDown("s")
local andandoD = love.keyboard.isScancodeDown("d")
local newX = player.body:getX()
local newY = player.body:getY()
local oldAnimState = player.animState
-- Update vertical movement and animation state
player.animState = "stopped" -- we start here, we refine it below
if andandoW ~= andandoS then -- one is true, the other is false - means we're moving up or down
if andandoW then -- walking up
newY = newY - player.speed * dt
player.animState = "walk up"
else -- walking down
newY = newY + player.speed * dt
player.animState = "walk down"
end
end
if andandoA ~= andandoD then -- one is true, the other is false - means we're moving left or right
if andandoA then -- walking left
newX = newX - player.speed * dt
-- We have already updated animState with the vertical movement. Use it to handle diagonals.
if player.animState == "walk up" then
player.animState = "walk up left"
elseif player.animState == "walk down" then
player.animState = "walk down left"
else -- vertically stopped
player.animState = "walk left"
end
else -- walking right
newX = newX + player.speed * dt
if player.animState == "walk up" then
player.animState = "walk up right"
elseif player.animState == "walk down" then
player.animState = "walk down right"
else -- vertically stopped
player.animState = "walk right"
end
end
end
if player.animState ~= oldAnimState then
-- The animation needs to be updated because the animation state has changed.
player.animation = playerAnimations[player.animState]
player.animation:gotoFrame(1) -- maybe?
end
-- This is not the best way because it won't handle collisions properly,
-- but it works the same as in your current code.
player.body:setX(newX)
player.body:setY(newY)
end