Page 1 of 1

[SOLVED] Top Down Character Animation in 4 Different Directions

Posted: Wed Nov 22, 2023 4:10 pm
by Todespreis
Hey there! I'm trying to animate my player character walking in different directions.
So my Code for it is

Code: Select all


local player

local direction


function love.load()
    
    FrameDuration = 0.1
    FrameTimer = 0
    FrameIndex = 1
    FramesWalkingDown =    {
       love.graphics.newImage("going_down_01.png"),
       love.graphics.newImage("going_down_02.png"),
       love.graphics.newImage("going_down_03.png"),
       love.graphics.newImage("going_down_04.png"),
       love.graphics.newImage("going_down_05.png"),
       love.graphics.newImage("going_down_06.png")
    }
    FramesWalkingUp = {
       love.graphics.newImage("going_up01.png"),
       love.graphics.newImage("going_up02.png"),
       love.graphics.newImage("going_up03.png"),
       love.graphics.newImage("going_up04.png"),
       love.graphics.newImage("going_up05.png"),
       love.graphics.newImage("going_up06.png")
    }
    FramesWalkingRight = {
      love.graphics.newImage("going_right01.png"),
      love.graphics.newImage("going_right02.png"),
      love.graphics.newImage("going_right03.png"),
      love.graphics.newImage("going_right04.png"),
      love.graphics.newImage("going_right05.png"),
      love.graphics.newImage("going_right06.png")
    }

    FramesWalkingLeft = {
      love.graphics.newImage("going_left01.png"),
      love.graphics.newImage("going_left02.png"),
      love.graphics.newImage("going_left03.png"),
      love.graphics.newImage("going_left04.png"),
      love.graphics.newImage("going_left05.png"),
      love.graphics.newImage("going_left06.png")
    }
  

    FrameEnabled = {FramesWalkingUp[FrameIndex], FramesWalkingDown[FrameIndex], FramesWalkingRight[FrameIndex], FramesWalkingLeft[FrameIndex]}    

    player = {}
    player.x = 70
    player.y = 70

    player.image = love.graphics.newImage("standing_down.png" )

    


end


Down={}
function love.joystickpressed( joystick, button )
  Down[button]=true
end
function love.joystickreleased( joystick, button )
  Down[button]=nil
end

love.update=function (dt)

    FrameTimer = FrameTimer + dt
    if FrameTimer >= FrameDuration then
        FrameTimer = 0
        FrameIndex = FrameIndex + 1
        
        if FrameIndex > #FramesWalkingDown then
            FrameIndex = 1
        end

        if FrameIndex > #FramesWalkingUp then
            FrameIndex = 1
        end

        if FrameIndex > #FramesWalkingLeft then
            FrameIndex = 1
        end

        if FrameIndex > #FramesWalkingRight then
            FrameIndex = 1
        end
        
        if Down[06] then 
            player.x = player.x + 1
            FramesEnabled = FramesWalkingUp[FrameIndex]
        end

        if Down[04] then 
            player.y = player.y + 1
            FramesEnabled = FramesWalkingDown[FrameIndex]
        end

        if Down[02] then 
            player.x = player.x - 1
            FramesEnabled = FramesWalkingRight[FrameIndex]
        end

        if Down[00] then 
            player.y = player.y - 1
            FrameEnabled = FramesWalkingUp[FrameIndex]
        end
    end

    

end



function love.draw()

   
    love.graphics.draw( FrameEnabled, player.x,         player.y  )
  
end
I get the error in line 121 "Bad argument for draw - drawable expected, got table" So i think, the syntax is correct? Can i put the sprites in an array? But how can i tell the interpreter, that he has to look up in the "Down" functions, so dependent of which button is pressed, he has to draw different sprites?

Re: Character Animation in different directions

Posted: Wed Nov 22, 2023 5:01 pm
by BrotSagtMist
As usual, no idea what you question means.
But here is the simplest animation example i could think of and it should probably fix your drawing issue:

Code: Select all

Right={love.graphics.newImage("r1.png"),love.graphics.newImage("r2.png")}
Left={love.graphics.newImage("l1.png"),love.graphics.newImage("l2.png")}
Dummy=Right
animationspeed=4
love.draw=function()
 love.graphics.draw( Dummy[math.floor((love.timer.getTime()*animationspeed)%2)+1], player.x,         player.y  )
