bevy-expedition-demo/src/player.rs
2ndbeam 337986d2b9 ui: Multiple inventories support
- Added scrollable container for inventories
- Fixed slots being visibly hovered when dragging items
2026-03-13 16:17:44 +03:00

97 lines
3.2 KiB
Rust

use bevy::prelude::*;
use leafwing_input_manager::prelude::*;
use crate::{GameState, InputAction as Action, inventory::{ActiveInventory, Inventory, item::Item}};
#[derive(Component, Reflect)]
pub struct Player {
// px/s
speed: f32,
}
fn player_bundle(asset_server: &Res<AssetServer>) -> impl Bundle {
let image = asset_server.load("sprites/player/player.png");
(
Player {
speed: 51.2,
},
Sprite::from_image(image),
Transform::from_xyz(0f32, 0f32, 1f32),
Action::default_input_map(),
Name::new("Player"),
children![
(Inventory::new(UVec2::new(6, 2)), ActiveInventory),
(Inventory::new(UVec2::new(5, 3)), ActiveInventory),
(Inventory::new(UVec2::new(4, 4)), ActiveInventory),
],
)
}
pub fn setup_player(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(player_bundle(&asset_server));
}
pub fn try_insert_item(
mut commands: Commands,
item_query: Query<&Item>,
inventory_query: Query<(Entity, &Inventory, Option<&Children>)>,
) {
let mut item = Item::new(UVec2::new(1, 1));
let name = Name::new(format!("Item {}x{}", item.size.x, item.size.y));
for (entity, inventory, children) in inventory_query.iter().sort::<Entity>() {
let children = match children {
Some(children) => &children[..],
None => &[],
};
match inventory.find_free_space(item_query, children, item.size) {
Some((position, should_rotate)) => {
if should_rotate {
item.rotate();
}
item.position = Some(position);
info!("Spawning item {item:?}");
commands.entity(entity).with_child((item, name));
break;
},
None => (),
}
}
}
pub fn handle_input(
mut commands: Commands,
time: Res<Time>,
state: Res<State<GameState>>,
mut next_state: ResMut<NextState<GameState>>,
mut player: Query<(&Player, &mut ActionState<Action>, &mut Transform, &mut Sprite)>,
) {
let player = player.single_mut().expect("Player should be single");
match state.get() {
GameState::Running => {
let (Player {speed}, mut action_state, mut transform, mut sprite) = player;
if action_state.just_released(&Action::ToggleInventory) {
next_state.set(GameState::Inventory);
action_state.reset(&Action::ToggleInventory);
}
let direction = action_state.clamped_value(&Action::Move);
transform.translation.x += direction * speed * time.delta_secs();
if direction != 0f32 {
sprite.flip_x = direction < 0f32;
}
if action_state.just_pressed(&Action::Interact) {
commands.run_system_cached(try_insert_item);
}
},
GameState::Inventory => {
let (_, mut action_state, _, _) = player;
if action_state.just_released(&Action::ToggleInventory) {
next_state.set(GameState::Running);
action_state.reset(&Action::ToggleInventory);
}
},
}
}