Skip to content

Commit 2be57d2

Browse files
committed
Improve platformer example
1 parent 465a455 commit 2be57d2

1 file changed

Lines changed: 68 additions & 15 deletions

File tree

vm/examples/platformer.asm

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ PLATFORMS:
6565
# L12 gw scratch: platform w
6666
# L13 gh scratch: platform h
6767
# L14 jump_held 1 while a jump key is held (edge detection)
68+
# L15 anim walk-cycle counter (0 when standing still)
6869
#
6970
push 10240; # L0 px = 40 * 256
7071
push 89600; # L1 py = 350 * 256
@@ -81,6 +82,7 @@ push 0; # L11 gy
8182
push 0; # L12 gw
8283
push 0; # L13 gh
8384
push 0; # L14 jump_held (1 while a jump key is held)
85+
push 0; # L15 anim (walk-cycle counter)
8486

8587
# Create the window
8688
push 640;
@@ -191,6 +193,16 @@ get_local 5; jz SKIP_L;
191193
get_local 2; push 720; sub_u64; set_local 2; # moving left
192194
SKIP_L:
193195

196+
# Advance the walk cycle while moving on the ground, else stand still
197+
get_local 2; push 0; ne_u64; # trying to move? (vx != 0)
198+
get_local 4; and_u64; # AND on the ground
199+
jz WALK_RESET;
200+
get_local 15; push 1; add_u64; set_local 15;
201+
jmp WALK_DONE;
202+
WALK_RESET:
203+
push 0; set_local 15;
204+
WALK_DONE:
205+
194206
# =====================================================================
195207
# Horizontal movement + collision
196208
# =====================================================================
@@ -346,9 +358,10 @@ push 400; push 136; call DRAW_DOOR, 2; pop;
346358
get_local 0; push 8; rshift_i64;
347359
get_local 1; push 8; rshift_i64;
348360
call DRAW_SHADOW, 2; pop;
349-
get_local 0; push 8; rshift_i64;
350-
get_local 1; push 8; rshift_i64;
351-
call DRAW_GUY, 2; pop;
361+
get_local 0; push 8; rshift_i64; # x
362+
get_local 1; push 8; rshift_i64; # y
363+
get_local 15; call WALK_SWING, 1; # leg swing for this frame
364+
call DRAW_GUY, 3; pop;
352365
jmp RENDER_PRESENT;
353366

354367
RENDER_WIN:
@@ -460,13 +473,33 @@ and_u64;
460473
ret;
461474