end
love.keypressed=function(butt)
 if butt=="right" then
  Dummy=Right
 else
  Dummy=Left
 end 
end
I hope this is self explaining.

Re: Character Animation in different directions

Posted: Wed Nov 22, 2023 6:08 pm
by Todespreis
Thank you very much for the fast reply, but that does'nt work in my case. Because i want to have more than 2 directions (top down). And as always, sorry for my bad english :nyu:

Re: Character Animation in different directions

Posted: Thu Nov 23, 2023 9:56 am
by pgimeno
You're mixing FrameEnabled (without 's') and FramesEnabled (with 's'). But the cause of the error is that you initialize FrameEnabled like this:

Code: Select all

    FrameEnabled = {FramesWalkingUp[FrameIndex], FramesWalkingDown[FrameIndex], FramesWalkingRight[FrameIndex], FramesWalkingLeft[FrameIndex]}    
That's indeed a table. There's nothing in love.update that modifies FrameEnabled during the first frame, therefore that table will reach love.draw(), where the love.graphics.draw(FrameEnabled, ...) call will try to draw a table. That will cause the error you see. Reading the error messages usually helps.

Re: [SOLVED] Top Down Character Animation in 4 Different Directions

Posted: Wed Dec 20, 2023 9:04 pm
by Todespreis
Here is the code, that worked:

Code: Select all

local player

local direction


function love.load()
    
    FrameDuration = 0.1
    FrameTimer = 0
    FrameIndex = 1
    FramesWalkingDown =    {
       love.graphics.newImage("going_down_01.png"),
       love.graphics.newImage("going_down_02.png"),
       love.graphics.newImage("going_down_03.png"),
       love.graphics.newImage("going_down_04.png"),
       love.graphics.newImage("going_down_05.png"),
       love.graphics.newImage("going_down_06.png")
    }
    FramesWalkingUp = {
       love.graphics.newImage("going_up01.png"),
       love.graphics.newImage("going_up02.png"),
       love.graphics.newImage("going_up03.png"),
       love.graphics.newImage("going_up04.png"),
       love.graphics.newImage("going_up05.png"),
       love.graphics.newImage("going_up06.png")
    }
    FramesWalkingRight = {
      love.graphics.newImage("going_right01.png"),
      love.graphics.newImage("going_right02.png"),
      love.graphics.newImage("going_right03.png"),
      love.graphics.newImage("going_right04.png"),
      love.graphics.newImage("going_right05.png"),
      love.graphics.newImage("going_right06.png")
    }

    FramesWalkingLeft = {
      love.graphics.newImage("going_left01.png"),
      love.graphics.newImage("going_left02.png"),
      love.graphics.newImage("going_left03.png"),
      love.graphics.newImage("going_left04.png"),
      love.graphics.newImage("going_left05.png"),
      love.graphics.newImage("going_left06.png")
    }
  

    FrameEnabledDown = FramesWalkingDown[FrameIndex]
    FrameEnabledUp = FramesWalkingUp[FrameIndex]
    FrameEnabledRight = FramesWalkingRight[FrameIndex]
    FrameEnabledLeft = FramesWalkingLeft[FrameIndex]

    player = {}
    player.x = 70
    player.y = 70

    player.image = love.graphics.newImage("standing_down.png" )

    


end


Down={}
function love.joystickpressed( joystick, button )
  Down[button]=true
end
function love.joystickreleased( joystick, button )
  Down[button]=nil
end

love.update=function (dt)

    FrameTimer = FrameTimer + dt
    if FrameTimer >= FrameDuration then
        FrameTimer = 0
        FrameIndex = FrameIndex + 1
        
        if FrameIndex > #FramesWalkingDown then
            FrameIndex = 1
        end

        if FrameIndex > #FramesWalkingUp then
            FrameIndex = 1
        end

        if FrameIndex > #FramesWalkingLeft then
            FrameIndex = 1
        end

        if FrameIndex > #FramesWalkingRight then
            FrameIndex = 1
        end
        
        if Down[06] then 
            player.x = player.x + 3
            FrameEnabledRight = FramesWalkingRight[FrameIndex]
        end

        if Down[04] then 
            player.y = player.y + 3
            FrameEnabledDown = FramesWalkingDown[FrameIndex]
        end

        if Down[02] then 
            player.x = player.x - 3
            FrameEnabledLeft = FramesWalkingLeft[FrameIndex]
        end

        if Down[00] then 
            player.y = player.y - 3
            FrameEnabledUp = FramesWalkingUp[FrameIndex]
        end
    end

    

