diff --git a/data/characters.stlst b/data/characters.stlst new file mode 100644 index 00000000000..5fcc21b18da --- /dev/null +++ b/data/characters.stlst @@ -0,0 +1,42 @@ +;; SuperTux character profiles +(supertux-playerlist + (player + (id "tux") + (name "Tux") + (sprite "tux.sprite") + (max-speed 230.0) + (max-speed-multiplier 1.0) + (acceleration 200.0) + (deceleration 200.0) + (jump-force 8.4) + (fall-acceleration 20.0) + (hitbox-width 31.8) + (hitbox-height 63.8) + ) + (player + (id "penny") + (name "Penny") + (sprite "penny.sprite") + (max-speed 230.0) + (max-speed-multiplier 1.0) + (acceleration 200.0) + (deceleration 200.0) + (jump-force 8.4) + (fall-acceleration 20.0) + (hitbox-width 31.8) + (hitbox-height 63.8) + ) + (player + (id "larry") + (name "Larry") + (sprite "larry.sprite") + (max-speed 230.0) + (max-speed-multiplier 1.0) + (acceleration 200.0) + (deceleration 200.0) + (jump-force 8.4) + (fall-acceleration 20.0) + (hitbox-width 31.8) + (hitbox-height 63.8) + ) +) diff --git a/data/images/creatures/larry/larry.sprite b/data/images/creatures/larry/larry.sprite new file mode 100644 index 00000000000..b8f73f5917c --- /dev/null +++ b/data/images/creatures/larry/larry.sprite @@ -0,0 +1,3060 @@ +(supertux-sprite + + (action + (name "gameover") + (fps 30.0) + (hitbox 18 6 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + +; Small Tux + + (action + (name "small-stand-right") + (fps 10.0) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-stand-left") + (fps 10.0) + (hitbox 16 26 32 32) + (mirror-action "small-stand-right")) + + (action + (name "small-idle-right") + (fps 12.0) + (loop-frame 5) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-idle-left") + (fps 12.0) + (loop-frame 5) + (hitbox 16 26 32 32) + (mirror-action "small-idle-right")) + + (action + (name "small-scratch-right") + (fps 12.0) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-scratch-left") + (fps 12.0) + (hitbox 16 26 32 32) + (mirror-action "small-scratch-right")) + + (action + (name "small-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 26 32 32) + (mirror-action "small-walk-right")) + + (action + (name "small-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 26 32 32) + (mirror-action "small-run-right")) + + (action + (name "small-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-jump-right")) + + (action + (name "small-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-fall-right")) + + (action + (name "small-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-walljump-right")) + + (action + (name "small-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-skid-right")) + + (action + (name "small-kick-right") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-kick-left") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-kick-right")) + + (action + (name "small-climb-right") + (fps 15.0) + (hitbox 16 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-climb-left") + (fps 15.0) + (hitbox 16 26 32 32) + (mirror-action "small-climb-right")) + + (action + (name "small-slide-right") + (fps 30.0) + (loops 1) + (hitbox 24 26 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-slide-left") + (fps 30.0) + (loops 1) + (hitbox 24 26 32 32) + (mirror-action "small-slide-right")) + + (action + (name "small-slidejump-right") + (fps 18.0) + (hitbox 16 14 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-slidejump-left") + (fps 18.0) + (hitbox 16 14 32 32) + (mirror-action "small-slidejump-right")) + + (action + (name "small-float-right") + (fps 10.0) + (hitbox 24 14 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-float-left") + (fps 10.0) + (hitbox 24 14 32 32) + (mirror-action "small-float-right")) + + (action + (name "small-swim-right") + (fps 12.0) + (hitbox 24 14 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-swim-left") + (fps 12.0) + (hitbox 24 14 32 32) + (mirror-action "small-swim-right")) + + (action + (name "small-boost-right") + (fps 18.0) + (hitbox 24 14 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-boost-left") + (fps 18.0) + (hitbox 24 14 32 32) + (mirror-action "small-boost-right")) + + (action + (name "small-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 24 14 32 32) + (images "small-larry.png" + "small-larry.png" + "small-larry.png")) + + (action + (name "small-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 24 14 32 32) + (mirror-action "small-swimjump-right")) + + +; Grow Powerup Transition + + (action + (name "grow-right") + (fps 16.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "grow-left") + (fps 16.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "grow-right")) + + (action + (name "swimgrow-right") + (fps 16.0) + (loops 1) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "swimgrow-left") + (fps 16.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "swimgrow-right")) + + (action + (name "climbgrow-right") + (fps 16.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "climbgrow-left") + (fps 16.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "climbgrow-right")) + + (action + (name "slidegrow-right") + (fps 16.0) + (loops 1) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "slidegrow-left") + (fps 16.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "slidegrow-right")) + + +; Big Tux + + (action + (name "big-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "big-stand-right")) + + (action + (name "big-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "big-idle-right")) + + (action + (name "big-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "big-scratch-right")) + + (action + (name "big-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "big-walk-right")) + + (action + (name "big-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "big-run-right")) + + (action + (name "big-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "big-jump-right")) + + (action + (name "big-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "big-fall-right")) + + (action + (name "big-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "big-walljump-right")) + + (action + (name "big-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "big-skid-right")) + + (action + (name "big-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "big-kick-right")) + + (action + (name "big-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "big-climb-right")) + + (action + (name "big-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "big-duck-right")) + + (action + (name "big-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "big-crawl-right")) + + (action + (name "big-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "big-backflip-right")) + + (action + (name "big-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "big-buttjump-right")) + + (action + (name "big-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "big-stomp-right")) + + (action + (name "big-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "big-slide-right")) + + (action + (name "big-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "big-slidejump-right")) + + (action + (name "big-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "big-float-right")) + + (action + (name "big-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "big-swim-right")) + + (action + (name "big-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "big-boost-right")) + + (action + (name "big-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "big-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "big-swimjump-right")) + + +; Fire Tux + + (action + (name "fire-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "fire-stand-right")) + + (action + (name "fire-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "fire-idle-right")) + + (action + (name "fire-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "fire-scratch-right")) + + (action + (name "fire-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "fire-walk-right")) + + (action + (name "fire-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "fire-run-right")) + + (action + (name "fire-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "fire-jump-right")) + + (action + (name "fire-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "fire-fall-right")) + + (action + (name "fire-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "fire-walljump-right")) + + (action + (name "fire-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "fire-skid-right")) + + (action + (name "fire-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "fire-kick-right")) + + (action + (name "fire-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "fire-climb-right")) + + (action + (name "fire-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "fire-duck-right")) + + (action + (name "fire-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "fire-crawl-right")) + + (action + (name "fire-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "fire-backflip-right")) + + (action + (name "fire-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "fire-buttjump-right")) + + (action + (name "fire-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "fire-stomp-right")) + + (action + (name "fire-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "fire-slide-right")) + + (action + (name "fire-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "fire-slidejump-right")) + + (action + (name "fire-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "fire-float-right")) + + (action + (name "fire-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "fire-swim-right")) + + (action + (name "fire-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "fire-boost-right")) + + (action + (name "fire-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "fire-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "fire-swimjump-right")) + + +; Ice Tux + + (action + (name "ice-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "ice-stand-right")) + + (action + (name "ice-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "ice-idle-right")) + + (action + (name "ice-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "ice-scratch-right")) + + (action + (name "ice-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "ice-walk-right")) + + (action + (name "ice-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "ice-run-right")) + + (action + (name "ice-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "ice-jump-right")) + + (action + (name "ice-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "ice-fall-right")) + + (action + (name "ice-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "ice-walljump-right")) + + (action + (name "ice-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "ice-skid-right")) + + (action + (name "ice-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "ice-kick-right")) + + (action + (name "ice-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "ice-climb-right")) + + (action + (name "ice-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "ice-duck-right")) + + (action + (name "ice-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "ice-crawl-right")) + + (action + (name "ice-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "ice-backflip-right")) + + (action + (name "ice-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "ice-buttjump-right")) + + (action + (name "ice-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "ice-stomp-right")) + + (action + (name "ice-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "ice-slide-right")) + + (action + (name "ice-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "ice-slidejump-right")) + + (action + (name "ice-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "ice-float-right")) + + (action + (name "ice-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "ice-swim-right")) + + (action + (name "ice-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "ice-boost-right")) + + (action + (name "ice-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "ice-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "ice-swimjump-right")) + + +; Earth Tux + + (action + (name "earth-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "earth-stand-right")) + + (action + (name "earth-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "earth-idle-right")) + + (action + (name "earth-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "earth-scratch-right")) + + (action + (name "earth-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "earth-walk-right")) + + (action + (name "earth-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "earth-run-right")) + + (action + (name "earth-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "earth-jump-right")) + + (action + (name "earth-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "earth-fall-right")) + + (action + (name "earth-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "earth-walljump-right")) + + (action + (name "earth-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "earth-skid-right")) + + (action + (name "earth-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "earth-kick-right")) + + (action + (name "earth-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "earth-climb-right")) + + (action + (name "earth-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "earth-duck-right")) + + (action + (name "earth-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "earth-crawl-right")) + + (action + (name "earth-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "earth-backflip-right")) + + (action + (name "earth-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "earth-buttjump-right")) + + (action + (name "earth-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "earth-stomp-right")) + + (action + (name "earth-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "earth-slide-right")) + + (action + (name "earth-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "earth-slidejump-right")) + + (action + (name "earth-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "earth-float-right")) + + (action + (name "earth-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "earth-swim-right")) + + (action + (name "earth-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "earth-boost-right")) + + (action + (name "earth-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "earth-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "earth-swimjump-right")) + +; Air Tux + + (action + (name "air-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "air-stand-right")) + + (action + (name "air-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "air-idle-right")) + + (action + (name "air-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "air-scratch-right")) + + (action + (name "air-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "air-walk-right")) + + (action + (name "air-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "air-run-right")) + + (action + (name "air-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "air-jump-right")) + + (action + (name "air-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "air-fall-right")) + + (action + (name "air-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "air-walljump-right")) + + (action + (name "air-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "air-skid-right")) + + (action + (name "air-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "air-kick-right")) + + (action + (name "air-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "air-climb-right")) + + (action + (name "air-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "air-duck-right")) + + (action + (name "air-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "air-crawl-right")) + + (action + (name "air-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "air-backflip-right")) + + (action + (name "air-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "air-buttjump-right")) + + (action + (name "air-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "air-stomp-right")) + + (action + (name "air-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "air-slide-right")) + + (action + (name "air-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "air-slidejump-right")) + + (action + (name "air-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "air-float-right")) + + (action + (name "air-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "air-swim-right")) + + (action + (name "air-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "air-boost-right")) + + (action + (name "air-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "larry.png" + "larry.png" + "larry.png")) + + (action + (name "air-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "air-swimjump-right")) + +; Cutscenes And Extras + + (action + (name "earth-stone") + (hitbox 10 13 32 32) + (images "earth/statue.png")) + + (action + (name "credits-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png" + "larry.png")) + + (action + (name "credits-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "credits-right")) +) diff --git a/data/images/creatures/larry/small-larry.png b/data/images/creatures/larry/small-larry.png new file mode 100644 index 00000000000..a49f808a082 Binary files /dev/null and b/data/images/creatures/larry/small-larry.png differ diff --git a/data/images/creatures/penny/penny.sprite b/data/images/creatures/penny/penny.sprite index 4f0dc766c38..24fdc3420cf 100644 --- a/data/images/creatures/penny/penny.sprite +++ b/data/images/creatures/penny/penny.sprite @@ -1,135 +1,3060 @@ -(supertux-sprite - (action - (name "stand-right") - (fps 10.0) - (hitbox 16 14 32 64) - (images "stand-0.png" - "stand-1.png" - "stand-2.png" - "stand-3.png" - "stand-4.png" - "stand-3.png" - "stand-2.png" - "stand-1.png" - "stand-0.png" - "stand-5.png" - "stand-0.png" - "stand-1.png" - "stand-2.png" - "stand-3.png" - "stand-4.png" - "stand-3.png" - "stand-2.png" - "stand-1.png" - "stand-0.png" - "stand-5.png" - "stand-0.png" - "stand-1.png" - "stand-2.png" - "stand-3.png" - "stand-4.png" - "stand-3.png" - "stand-2.png" - "stand-1.png" - "stand-0.png" - "stand-6.png" - "stand-7.png" - "stand-8.png" - "stand-2.png" - "stand-3.png" - "stand-4.png" - "stand-3.png" - "stand-2.png" - "stand-1.png" - "stand-0.png" - "stand-5.png") - ) - - (action - (name "stand-left") - (fps 10.0) - (hitbox 16 14 32 64) - (mirror-action "stand-right") - ) - - -; Cutscenes And Extras - - (action - (name "credits-right") - (fps 10.0) - (hitbox 16 14 32 64) - (images "credits-0.png" - "credits-1.png" - "credits-2.png" - "credits-3.png" - "credits-2.png" - "credits-1.png" - "credits-0.png" - "credits-4.png" - "credits-0.png" - "credits-1.png" - "credits-2.png" - "credits-3.png" - "credits-2.png" - "credits-1.png" - "credits-0.png" - "credits-4.png" - "credits-0.png" - "credits-1.png" - "credits-2.png" - "credits-3.png" - "credits-2.png" - "credits-1.png" - "credits-0.png" - "credits-4.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-5.png" - "credits-6.png" - "credits-7.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-0.png" - "credits-5.png" - "credits-6.png" - "credits-7.png" - ) - ) - (action - (name "credits-left") - (fps 10.0) - (hitbox 16 14 32 64) - (mirror-action "credits-right") - ) -) +(supertux-sprite + + (action + (name "gameover") + (fps 30.0) + (hitbox 18 6 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + +; Small Tux + + (action + (name "small-stand-right") + (fps 10.0) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-stand-left") + (fps 10.0) + (hitbox 16 26 32 32) + (mirror-action "small-stand-right")) + + (action + (name "small-idle-right") + (fps 12.0) + (loop-frame 5) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-idle-left") + (fps 12.0) + (loop-frame 5) + (hitbox 16 26 32 32) + (mirror-action "small-idle-right")) + + (action + (name "small-scratch-right") + (fps 12.0) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-scratch-left") + (fps 12.0) + (hitbox 16 26 32 32) + (mirror-action "small-scratch-right")) + + (action + (name "small-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 26 32 32) + (mirror-action "small-walk-right")) + + (action + (name "small-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 26 32 32) + (mirror-action "small-run-right")) + + (action + (name "small-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-jump-right")) + + (action + (name "small-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-fall-right")) + + (action + (name "small-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-walljump-right")) + + (action + (name "small-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-skid-right")) + + (action + (name "small-kick-right") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-kick-left") + (fps 20.0) + (loops 1) + (hitbox 16 26 32 32) + (mirror-action "small-kick-right")) + + (action + (name "small-climb-right") + (fps 15.0) + (hitbox 16 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-climb-left") + (fps 15.0) + (hitbox 16 26 32 32) + (mirror-action "small-climb-right")) + + (action + (name "small-slide-right") + (fps 30.0) + (loops 1) + (hitbox 24 26 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-slide-left") + (fps 30.0) + (loops 1) + (hitbox 24 26 32 32) + (mirror-action "small-slide-right")) + + (action + (name "small-slidejump-right") + (fps 18.0) + (hitbox 16 14 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-slidejump-left") + (fps 18.0) + (hitbox 16 14 32 32) + (mirror-action "small-slidejump-right")) + + (action + (name "small-float-right") + (fps 10.0) + (hitbox 24 14 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-float-left") + (fps 10.0) + (hitbox 24 14 32 32) + (mirror-action "small-float-right")) + + (action + (name "small-swim-right") + (fps 12.0) + (hitbox 24 14 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-swim-left") + (fps 12.0) + (hitbox 24 14 32 32) + (mirror-action "small-swim-right")) + + (action + (name "small-boost-right") + (fps 18.0) + (hitbox 24 14 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-boost-left") + (fps 18.0) + (hitbox 24 14 32 32) + (mirror-action "small-boost-right")) + + (action + (name "small-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 24 14 32 32) + (images "small-stand-0.png" + "small-stand-0.png" + "small-stand-0.png")) + + (action + (name "small-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 24 14 32 32) + (mirror-action "small-swimjump-right")) + + +; Grow Powerup Transition + + (action + (name "grow-right") + (fps 16.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "grow-left") + (fps 16.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "grow-right")) + + (action + (name "swimgrow-right") + (fps 16.0) + (loops 1) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "swimgrow-left") + (fps 16.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "swimgrow-right")) + + (action + (name "climbgrow-right") + (fps 16.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "climbgrow-left") + (fps 16.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "climbgrow-right")) + + (action + (name "slidegrow-right") + (fps 16.0) + (loops 1) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "slidegrow-left") + (fps 16.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "slidegrow-right")) + + +; Big Tux + + (action + (name "big-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "big-stand-right")) + + (action + (name "big-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "big-idle-right")) + + (action + (name "big-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "big-scratch-right")) + + (action + (name "big-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "big-walk-right")) + + (action + (name "big-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "big-run-right")) + + (action + (name "big-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "big-jump-right")) + + (action + (name "big-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "big-fall-right")) + + (action + (name "big-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "big-walljump-right")) + + (action + (name "big-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "big-skid-right")) + + (action + (name "big-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "big-kick-right")) + + (action + (name "big-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "big-climb-right")) + + (action + (name "big-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "big-duck-right")) + + (action + (name "big-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "big-crawl-right")) + + (action + (name "big-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "big-backflip-right")) + + (action + (name "big-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "big-buttjump-right")) + + (action + (name "big-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "big-stomp-right")) + + (action + (name "big-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "big-slide-right")) + + (action + (name "big-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "big-slidejump-right")) + + (action + (name "big-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "big-float-right")) + + (action + (name "big-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "big-swim-right")) + + (action + (name "big-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "big-boost-right")) + + (action + (name "big-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "big-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "big-swimjump-right")) + + +; Fire Tux + + (action + (name "fire-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "fire-stand-right")) + + (action + (name "fire-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "fire-idle-right")) + + (action + (name "fire-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "fire-scratch-right")) + + (action + (name "fire-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "fire-walk-right")) + + (action + (name "fire-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "fire-run-right")) + + (action + (name "fire-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "fire-jump-right")) + + (action + (name "fire-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "fire-fall-right")) + + (action + (name "fire-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "fire-walljump-right")) + + (action + (name "fire-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "fire-skid-right")) + + (action + (name "fire-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "fire-kick-right")) + + (action + (name "fire-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "fire-climb-right")) + + (action + (name "fire-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "fire-duck-right")) + + (action + (name "fire-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "fire-crawl-right")) + + (action + (name "fire-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "fire-backflip-right")) + + (action + (name "fire-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "fire-buttjump-right")) + + (action + (name "fire-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "fire-stomp-right")) + + (action + (name "fire-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "fire-slide-right")) + + (action + (name "fire-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "fire-slidejump-right")) + + (action + (name "fire-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "fire-float-right")) + + (action + (name "fire-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "fire-swim-right")) + + (action + (name "fire-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "fire-boost-right")) + + (action + (name "fire-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "fire-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "fire-swimjump-right")) + + +; Ice Tux + + (action + (name "ice-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "ice-stand-right")) + + (action + (name "ice-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "ice-idle-right")) + + (action + (name "ice-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "ice-scratch-right")) + + (action + (name "ice-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "ice-walk-right")) + + (action + (name "ice-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "ice-run-right")) + + (action + (name "ice-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "ice-jump-right")) + + (action + (name "ice-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "ice-fall-right")) + + (action + (name "ice-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "ice-walljump-right")) + + (action + (name "ice-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "ice-skid-right")) + + (action + (name "ice-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "ice-kick-right")) + + (action + (name "ice-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "ice-climb-right")) + + (action + (name "ice-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "ice-duck-right")) + + (action + (name "ice-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "ice-crawl-right")) + + (action + (name "ice-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "ice-backflip-right")) + + (action + (name "ice-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "ice-buttjump-right")) + + (action + (name "ice-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "ice-stomp-right")) + + (action + (name "ice-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "ice-slide-right")) + + (action + (name "ice-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "ice-slidejump-right")) + + (action + (name "ice-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "ice-float-right")) + + (action + (name "ice-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "ice-swim-right")) + + (action + (name "ice-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "ice-boost-right")) + + (action + (name "ice-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "ice-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "ice-swimjump-right")) + + +; Earth Tux + + (action + (name "earth-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "earth-stand-right")) + + (action + (name "earth-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "earth-idle-right")) + + (action + (name "earth-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "earth-scratch-right")) + + (action + (name "earth-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "earth-walk-right")) + + (action + (name "earth-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "earth-run-right")) + + (action + (name "earth-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "earth-jump-right")) + + (action + (name "earth-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "earth-fall-right")) + + (action + (name "earth-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "earth-walljump-right")) + + (action + (name "earth-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "earth-skid-right")) + + (action + (name "earth-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "earth-kick-right")) + + (action + (name "earth-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "earth-climb-right")) + + (action + (name "earth-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "earth-duck-right")) + + (action + (name "earth-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "earth-crawl-right")) + + (action + (name "earth-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "earth-backflip-right")) + + (action + (name "earth-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "earth-buttjump-right")) + + (action + (name "earth-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "earth-stomp-right")) + + (action + (name "earth-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "earth-slide-right")) + + (action + (name "earth-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "earth-slidejump-right")) + + (action + (name "earth-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "earth-float-right")) + + (action + (name "earth-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "earth-swim-right")) + + (action + (name "earth-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "earth-boost-right")) + + (action + (name "earth-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "earth-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "earth-swimjump-right")) + +; Air Tux + + (action + (name "air-stand-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-stand-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "air-stand-right")) + + (action + (name "air-idle-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-idle-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "air-idle-right")) + + (action + (name "air-scratch-right") + (fps 12.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-scratch-left") + (fps 12.0) + (hitbox 16 14 32 64) + (mirror-action "air-scratch-right")) + + (action + (name "air-walk-right") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-walk-left") + (fps 14.0) + (loop-frame 2) + (hitbox 16 14 32 64) + (mirror-action "air-walk-right")) + + (action + (name "air-run-right") + (fps 15.0) + (loop-frame 2) + (hitbox 18 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-run-left") + (fps 15.0) + (loop-frame 2) + (hitbox 20 14 32 64) + (mirror-action "air-run-right")) + + (action + (name "air-jump-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-jump-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "air-jump-right")) + + (action + (name "air-fall-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-fall-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "air-fall-right")) + + (action + (name "air-walljump-right") + (fps 20.0) + (loops 1) + (hitbox 24 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-walljump-left") + (fps 20.0) + (loops 1) + (hitbox 8 14 32 64) + (mirror-action "air-walljump-right")) + + (action + (name "air-skid-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-skid-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "air-skid-right")) + + (action + (name "air-kick-right") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-kick-left") + (fps 15.0) + (loops 1) + (hitbox 16 14 32 64) + (mirror-action "air-kick-right")) + + (action + (name "air-climb-right") + (fps 15.0) + (hitbox 16 16 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-climb-left") + (fps 15.0) + (hitbox 16 16 32 64) + (mirror-action "air-climb-right")) + + (action + (name "air-duck-right") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-duck-left") + (fps 30.0) + (loops 1) + (hitbox 16 45 32 32) + (mirror-action "air-duck-right")) + + (action + (name "air-crawl-right") + (fps 12.0) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-crawl-left") + (fps 12.0) + (hitbox 32 46 64 32) + (mirror-action "air-crawl-right")) + + (action + (name "air-backflip-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-backflip-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "air-backflip-right")) + + (action + (name "air-buttjump-right") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-buttjump-left") + (fps 30.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "air-buttjump-right")) + + (action + (name "air-stomp-right") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-stomp-left") + (fps 20.0) + (loops 1) + (hitbox 16 14 32 46) + (mirror-action "air-stomp-right")) + + (action + (name "air-slide-right") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-slide-left") + (fps 30.0) + (loops 1) + (hitbox 32 46 64 32) + (mirror-action "air-slide-right")) + + (action + (name "air-slidejump-right") + (fps 18.0) + (hitbox 19 28 32 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-slidejump-left") + (fps 18.0) + (hitbox 19 28 32 32) + (mirror-action "air-slidejump-right")) + + (action + (name "air-float-right") + (fps 10.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-float-left") + (fps 10.0) + (hitbox 32 15 64 32) + (mirror-action "air-float-right")) + + (action + (name "air-swim-right") + (fps 12.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-swim-left") + (fps 12.0) + (hitbox 32 15 64 32) + (mirror-action "air-swim-right")) + + (action + (name "air-boost-right") + (fps 18.0) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-boost-left") + (fps 18.0) + (hitbox 32 15 64 32) + (mirror-action "air-boost-right")) + + (action + (name "air-swimjump-right") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (images "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "air-swimjump-left") + (fps 15.0) + (loops 1) + (hitbox 32 15 64 32) + (mirror-action "air-swimjump-right")) + +; Cutscenes And Extras + + (action + (name "earth-stone") + (hitbox 10 13 32 32) + (images "stand-0.png")) + + (action + (name "credits-right") + (fps 10.0) + (hitbox 16 14 32 64) + (images "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png" + "stand-0.png")) + + (action + (name "credits-left") + (fps 10.0) + (hitbox 16 14 32 64) + (mirror-action "credits-right")) +) diff --git a/data/images/creatures/penny/small-stand-0.png b/data/images/creatures/penny/small-stand-0.png new file mode 100644 index 00000000000..85674d5035b Binary files /dev/null and b/data/images/creatures/penny/small-stand-0.png differ diff --git a/src/object/character_profile.hpp b/src/object/character_profile.hpp new file mode 100644 index 00000000000..9f1f1a28be4 --- /dev/null +++ b/src/object/character_profile.hpp @@ -0,0 +1,63 @@ +// SuperTux +// Copyright (C) 2024 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include + +enum class CharacterType { + TUX = 0, + PENNY = 1, + LARRY = 2 +}; + +/** + * Defines all gameplay and visual attributes for a character. + * Adding new characters or changing gameplay only requires + * adding an entry to CharacterRegistry + */ +struct CharacterProfile +{ + std::string id; + std::string name; + + std::string sprite_path; + + float max_speed; + float max_speed_multiplier; + float acceleration; + float deceleration; + float jump_force; + float fall_acceleration; + + float hitbox_width; + float hitbox_height; + + // Default constructor for Tux (fallback) + CharacterProfile() : + id("tux"), + name("Tux"), + sprite_path("tux.sprite"), + max_speed(230.0f), + max_speed_multiplier(1.0f), + acceleration(200.0f), + deceleration(200.0f), + jump_force(8.4f), + fall_acceleration(20.0f), + hitbox_width(31.8f), + hitbox_height(63.8f) + {} +}; diff --git a/src/object/character_registry.cpp b/src/object/character_registry.cpp new file mode 100644 index 00000000000..c24657bde17 --- /dev/null +++ b/src/object/character_registry.cpp @@ -0,0 +1,121 @@ +// SuperTux +// Copyright (C) 2024 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "object/character_registry.hpp" +#include "object/character_profile.hpp" +#include "util/log.hpp" +#include "util/reader_collection.hpp" +#include "util/reader_document.hpp" +#include "util/reader_mapping.hpp" + +#include + +CharacterRegistry::CharacterRegistry() : + m_default_character_id("tux") +{ + load_profiles("characters.stlst"); +} + +void CharacterRegistry::load_profiles(const std::string& filename) +{ + auto doc = ReaderDocument::from_file(filename); + auto root = doc.get_root(); + if (root.get_name() != "supertux-playerlist") + { + throw std::runtime_error("File is not a supertux-playerlist file: " + filename); + } + + auto collection = root.get_collection(); + for (const auto& obj : collection.get_objects()) + { + if (obj.get_name() != "player") + { + log_warning << "Unknown token '" << obj.get_name() << "' in player list" << std::endl; + continue; + } + + CharacterProfile profile; + auto mapping = obj.get_mapping(); + mapping.get("id", profile.id); + mapping.get("name", profile.name); + mapping.get("sprite", profile.sprite_path); + mapping.get("max-speed", profile.max_speed); + mapping.get("max-speed-multiplier", profile.max_speed_multiplier); + mapping.get("acceleration", profile.acceleration); + mapping.get("deceleration", profile.deceleration); + mapping.get("jump-force", profile.jump_force); + mapping.get("fall-acceleration", profile.fall_acceleration); + mapping.get("hitbox-width", profile.hitbox_width); + mapping.get("hitbox-height", profile.hitbox_height); + + if (profile.id.empty()) + { + log_warning << "Skipping player entry with empty id in " << filename << std::endl; + continue; + } + + m_profiles[profile.id] = profile; + } +} + +const CharacterProfile& CharacterRegistry::get_profile(const std::string& character_id) const +{ + auto it = m_profiles.find(character_id); + if (it != m_profiles.end()) + { + return it->second; + } + + return get_default_character(); +} + +std::vector CharacterRegistry::get_character_ids() const +{ + std::vector ids; + for (const auto& pair : m_profiles) + { + ids.push_back(pair.first); + } + return ids; +} + +bool CharacterRegistry::has_character(const std::string& character_id) const +{ + return m_profiles.find(character_id) != m_profiles.end(); +} + +const CharacterProfile& CharacterRegistry::get_default_character() const +{ + return m_profiles.at(m_default_character_id); +} + +CharacterType CharacterRegistry::string_to_character(const std::string& id) +{ + if (id == "penny") return CharacterType::PENNY; + if (id == "larry") return CharacterType::LARRY; + return CharacterType::TUX; +} + +std::string CharacterRegistry::character_to_string(CharacterType type) +{ + switch(type) { + case CharacterType::PENNY: return "penny"; + case CharacterType::LARRY: return "larry"; + case CharacterType::TUX: return "tux"; + } + return "tux"; +} + diff --git a/src/object/character_registry.hpp b/src/object/character_registry.hpp new file mode 100644 index 00000000000..e5334084957 --- /dev/null +++ b/src/object/character_registry.hpp @@ -0,0 +1,70 @@ +// SuperTux +// Copyright (C) 2024 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include "object/character_profile.hpp" +#include "util/currenton.hpp" + +#include +#include +#include +#include + +/** + * Central registry for all character profiles. + */ +class CharacterRegistry final : public Currenton +{ +public: + CharacterRegistry(); + + /** + * Get a character profile by ID + * @param character_id The character ID (e.g., "tux", "penny", "larry") + * @return Reference to the CharacterProfile (always valid, returns fallback if not found) + */ + const CharacterProfile& get_profile(const std::string& character_id) const; + + /** + * Get all registered character IDs + * @return Vector of character ID strings + */ + std::vector get_character_ids() const; + + /** + * Check if a character exists + * @param character_id The character ID to check + * @return true if character is registered, false otherwise + */ + bool has_character(const std::string& character_id) const; + + /** + * Get the default/fallback character (Tux) + * @return Reference to Tux's CharacterProfile + */ + const CharacterProfile& get_default_character() const; + + static CharacterType string_to_character(const std::string& id); + static std::string character_to_string(CharacterType type); + +private: + void load_profiles(const std::string& filename); + +private: + std::map m_profiles; + std::string m_default_character_id; +}; diff --git a/src/object/player.cpp b/src/object/player.cpp index a6fcf2a5ff2..573f3898d0d 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -27,6 +27,7 @@ #include "control/input_manager.hpp" #include "editor/editor.hpp" #include "math/util.hpp" +#include "object/character_registry.hpp" #include "math/random.hpp" #include "object/brick.hpp" #include "object/bullet.hpp" @@ -70,19 +71,13 @@ const std::vector IDLE_STAGES "idle" }); -/** acceleration in horizontal direction when walking +/** acceleration in horizontal direction when running * (all accelerations are in pixel/s^2) */ -const float WALK_ACCELERATION_X = 300; -/** acceleration in horizontal direction when running */ const float RUN_ACCELERATION_X = 400; /** acceleration when skidding */ const float SKID_XM = 200; /** time of skidding in seconds */ const float SKID_TIME = .3f; -/** maximum walk velocity (pixel/s) */ -const float MAX_WALK_XM = 230; -/** maximum run velocity (pixel/s) */ -const float MAX_RUN_XM = 320; /** bonus run velocity addition (pixel/s) */ const float BONUS_RUN_XM = 80; /** maximum horizontal climb velocity */ @@ -157,8 +152,19 @@ const int MAX_ICE_BULLETS = 2; } // namespace -Player::Player(PlayerStatus& player_status, const std::string& name_, int player_id) : - MovingSprite({0, 0}, "images/creatures/tux/tux.sprite", 9001, COLGROUP_MOVING), +std::string Player::get_sprite_path_for_character(CharacterType character_type) +{ + std::string character_id = CharacterRegistry::character_to_string(character_type); + if (auto* registry = CharacterRegistry::current()) { + const CharacterProfile& profile = registry->get_profile(character_id); + return "images/creatures/" + character_id + "/" + profile.sprite_path; + } + return "images/creatures/tux/tux.sprite"; +} + +Player::Player(PlayerStatus& player_status, const std::string& name_, int player_id, + CharacterType character_type) : + MovingSprite({0, 0}, get_sprite_path_for_character(character_type), 9001, COLGROUP_MOVING), m_id(player_id), m_target(nullptr), m_deactivated(false), @@ -186,6 +192,13 @@ Player::Player(PlayerStatus& player_status, const std::string& name_, int player m_can_walljump(false), m_boost(0.f), m_speedlimit(0), //no special limit + m_max_walk_speed(230.0f), + m_max_run_speed(320.0f), + m_walk_acceleration(300.0f), + m_max_speed_multiplier(1.0f), + m_deceleration(200.0f), + m_jump_force(8.4f), + m_fall_acceleration(20.0f), m_velocity_override(), m_scripting_controller_old(nullptr), m_jump_early_apex(false), @@ -268,6 +281,19 @@ Player::Player(PlayerStatus& player_status, const std::string& name_, int player m_col.set_size(TUX_WIDTH, is_big() ? BIG_TUX_HEIGHT : SMALL_TUX_HEIGHT); m_col.set_physic_hint(m_physic); + // Load character profile and apply all physics attributes + std::string character_id = CharacterRegistry::character_to_string(character_type); + if (auto* registry = CharacterRegistry::current()) { + const CharacterProfile& profile = registry->get_profile(character_id); + m_max_walk_speed = profile.max_speed; + m_max_run_speed = profile.max_speed * 1.4f; + m_walk_acceleration = profile.acceleration; + m_max_speed_multiplier = profile.max_speed_multiplier; + m_deceleration = profile.deceleration; + m_jump_force = profile.jump_force; + m_fall_acceleration = profile.fall_acceleration; + } + m_sprite->set_angle(0.0f); //m_santahatsprite->set_angle(0.0f); @@ -694,7 +720,7 @@ Player::update(float dt_sec) // extend/shrink tux collision rectangle so that we fall through/walk over 1 // tile holes - if (fabsf(m_physic.get_velocity_x()) > MAX_WALK_XM) { + if (fabsf(m_physic.get_velocity_x()) > m_max_walk_speed) { m_col.set_width(RUNNING_TUX_WIDTH); } else { @@ -1189,7 +1215,7 @@ Player::apply_friction() m_physic.set_acceleration_x(0); return; } - float friction = WALK_ACCELERATION_X; + float friction = m_walk_acceleration; if (m_on_ice && is_on_ground) //we need this or else sliding on ice will cause Tux to go on for a very long time friction *= (ICE_FRICTION_MULTIPLIER*(m_sliding ? 4.f : m_stone ? 5.f : 1.f)); @@ -1262,23 +1288,23 @@ Player::handle_horizontal_input() // do not run if we're holding something which slows us down if ( m_grabbed_object && m_grabbed_object->is_hampering() ) { - ax = dirsign * WALK_ACCELERATION_X; + ax = dirsign * m_walk_acceleration; // limit speed - if (vx >= MAX_WALK_XM && dirsign > 0) { + if (vx >= m_max_walk_speed && dirsign > 0) { ax = std::min(ax, -OVERSPEED_DECELERATION); - } else if (vx <= -MAX_WALK_XM && dirsign < 0) { + } else if (vx <= -m_max_walk_speed && dirsign < 0) { ax = std::max(ax, OVERSPEED_DECELERATION); } } else { - if ( vx * dirsign < MAX_WALK_XM ) { - ax = dirsign * WALK_ACCELERATION_X; + if ( vx * dirsign < m_max_walk_speed ) { + ax = dirsign * m_walk_acceleration; } else { ax = dirsign * RUN_ACCELERATION_X; } // limit speed - if (vx >= MAX_RUN_XM + BONUS_RUN_XM *((get_bonus() == BONUS_AIR) ? 1 : 0)) { + if (vx >= m_max_run_speed + BONUS_RUN_XM *((get_bonus() == BONUS_AIR) ? 1 : 0)) { ax = std::min(ax, -OVERSPEED_DECELERATION); - } else if (vx <= -MAX_RUN_XM - BONUS_RUN_XM * ((get_bonus() == BONUS_AIR) ? 1 : 0)) { + } else if (vx <= -m_max_run_speed - BONUS_RUN_XM * ((get_bonus() == BONUS_AIR) ? 1 : 0)) { ax = std::max(ax, OVERSPEED_DECELERATION); } } @@ -1503,9 +1529,9 @@ Player::handle_vertical_input() // jump a bit higher if we are running; else do a normal jump if (!m_can_walljump) { if (get_bonus() == BONUS_AIR) - do_jump((fabsf(m_physic.get_velocity_x()) > MAX_WALK_XM) ? -620.0f : -580.0f); + do_jump((fabsf(m_physic.get_velocity_x()) > m_max_walk_speed) ? -620.0f : -580.0f); else - do_jump((fabsf(m_physic.get_velocity_x()) > MAX_WALK_XM) ? -580.0f : -520.0f); + do_jump((fabsf(m_physic.get_velocity_x()) > m_max_walk_speed) ? -580.0f : -520.0f); } } //Stop the coyote timer only after calling do_jump, because do_jump also checks for the timer @@ -1888,17 +1914,17 @@ Player::handle_input_ghost() float vy = 0; if (m_controller->hold(Control::LEFT)) { m_dir = Direction::LEFT; - vx -= MAX_RUN_XM * 2; + vx -= m_max_run_speed * 2; } if (m_controller->hold(Control::RIGHT)) { m_dir = Direction::RIGHT; - vx += MAX_RUN_XM * 2; + vx += m_max_run_speed * 2; } if (m_controller->hold(Control::UP)) { - vy -= MAX_RUN_XM * 2; + vy -= m_max_run_speed * 2; } if (m_controller->hold(Control::DOWN)) { - vy += MAX_RUN_XM * 2; + vy += m_max_run_speed * 2; } if (m_controller->hold(Control::ACTION)) { set_ghost_mode(false); @@ -2284,7 +2310,7 @@ Player::draw(DrawingContext& context) } else { - if (std::abs(m_physic.get_velocity_x()) >= MAX_RUN_XM - 3) + if (std::abs(m_physic.get_velocity_x()) >= m_max_run_speed - 3) set_action(sa_prefix + "-run" + sa_postfix); else set_action(sa_prefix + "-walk" + sa_postfix); @@ -2425,8 +2451,8 @@ Player::handle_collision_logic(const CollisionHit& hit) m_physic.set_velocity_y(.2f); } - if (m_stone && m_floor_normal.y == 0 && (((m_physic.get_velocity_x() < -MAX_RUN_XM) && hit.left) || - ((m_physic.get_velocity_x() > MAX_RUN_XM) && hit.right))) + if (m_stone && m_floor_normal.y == 0 && (((m_physic.get_velocity_x() < -m_max_run_speed) && hit.left) || + ((m_physic.get_velocity_x() > m_max_run_speed) && hit.right))) { m_physic.set_acceleration_x(0); m_physic.set_velocity_x(0); diff --git a/src/object/player.hpp b/src/object/player.hpp index ca64c01eb14..1c3a5e2aa0d 100644 --- a/src/object/player.hpp +++ b/src/object/player.hpp @@ -18,6 +18,7 @@ #include "moving_sprite.hpp" #include "sprite/sprite_ptr.hpp" +#include "object/character_profile.hpp" #include "supertux/direction.hpp" #include "supertux/moving_object.hpp" #include "supertux/object_remove_listener.hpp" @@ -78,9 +79,12 @@ class Player final : public MovingSprite static Color get_player_color(int id); public: - Player(PlayerStatus& player_status, const std::string& name, int player_id); + Player(PlayerStatus& player_status, const std::string& name, int player_id, + CharacterType character_type = CharacterType::TUX); ~Player() override; + static std::string get_sprite_path_for_character(CharacterType character_type); + virtual void update(float dt_sec) override; virtual void draw(DrawingContext& context) override; virtual void collision_solid(const CollisionHit& hit) override; @@ -544,6 +548,15 @@ class Player final : public MovingSprite bool m_can_walljump; float m_boost; float m_speedlimit; + + float m_max_walk_speed; + float m_max_run_speed; + float m_walk_acceleration; + float m_max_speed_multiplier; + float m_deceleration; + float m_jump_force; + float m_fall_acceleration; + bool m_velocity_override; const Controller* m_scripting_controller_old; /**< Saves the old controller while the scripting_controller is used */ bool m_jump_early_apex; diff --git a/src/supertux/game_manager.cpp b/src/supertux/game_manager.cpp index 1bf6175cd31..8b6d63b6d34 100644 --- a/src/supertux/game_manager.cpp +++ b/src/supertux/game_manager.cpp @@ -21,6 +21,7 @@ #include "supertux/levelset_screen.hpp" #include "supertux/player_status.hpp" #include "supertux/profile.hpp" +#include "supertux/profile_manager.hpp" #include "supertux/savegame.hpp" #include "supertux/screen.hpp" #include "supertux/screen_fade.hpp" @@ -49,13 +50,72 @@ GameManager::save() m_savegame->save(); } +void +GameManager::ensure_savegame_for_profile() +{ + if (!m_savegame) + { + auto savegame = std::make_unique(ProfileManager::current()->get_current_profile(), ""); + m_savegame = std::move(savegame); + } +} + +void +GameManager::ensure_title_screen_savegame() +{ + if (!m_savegame || !m_savegame->is_title_screen()) + { + auto savegame = std::make_unique(ProfileManager::current()->get_current_profile(), ""); + m_savegame = std::move(savegame); + } +} + +Savegame* +GameManager::get_active_savegame() +{ + if (worldmap::WorldMap::current()) + return &worldmap::WorldMap::current()->get_savegame(); + + if (GameSession::current()) + return &GameSession::current()->get_savegame(); + + if (GameManager::current() && GameManager::current()->m_savegame) + return GameManager::current()->m_savegame.get(); + + return nullptr; +} + void GameManager::start_level(const World& world, const std::string& level_filename, const std::optional>& start_pos, bool skip_intro) { + std::vector gameplay_character_ids; + + Savegame* current_savegame = get_active_savegame(); + if (current_savegame) + { + PlayerStatus& old_status = current_savegame->get_player_status(); + int num_players_to_preserve = InputManager::current()->get_num_users(); + for (int i = 0; i < num_players_to_preserve; ++i) + { + CharacterType char_id = old_status.get_character_id(i); + gameplay_character_ids.push_back(char_id); + } + } + m_savegame = Savegame::from_current_profile(world.get_basename()); + if (!gameplay_character_ids.empty()) + { + PlayerStatus& new_status = m_savegame->get_player_status(); + while (new_status.m_num_players < static_cast(gameplay_character_ids.size())) + new_status.add_player(); + + for (size_t i = 0; i < gameplay_character_ids.size(); ++i) + new_status.set_character_id(i, gameplay_character_ids[i]); + } + auto screen = std::make_unique(world.get_basedir(), level_filename, *m_savegame, @@ -92,8 +152,31 @@ GameManager::create_worldmap_instance(const World& world, const std::string& wor const std::string& sector, const std::string& spawnpoint) try { + std::vector menu_character_ids; + if (m_savegame && m_savegame->is_title_screen()) + { + PlayerStatus& old_status = m_savegame->get_player_status(); + int num_players_to_preserve = InputManager::current()->get_num_users(); + + for (int i = 0; i < num_players_to_preserve; ++i) + { + CharacterType char_id = old_status.get_character_id(i); + menu_character_ids.push_back(char_id); + } + } + m_savegame = Savegame::from_current_profile(world.get_basename()); + if (!menu_character_ids.empty()) + { + PlayerStatus& new_status = m_savegame->get_player_status(); + while (new_status.m_num_players < static_cast(menu_character_ids.size())) + new_status.add_player(); + + for (size_t i = 0; i < menu_character_ids.size(); ++i) + new_status.set_character_id(i, menu_character_ids[i]); + } + auto filename = m_savegame->get_player_status().last_worldmap; // If we specified a worldmap filename manually, // this overrides the default choice of "last worldmap". @@ -127,7 +210,7 @@ GameManager::start_worldmap(const World& world, const std::string& worldmap_file create_worldmap_instance(world, worldmap_filename, sector, spawnpoint)); if (!worldmap) return false; - + if (!Editor::current()) m_savegame->get_profile().set_last_world(world.get_basename()); diff --git a/src/supertux/game_manager.hpp b/src/supertux/game_manager.hpp index fc3931a963a..f1e176d5a50 100644 --- a/src/supertux/game_manager.hpp +++ b/src/supertux/game_manager.hpp @@ -36,9 +36,14 @@ class GameManager final : public Currenton { public: GameManager(); - + void save(); + void ensure_savegame_for_profile(); + void ensure_title_screen_savegame(); + + static Savegame* get_active_savegame(); + worldmap::WorldMap* create_worldmap_instance(const World& world, const std::string& worldmap_filename = "", const std::string& sector = "", const std::string& spawnpoint = ""); bool start_worldmap(const World& world, const std::string& worldmap_filename = "", @@ -53,10 +58,10 @@ class GameManager final : public Currenton public: std::unique_ptr m_savegame; - + private: std::unique_ptr m_current_level; - + // Must keep stringstream in memory or else GameSession can't restart. std::stringstream m_levelstream; diff --git a/src/supertux/game_session.cpp b/src/supertux/game_session.cpp index a201cab43d1..18772423f47 100644 --- a/src/supertux/game_session.cpp +++ b/src/supertux/game_session.cpp @@ -27,6 +27,7 @@ #include "gui/mousecursor.hpp" #include "math/vector.hpp" #include "object/camera.hpp" +#include "object/character_registry.hpp" #include "object/endsequence_fireworks.hpp" #include "object/endsequence_walk.hpp" #include "object/level_time.hpp" @@ -91,6 +92,7 @@ GameSession::GameSession(Savegame* savegame, Statistics* statistics) : m_coins_at_start(), m_boni_at_start(), m_pockets_at_start(), + m_character_ids_at_start(), m_active(false), m_end_seq_started(false), m_pause_target_timer(false), @@ -101,6 +103,7 @@ GameSession::GameSession(Savegame* savegame, Statistics* statistics) : m_boni_at_start.resize(InputManager::current()->get_num_users(), BONUS_NONE); m_pockets_at_start.resize(InputManager::current()->get_num_users(), BONUS_NONE); + m_character_ids_at_start.resize(InputManager::current()->get_num_users(), CharacterType::TUX); m_data_table.clear(); } @@ -124,9 +127,11 @@ GameSession::GameSession(std::istream& istream_, Savegame* savegame, Statistics* m_levelstream = &istream_; } + void GameSession::reset_level() { + log_warning << "reset_level called" << std::endl; for (const auto& p : m_currentsector->get_players()) { try @@ -170,11 +175,14 @@ GameSession::on_player_added(int id) } if (player_status->m_num_players <= id) + { player_status->add_player(); + } - + CharacterType character_type = player_status->get_character_id(id); + // ID = 0 is impossible, so no need to write `(id == 0) ? "" : ...` - auto& player = m_currentsector->add(*player_status, "Tux" + std::to_string(id + 1), id); + auto& player = m_currentsector->add(*player_status, "Tux" + std::to_string(id + 1), id, character_type); player.multiplayer_prepare_spawn(); } @@ -206,7 +214,8 @@ GameSession::restart_level(bool after_death, bool preserve_music) m_coins_at_start = currentStatus.coins; m_boni_at_start = currentStatus.bonus; m_pockets_at_start = currentStatus.m_item_pockets; - + m_character_ids_at_start = currentStatus.m_character_ids; + // Needed for the title screen apparently. if (m_currentsector) { diff --git a/src/supertux/game_session.hpp b/src/supertux/game_session.hpp index 2303e52f955..5cdff1a8214 100644 --- a/src/supertux/game_session.hpp +++ b/src/supertux/game_session.hpp @@ -29,6 +29,7 @@ #include #include "math/vector.hpp" +#include "object/character_profile.hpp" #include "squirrel/squirrel_scheduler.hpp" #include "squirrel/squirrel_util.hpp" #include "supertux/game_object.hpp" @@ -211,6 +212,7 @@ class GameSession final : public Screen, int m_coins_at_start; /** How many coins does the player have at the start */ std::vector m_boni_at_start; /** What boni does the player have at the start */ std::vector m_pockets_at_start; /** What is in the pockets of the players */ + std::vector m_character_ids_at_start; /** What character each player has at the start */ bool m_active; /** Game active? **/ diff --git a/src/supertux/level.cpp b/src/supertux/level.cpp index 4431a281f2d..fbae3bfa92a 100644 --- a/src/supertux/level.cpp +++ b/src/supertux/level.cpp @@ -95,7 +95,7 @@ Level::initialize() // All players will be added to the first sector. They are moved between sectors. Sector* sector = m_sectors.at(0).get(); - sector->add(player_status, "Tux", 0); + sector->add(player_status, "Tux", 0, player_status.get_character_id(0)); if (savegame && !savegame->is_title_screen()) { @@ -107,7 +107,7 @@ Level::initialize() s_dummy_player_status.add_player(); - sector->add(player_status, "Tux" + std::to_string(id + 1), id); + sector->add(player_status, "Tux" + std::to_string(id + 1), id, player_status.get_character_id(id)); } } sector->flush_game_objects(); diff --git a/src/supertux/levelintro.cpp b/src/supertux/levelintro.cpp index 359f1d3948d..92bd19ed8a5 100644 --- a/src/supertux/levelintro.cpp +++ b/src/supertux/levelintro.cpp @@ -19,6 +19,7 @@ #include "control/input_manager.hpp" #include "gui/mousecursor.hpp" #include "math/random.hpp" +#include "object/character_profile.hpp" #include "object/player.hpp" #include "sprite/sprite.hpp" #include "sprite/sprite_manager.hpp" @@ -231,8 +232,10 @@ LevelIntro::push_player() return; } - m_player_sprite.push_back(SpriteManager::current()->create("images/creatures/tux/tux.sprite")); - m_santa_sprite.push_back(SpriteManager::current()->create("images/creatures/tux/santahat.sprite")); + CharacterType character_type = m_player_status.get_character_id(i); + m_player_sprite.push_back(SpriteManager::current()->create(Player::get_sprite_path_for_character(character_type))); + if (character_type == CharacterType::TUX) + m_santa_sprite.push_back(SpriteManager::current()->create("images/creatures/tux/santahat.sprite")); m_player_sprite_py.push_back(0); m_player_sprite_vy.push_back(0); m_player_sprite_jump_timer.push_back(std::make_unique()); diff --git a/src/supertux/menu/character_selector_menu.cpp b/src/supertux/menu/character_selector_menu.cpp new file mode 100644 index 00000000000..e25c3103a8b --- /dev/null +++ b/src/supertux/menu/character_selector_menu.cpp @@ -0,0 +1,54 @@ +// SuperTux +// Copyright (C) 2024 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "supertux/menu/character_selector_menu.hpp" + +#include "gui/menu_manager.hpp" +#include "util/gettext.hpp" + +CharacterSelectorMenu::CharacterSelectorMenu( + const std::function& on_select, + const std::function& on_cancel) + : m_on_select(on_select), m_on_cancel(on_cancel) +{ + add_label(_("Select Character")); + add_hl(); + + add_entry(_("Tux"), [this] { + if (m_on_select) + m_on_select(CHARACTER_TUX); + }); + + add_entry(_("Penny"), [this] { + if (m_on_select) + m_on_select(CHARACTER_PENNY); + }); + + add_entry(_("Larry"), [this] { + if (m_on_select) + m_on_select(CHARACTER_LARRY); + }); + + add_hl(); + add_back(_("Cancel")); +} + +bool CharacterSelectorMenu::on_back_action() +{ + if (m_on_cancel) + m_on_cancel(); + return true; // Allow menu to pop +} diff --git a/src/supertux/menu/character_selector_menu.hpp b/src/supertux/menu/character_selector_menu.hpp new file mode 100644 index 00000000000..1c17248253c --- /dev/null +++ b/src/supertux/menu/character_selector_menu.hpp @@ -0,0 +1,44 @@ +// SuperTux +// Copyright (C) 2024 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include "gui/menu.hpp" +#include + +class CharacterSelectorMenu final : public Menu +{ +public: + /** + * @param on_select Callback called with character ID (0=Tux, 1=Penny, 2=Larry) + * @param on_cancel Callback called if user presses BACK or cancels + */ + CharacterSelectorMenu( + const std::function& on_select, + const std::function& on_cancel); + + void menu_action(MenuItem& item) override {} + bool on_back_action() override; + +private: + std::function m_on_select; + std::function m_on_cancel; + + // Character IDs + static constexpr int CHARACTER_TUX = 0; + static constexpr int CHARACTER_PENNY = 1; + static constexpr int CHARACTER_LARRY = 2; +}; diff --git a/src/supertux/menu/multiplayer_player_menu.cpp b/src/supertux/menu/multiplayer_player_menu.cpp index daa50630e57..422b4ae3578 100644 --- a/src/supertux/menu/multiplayer_player_menu.cpp +++ b/src/supertux/menu/multiplayer_player_menu.cpp @@ -24,23 +24,97 @@ #include "control/joystick_manager.hpp" #include "gui/dialog.hpp" #include "gui/item_toggle.hpp" +#include "gui/item_stringselect.hpp" #include "object/player.hpp" +#include "supertux/game_manager.hpp" #include "supertux/game_session.hpp" #include "supertux/gameconfig.hpp" #include "supertux/globals.hpp" #include "supertux/savegame.hpp" #include "supertux/sector.hpp" +#include "worldmap/worldmap.hpp" #include "util/gettext.hpp" #include "util/log.hpp" -MultiplayerPlayerMenu::MultiplayerPlayerMenu(int player_id) +int character_type_to_index(CharacterType character_type) { + switch(character_type) { + case CharacterType::PENNY: return 1; + case CharacterType::LARRY: return 2; + default: return 0; // TUX + } +} + +CharacterType index_to_character_type(int index) +{ + switch(index) { + case 1: return CharacterType::PENNY; + case 2: return CharacterType::LARRY; + default: return CharacterType::TUX; + } +} + +static PlayerStatus* get_player_status() +{ + if (GameManager::current() && GameManager::current()->m_savegame + && GameManager::current()->m_savegame->is_title_screen()) + return &GameManager::current()->m_savegame->get_player_status(); + + if (worldmap::WorldMap::current()) + return &worldmap::WorldMap::current()->get_savegame().get_player_status(); + + if (GameSession::current()) + return &GameSession::current()->get_savegame().get_player_status(); + + if (GameManager::current() && GameManager::current()->m_savegame) + return &GameManager::current()->m_savegame->get_player_status(); + + return nullptr; +} + +MultiplayerPlayerMenu::MultiplayerPlayerMenu(int player_id) : m_player_id(player_id) +{ + if (GameManager::current()) + GameManager::current()->ensure_savegame_for_profile(); + add_label(fmt::format(_("Player {}"), player_id + 1)); add_hl(); add_toggle(-1, _("Play with the keyboard"), &InputManager::current()->m_uses_keyboard[player_id]) .set_help(_("Don't automatically bind controllers to this player, and spawn it even if it has no controller.")); + m_selected_character = 0; + PlayerStatus* player_status = get_player_status(); + if (player_status) + m_selected_character = character_type_to_index(player_status->get_character_id(player_id)); + + std::vector characters = { + _("Tux"), + _("Penny"), + _("Larry") + }; + auto& char_select = add_string_select(-1, + _("Character"), + m_selected_character, + characters); + char_select.set_help(_("Select character for this player (use LEFT/RIGHT arrows)")); + char_select.set_callback([this](int selected) { + if (selected >= 0 && selected < 3) { + PlayerStatus* status = get_player_status(); + if (status) { + status->set_character_id(m_player_id, index_to_character_type(selected)); + m_selected_character = selected; + + if (GameManager::current() && GameManager::current()->m_savegame + && GameManager::current()->m_savegame->is_title_screen() + && !worldmap::WorldMap::current() + && !GameSession::current()) { + GameManager::current()->m_savegame->save(); + } + } + } + }); + if (player_id != 0 && GameSession::current() && !GameSession::current()->get_savegame().is_title_screen()) { diff --git a/src/supertux/menu/multiplayer_player_menu.hpp b/src/supertux/menu/multiplayer_player_menu.hpp index a8a62d8f425..aa7e0cb09b9 100644 --- a/src/supertux/menu/multiplayer_player_menu.hpp +++ b/src/supertux/menu/multiplayer_player_menu.hpp @@ -24,4 +24,8 @@ class MultiplayerPlayerMenu final : public Menu MultiplayerPlayerMenu(int player_id); void menu_action(MenuItem& item) override {} + +private: + int m_player_id; + int m_selected_character = 0; // 0=Tux, 1=Penny, 2=Larry }; diff --git a/src/supertux/menu/multiplayer_players_menu.cpp b/src/supertux/menu/multiplayer_players_menu.cpp index 2f143470961..4e9794962e5 100644 --- a/src/supertux/menu/multiplayer_players_menu.cpp +++ b/src/supertux/menu/multiplayer_players_menu.cpp @@ -22,15 +22,31 @@ #include "control/input_manager.hpp" #include "control/joystick_manager.hpp" #include "gui/dialog.hpp" +#include "gui/menu_manager.hpp" +#include "object/character_registry.hpp" +#include "supertux/game_manager.hpp" #include "supertux/game_session.hpp" +#include "supertux/menu/character_selector_menu.hpp" #include "supertux/menu/multiplayer_player_menu.hpp" #include "supertux/savegame.hpp" #include "supertux/sector.hpp" +#include "worldmap/worldmap.hpp" #include "object/player.hpp" #include "util/gettext.hpp" +#include "util/log.hpp" MultiplayerPlayersMenu::MultiplayerPlayersMenu() { + if (GameManager::current()) + GameManager::current()->ensure_savegame_for_profile(); + refresh(); +} + +void +MultiplayerPlayersMenu::refresh() +{ + clear(); + add_label(_("Multiplayer")); add_hl(); @@ -45,27 +61,59 @@ MultiplayerPlayersMenu::MultiplayerPlayersMenu() if (InputManager::current()->can_add_user()) { - add_entry(_("Add Player (Keyboard)"), [] { - InputManager::current()->push_user(); - InputManager::current()->m_uses_keyboard[InputManager::current()->get_num_users() - 1] = true; + auto on_character_selected = [](int character_id) { + PlayerStatus* status = nullptr; - if (GameSession::current() && GameSession::current()->get_savegame().get_player_status().m_num_players < InputManager::current()->get_num_users()) + if (GameManager::current() && GameManager::current()->m_savegame + && GameManager::current()->m_savegame->is_title_screen()) + { + status = &GameManager::current()->m_savegame->get_player_status(); + } + else if (worldmap::WorldMap::current()) + { + status = &worldmap::WorldMap::current()->get_savegame().get_player_status(); + } + else if (GameSession::current()) + { + status = &GameSession::current()->get_savegame().get_player_status(); + } + else if (GameManager::current() && GameManager::current()->m_savegame) { - GameSession::current()->get_savegame().get_player_status().add_player(); + status = &GameManager::current()->m_savegame->get_player_status(); } - MenuManager::instance().set_menu(std::make_unique()); - }); + if (!status) + return; - add_entry(_("Add Player (Controller)"), [] { - InputManager::current()->push_user(); + const char* char_ids[] = {"tux", "penny", "larry"}; + int player_index = InputManager::current()->get_num_users() - 1; - if (GameSession::current() && GameSession::current()->get_savegame().get_player_status().m_num_players < InputManager::current()->get_num_users()) - { - GameSession::current()->get_savegame().get_player_status().add_player(); - } + if (status->m_num_players <= player_index) + status->add_player(); + + if (character_id >= 0 && character_id < 3) + status->set_character_id(player_index, CharacterRegistry::string_to_character(char_ids[character_id])); + + MenuManager::instance().pop_menu(); + if (MenuManager::instance().current_menu()) + MenuManager::instance().current_menu()->refresh(); + }; - MenuManager::instance().set_menu(std::make_unique()); + add_entry(_("Add Player (Keyboard)"), [this, on_character_selected] { + InputManager::current()->push_user(); + InputManager::current()->m_uses_keyboard[InputManager::current()->get_num_users() - 1] = true; + MenuManager::instance().push_menu(std::make_unique( + on_character_selected, + [this]() { InputManager::current()->pop_user(); } + )); + }); + + add_entry(_("Add Player (Controller)"), [this, on_character_selected] { + InputManager::current()->push_user(); + MenuManager::instance().push_menu(std::make_unique( + on_character_selected, + [this]() { InputManager::current()->pop_user(); } + )); }); } @@ -77,9 +125,9 @@ MultiplayerPlayersMenu::MultiplayerPlayersMenu() Dialog::show_confirmation(_("Warning: The player you are trying to\nremove is currently in-game.\n\nDo you wish to remove them anyways?"), [] { // Remove the player before the controller, else it'll behave funny - auto num = InputManager::current()->get_num_users(); + int num = InputManager::current()->get_num_users(); // FIXME: Probably not a good idea to get a player by name - auto player = Sector::current()->get_object_by_name("Tux" + std::to_string(num)); + Player* player = Sector::current()->get_object_by_name("Tux" + std::to_string(num)); if (player) { diff --git a/src/supertux/menu/multiplayer_players_menu.hpp b/src/supertux/menu/multiplayer_players_menu.hpp index f3104d15fec..92ead6815f9 100644 --- a/src/supertux/menu/multiplayer_players_menu.hpp +++ b/src/supertux/menu/multiplayer_players_menu.hpp @@ -24,4 +24,5 @@ class MultiplayerPlayersMenu final : public Menu MultiplayerPlayersMenu(); void menu_action(MenuItem& item) override {} + void refresh() override; }; diff --git a/src/supertux/player_status.cpp b/src/supertux/player_status.cpp index f9dbf0987d2..a148107f3b7 100644 --- a/src/supertux/player_status.cpp +++ b/src/supertux/player_status.cpp @@ -21,6 +21,7 @@ #include "audio/sound_manager.hpp" #include "object/player.hpp" +#include "object/character_registry.hpp" #include "supertux/globals.hpp" #include "supertux/game_session.hpp" #include "supertux/player_status_hud.hpp" @@ -76,6 +77,9 @@ PlayerStatus::reset(int num_players) m_item_pockets.clear(); m_item_pockets.resize(num_players, BONUS_NONE); + if (m_character_ids.size() < static_cast(num_players)) + m_character_ids.resize(num_players, CharacterType::TUX); + m_num_players = num_players; } @@ -353,9 +357,8 @@ PlayerStatus::parse_bonus_mapping(const ReaderMapping& map, int id) bonus[id] = get_bonus_from_name(bonusname); } - if (map.get("item-pocket", bonusname)) { + if (map.get("item-pocket", bonusname)) m_item_pockets[id] = get_bonus_from_name(bonusname); - } } std::string @@ -382,9 +385,11 @@ void PlayerStatus::add_player() { m_num_players++; - bonus.resize(m_num_players, BONUS_NONE); m_item_pockets.resize(m_num_players, BONUS_NONE); + + if (m_character_ids.size() < static_cast(m_num_players)) + m_character_ids.resize(m_num_players, CharacterType::TUX); } void @@ -396,10 +401,12 @@ PlayerStatus::remove_player(int player_id) { bonus[i] = bonus[i + 1]; m_item_pockets[i] = m_item_pockets[i + 1]; + m_character_ids[i] = m_character_ids[i + 1]; } bonus.resize(m_num_players, BONUS_NONE); m_item_pockets.resize(m_num_players, BONUS_NONE); + m_character_ids.resize(m_num_players, CharacterType::TUX); } void @@ -408,6 +415,27 @@ PlayerStatus::set_hud_hint(PlayerStatusHUD* hud) m_hud = hud; } +CharacterType +PlayerStatus::get_character_id(int player_id) const +{ + if (player_id < 0 || player_id >= static_cast(m_character_ids.size())) + return CharacterType::TUX; + return m_character_ids[player_id]; +} + +void +PlayerStatus::set_character_id(int player_id, CharacterType character_type) +{ + if (player_id < 0) + return; + + if (player_id >= static_cast(m_character_ids.size())) { + m_character_ids.resize(player_id + 1, CharacterType::TUX); + } + + m_character_ids[player_id] = character_type; +} + PlayerStatus::PocketPowerUp::PocketPowerUp(BonusType bonustype, Vector pos): PowerUp(pos, PowerUp::get_type_from_bonustype(bonustype)), m_cooldown_timer(), diff --git a/src/supertux/player_status.hpp b/src/supertux/player_status.hpp index 0892acff800..918fd22ebdd 100644 --- a/src/supertux/player_status.hpp +++ b/src/supertux/player_status.hpp @@ -23,6 +23,7 @@ #include #include "object/powerup.hpp" +#include "object/character_profile.hpp" #include "supertux/timer.hpp" #include "supertux/level.hpp" @@ -116,11 +117,16 @@ class PlayerStatus final int coins; int tuxdolls; std::vector bonus; + std::vector m_character_ids; /**< Character type for each player*/ std::string worldmap_sprite; /**< the sprite of Tux that should be used in worldmap */ std::string last_worldmap; /**< the last played worldmap */ std::string title_level; /**< level to be used for the title screen, overrides the value of the same property for the world */ + CharacterType get_character_id(int player_id) const; + + void set_character_id(int player_id, CharacterType character_type); + private: PlayerStatus(const PlayerStatus&) = delete; PlayerStatus& operator=(const PlayerStatus&) = delete; diff --git a/src/supertux/resources.cpp b/src/supertux/resources.cpp index 5b4693aca1c..d76cc9a9bbb 100644 --- a/src/supertux/resources.cpp +++ b/src/supertux/resources.cpp @@ -18,6 +18,7 @@ #include "supertux/resources.hpp" #include "gui/mousecursor.hpp" +#include "object/character_registry.hpp" #include "sprite/sprite.hpp" #include "sprite/sprite_manager.hpp" #include "supertux/debug.hpp" @@ -69,6 +70,13 @@ Resources::load(bool reload) // Load the mouse-cursor mouse_cursor.reset(new MouseCursor(SpriteManager::current()->create("images/engine/menu/mousecursor.sprite"))); MouseCursor::set_current(mouse_cursor.get()); + + // Initialize character registry + static std::unique_ptr character_registry; + if (!character_registry) + { + character_registry.reset(new CharacterRegistry()); + } } default_font.reset(new TTFFont("fonts/SuperTux-Medium.ttf", 18, 1.25f, 2, 1)); diff --git a/src/supertux/title_screen.cpp b/src/supertux/title_screen.cpp index 22184cf44f1..985391aa55b 100644 --- a/src/supertux/title_screen.cpp +++ b/src/supertux/title_screen.cpp @@ -28,6 +28,7 @@ #include "sdk/integration.hpp" #include "supertux/constants.hpp" #include "supertux/gameconfig.hpp" +#include "supertux/game_manager.hpp" #include "supertux/game_session.hpp" #include "supertux/globals.hpp" #include "supertux/level.hpp" @@ -78,6 +79,9 @@ TitleScreen::setup() // calls) we only do this when setup is called again (usually after leaving // the game/editor), not on first initialization (because then we'd call // apply_config twice...) + if (GameManager::current()) + GameManager::current()->ensure_title_screen_savegame(); + if (m_fully_initialized) { VideoSystem::current()->get_viewport().force_full_viewport(g_config->max_viewport);