From 001c74ba6a20ddf5f027fa6a6bd2f5e3a31da62c Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 4 Jan 2024 21:41:15 -0800 Subject: [PATCH] Added reverse animation --- content/sprite.toml | 4 +-- crates/content/src/part/sprite.rs | 9 +++++-- crates/render/shaders/include/animate.wgsl | 29 +++++++++++++++++----- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/content/sprite.toml b/content/sprite.toml index 17f07fa..7ce88b8 100644 --- a/content/sprite.toml +++ b/content/sprite.toml @@ -20,8 +20,8 @@ file = "projectile/blaster.png" file = "ship/gypsum.png" [sprite."ship::peregrine"] -duration = 1 -repeat = "repeat" +duration = 1.3 +repeat = "reverse" frames = [ "ship/peregrine/01.png", "ship/peregrine/02.png", diff --git a/crates/content/src/part/sprite.rs b/crates/content/src/part/sprite.rs index 060cf09..2b901d8 100644 --- a/crates/content/src/part/sprite.rs +++ b/crates/content/src/part/sprite.rs @@ -44,6 +44,10 @@ pub enum RepeatMode { /// After the first frame, jump to the last frame #[serde(rename = "repeat")] Repeat, + + /// Play this animation in reverse after the last frame + #[serde(rename = "reverse")] + Reverse, } impl RepeatMode { @@ -51,8 +55,9 @@ impl RepeatMode { /// Used to pass this enum into shaders pub fn as_int(&self) -> u32 { match self { - Self::Once => 0, - Self::Repeat => 1, + Self::Repeat => 0, + Self::Once => 1, + Self::Reverse => 2, } } } diff --git a/crates/render/shaders/include/animate.wgsl b/crates/render/shaders/include/animate.wgsl index 58f86df..507ae79 100644 --- a/crates/render/shaders/include/animate.wgsl +++ b/crates/render/shaders/include/animate.wgsl @@ -10,16 +10,33 @@ fn animate(instance: InstanceInput, age: f32) -> u32 { let fps = sprites.data[idx].fps; var frame: u32 = u32(0); - if rep == u32(1) { // Repeat - let x = age / fps; - let m = f32(len); - // x fmod m - frame = u32(x - floor(x / m) * m); - } else { // Once + + // Repeat + if rep == u32(1) { + frame = u32(min( (age / fps), f32(len) - 1.0 )); + + // Reverse + } else if rep == u32(2) { + let x = age / fps; + let m = f32(len) * 2.0 - 1.0; + // x fmod m + frame = u32(x - floor(x / m) * m); + + if frame >= len { + frame = len + len - frame - u32(1); + } + + // Repeat (default) + } else { + let x = age / fps; + let m = f32(len); + // x fmod m + frame = u32(x - floor(x / m) * m); + } return frame + sprites.data[idx].first_frame;