From e5c5db30eb06f5d011d7206d3525714a253b768d Mon Sep 17 00:00:00 2001 From: Zicklag Date: Thu, 7 Apr 2022 17:20:13 -0500 Subject: [PATCH 1/2] Make Eaiser to Create Animated Sprites From Meta `impl From for Animated Sprite` and clean up some of the code that could benefit from it. --- src/drawables/animated_sprite.rs | 21 ++++++++++++++++++++ src/effects/active/triggered.rs | 19 ++++++------------ src/gui/select_character.rs | 28 +++------------------------ src/items.rs | 33 ++++---------------------------- src/map/decoration.rs | 20 ++++++------------- 5 files changed, 40 insertions(+), 81 deletions(-) diff --git a/src/drawables/animated_sprite.rs b/src/drawables/animated_sprite.rs index 948ae0d44e..24b4528cb1 100644 --- a/src/drawables/animated_sprite.rs +++ b/src/drawables/animated_sprite.rs @@ -149,6 +149,27 @@ pub struct AnimatedSprite { pub wait_timer: f32, } +impl From for AnimatedSprite { + fn from(meta: AnimatedSpriteMetadata) -> Self { + let animations = meta + .animations + .into_iter() + .map(Into::into) + .collect::>(); + + let params = AnimatedSpriteParams { + scale: meta.scale.unwrap_or(1.0), + offset: meta.offset, + pivot: meta.pivot, + tint: meta.tint.unwrap_or(color::WHITE), + autoplay_id: meta.autoplay_id, + ..Default::default() + }; + + AnimatedSprite::new(&meta.texture_id, animations.as_slice(), params) + } +} + impl AnimatedSprite { pub fn new(texture_id: &str, animations: &[Animation], params: AnimatedSpriteParams) -> Self { let animations = animations.to_vec(); diff --git a/src/effects/active/triggered.rs b/src/effects/active/triggered.rs index c934e08067..bd83ed8360 100644 --- a/src/effects/active/triggered.rs +++ b/src/effects/active/triggered.rs @@ -13,7 +13,7 @@ use crate::particles::{ParticleEmitter, ParticleEmitterMetadata}; use crate::physics; use crate::player::{Player, PlayerState}; use crate::{ActiveEffectMetadata, AnimatedSpriteMetadata, CollisionWorld, PhysicsBody}; -use crate::{Drawable, PhysicsBodyParams}; +use crate::{Drawable, DrawableKind, PhysicsBodyParams}; const TRIGGERED_EFFECT_DRAW_ORDER: u32 = 5; @@ -114,19 +114,12 @@ pub fn spawn_triggered_effect( )); if let Some(meta) = meta.sprite.clone() { - let animations = meta - .animations - .clone() - .into_iter() - .map(|a| a.into()) - .collect::>(); + let animated_sprite = meta.into(); - let mut drawable = Drawable::new_animated_sprite( - TRIGGERED_EFFECT_DRAW_ORDER, - &meta.texture_id, - animations.as_slice(), - meta.clone().into(), - ); + let mut drawable = Drawable { + draw_order: TRIGGERED_EFFECT_DRAW_ORDER, + kind: DrawableKind::AnimatedSprite(animated_sprite), + }; { let sprite = drawable.get_animated_sprite_mut().unwrap(); diff --git a/src/gui/select_character.rs b/src/gui/select_character.rs index da09176898..d6ed4c6d11 100644 --- a/src/gui/select_character.rs +++ b/src/gui/select_character.rs @@ -10,8 +10,7 @@ use crate::gui::{ }; use crate::player::PlayerCharacterMetadata; use crate::{ - draw_one_animated_sprite, update_one_animated_sprite, AnimatedSprite, AnimatedSpriteMetadata, - Resources, + draw_one_animated_sprite, update_one_animated_sprite, AnimatedSpriteMetadata, Resources, }; use core::input::{update_gamepad_context, GameInputScheme}; use core::Transform; @@ -59,17 +58,7 @@ pub async fn show_select_characters_menu( let meta: AnimatedSpriteMetadata = character.sprite.clone().into(); - let animations = meta - .animations - .iter() - .cloned() - .map(|a| a.into()) - .collect::>(); - - let sprite = - AnimatedSprite::new(&meta.texture_id, animations.as_slice(), meta.clone().into()); - - animated_sprites.push(sprite); + animated_sprites.push(meta.into()); } let mut is_ready = false; @@ -246,18 +235,7 @@ pub async fn show_select_characters_menu( let meta: AnimatedSpriteMetadata = character.sprite.clone().into(); - let animations = meta - .animations - .iter() - .cloned() - .map(|a| a.into()) - .collect::>(); - - animated_sprites[i] = AnimatedSprite::new( - &meta.texture_id, - animations.as_slice(), - meta.clone().into(), - ); + animated_sprites[i] = meta.into(); } is_ready = !selected_params.iter().any(|params| params.is_none()); diff --git a/src/items.rs b/src/items.rs index 1ec8200205..a2af8e2987 100644 --- a/src/items.rs +++ b/src/items.rs @@ -9,8 +9,8 @@ use macroquad::prelude::*; use serde::{Deserialize, Serialize}; use crate::{ - ActiveEffectMetadata, AnimatedSprite, AnimatedSpriteMetadata, CollisionWorld, Drawable, - PassiveEffectMetadata, PhysicsBody, QueuedAnimationAction, Resources, + ActiveEffectMetadata, AnimatedSpriteMetadata, CollisionWorld, Drawable, PassiveEffectMetadata, + PhysicsBody, QueuedAnimationAction, Resources, }; use core::{Result, Transform}; @@ -178,19 +178,7 @@ pub fn spawn_item(world: &mut World, position: Vec2, meta: MapItemMetadata) -> R collider_size.y as i32, ); - let animations = meta - .sprite - .animations - .clone() - .into_iter() - .map(|a| a.into()) - .collect::>(); - - let sprite = AnimatedSprite::new( - &meta.sprite.texture_id, - animations.as_slice(), - meta.sprite.clone().into(), - ); + let sprite = meta.sprite.into(); sprites.push((SPRITE_ANIMATED_SPRITE_ID, sprite)); @@ -257,20 +245,7 @@ pub fn spawn_item(world: &mut World, position: Vec2, meta: MapItemMetadata) -> R } if let Some(effect_sprite) = meta.effect_sprite { - let animations = effect_sprite - .animations - .clone() - .into_iter() - .map(|a| a.into()) - .collect::>(); - - let mut sprite = AnimatedSprite::new( - &effect_sprite.texture_id, - animations.as_slice(), - effect_sprite.clone().into(), - ); - - sprite.is_deactivated = true; + let sprite = effect_sprite.into(); sprites.push((EFFECT_ANIMATED_SPRITE_ID, sprite)); } diff --git a/src/map/decoration.rs b/src/map/decoration.rs index 41dd8a16a7..380f7997d7 100644 --- a/src/map/decoration.rs +++ b/src/map/decoration.rs @@ -4,7 +4,7 @@ use hecs::{Entity, World}; use serde::{Deserialize, Serialize}; -use crate::{AnimatedSpriteMetadata, Drawable}; +use crate::{AnimatedSpriteMetadata, Drawable, DrawableKind}; use core::Transform; const DECORATION_DRAW_ORDER: u32 = 0; @@ -26,22 +26,14 @@ impl Decoration { } pub fn spawn_decoration(world: &mut World, position: Vec2, meta: DecorationMetadata) -> Entity { - let animations = meta - .sprite - .animations - .clone() - .into_iter() - .map(|m| m.into()) - .collect::>(); + let sprite = meta.sprite.into(); world.spawn(( Decoration::new(&meta.id), Transform::from(position), - Drawable::new_animated_sprite( - DECORATION_DRAW_ORDER, - &meta.sprite.texture_id, - animations.as_slice(), - meta.sprite.clone().into(), - ), + Drawable { + draw_order: DECORATION_DRAW_ORDER, + kind: DrawableKind::AnimatedSprite(sprite), + }, )) } From 39f6a34017c57f13a2af0dbeb21e2e74169fca23 Mon Sep 17 00:00:00 2001 From: Zicklag Date: Thu, 7 Apr 2022 20:53:45 -0500 Subject: [PATCH 2/2] Add The Ability to Give Passive Effects Sprites --- src/effects/mod.rs | 2 +- src/effects/passive/mod.rs | 10 ++++++- src/player/state.rs | 56 ++++++++++++++++++++++++++++++++++---- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/effects/mod.rs b/src/effects/mod.rs index 00d5ae935c..dc7c6852e3 100644 --- a/src/effects/mod.rs +++ b/src/effects/mod.rs @@ -12,5 +12,5 @@ pub use active::{ActiveEffectKind, ActiveEffectMetadata, TriggeredEffectTrigger} #[serde(untagged)] pub enum AnyEffectParams { Active(ActiveEffectMetadata), - Passive(PassiveEffectMetadata), + Passive(Box), } diff --git a/src/effects/passive/mod.rs b/src/effects/passive/mod.rs index 1efed2b452..dddc298716 100644 --- a/src/effects/passive/mod.rs +++ b/src/effects/passive/mod.rs @@ -9,7 +9,7 @@ use hecs::{Entity, World}; mod turtle_shell; use crate::player::PlayerEventKind; -use crate::PlayerEvent; +use crate::{AnimatedSprite, AnimatedSpriteMetadata, PlayerEvent}; static mut PASSIVE_EFFECT_FUNCS: Option> = None; @@ -46,6 +46,8 @@ pub struct PassiveEffectInstance { pub name: String, pub function: Option, pub activated_on: Vec, + pub sprite: Option, + pub sprite_entity: Option, pub particle_effect_id: Option, pub event_particle_effect_id: Option, pub blocks_damage: bool, @@ -64,6 +66,8 @@ impl PassiveEffectInstance { name: meta.name, function, activated_on: meta.activated_on, + sprite: meta.sprite.map(Into::into), + sprite_entity: None, particle_effect_id: meta.particle_effect_id, event_particle_effect_id: meta.event_particle_effect_id, blocks_damage: meta.blocks_damage, @@ -127,4 +131,8 @@ pub struct PassiveEffectMetadata { /// This is the duration of the effect. #[serde(default, skip_serializing_if = "Option::is_none")] pub duration: Option, + + /// An optional sprite to add to the player along with the effect + #[serde(alias = "animation")] + pub sprite: Option, } diff --git a/src/player/state.rs b/src/player/state.rs index efdd436426..0b568740c8 100644 --- a/src/player/state.rs +++ b/src/player/state.rs @@ -10,7 +10,9 @@ use crate::player::{ Player, PlayerAttributes, PlayerController, PlayerEventQueue, JUMP_SOUND_ID, LAND_SOUND_ID, RESPAWN_DELAY, }; -use crate::{CollisionWorld, Item, Map, PhysicsBody, PlayerEvent, Resources}; +use crate::{ + CollisionWorld, Drawable, DrawableKind, Item, Map, PhysicsBody, PlayerEvent, Resources, +}; const SLIDE_STOP_THRESHOLD: f32 = 2.0; const JUMP_FRAME_COUNT: u16 = 8; @@ -193,16 +195,50 @@ pub fn update_player_states(world: &mut World) { pub fn update_player_passive_effects(world: &mut World) { let mut function_calls = Vec::new(); - for (entity, (player, events)) in world.query::<(&mut Player, &mut PlayerEventQueue)>().iter() { + let mut sprites_to_spawn = Vec::new(); + let mut sprites_to_despawn = Vec::new(); + + for (entity, (player, player_transform, player_drawable, events)) in world + .query::<(&mut Player, &Transform, &Drawable, &mut PlayerEventQueue)>() + .iter() + { let dt = get_frame_time(); for effect in &mut player.passive_effects { effect.duration_timer += dt; + + // Move the sprite to follow the player + if let Some(sprite_entity) = effect.sprite_entity { + let mut transform = world.get_mut::(sprite_entity).unwrap(); + transform.position = player_transform.position; + } + + // Spawn the effect sprite if it hasn't been spawned yet + if let Some(sprite) = effect.sprite.take() { + let sprite_entity = world.reserve_entity(); + + let drawable = Drawable { + draw_order: player_drawable.draw_order + 1, + kind: DrawableKind::AnimatedSprite(sprite), + }; + + sprites_to_spawn.push((sprite_entity, drawable, player_transform.position)); + + effect.sprite_entity = Some(sprite_entity); + } } - player - .passive_effects - .retain(|effect| !effect.is_depleted()); + player.passive_effects.retain(|effect| { + if effect.is_depleted() { + if let Some(sprite_entity) = effect.sprite_entity { + sprites_to_despawn.push(sprite_entity); + } + + false + } else { + true + } + }); events.queue.push(PlayerEvent::Update { dt }); @@ -230,6 +266,16 @@ pub fn update_player_passive_effects(world: &mut World) { for (f, player_entity, item_entity, event) in function_calls.drain(0..) { f(world, player_entity, item_entity, event); } + + for (sprite_entity, drawable, position) in sprites_to_spawn { + world + .insert(sprite_entity, (Transform::from(position), drawable)) + .unwrap(); + } + + for entity in sprites_to_despawn { + world.despawn(entity).unwrap(); + } } pub fn on_player_damage(world: &mut World, damage_from_entity: Entity, damage_to_entity: Entity) {