diff options
| author | KonAki <konaki@anokonaki.org> | 2026-10-12 13:45:23 +0800 |
|---|---|---|
| committer | KonAki <konaki@anokonaki.org> | 2026-10-12 13:45:23 +0800 |
| commit | 79edd4027ab956c441c660367c497508c99696bb (patch) | |
| tree | ebcde84b982ebaa527ced4d23d59858ae89c14f8 /kon | |
| parent | 25bb4216fd726824c237a00c8ca0ee23b39d995e (diff) | |
add 2d module: camera, frame animation, tweens
Diffstat (limited to 'kon')
| -rw-r--r-- | kon/kon2d.c | 56 | ||||
| -rw-r--r-- | kon/kon2d.h | 31 |
2 files changed, 87 insertions, 0 deletions
diff --git a/kon/kon2d.c b/kon/kon2d.c index 8ce56d8..0b963ac 100644 --- a/kon/kon2d.c +++ b/kon/kon2d.c @@ -128,3 +128,59 @@ void kon_drawFrame(kon_framebuffer_t *fb, const kon_image *sheet, int frameWidth kon_drawImageEx(fb, sheet, src, (float)x + (float)frameWidth * 0.5f, (float)y + (float)frameHeight * 0.5f, (float)frameWidth * 0.5f, (float)frameHeight * 0.5f, -1.0f, 1.0f, 0.0f, KON_FILTER_NEAREST); } + +/*** tweens ***/ + +float kon_easeValue(kon_ease_t ease, float t) +{ + if (!(t > 0.0f)) return 0.0f; + if (t >= 1.0f) return 1.0f; + switch (ease) { + case KON_EASE_IN: return t * t * t; + case KON_EASE_OUT: return 1.0f - (1.0f - t) * (1.0f - t) * (1.0f - t); + case KON_EASE_INOUT: return t < 0.5f ? 4.0f * t * t * t : 1.0f - 4.0f * (1.0f - t) * (1.0f - t) * (1.0f - t); + case KON_EASE_LINEAR: break; + } + return t; +} + +void kon_tweenSet(kon_tween_t *tween, float value) +{ + tween->from = tween->to = value; + tween->duration = tween->time = 0.0f; + tween->ease = KON_EASE_LINEAR; +} + +void kon_tweenStart(kon_tween_t *tween, float from, float to, float seconds, kon_ease_t ease) +{ + tween->from = from; + tween->to = to; + tween->ease = ease; + tween->time = 0.0f; + tween->duration = seconds > 0.0f ? seconds : 0.0f; +} + +void kon_tweenTo(kon_tween_t *tween, float to, float seconds, kon_ease_t ease) +{ + kon_tweenStart(tween, kon_tweenValue(tween), to, seconds, ease); +} + +float kon_tweenStep(kon_tween_t *tween, float dt) +{ + if (dt > 0.0f && tween->time < tween->duration) { + tween->time += dt; + if (tween->time > tween->duration) tween->time = tween->duration; + } + return kon_tweenValue(tween); +} + +float kon_tweenValue(const kon_tween_t *tween) +{ + if (!(tween->duration > 0.0f)) return tween->to; + return tween->from + (tween->to - tween->from) * kon_easeValue(tween->ease, tween->time / tween->duration); +} + +int kon_tweenDone(const kon_tween_t *tween) +{ + return tween->time >= tween->duration; +} diff --git a/kon/kon2d.h b/kon/kon2d.h index fce4bb2..badaed0 100644 --- a/kon/kon2d.h +++ b/kon/kon2d.h @@ -72,4 +72,35 @@ int kon_animDone(const kon_anim_t *anim); /* draws frame index of a sheet of frameWidth by frameHeight frames with its top left at x, y */ void kon_drawFrame(kon_framebuffer_t *fb, const kon_image *sheet, int frameWidth, int frameHeight, int index, int x, int y, int flip); +/*** tweens ***/ + +typedef enum kon_ease { + KON_EASE_LINEAR, + KON_EASE_IN, /* starts slow */ + KON_EASE_OUT, /* ends slow */ + KON_EASE_INOUT +} kon_ease_t; + +/* a number that glides from one value to another. start one with kon_tweenStart, feed it time with kon_tweenStep and read it with + kon_tweenValue. a tween that was never started just holds 0, kon_tweenSet gives it a value to hold */ +typedef struct kon_tween { + float from, to; + float duration, time; + kon_ease_t ease; +} kon_tween_t; + +/* t from 0 to 1, out of range is clamped */ +float kon_easeValue(kon_ease_t ease, float t); + +void kon_tweenSet(kon_tween_t *tween, float value); +void kon_tweenStart(kon_tween_t *tween, float from, float to, float seconds, kon_ease_t ease); + +/* glides from wherever it is now, so it can be redirected in the middle of a move */ +void kon_tweenTo(kon_tween_t *tween, float to, float seconds, kon_ease_t ease); + +/* returns the new value */ +float kon_tweenStep(kon_tween_t *tween, float dt); +float kon_tweenValue(const kon_tween_t *tween); +int kon_tweenDone(const kon_tween_t *tween); + #endif |