end



function love.draw()

    if Down[06] then
    
      love.graphics.draw( FrameEnabledRight, player.x, player.y  )
    
    elseif Down[04] then 
   
      love.graphics.draw( FrameEnabledDown, player.x, player.y  ) 
    
    elseif Down[02] then
    
      love.graphics.draw( FrameEnabledLeft, player.x, player.y  )
    
    elseif Down[00] then
      
      love.graphics.draw( FrameEnabledUp, player.x, player.y  )

    else 
            love.graphics.draw( player.image, player.x, player.y  )
    end
  
end
I had to modify the FrameEnabled for every direction, so that it has only to take the frames from that single frame group. It is simple and a bit too long, i guess. I think, i have to short it somehow and try to add a button to run, to crouch and to jump. Still much left to do. But a small victory for today - it's working :-D

Re: [SOLVED] Top Down Character Animation in 4 Different Directions

Posted: Thu Dec 21, 2023 3:37 pm
by RNavega
Looking at your code, two things I think would help you a lot:

- To separate responsibilities better. The love.draw() function should not be the one to find out what frame to draw based on the joystick buttons pressed. Like on that last line that you have in love.draw(), it should just grab whatever image is referenced in some table field, like "player.currentImage", and draw that, at whatever coordinates are stored in player.x and player.y.
Then another part of your code completely separate will be responsible for figuring out what image reference that should be placed in that "player.currentImage".

- To study and practice "finite state machines", something that is used a lot to implement behaviors in games and other interactive programs. It can be used to handle animations, enemy A.I., player control etc.

PS I can tell that you're gonna run into problems with this part here of your code:

Code: Select all

love.update=function (dt)

    FrameTimer = FrameTimer + dt
    if FrameTimer >= FrameDuration then
        FrameTimer = 0
        FrameIndex = FrameIndex + 1
        
        if FrameIndex > #FramesWalkingDown then
            FrameIndex = 1
        end

        if FrameIndex > #FramesWalkingUp then
            FrameIndex = 1
        end

        if FrameIndex > #FramesWalkingLeft then
            FrameIndex = 1
        end

        if FrameIndex > #FramesWalkingRight then
            FrameIndex = 1
        end
...because you're checking the same counter ("FrameIndex") against many different limits, all at once.

By using a different table for each animation, that code of yours could become something like this:

Code: Select all

function love.update(dt)
    advanceAnimation(player.currentAnimation, dt)
end


function love.draw()
    love.graphics.draw(getAnimationFrame(player.currentAnimation), player.x, player.y)
end


function resetAnimation(animation)
    animation.timer = 0.0
    animation.index = 1
end


function advanceAnimation(animation, dt)
    animation.timer = animation.timer + dt
    if animation.timer > animation.duration then
        animation.timer = 0
        animation.index = animation.index + 1
        if animation.index > animation.lastIndex then
            animation.index = 1
        end
    end
end


function getAnimationFrame(animation)
    return animation.frames[animation.index]
end


function createAnimation(frameDuration, frames)
    local animation = {timer=0.0, index=1, duration=frameDuration,
                       frames=frames, lastIndex=#frames}
    return animation
end


local walkingDownAnimation = createAnimation(0.1, FramesWalkingDown)
player.currentAnimation = walkingDownAnimation
Each animation table keeps track of their own timer, frame index and frame limit.

Re: [SOLVED] Top Down Character Animation in 4 Different Directions

Posted: Fri Dec 22, 2023 9:17 am
by Todespreis
Thank you very much for your help @RNavega! Yes, i had a problem with it at the beginning, as i gave an array of animation PNG's to a pointer, so i had to tell him, which animation is to be done at what point. And so i came to this solution. I still don't understand many things and i think, you can see my poor programming skills on the big count of if - statements ^^" . Thank you again, have a nice day and great holidays!