Skip to content

Commit

Permalink
refactor footsteps
Browse files Browse the repository at this point in the history
  • Loading branch information
aratama committed Nov 17, 2024
1 parent bdfd220 commit fac015b
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 56 deletions.
11 changes: 4 additions & 7 deletions src/controller/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use crate::{
states::GameState,
};
use bevy::{core::FrameCount, prelude::*, utils::HashMap};
use bevy_kira_audio::Audio;
use bevy_rapier2d::{plugin::PhysicsSet, prelude::Velocity};
use bevy_simple_websocket::{ClientMessage, ReadyState, ServerMessage, WebSocketState};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -191,7 +190,6 @@ fn receive_events(
frame_count: Res<FrameCount>,
life_bar_res: Res<LifeBarResource>,
mut writer: EventWriter<GameCommand>,
audio: Res<Audio>,
) {
// キャラクターを生成されたときに実際に反映させるのは次のフレームからですが、
// 1フレームに複数のメッセージが届くことがあるため、
Expand Down Expand Up @@ -249,16 +247,15 @@ fn receive_events(
life,
max_life,
&life_bar_res,
true,
3.0,
false,
[None, None, None, None],
RemotePlayer {
name,
golds,
last_update: *frame_count,
},
true,
3.0,
&audio,
false,
[None, None, None, None],
);
info!("Remote player spawned: {}", uuid);
}
Expand Down
2 changes: 2 additions & 0 deletions src/enemy/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::constant::*;
use crate::controller::enemy::Enemy;
use crate::entity::actor::{Actor, ActorFireState};
use crate::entity::breakable::{Breakable, BreakableSprite};
use crate::entity::witch::ActorState;
use crate::entity::EntityDepth;
use crate::hud::life_bar::{spawn_life_bar, LifeBarResource};
use crate::spell::SpellType;
Expand Down Expand Up @@ -58,6 +59,7 @@ pub fn spawn_basic_enemy<T: Component>(
None,
],
},
ActorState::default(),
EntityDepth,
Breakable {
life: 0,
Expand Down
11 changes: 11 additions & 0 deletions src/entity/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ pub struct CastEffects {
pub homing: f32,
}

#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)]
pub enum AnimationState {
#[default]
Idle,
Walk,
}

/// ライフを持ち、弾丸のダメージの対象となるエンティティを表します
#[derive(Component)]
pub struct Actor {
Expand All @@ -35,6 +42,7 @@ pub struct Actor {
pub max_mana: i32,

pub life: i32,

pub max_life: i32,

/// プレイヤーの位置からの相対的なポインターの位置
Expand All @@ -61,6 +69,9 @@ pub struct Actor {

pub current_wand: usize,

/// アクターが所持している杖のリスト
/// モンスターの呪文詠唱の仕組みもプレイヤーキャラクターと同一であるため、
/// 内部的にはモンスターも杖を持っていることになっています
pub wands: [Option<Wand>; MAX_WANDS],
// pub queue: Vec,

Expand Down
50 changes: 19 additions & 31 deletions src/entity/witch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ use bevy_aseprite_ultra::prelude::*;
use bevy_kira_audio::prelude::*;
use bevy_rapier2d::prelude::*;
use std::f32::consts::PI;
use std::time::Duration;
use uuid::Uuid;

use super::actor::AnimationState;

pub const WITCH_COLLIDER_RADIUS: f32 = 5.0;

pub const PLAYER_MOVE_FORCE: f32 = 50000.0;
Expand All @@ -24,40 +25,30 @@ pub const PLAYER_MOVE_FORCE: f32 = 50000.0;
pub struct WitchWandSprite;

#[derive(Default, Component, Reflect)]
pub struct Footsteps(Handle<AudioInstance>);
pub struct Footsteps(pub Handle<AudioInstance>);

#[derive(Component)]
pub struct Witch;

#[derive(Component, Default)]
pub struct ActorState(pub AnimationState);

pub fn spawn_witch<T: Component>(
commands: &mut Commands,
assets: &Res<GameAssets>,
position: Vec2,
angle: f32,
uuid: Uuid,
name: Option<String>,
name_plate: Option<String>,
life: i32,
max_life: i32,
res: &Res<LifeBarResource>,
controller: T,
life_bar: bool,
intensity: f32,

// 足音のオーディオインスタンス
footstep_audio: &Res<Audio>,

interaction: bool,

wands: [Option<Wand>; 4],
) {
let audio_instance = footstep_audio
.play(assets.taiikukan.clone())
.looped()
.with_volume(0.0)
// .with_volume(Volume::Amplitude((config.se_volume * volume) as f64))
// .with_panning(panning as f64)
.handle();

controller: T,
) -> Entity {
let mut entity = commands.spawn((
Name::new("witch"),
StateScoped(GameState::InGame),
Expand All @@ -79,6 +70,7 @@ pub fn spawn_witch<T: Component>(
effects: default(),
wands,
},
ActorState::default(),
Witch,
controller,
EntityDepth,
Expand Down Expand Up @@ -112,7 +104,6 @@ pub fn spawn_witch<T: Component>(
| MAGIC_CIRCLE_GROUP,
),
),
Footsteps(audio_instance),
));

entity.with_children(move |mut spawn_children| {
Expand Down Expand Up @@ -146,7 +137,7 @@ pub fn spawn_witch<T: Component>(

// リモートプレイヤーの名前
// 自分のプレイヤーキャラクターは名前を表示しません
if let Some(name) = name {
if let Some(name) = name_plate {
let mut sections = Vec::new();
sections.push(TextSection {
value: name,
Expand All @@ -170,32 +161,29 @@ pub fn spawn_witch<T: Component>(
spawn_life_bar(spawn_children, &res);
}
});

return entity.id();
}

fn update_animation(
mut witch_query: Query<(&Actor, &mut Footsteps)>,
mut witch_query: Query<(&Actor, &mut ActorState)>,
mut witch_animation_query: Query<(&Parent, &mut Animation)>,
mut audio_instances: ResMut<Assets<AudioInstance>>,
) {
for (parent, mut animation) in witch_animation_query.iter_mut() {
if let Ok((actor, footsteps)) = witch_query.get_mut(**parent) {
if let Ok((actor, mut state)) = witch_query.get_mut(**parent) {
if actor.move_direction.length() < 0.01 {
*state = ActorState(AnimationState::Idle);

if animation.tag != Some("idle".to_string()) {
// アニメーションを切り替えても現在のフレーム位置が巻き戻らない?
// https://github.com/Lommix/bevy_aseprite_ultra/issues/14
animation.play("idle", AnimationRepeat::Loop);

if let Some(instance) = audio_instances.get_mut(&footsteps.0) {
instance.set_volume(0.0, AudioTween::linear(Duration::from_millis(200)));
}
}
} else {
*state = ActorState(AnimationState::Walk);

if animation.tag != Some("run".to_string()) {
animation.play("run", AnimationRepeat::Loop);

if let Some(instance) = audio_instances.get_mut(&footsteps.0) {
instance.set_volume(0.6, AudioTween::linear(Duration::from_millis(100)));
}
}
}
}
Expand Down
35 changes: 35 additions & 0 deletions src/footsteps.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::entity::actor::AnimationState;
use crate::entity::witch::ActorState;
use crate::states::GameState;
use bevy::prelude::*;
use bevy_kira_audio::prelude::*;
use std::time::Duration;

#[derive(Default, Component, Reflect)]
pub struct WitchWandSprite;

#[derive(Default, Component, Reflect)]
pub struct Footsteps(Handle<AudioInstance>);

fn update_volume(
mut witch_query: Query<(&ActorState, &mut Footsteps), Changed<ActorState>>,
mut audio_instances: ResMut<Assets<AudioInstance>>,
) {
for (state, footsteps) in witch_query.iter_mut() {
if let Some(instance) = audio_instances.get_mut(&footsteps.0) {
let volume = match state.0 {
AnimationState::Idle => 0.0,
AnimationState::Walk => 0.6,
};
instance.set_volume(volume, AudioTween::linear(Duration::from_millis(200)));
}
}
}

pub struct FootStepsPlugin;

impl Plugin for FootStepsPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, (update_volume).run_if(in_state(GameState::InGame)));
}
}
2 changes: 2 additions & 0 deletions src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::entity::magic_circle::MagicCirclePlugin;
use crate::entity::stone_lantern::StoneLanternPlugin;
use crate::entity::witch::WitchPlugin;
use crate::entity::EntityPlugin;
use crate::footsteps::FootStepsPlugin;
use crate::hud::life_bar::LifeBarPlugin;
use crate::hud::overlay::*;
use crate::hud::pointer::PointerPlugin;
Expand Down Expand Up @@ -172,6 +173,7 @@ pub fn run_game() {
.add_plugins(EntityPickerPlugin)
.add_plugins(EnemyPlugin)
.add_plugins(EquipmentListPlugin)
.add_plugins(FootStepsPlugin)
.add_plugins(GameAudioPlugin)
.add_plugins(GameCommandPlugin)
.add_plugins(GameConfigPlugin)
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod debug;
mod enemy;
mod entity;
mod equipment;
mod footsteps;
mod game;
mod hud;
mod input;
Expand Down
42 changes: 25 additions & 17 deletions src/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::entity::magic_circle::spawn_magic_circle;
use crate::entity::magic_circle::MagicCircleDestination;
use crate::entity::stone_lantern::spawn_stone_lantern;
use crate::entity::witch::spawn_witch;
use crate::entity::witch::Footsteps;
use crate::entity::GameEntity;
use crate::hud::life_bar::LifeBarResource;
use crate::inventory_item::InventoryItem;
Expand All @@ -36,9 +37,10 @@ use bevy::core::FrameCount;
use bevy::prelude::*;
use bevy_aseprite_ultra::prelude::*;
use bevy_kira_audio::Audio;
use bevy_kira_audio::AudioControl;
use map::image_to_spawn_tiles;
use uuid::Uuid;
use wall::respawn_wall_collisions;
use wall::spawn_wall_collisions;
use wall::WallCollider;

#[derive(Resource, Debug, Clone, Default)]
Expand All @@ -55,6 +57,7 @@ pub enum GameLevel {
MultiPlayArena,
}

/// レベルとプレイヤーキャラクターを生成します
fn setup_world(
mut commands: Commands,
level_aseprites: Res<Assets<Aseprite>>,
Expand Down Expand Up @@ -97,7 +100,8 @@ fn setup_world(
camera.translation.y = player_y;
}

spawn_witch(
// プレイヤーキャラクターの魔法使いを生成
let witch_entity = spawn_witch(
&mut commands,
&assets,
Vec2::new(player_x, player_y),
Expand All @@ -107,6 +111,10 @@ fn setup_world(
player.life,
player.max_life,
&life_bar_res,
false,
3.0,
true,
player.wands,
Player {
name: player.name,
golds: player.golds,
Expand All @@ -120,12 +128,19 @@ fn setup_world(
inventory: player.inventory,
equipments: player.equipments,
},
false,
3.0,
&audio,
true,
player.wands,
);

// 足音が必要なのはプレイヤーキャラクターだけなので、足音コンポーネントを追加
let audio_instance = audio
.play(assets.taiikukan.clone())
.looped()
.with_volume(0.0)
// .with_volume(Volume::Amplitude((config.se_volume * volume) as f64))
// .with_panning(panning as f64)
.handle();
commands
.entity(witch_entity)
.insert(Footsteps(audio_instance));
}

fn select_bgm(next: Res<NextLevel>, mut writer: EventWriter<GameCommand>) {
Expand Down Expand Up @@ -186,11 +201,9 @@ fn spawn_level(

let mut empties = image_to_spawn_tiles(&chunk);

// despown if exisiting
spawn_world_tilemap(&mut commands, &assets, &chunk);

// spawn

respawn_world(&mut commands, &assets, &chunk);
spawn_wall_collisions(&mut commands, &chunk);

spawn_entities(&mut commands, &assets, &chunk);

Expand Down Expand Up @@ -225,12 +238,7 @@ fn spawn_level(
return chunk;
}

fn respawn_world(mut commands: &mut Commands, assets: &Res<GameAssets>, chunk: &LevelTileMap) {
respawn_world_tilemap(&mut commands, &assets, &chunk);
respawn_wall_collisions(&mut commands, &chunk);
}

fn respawn_world_tilemap(commands: &mut Commands, assets: &Res<GameAssets>, chunk: &LevelTileMap) {
fn spawn_world_tilemap(commands: &mut Commands, assets: &Res<GameAssets>, chunk: &LevelTileMap) {
// 床と壁の生成
for y in chunk.min_y..chunk.max_y as i32 {
for x in chunk.min_x..chunk.max_x as i32 {
Expand Down
2 changes: 1 addition & 1 deletion src/world/wall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub fn get_wall_collisions(chunk: &LevelTileMap) -> Vec<Rect> {
#[derive(Debug, Clone, Eq, PartialEq, Hash, Component)]
pub struct WallCollider;

pub fn respawn_wall_collisions(commands: &mut Commands, chunk: &LevelTileMap) {
pub fn spawn_wall_collisions(commands: &mut Commands, chunk: &LevelTileMap) {
// 衝突形状の生成
for rect in get_wall_collisions(&chunk) {
let w = TILE_HALF * (rect.width() + 1.0);
Expand Down

0 comments on commit fac015b

Please sign in to comment.