summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-12 13:45:23 +0800
committerKonAki <konaki@anokonaki.org>2026-10-12 13:45:23 +0800
commit79edd4027ab956c441c660367c497508c99696bb (patch)
treeebcde84b982ebaa527ced4d23d59858ae89c14f8
parent25bb4216fd726824c237a00c8ca0ee23b39d995e (diff)
add 2d module: camera, frame animation, tweens
-rw-r--r--kon/kon2d.c56
-rw-r--r--kon/kon2d.h31
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