Proposal: 2D animation — spritesheet/frame animation + tweening (deterministic, ECS-native) #5
Labels
No labels
area:ci
area:docs
area:input
area:net
area:rendering
area:repo
area:stdlib
area:tooling
area:types
cleanup
dx
priority:high
priority:low
priority:medium
proposal
status:in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: workshopsoft/ludic#5
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Two kinds of motion cover almost all 2D games, and Godot cleanly separates them: sprite-frame animation (named clips like
idle/run/jumpplayed from a spritesheet, viaAnimatedSprite2D+SpriteFrames) and tweening (interpolating any value over time with easing, viaTween). Ludic has neither today. This proposes both, ECS-native and deterministic.Part 1 — Spritesheet & frame animation (
Sprite.+ a component)Define clips over a spritesheet (grid of cells), then play by name:
fps,loop,ping_pong,flip_x/flip_y.eventon a given frame (footstep sound, hitbox active) — ties to Ludic'sevent/@On.Screen.sprite(sheet, frame, x, y)(from #2) is the low-level draw the system calls.Part 2 — Tweening (
Tween.)Short, disposable interpolation — damage numbers, fades, camera recoil, UI pops:
Tween.chain(...),Tween.parallel(...),delay,loop,yoyo(DOTween/GodotTweenstyle).Ease.*in #2 (in/out/in_out/elastic/bounce/back).int,fixed,vec2, andcolor(types from #1) — position, scale, rotation, tint, alpha.Tween/Motioncomponent for entity-bound motion advanced by a built-in system (ECS-native, replay-safe).Why both (Godot's rule of thumb)
Reusable, repeated motion → frame animation (clips). Throwaway one-off motion → tween. Offering both keeps each simple.
Phasing
Sprite.sheet/Sprite.clip+SpriteAnimcomponent + built-in frame stepper.Tween.to/byone-offs withEase.*.ping_pong/flip, tween chain/parallel/loop/yoyo.Tween/Motioncomponent; tweeningvec2/color.References
AnimatedSprite2D(SpriteFrames: named clips, fps, loop); GodotTweenfor throwaway interpolation; DOTween-style chaining.Ease.*in #2;vec2/colorin #1;Time.*in #2;event/@Onfor frame callbacks.Frame animation + tweening, ECS-native and advanced on the deterministic fixed frame clock.
Shipped the deterministic math core of both halves in
e4d1e95(pushed tomain).Anim.*— spritesheet frame animation:frame(looping),once(clamped one-shot),pingpong,finished,duration, andcell_x/cell_y(source rect on a grid sheet).Tween.*— value tweening over a timeline:progress/loop/yoyo/done(normalized amount from a timer + duration),ease(t, mode)(curve0..6, sharing Ease.*'s exact formulas via a new sharedease_eval), and typed blendsnumber/round/point/tintfor afixed/int/Vector/ color.Everything is pure Q16.16 / integer math with no new runtime and no heap — the game stores a timer on a component and calls these each frame, exactly like
Collision.*/Grid.*. Because it runs off the fixed frame clock, a replay reproduces every frame and every eased value bit-for-bit, so lockstep netcode and diffable headless renders stay exact.Verified by
examples/library/anim.ludic(34 self-asserting cases: frame math, clamping, ping-pong, cell geometry, timeline clamp/loop/yoyo, half-up rounding, color/vector blends, andEase.in == Tween.ease(., 1)), wired intox test(now 62 passed). Docs:Anim+Tweensections with 16 per-symbol pages;x check-impl/x check-docsgreen. Seed reseeded and the C-free bootstrap fixpoint holds.The stateful sugar the proposal sketches — named clips,
Anim.play, fluentTween.chain/parallelhandles, frame-event callbacks, and an auto-injected advance system — is tracked as a follow-up in #43, since it needs engine-owned systems over user components rather than pure inline math. Closing this as the math core both halves stand on.