Files
battery/tests/test_physics.py

153 lines
3.7 KiB
Python
Raw Normal View History

2026-07-21 19:36:02 -04:00
"""Player movement & collision."""
from conftest import step, run, place, hold
from game import settings as S
FLAT = """
name: t
tile_size: 32
map: |
##########
#........#
#........#
#........#
#P......G#
##########
"""
def test_falls_and_lands_on_floor(make_game):
g = make_game(FLAT)
2026-08-01 12:19:46 -04:00
place(g, 4, 1) # up in the air
2026-07-21 19:36:02 -04:00
run(g, 60)
assert g.player.on_ground
2026-08-01 12:19:46 -04:00
assert g.player.rect.bottom == 5 * 32 # floor is row 5's top (y=160)
2026-07-21 19:36:02 -04:00
def test_terminal_velocity(make_game):
g = make_game(FLAT)
place(g, 4, 1)
for _ in range(200):
step(g)
assert g.player.vy <= S.MAX_FALL + 1
def test_jump_gains_height_then_returns(make_game):
g = make_game(FLAT)
2026-08-01 12:19:46 -04:00
run(g, 30) # settle on floor
2026-07-21 19:36:02 -04:00
ground = g.player.rect.bottom
peak = ground
for i in range(60):
step(g, hold(jump_pressed=(i == 0), jump_held=True))
peak = min(peak, g.player.rect.bottom)
2026-08-01 12:19:46 -04:00
assert peak < ground - 32 # rose at least a tile
2026-07-21 19:36:02 -04:00
def test_variable_jump_height(make_game):
# Full-hold jump should out-climb a 1-frame tap.
def peak(hold_frames):
g = make_game(FLAT)
run(g, 30)
ground = g.player.rect.bottom
hi = ground
for i in range(60):
held = i < hold_frames
step(g, hold(jump_pressed=(i == 0), jump_held=held))
hi = min(hi, g.player.rect.bottom)
return ground - hi
2026-08-01 12:19:46 -04:00
2026-07-21 19:36:02 -04:00
assert peak(60) > peak(1) + 8
def test_coyote_time_allows_jump_after_leaving_ledge(make_game):
# Walk off a ledge, then jump within the coyote window -> should rise.
g = make_game("""
name: t
tile_size: 32
map: |
#######
#.....#
#.....#
##....#
#P#...#
#######
""")
2026-08-01 12:19:46 -04:00
place(g, 1, 3) # standing on the little step at [1,3] top
2026-07-21 19:36:02 -04:00
# walk right off the step for a couple frames, then jump
run(g, 4, lambda i: hold(right=True))
y_before = g.player.rect.bottom
step(g, hold(right=True, jump_pressed=True, jump_held=True))
step(g, hold(right=True, jump_held=True))
2026-08-01 12:19:46 -04:00
assert g.player.vy < 0 # a jump actually started
2026-07-21 19:36:02 -04:00
def test_walls_stop_horizontal_movement(make_game):
g = make_game(FLAT)
place(g, 1, 4)
run(g, 120, lambda i: hold(right=True))
2026-08-01 12:19:46 -04:00
assert g.player.rect.right <= 9 * 32 # right wall inner edge (x=288)
2026-07-21 19:36:02 -04:00
run(g, 120, lambda i: hold(left=True))
2026-08-01 12:19:46 -04:00
assert g.player.rect.left >= 1 * 32 # left wall inner edge (x=32)
2026-07-21 19:36:02 -04:00
def test_oneway_platform_land_from_above_pass_from_below(make_game):
g = make_game("""
name: t
tile_size: 32
map: |
#######
#.....#
#.....#
#--...#
#.....#
#P...G#
#######
""")
# Fall onto the one-way from above -> lands on it.
2026-08-01 12:19:46 -04:00
place(g, 1, 1) # open air above the one-way (row 3)
2026-07-21 19:36:02 -04:00
run(g, 60)
assert g.player.on_ground and g.player.rect.bottom == 3 * 32
# From below, jumping up passes through it (doesn't block the head).
g2 = make_game("""
name: t
tile_size: 32
map: |
#######
#.....#
#--...#
#.....#
#P...G#
#######
""")
2026-08-01 12:19:46 -04:00
place(g2, 1, 4) # on the floor, below the one-way (row 2)
run(g2, 5) # settle so on_ground is set before jumping
2026-07-21 19:36:02 -04:00
passed = False
for i in range(40):
step(g2, hold(jump_pressed=(i == 0), jump_held=(i < 12)))
2026-08-01 12:19:46 -04:00
if g2.player.rect.top < 2 * 32: # rose above the one-way row
2026-07-21 19:36:02 -04:00
passed = True
assert passed
def test_drop_through_oneway(make_game):
g = make_game("""
name: t
tile_size: 32
map: |
#######
#.....#
#.....#
#--...#
#.....#
#....G#
#######
""")
2026-08-01 12:19:46 -04:00
place(g, 1, 2) # standing on the one-way at row 3
2026-07-21 19:36:02 -04:00
run(g, 20)
assert g.player.on_ground
# press down + jump to drop through
for i in range(30):
step(g, hold(down=True, jump_pressed=(i == 0)))
2026-08-01 12:19:46 -04:00
assert g.player.rect.top > 3 * 32 # fell below the one-way