Stagger cloud trail dissolution so tiles fade one at a time
Each cloud in the trail gets a slightly longer TTL than the one before it (0.15s stagger). The origin cloud dissolves first, then each subsequent tile follows. Two consecutive flights produce a trail where the oldest clouds are already gone.
This commit is contained in:
parent
93ad4523e2
commit
a10f3d4e70
2 changed files with 19 additions and 9 deletions
|
|
@ -14,8 +14,10 @@ world: Any = None
|
||||||
# how far you fly
|
# how far you fly
|
||||||
FLY_DISTANCE = 5
|
FLY_DISTANCE = 5
|
||||||
|
|
||||||
# how long cloud trail lingers (seconds)
|
# origin cloud gets the base ttl, each step toward destination adds stagger.
|
||||||
CLOUD_TTL = 2.0
|
# trail visibly shrinks from origin toward the player, one tile at a time.
|
||||||
|
CLOUD_TTL = 1.5
|
||||||
|
CLOUD_STAGGER = 0.4 # seconds between each cloud's expiry
|
||||||
|
|
||||||
# ANSI color for cloud trails
|
# ANSI color for cloud trails
|
||||||
CLOUD_COLOR = BOLD + BRIGHT_WHITE
|
CLOUD_COLOR = BOLD + BRIGHT_WHITE
|
||||||
|
|
@ -68,10 +70,13 @@ async def cmd_fly(player: Player, args: str) -> None:
|
||||||
dx, dy = delta
|
dx, dy = delta
|
||||||
start_x, start_y = player.x, player.y
|
start_x, start_y = player.x, player.y
|
||||||
|
|
||||||
# lay cloud trail at starting position and each intermediate step
|
# lay cloud trail at starting position and each intermediate step.
|
||||||
|
# origin cloud expires first, near-dest cloud lingers longest.
|
||||||
|
# the trail shrinks from behind toward the player over time.
|
||||||
for step in range(FLY_DISTANCE):
|
for step in range(FLY_DISTANCE):
|
||||||
trail_x, trail_y = world.wrap(start_x + dx * step, start_y + dy * step)
|
trail_x, trail_y = world.wrap(start_x + dx * step, start_y + dy * step)
|
||||||
add_effect(trail_x, trail_y, "~", CLOUD_COLOR, ttl=CLOUD_TTL)
|
ttl = CLOUD_TTL + step * CLOUD_STAGGER
|
||||||
|
add_effect(trail_x, trail_y, "~", CLOUD_COLOR, ttl=ttl)
|
||||||
|
|
||||||
# move player to destination
|
# move player to destination
|
||||||
dest_x, dest_y = world.wrap(
|
dest_x, dest_y = world.wrap(
|
||||||
|
|
|
||||||
|
|
@ -219,17 +219,22 @@ async def test_cloud_trail_chars_are_tilde(player):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_cloud_trail_has_ttl(player):
|
async def test_cloud_trail_dissolves_from_origin(player):
|
||||||
"""Cloud effects should expire after roughly 2 seconds."""
|
"""Origin cloud expires first, trail shrinks toward player."""
|
||||||
players[player.name] = player
|
players[player.name] = player
|
||||||
player.flying = True
|
player.flying = True
|
||||||
|
|
||||||
before = time.monotonic()
|
before = time.monotonic()
|
||||||
await fly.cmd_fly(player, "east")
|
await fly.cmd_fly(player, "east")
|
||||||
|
|
||||||
for e in active_effects:
|
# effects are in path order (step 0..4)
|
||||||
remaining = e.expires_at - before
|
expiries = [e.expires_at for e in active_effects]
|
||||||
assert 1.5 <= remaining <= 2.5
|
# each should expire after the previous one (origin fades first)
|
||||||
|
for i in range(1, len(expiries)):
|
||||||
|
assert expiries[i] > expiries[i - 1]
|
||||||
|
# origin cloud ~1.5s, near-dest cloud ~1.5 + 4*0.4 = ~3.1s
|
||||||
|
assert 1.3 <= expiries[0] - before <= 1.7
|
||||||
|
assert 2.9 <= expiries[-1] - before <= 3.3
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue