diff --git a/game/src/game/seaquest/seaquest_state.rs b/game/src/game/seaquest/seaquest_state.rs index 5f8bbd51f5231a35002a9f7e06ca184051d76fd1..a007683a048545a6645243d79b86a85f6c0edf57 100644 --- a/game/src/game/seaquest/seaquest_state.rs +++ b/game/src/game/seaquest/seaquest_state.rs @@ -96,6 +96,7 @@ pub struct BackgroundTheme pub background_animation_id: AnimationId, } +#[derive(Clone, Debug, PartialEq, Eq)] pub struct AssetTheme { pub theme_name: String, @@ -143,6 +144,27 @@ pub struct BoundingCircle pub radius: f32, } +#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] +pub struct ExplosionState +{ + pub position: Vector2<f32>, + pub animation_instance_id: AnimationInstanceId, + pub active: bool, +} + +impl ExplosionState +{ + pub fn adjusted_position( + &self, + sprite_manager: &SpriteManager, + sprite_state_manager: &SpriteStateManager, + ) -> Vector2<f32> + { + let origin = sprite_manager.get_animation_instance_origin(sprite_state_manager, self.animation_instance_id); + self.position - origin + } +} + #[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] pub struct BulletState { @@ -566,7 +588,7 @@ enum Sprites Shark, Sub, Bullet, - Bullet2, + Explosion, Background, } @@ -575,6 +597,7 @@ pub struct GameState { pub players: Vec<PlayerState>, pub player_bullets: Vec<Vec<BulletState>>, + pub bullet_explosions: Vec<ExplosionState>, // pub time_multiplier: f32, // pub camera: Camera, // pub proj: Matrix4<f32>, @@ -619,6 +642,7 @@ impl Default for GameState level: 1, players, player_bullets: Vec::new(), + bullet_explosions: Vec::new(), patrol_sub: PatrolSub::new(&game_defines), enemy_groups: EnemyGroups { groups: Vec::new(), @@ -1018,7 +1042,7 @@ impl GameSystem .animation_mapping .get(&("bullet".into(), "idle".into())) .expect("Failed to find bullet idle animation"); - self.sprite_builders[Sprites::Bullet2 as usize].animation_id = *asset_theme + self.sprite_builders[Sprites::Explosion as usize].animation_id = *asset_theme .animation_mapping .get(&("bullet".into(), "collision".into())) .expect("Failed to find bullet collision animation"); @@ -1109,6 +1133,7 @@ impl GameSystem Ok(()) } + // TODO: Return a list of collision pairs and handle collision responses outside of this function pub fn handle_collision(&mut self, game_state: &mut game::GameState, sprite_manager: &SpriteManager) { let mut player_collisions = HashSet::new(); @@ -1191,6 +1216,37 @@ impl GameSystem if bullet_bounding_box.intersects(&enemy_bounding_box) { + // TODO: Move these lookups that don't change out of the funcion + let theme = &self.asset_themes[game_state.game_state.current_theme]; + let animation_id = *theme + .animation_mapping + .get(&("bullet".to_string(), "collision".to_string())) + .expect("Failed to find bullet collision animation"); + + let explosion_builder = + SpriteAnimationBuilder::new(animation_id, PlaybackState::Playing) + .billboard_mode(BillboardMode::XYAxis) + .playback_type(PlaybackLoopingMode::Once); + + let animation_instance_id = sprite_manager + .create_animation_instance(&mut game_state.sprite_state, &explosion_builder); + + let sprite_size = sprite_manager.get_animation_size(animation_id); + let offset = if player.direction == Direction::Right + { + Vector2::new(sprite_size.x * 0.5, sprite_size.y * -0.5) + } + else + { + Vector2::new(sprite_size.x * -0.5, sprite_size.y * -0.5) + }; + + game_state.game_state.bullet_explosions.push(ExplosionState { + position: bullet.position + offset, + animation_instance_id, + active: true, + }); + let lunge_multiplier = if g.lunging { self.game_defines.enemy_group_defines.lunging_points_multiplier @@ -1315,6 +1371,17 @@ impl GameSystem sprite_manager.update_sprite_animations(&mut game_state.sprite_state, dt, &mut sprite_updates); game_state.sprite_state.update_animation_palette_sets(sprite_manager); + for instance_id in sprite_updates.completed_animations + { + sprite_manager.free_animation_instance(&mut game_state.sprite_state, instance_id); + game_state.game_state.bullet_explosions.iter_mut().for_each(|b| { + if b.animation_instance_id == instance_id + { + b.active = false + } + }); + } + input_states.player_input.iter().nth(0).map(|action_states| { action_states.input.new_theme.map(|theme| { game_state.game_state.current_theme = theme as usize; @@ -1555,6 +1622,8 @@ impl GameSystem player_bullets.retain(|b| b.active); } + game_state.game_state.bullet_explosions.retain(|b| b.active); + for enemy_group in &game_state.game_state.enemy_groups.groups { for animation_instance_id in &enemy_group.animation_instance_ids @@ -1670,10 +1739,17 @@ impl GameSystem current_state: &SpriteStateManager, previous_state: &SpriteStateManager| -> SpriteInstance { - let exists = previous_state - .animation_instances - .get(animation_instance_id.0 as usize) - .is_some(); + let previous_animation_instance = previous_state.animation_instances.get(animation_instance_id.0 as usize); + let current_animation_instance = current_state.animation_instances.get(animation_instance_id.0 as usize); + let exists = if let (Some(prev), Some(cur)) = (previous_animation_instance, current_animation_instance) + { + prev.sprite_instance_id == cur.sprite_instance_id && prev.animation_id == cur.animation_id + } + else + { + false + }; + let state = if exists && frame_percentage < 0.5 { previous_state } else { current_state }; let mut sprite = get_sprite_instance(animation_instance_id, sprite_manager, state); @@ -1770,6 +1846,23 @@ impl GameSystem sprite_instances.push(sprite_instance); } + for explosion in &game_state.bullet_explosions + { + let sprite_instance_id = + sprite_manager.get_sprite_instance_id(&sprite_state_manager, explosion.animation_instance_id); + let mut sprite_instance = sprite_state_manager.get_sprite_instance(sprite_instance_id).clone(); + let dimensions = sprite_manager.get_sprite_size(sprite_instance.sprite_id); + let origin = get_sprite_origin( + explosion.animation_instance_id, + sprite_manager, + sprite_state_manager, + &dimensions, + ); + let position = explosion.position - origin; + sprite_instance.position_mut(position.x, position.y); + sprite_instances.push(sprite_instance.clone()); + } + for (player, player_prev) in game_state .players .iter() diff --git a/game/src/sprites/sprite_manager.rs b/game/src/sprites/sprite_manager.rs index 23891f818604cb0ad1985e7a22ce4bb87a7d9d3b..2b8dd8d25437e7ece32a3f0997ec736f1f68b237 100644 --- a/game/src/sprites/sprite_manager.rs +++ b/game/src/sprites/sprite_manager.rs @@ -378,6 +378,12 @@ impl SpriteManager sprite_state_manager.animation_instances[animation_instance_id].sprite_instance_id } + pub fn get_sprite_size(&self, sprite_id: SpriteId) -> Vector2<f32> + { + let sprite = &self.sprites[sprite_id.0 as usize]; + Vector2::new(sprite.width, sprite.height) + } + pub fn get_animation_instance_origin( &self, sprite_state_manager: &SpriteStateManager, @@ -419,6 +425,13 @@ impl SpriteManager offset } + pub fn get_animation_size(&self, animation_id: AnimationId) -> Vector2<f32> + { + let animation = &self.animations[animation_id.0 as usize]; + let frame = &animation.frames[0]; + Vector2::new(frame.width, frame.height) + } + pub fn load_sprite_parses( &mut self, vulkan: &VulkanAppResources,