462475
#
463-
# DRAW_GUY(i64 x, i64 y)
476+
# DRAW_GUY(i64 x, i64 y, i64 swing)
464477
#
465478
# Draw a little character inside the 24 x 32 player box whose top-left
466479
# corner is at the given pixel coordinates. Built out of FILL_RECT parts:
467-
# hair, head, eyes, shirt, arms, legs and shoes. Returns 0.
480+
# hair, head, eyes, shirt, arms, legs and shoes. The signed `swing`
481+
# (-3..3) lifts alternate feet to produce a simple walk cycle; 0 is the
482+
# standing pose. Returns 0.
483+
#
484+
# Locals:
485+
# L0 lift_l how far the left foot is lifted = max(0, swing)
486+
# L1 lift_r how far the right foot is lifted = max(0, -swing)
468487
#
469488
DRAW_GUY:
489+
push 0; push 0;
490+
# lift_l = max(0, swing)
491+
get_arg 2;
492+
dup; push 0; lt_i64; jz DG_LIFTL;
493+
pop; push 0;
494+
DG_LIFTL:
495+
set_local 0;
496+
# lift_r = max(0, -swing)
497+
push 0; get_arg 2; sub_u64;
498+
dup; push 0; lt_i64; jz DG_LIFTR;
499+
pop; push 0;
500+
DG_LIFTR:
501+
set_local 1;
502+
470503
# head (skin)
471504
get_arg 0; push 6; add_u64; get_arg 1; push 2; add_u64; push 12; push 9; push_u32 0xFFF0C8A0; call FILL_RECT, 5; pop;
472505
# hair crown (slightly wider than the head, drawn over its top)
@@ -490,17 +523,35 @@ get_arg 0; push 4; add_u64; get_arg 1; push 18; add_u64; push 16; push 3; push
490523
get_arg 0; push 1; add_u64; get_arg 1; push 11; add_u64; push 3; push 9; push_u32 0xFFF0C8A0; call FILL_RECT, 5; pop;
491524
# right arm
492525
get_arg 0; push 20; add_u64; get_arg 1; push 11; add_u64; push 3; push 9; push_u32 0xFFF0C8A0; call FILL_RECT, 5; pop;
493-
# left leg
494-
get_arg 0; push 5; add_u64; get_arg 1; push 21; add_u64; push 6; push 9; push_u32 0xFF2A50A0; call FILL_RECT, 5; pop;
495-
# right leg
496-
get_arg 0; push 13; add_u64; get_arg 1; push 21; add_u64; push 6; push 9; push_u32 0xFF2A50A0; call FILL_RECT, 5; pop;
497-
# left shoe
498-
get_arg 0; push 5; add_u64; get_arg 1; push 29; add_u64; push 6; push 3; push_u32 0xFF3A2A1A; call FILL_RECT, 5; pop;
499-
# right shoe
500-
get_arg 0; push 13; add_u64; get_arg 1; push 29; add_u64; push 6; push 3; push_u32 0xFF3A2A1A; call FILL_RECT, 5; pop;
526+
# left leg (shortened by lift_l so the foot rises)
527+
get_arg 0; push 5; add_u64; get_arg 1; push 21; add_u64; push 6; push 9; get_local 0; sub_u64; push_u32 0xFF2A50A0; call FILL_RECT, 5; pop;
528+
# right leg (shortened by lift_r)
529+
get_arg 0; push 13; add_u64; get_arg 1; push 21; add_u64; push 6; push 9; get_local 1; sub_u64; push_u32 0xFF2A50A0; call FILL_RECT, 5; pop;
530+
# left shoe (raised by lift_l)
531+
get_arg 0; push 5; add_u64; get_arg 1; push 29; add_u64; get_local 0; sub_u64; push 6; push 3; push_u32 0xFF3A2A1A; call FILL_RECT, 5; pop;
532+
# right shoe (raised by lift_r)
533+
get_arg 0; push 13; add_u64; get_arg 1; push 29; add_u64; get_local 1; sub_u64; push 6; push 3; push_u32 0xFF3A2A1A; call FILL_RECT, 5; pop;
501534
push 0;
502535
ret;
503536

537+
#
538+
# WALK_SWING(i64 counter) -> i64 swing
539+
#
540+
# Map a free-running animation counter onto a 4-phase leg swing:
541+
# 0 (both feet down), +3 (left foot up), 0, -3 (right foot up), repeating.
542+
# Phase 0 is neutral so a counter of 0 (standing still) keeps both feet on
543+
# the ground. Each phase lasts 3 frames, so a full stride takes 12 frames.
544+
#
545+
WALK_SWING:
546+
get_arg 0; push 3; div_i64; push 4; mod_u64; # phase 0..3
547+
dup; push 1; eq_u64; jnz WS_POS;
548+
dup; push 3; eq_u64; jnz WS_NEG;
549+
pop; push 0; ret;
550+
WS_POS:
551+
pop; push 3; ret;
552+
WS_NEG:
553+
pop; push -3; ret;
554+
504555
#
505556
# DRAW_DOOR(i64 x, i64 y)
506557
#
@@ -637,10 +688,12 @@ push 32;
637688
push_u32 0xFFFFE9A0;
638689
call FILL_RECT, 5; pop;
639690

640-
# the little guy steps into the doorway during the first ~48 frames
691+
# the little guy walks into the doorway during the first ~48 frames
641692
get_arg 0; push 48; lt_i64; jz DW_NOGUY;
642693
push 372; get_arg 0; push 2; mul_u64; push 3; div_i64; add_u64; set_local 1; # gx = 372 + t*2/3
643-
get_local 1; push 144; call DRAW_GUY, 2; pop;
694+
get_local 1; push 144;
695+
get_arg 0; call WALK_SWING, 1; # animate his legs as he walks in
696+
call DRAW_GUY, 3; pop;
644697
DW_NOGUY:
645698

646699
# confetti: 16 falling squares whose colour cycles

0 commit comments

Comments
 (0)