fuzzyworld

explodorama / files / test / animation.test.ts

animation.test.ts

2.9 KB · history · blame

1import { describe, expect, it } from 'vitest'
2import { isSlide, moveProgress, moveSeconds, playerTransition, SLIDE_SECONDS_PER_TILE, WALK_SECONDS } from '../src/render/effects'
3import { step } from '../src/sim/turn'
4import { board, v } from './helpers'
5
6/**
7 * Every move of the player is animated, whatever else the turn brings (user request, 2026-10-23,
8 * after moves into flame and into the doorway weren't): the move comes from the change of tile.
9 */
10describe('the player always moves on screen', () => {
11 it('a step into flame: the move, then the hit pose', () => {
12 const s = board(`
13 ######
14 #P.1.#
15 ######`)
16 const r = step(s, { id: 'move', target: v(2, 1) })
17 expect(r.state.status).toBe('dead')
18 const t = playerTransition(s, r.state, r.events, false, 10)
19 expect(t.move).toEqual({ from: v(1, 1), at: 10, teleport: false, tiles: 1 })
20 expect(t.pose.kind).toBe('hit')
21 })
22
23 it('a step into the open exit: the move, then the jump', () => {
24 const s = board(`
25 ####
26 #PE#
27 ####`)
28 const r = step(s, { id: 'move', target: v(2, 1) })
29 const t = playerTransition(s, r.state, r.events, false, 10)
30 expect(t.move?.from).toEqual(v(1, 1))
31 expect(t.pose.kind).toBe('jump')
32 })
33
34 it('a teleport vanishes and reappears; a bomb is a crouch, with no move', () => {
35 const s = board(`
36 ######
37 #P...#
38 ######`)
39 s.charge = { kind: 'teleport', left: 3 }
40 const tele = step(s, { id: 'teleport', target: v(4, 1) })
41 expect(playerTransition(s, tele.state, tele.events, true, 10).move).toEqual({ from: v(1, 1), at: 10, teleport: true, tiles: 3 })
42 const bomb = step({ ...s, charge: null }, { id: 'bomb', target: v(2, 1) })
43 const t = playerTransition(s, bomb.state, bomb.events, false, 10)
44 expect(t.move).toBeNull()
45 expect(t.pose.kind).toBe('duck')
46 })
47
48 it('a new level or a retry starts still', () => {
49 const s = board(`
50 ####
51 #PE#
52 ####`)
53 const cleared = step(s, { id: 'move', target: v(2, 1) }).state
54 const next = step(cleared, { id: 'continue' })
55 expect(playerTransition(cleared, next.state, next.events, false, 10).move).toBeNull()
56 })
57})
58
59describe('a slide glides', () => {
60 it('takes longer the further it goes, eases out, and a step or run is unchanged', () => {
61 const step1 = { from: v(1, 1), at: 0, teleport: false, tiles: 1 }
62 const slide6 = { from: v(1, 1), at: 0, teleport: false, tiles: 6 }
63 expect(isSlide(step1)).toBe(false)
64 expect(isSlide({ ...step1, tiles: 2 })).toBe(false)
65 expect(isSlide(slide6)).toBe(true)
66 expect(moveSeconds(slide6)).toBeCloseTo(6 * SLIDE_SECONDS_PER_TILE)
67 expect(moveSeconds(step1)).toBe(WALK_SECONDS)
68 // Halfway in time, more than halfway there; then at rest at the end.
69 expect(moveProgress(slide6, moveSeconds(slide6) / 2)).toBeGreaterThan(0.5)
70 expect(moveProgress(slide6, moveSeconds(slide6))).toBe(1)
71 })
72})