Skip to content

Commit

Permalink
refactor(plugins): consolidate plugin functionality and improve struc…
Browse files Browse the repository at this point in the history
…ture

- Merge individual plugin files into a single plugins.rs file
- Refactor plugin implementations to use a consistent structure
  • Loading branch information
ShenMian committed Feb 12, 2025
1 parent 44341ee commit cd375a2
Show file tree
Hide file tree
Showing 12 changed files with 573 additions and 612 deletions.
31 changes: 11 additions & 20 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,10 @@ mod utils;
use events::*;
use input_map::*;
use leafwing_input_manager::{action_diff::ActionDiffEvent, prelude::*};
use plugins::{
auto_move::AutoMovePlugin, auto_solve::AutoSolvePlugin, camera::CameraPlugin,
config::ConfigPlugin, performance_matrix, ui::UiPlugin, version_information,
};
use plugins::*;
use resources::*;
use state::*;
use systems::{audio::*, input::*, level::*, render::*, ui::*};
use systems::{input::*, level::*, render::*};
use utils::*;

use bevy::prelude::*;
Expand All @@ -43,23 +40,14 @@ fn main() {
..default()
}),
AudioPlugin,
))
.add_plugins((
performance_matrix::plugin,
version_information::plugin,
InputManagerPlugin::<Action>::default(),
))
.init_state::<AppState>()
.enable_state_scoped_entities::<AppState>();

app.add_systems(PreStartup, (setup_camera, setup_database));
app.add_systems(
Startup,
(set_windows_icon, setup_button, setup_hud, setup_level),
);
app.add_systems(Update, handle_audio_event);
app.add_systems(Startup, (set_windows_icon, setup_level));
app.add_systems(FixedUpdate, animate_player);

app.add_systems(
Update,
(
Expand All @@ -80,11 +68,14 @@ fn main() {
);

app.add_plugins((
ConfigPlugin,
UiPlugin,
CameraPlugin,
AutoSolvePlugin,
AutoMovePlugin,
performance_matrix::plugin,
version_information::plugin,
ui::plugin,
audio::plugin,
config::plugin,
camera::plugin,
auto_move::plugin,
auto_solve::plugin,
));

app.init_resource::<ActionState<Action>>()
Expand Down
4 changes: 4 additions & 0 deletions src/systems/audio.rs → src/plugins/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ use bevy_kira_audio::prelude::*;

use crate::{events::*, resources::*};

pub fn plugin(app: &mut App) {
app.add_systems(Update, handle_audio_event);
}

/// Play audio based on events.
pub fn handle_audio_event(
audio: Res<Audio>,
Expand Down
127 changes: 116 additions & 11 deletions src/plugins/auto_move.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,123 @@
#![allow(clippy::type_complexity)]

use bevy::{color::palettes::css::*, prelude::*};
use itertools::Itertools;
use soukoban::{deadlock::calculate_static_deadlocks, path_finding::reachable_area, Tiles};

use crate::{
resources::AutoMoveState,
state::*,
systems::{auto_move::*, input::*},
box_pushable_paths, components::*, resources::AutoMoveState, systems::input::*, AppState,
};

use bevy::prelude::*;
pub fn plugin(app: &mut App) {
app.add_systems(OnEnter(AppState::AutoMove), spawn_auto_move_marks)
.add_systems(Update, mouse_input.run_if(in_state(AppState::AutoMove)))
.add_systems(OnExit(AppState::AutoMove), cleanup_sprite_color);
app.insert_resource(AutoMoveState::default());
}

/// Spawns auto-move reachable marks for boxes or the player.
pub fn spawn_auto_move_marks(
mut commands: Commands,
mut auto_move_state: ResMut<AutoMoveState>,
board: Query<&Board>,
mut boxes: Query<(&GridPosition, &mut Sprite), (With<Box>, Without<Player>)>,
mut player: Query<&mut Sprite, With<Player>>,
mut next_state: ResMut<NextState<AppState>>,
) {
let Board { board, tile_size } = board.single();
let map = &board.map;

const MARK_COLOR: Srgba = LIME;
const HIGHLIGHT_COLOR: Srgba = TURQUOISE;

match &mut *auto_move_state {
AutoMoveState::Box {
position: box_position,
paths,
} => {
*paths = box_pushable_paths(map, box_position);

// remove static deadlock positions
let static_deadlocks = calculate_static_deadlocks(map);
paths.retain(|state, _| !static_deadlocks.contains(&state.box_position));

pub struct AutoMovePlugin;
// spawn box pushable marks
for box_position in paths.keys().map(|state| state.box_position).unique() {
commands.spawn((
Name::new("Pushable mark"),
Sprite::from_color(
MARK_COLOR.with_alpha(0.8),
Vec2::new(tile_size.x as f32 / 4.0, tile_size.y as f32 / 4.0),
),
Transform::from_xyz(
box_position.x as f32 * tile_size.x as f32,
(map.dimensions().y - box_position.y) as f32 * tile_size.y as f32,
10.0,
),
StateScoped(AppState::AutoMove),
));
}

if paths.is_empty() {
next_state.set(AppState::Main);
return;
}

// highlight selected box
boxes
.iter_mut()
.filter(|(grid_position, ..)| ***grid_position == *box_position)
.for_each(|(_, mut sprite)| sprite.color = HIGHLIGHT_COLOR.into());
}
AutoMoveState::Player => {
let mut reachable_area = reachable_area(map.player_position(), |position| {
!map[position].intersects(Tiles::Wall) && !map.box_positions().contains(&position)
});
reachable_area.remove(&map.player_position());

// spawn player movable marks
for box_position in reachable_area {
commands.spawn((
Name::new("Movable mark"),
Sprite::from_color(
MARK_COLOR.with_alpha(0.8),
Vec2::new(tile_size.x as f32 / 4.0, tile_size.y as f32 / 4.0),
),
Transform::from_xyz(
box_position.x as f32 * tile_size.x as f32,
(map.dimensions().y - box_position.y) as f32 * tile_size.y as f32,
10.0,
),
StateScoped(AppState::AutoMove),
));
}

// highlight selected player
let mut sprite = player.single_mut();
sprite.color = HIGHLIGHT_COLOR.into();
}
}
}

impl Plugin for AutoMovePlugin {
fn build(&self, app: &mut App) {
app.add_systems(OnEnter(AppState::AutoMove), spawn_auto_move_marks)
.add_systems(Update, mouse_input.run_if(in_state(AppState::AutoMove)))
.add_systems(OnExit(AppState::AutoMove), cleanup_sprite_color);
app.insert_resource(AutoMoveState::default());
/// Cleans up the visual representation of boxes or the player sprite.
pub fn cleanup_sprite_color(
mut boxes: Query<(&GridPosition, &mut Sprite), (With<Box>, Without<Player>)>,
mut player: Query<&mut Sprite, With<Player>>,
auto_move_state: Res<AutoMoveState>,
) {
match *auto_move_state {
AutoMoveState::Box {
position: box_position,
..
} => {
boxes
.iter_mut()
.filter(|(grid_position, _)| ***grid_position == box_position)
.for_each(|(_, mut sprite)| sprite.color = Color::WHITE);
}
AutoMoveState::Player => {
let mut sprite = player.single_mut();
sprite.color = Color::WHITE;
}
}
}
Loading

0 comments on commit cd375a2

Please sign in to comment.