Log In  

Hello together

I just started with pico8, lua and game-programming. I am trying to make a small fighting game and have a question concering animations. I want the player-sprite to be idle and if i click a button it should respond instantly and play an animation. Is there a way I could write the function "punching" with less code? Sprite Number 17, 18 and 19 are the sprites for a punching animation. The function first checks if the current sprite is between 17 or 19...if not it sets it to 17 (start of the punching animation)...then it iterats through the animation and checks again if the sprite is greater then 19 to set it back to 17. I have the feeling I have to much code in it...especially that I check twice if player.sp is greater then 19. Is there a more efficient way? Thanks in advance :)

function _init()
    player={
        sp=1,
        x=59,
        y=59,
        anim=0,
        state="idle",
        flp=false,
    }
end

function _update()
    set_state()
    player_animate()
end

function _draw()
    cls()
    spr(player.sp, player.x, player.y, 1, 1, player.flp)
end

function player_animate()
    if player.state == "idle" then
        idle()
    elseif player.state == "left" then
        printh("left")
    elseif player.state == "right" then
        printh("right")
    elseif player.state == "punching" then
        punching()
    elseif player.state == "defending" then
        printh("defending")
    end
end

function idle()
    if player.sp > 2 then
        player.sp = 1
    elseif time() - player.anim> .5 then
        player.anim=time()
        player.sp+=1
        if player.sp>2 then
            player.sp=1
        end
    end
end

function punching()
    if player.sp < 17 
    or player.sp > 19 then
        player.sp = 17
    elseif time() - player.anim> .1 then
        player.anim=time()
        player.sp+=1
        if player.sp > 19 then
            player.sp = 17
        end
    end
end
P#75555 2020-04-28 13:42

1

You could use a global animation table instead:

anims={
 idle={1},
 punching={17,18,19},
 --etc etc
}
function _init()
 player={ x=59, y=59, flp=false }
 player.play="idle" --you can set a new animation like this, the other variables will be added automatically
end

function _update()
 set_state()
 player_animate(player) --give the function a player, so you can re-use this code
end
function player_animate(p)
 if p.state != p.play then --start a new animation
  p.state = p.play
  p.animindex = 1 --start with the first number in the animation table under that name
  p.time = 0 --reset the timer
 elseif #anims[p.state] > 1 then --continue playing an animation with multiple frames
  p.time += 1
  if p.time >= 3 then --change "3" to adjust the animation framerate
   p.time = 0
   p.animindex = (p.animindex % #anims[p.state]) + 1
   --loops animations. "punching" becomes (ix % 3) + 1, so 1,2,3,1,2,3,1...
  end
 end
 p.sp = anims[p.state][p.animindex]
end

Then you can just add new animations to the anims table. If you want some frames to last longer, just enter them in the list twice, or change the framerate for all animations to be longer. There are more complicated and efficient ways to do this, but this should get you started!

P#75584 2020-04-29 10:38

Thanks a lot shy...this is really good....way better then the code i had in place.

P#75587 2020-04-29 12:37
2

You're welcome! I just realized that "idle" is two frames played slowly, though, so you can change its animation to this to make it match your old one:

idle={1,1,1,1,1,2,2,2,2,2},
P#75600 2020-04-29 18:16

Yes thank you....got it....just play the same sprite a couple of times to make it appear slower :)

P#75623 2020-04-30 07:09
2

Yep! Though since you're learning Lua, here's an optimization that might help:

idle={fr=15,1,2},                    --set the framerate inside the animation!

--if p.time >= 3 then                --replace this line with the one below:
if p.time >= anims[p.state].fr then

The length operator # only counts entries at indices [1],[2],... without gaps, so it will still return 2 for #anims["idle"], even with a framerate saved in the table as well. Also, you can reference named table entries as anims.idle, or anims["idle"], but just remember that table[1] isn't the same as table["1"].

You can also add a "next" entry, if you wanted the animation to switch states when it finishes:

punching={fr=3,next="idle",17,18,19},

-- then, after the "loops animations" comment:
if p.animindex == 1 and anims[p.state].next then --at the moment the animation restarts,
 p.play = anims[p.state].next                    --play something else instead
 p.state = p.play
end
P#75647 2020-04-30 17:56

Shy :) Thanks again a lot. I really appreciate your help. This code of yours makes my animation-system so much more organised....I think for a new coder like me the difficulty is not to learn lua...its really to find a nice way to organise the code in a logic way and make it reusable for other stuff...i hack together something which works but looks ugly, takes to much space and with ignoring the dry (do not repeat yourself) principle....your code snippet have been exactly what i needed...grazie :)

P#75689 2020-05-01 11:35
1

You're welcome! I can see that you're motivated and putting in the time and effort to learn Lua yourself, which made me want to show you some of these cool features. The more you know about the tools you can use, the easier it is to organize and optimize your code. I'm sure you'll learn a lot quickly, and this forum is great because you can view the code in any cart and see how other people do things. :)

P#75707 2020-05-01 19:56

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-28 09:54:15 | 0.006s | Q:15