sprite working
This commit is contained in:
1225
Cargo.lock
generated
1225
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -6,4 +6,5 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version="0.15.3", features = ["jpeg"]}
|
bevy = { version="0.15.3", features = ["jpeg"]}
|
||||||
bevy_asset_loader = { version ="0.22.0", features = ["standard_dynamic_assets"] }
|
bevy_asset_loader = { version ="0.22.0", features = ["standard_dynamic_assets"] }
|
||||||
|
bevy_egui = "0.33.0"
|
||||||
bevy_rapier3d = "0.29.0"
|
bevy_rapier3d = "0.29.0"
|
||||||
|
|||||||
BIN
assets/meshes/library/hammer.glb
Normal file
BIN
assets/meshes/library/hammer.glb
Normal file
Binary file not shown.
BIN
assets/meshes/library/space2.glb
Normal file
BIN
assets/meshes/library/space2.glb
Normal file
Binary file not shown.
BIN
assets/meshes/library/space_corner_inside.glb
Normal file
BIN
assets/meshes/library/space_corner_inside.glb
Normal file
Binary file not shown.
BIN
assets/meshes/library/space_corner_outside.glb
Normal file
BIN
assets/meshes/library/space_corner_outside.glb
Normal file
Binary file not shown.
BIN
assets/meshes/library/space_door.glb
Normal file
BIN
assets/meshes/library/space_door.glb
Normal file
Binary file not shown.
BIN
assets/meshes/library/space_round_door.glb
Normal file
BIN
assets/meshes/library/space_round_door.glb
Normal file
Binary file not shown.
BIN
assets/meshes/library/space_round_hole.glb
Normal file
BIN
assets/meshes/library/space_round_hole.glb
Normal file
Binary file not shown.
BIN
assets/meshes/library/space_wall.glb
Normal file
BIN
assets/meshes/library/space_wall.glb
Normal file
Binary file not shown.
BIN
assets/space1.blend
Normal file
BIN
assets/space1.blend
Normal file
Binary file not shown.
BIN
assets/space2.blend
Normal file
BIN
assets/space2.blend
Normal file
Binary file not shown.
@@ -31,8 +31,6 @@ pub(crate) struct AudioAssets {}
|
|||||||
|
|
||||||
#[derive(AssetCollection, Resource, Clone)]
|
#[derive(AssetCollection, Resource, Clone)]
|
||||||
pub(crate) struct GltfAssets {
|
pub(crate) struct GltfAssets {
|
||||||
#[asset(key = "house")]
|
|
||||||
pub(crate) house: Handle<Gltf>,
|
|
||||||
#[asset(key = "library", collection(typed, mapped))]
|
#[asset(key = "library", collection(typed, mapped))]
|
||||||
pub(crate) library: HashMap<String, Handle<Gltf>>,
|
pub(crate) library: HashMap<String, Handle<Gltf>>,
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/interaction/dialog.rs
Normal file
1
src/interaction/dialog.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
8
src/interaction/mod.rs
Normal file
8
src/interaction/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
mod objects;
|
||||||
|
mod ui;
|
||||||
|
|
||||||
|
pub fn plugin(app: &mut App) {
|
||||||
|
app.add_plugins((ui::plugin, objects::plugin));
|
||||||
|
}
|
||||||
40
src/interaction/objects.rs
Normal file
40
src/interaction/objects.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
use bevy::{gltf::GltfMesh, math::Vec3A, prelude::*, render::mesh::MeshAabb};
|
||||||
|
use bevy_rapier3d::prelude::{Collider, RigidBody};
|
||||||
|
|
||||||
|
use crate::{GameState, asset_loading::GltfAssets};
|
||||||
|
|
||||||
|
pub fn plugin(app: &mut App) {
|
||||||
|
app.add_systems(OnEnter(GameState::Playing), spawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Interact;
|
||||||
|
|
||||||
|
fn spawn(mut commands: Commands, models: Res<Assets<Gltf>>, gltf_assets: Res<GltfAssets>) {
|
||||||
|
let hammer = gltf_assets
|
||||||
|
.library
|
||||||
|
.get("meshes/library/hammer.glb")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let hammer = models.get(hammer).unwrap();
|
||||||
|
let asset = hammer.default_scene.as_ref().unwrap();
|
||||||
|
// hammer
|
||||||
|
commands
|
||||||
|
.spawn((
|
||||||
|
Transform::from_xyz(0.0, 100.0, 0.0).with_scale(Vec3::splat(0.1)),
|
||||||
|
Interact,
|
||||||
|
RigidBody::Dynamic,
|
||||||
|
SceneRoot(asset.clone()),
|
||||||
|
))
|
||||||
|
.with_children(|parent| {
|
||||||
|
parent
|
||||||
|
.spawn(Collider::cuboid(0.8, 10f32, 0.8))
|
||||||
|
.insert(Transform::from_xyz(0.0, -5.0, 0.0));
|
||||||
|
parent
|
||||||
|
.spawn(Collider::cuboid(1.0, 1.0, 4.5))
|
||||||
|
// Position the collider relative to the rigid-body.
|
||||||
|
.insert(Transform::from_xyz(0.0, 4.2, 1.0));
|
||||||
|
});
|
||||||
|
|
||||||
|
//tools
|
||||||
|
}
|
||||||
78
src/interaction/ui.rs
Normal file
78
src/interaction/ui.rs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
use crate::GameState;
|
||||||
|
use crate::player::{Player, PlayerAction};
|
||||||
|
use crate::util::{single, single_mut};
|
||||||
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
|
use bevy_egui::{EguiContexts, EguiPlugin, egui};
|
||||||
|
use std::f32::consts::TAU;
|
||||||
|
|
||||||
|
use super::objects::Interact;
|
||||||
|
|
||||||
|
pub(super) fn plugin(app: &mut App) {
|
||||||
|
app.add_plugins(EguiPlugin)
|
||||||
|
.init_resource::<InteractionOpportunity>()
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(update_interaction_opportunities, display_interaction_prompt)
|
||||||
|
.chain()
|
||||||
|
.run_if(in_state(GameState::Playing)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, Resource, Default)]
|
||||||
|
struct InteractionOpportunity(Option<Entity>);
|
||||||
|
|
||||||
|
fn update_interaction_opportunities(
|
||||||
|
player_query: Query<&GlobalTransform, With<Player>>,
|
||||||
|
parents: Query<&Parent>,
|
||||||
|
target_query: Query<
|
||||||
|
(Entity, &GlobalTransform),
|
||||||
|
(Without<Player>, Without<Camera>, With<Interact>),
|
||||||
|
>,
|
||||||
|
mut interaction_opportunity: ResMut<InteractionOpportunity>,
|
||||||
|
) {
|
||||||
|
interaction_opportunity.0 = None;
|
||||||
|
let player_transform = single!(player_query);
|
||||||
|
|
||||||
|
let (target_entity, target_transform) = single!(target_query);
|
||||||
|
|
||||||
|
let player_translation = player_transform.translation();
|
||||||
|
let target_translation = target_transform.translation();
|
||||||
|
if player_translation.distance(target_translation) <= 2.0 {
|
||||||
|
interaction_opportunity.0.replace(target_entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_facing_target(
|
||||||
|
player: Vec3,
|
||||||
|
target: Vec3,
|
||||||
|
camera_transform: Transform,
|
||||||
|
camera: &Camera,
|
||||||
|
) -> bool {
|
||||||
|
let camera_to_player = camera_transform.forward();
|
||||||
|
let player_to_target = target - player;
|
||||||
|
let angle = camera_to_player.angle_between(player_to_target);
|
||||||
|
angle < TAU / 8.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display_interaction_prompt(
|
||||||
|
interaction_opportunity: Res<InteractionOpportunity>,
|
||||||
|
mut egui_contexts: EguiContexts,
|
||||||
|
action: Query<&PlayerAction, With<Player>>,
|
||||||
|
primary_windows: Query<&Window, With<PrimaryWindow>>,
|
||||||
|
) {
|
||||||
|
let Some(opportunity) = interaction_opportunity.0 else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let window = single!(primary_windows);
|
||||||
|
|
||||||
|
egui::Window::new("Interaction")
|
||||||
|
.collapsible(false)
|
||||||
|
.title_bar(false)
|
||||||
|
.auto_sized()
|
||||||
|
.fixed_pos(egui::Pos2::new(window.width() / 2., window.height() / 2.))
|
||||||
|
.show(egui_contexts.ctx_mut(), |ui| {
|
||||||
|
ui.label("E: Pick Up");
|
||||||
|
});
|
||||||
|
|
||||||
|
let action = single!(action);
|
||||||
|
}
|
||||||
@@ -12,10 +12,14 @@ fn spawn_level(
|
|||||||
gltf_assets: Res<GltfAssets>
|
gltf_assets: Res<GltfAssets>
|
||||||
) {
|
) {
|
||||||
println!("LIBRARY: {:?}", gltf_assets.library);
|
println!("LIBRARY: {:?}", gltf_assets.library);
|
||||||
let jumbo = gltf_assets.library.get("meshes/library/wall.glb").unwrap();
|
let mut x_offset = 0.0;
|
||||||
let gltf = models.get(jumbo).unwrap();
|
for mesh_name in ["corner_inside", "corner_outside", "wall", "door", "round_door", "round_hole"] {
|
||||||
|
let path = format!("meshes/library/space_{}.glb", mesh_name);
|
||||||
|
let handle = gltf_assets.library.get(&path).expect(&format!("Couldn't find {} in library", mesh_name));
|
||||||
|
let gltf = models.get(handle).expect(&format!("No model for {}", mesh_name));
|
||||||
|
|
||||||
// commands.spawn(SceneRoot(gltf.scenes[0].clone()));
|
let asset = gltf.default_scene.as_ref().expect(&format!("No scene in {}", mesh_name));
|
||||||
let asset = gltf.default_scene.as_ref().unwrap();
|
commands.spawn((SceneRoot(asset.clone()), TransformBundle::from_transform(Transform::from_xyz(x_offset, 0.0, 0.0))));
|
||||||
commands.spawn(SceneRoot(asset.clone()));
|
x_offset += 2.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/main.rs
14
src/main.rs
@@ -1,20 +1,23 @@
|
|||||||
use asset_loading::ImageAssets;
|
use asset_loading::ImageAssets;
|
||||||
use bevy::prelude::*;
|
use bevy::{prelude::*};
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
mod asset_loading;
|
mod asset_loading;
|
||||||
mod bevy_plugin;
|
mod bevy_plugin;
|
||||||
|
mod interaction;
|
||||||
mod level_instantiation;
|
mod level_instantiation;
|
||||||
mod main_menu;
|
mod main_menu;
|
||||||
mod player;
|
mod player;
|
||||||
|
mod util;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
bevy_plugin::plugin,
|
bevy_plugin::plugin,
|
||||||
asset_loading::plugin,
|
asset_loading::plugin,
|
||||||
level_instantiation::map_plugin,
|
|
||||||
main_menu::plugin,
|
main_menu::plugin,
|
||||||
|
level_instantiation::map_plugin,
|
||||||
|
interaction::plugin,
|
||||||
RapierPhysicsPlugin::<NoUserData>::default(),
|
RapierPhysicsPlugin::<NoUserData>::default(),
|
||||||
RapierDebugRenderPlugin::default(),
|
RapierDebugRenderPlugin::default(),
|
||||||
player::plugin,
|
player::plugin,
|
||||||
@@ -47,16 +50,13 @@ fn setup(
|
|||||||
MeshMaterial3d(materials.add(image.king.clone())),
|
MeshMaterial3d(materials.add(image.king.clone())),
|
||||||
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
));
|
));
|
||||||
commands.spawn((
|
commands.spawn((RigidBody::Fixed, Collider::cylinder(0.1, 4.0)));
|
||||||
RigidBody::Fixed,
|
|
||||||
Collider::cylinder(0.1, 4.0)
|
|
||||||
));
|
|
||||||
// cube
|
// cube
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
Transform::from_xyz(3.0, 0.5, 0.0),
|
Transform::from_xyz(3.0, 0.5, 0.0),
|
||||||
RigidBody::Fixed,
|
RigidBody::Fixed,
|
||||||
Collider::cuboid(0.5, 0.5, 0.5),
|
Collider::cuboid(0.5, 0.5, 0.5),
|
||||||
));
|
));
|
||||||
// light
|
// light
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
input::mouse::AccumulatedMouseMotion, prelude::*,
|
input::mouse::AccumulatedMouseMotion, prelude::*, render::view::RenderLayers, transform, window::{self, PrimaryWindow}
|
||||||
render::view::RenderLayers, window::PrimaryWindow,
|
|
||||||
};
|
};
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
use crate::{asset_loading::{FlashlightAssets, ImageAssets}, GameState};
|
pub mod toolbar;
|
||||||
|
|
||||||
|
use crate::{asset_loading::{FlashlightAssets}, GameState};
|
||||||
|
|
||||||
#[derive(Debug, Component)]
|
#[derive(Debug, Component)]
|
||||||
pub struct Player;
|
pub struct Player;
|
||||||
@@ -26,7 +27,8 @@ pub struct PlayerInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn plugin(app: &mut App) {
|
pub fn plugin(app: &mut App) {
|
||||||
app.add_systems(OnEnter(GameState::Playing), (init_player, hide_cursor))
|
app.add_plugins(toolbar::plugin)
|
||||||
|
.add_systems(OnEnter(GameState::Playing), (init_player, hide_cursor))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(move_camera, handle_input).run_if(in_state(GameState::Playing)),
|
(move_camera, handle_input).run_if(in_state(GameState::Playing)),
|
||||||
@@ -43,14 +45,17 @@ const STATIC_LAYER: usize = 1;
|
|||||||
pub fn init_player(
|
pub fn init_player(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
flashlights: Res<FlashlightAssets>,
|
flashlights: Res<FlashlightAssets>,
|
||||||
images: Res<ImageAssets>,
|
window: Query<&Window>,
|
||||||
) {
|
) {
|
||||||
|
let window = window.single();
|
||||||
|
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
Player,
|
Player,
|
||||||
|
PlayerAction::default(),
|
||||||
CameraSensitivity::default(),
|
CameraSensitivity::default(),
|
||||||
PlayerInput::default(),
|
PlayerInput::default(),
|
||||||
|
toolbar::Item::none(),
|
||||||
// rapier
|
// rapier
|
||||||
RigidBody::Dynamic,
|
RigidBody::Dynamic,
|
||||||
Collider::capsule(Vec3::new(0.0, -0.5, 0.0), Vec3::new(0.0, 0.5, 0.0), 0.5),
|
Collider::capsule(Vec3::new(0.0, -0.5, 0.0), Vec3::new(0.0, 0.5, 0.0), 0.5),
|
||||||
@@ -60,7 +65,7 @@ pub fn init_player(
|
|||||||
linear_damping: 6.0,
|
linear_damping: 6.0,
|
||||||
angular_damping: 1.0,
|
angular_damping: 1.0,
|
||||||
},
|
},
|
||||||
|
GravityScale(3.0),
|
||||||
Transform::from_xyz(0.0, 1.0, 0.0),
|
Transform::from_xyz(0.0, 1.0, 0.0),
|
||||||
))
|
))
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
@@ -75,26 +80,30 @@ pub fn init_player(
|
|||||||
|
|
||||||
// camera voor pitslampke
|
// camera voor pitslampke
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
Camera3d::default(),
|
Camera2d::default(),
|
||||||
Camera {
|
Camera {
|
||||||
order: 1,
|
order: 1,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
RenderLayers::layer(STATIC_LAYER),
|
RenderLayers::layer(STATIC_LAYER),
|
||||||
));
|
));
|
||||||
|
|
||||||
// pitslampke
|
let window_size = Vec2::new(window.resolution.width(), window.resolution.height());
|
||||||
|
let sprite_size = Vec2::new(101.0, 101.0);
|
||||||
|
let scale = 2.2;
|
||||||
|
let world_size = sprite_size * scale;
|
||||||
|
let offset = 70.0;
|
||||||
|
|
||||||
|
let mut transform = Transform::from_translation(
|
||||||
|
Vec3::new(window_size.x / 2.0 - world_size.x / 2.0 - offset, -window_size.y / 2.0 + world_size.y / 2.0, 0.0)
|
||||||
|
);
|
||||||
|
transform.scale = Vec3::new(scale, scale, 1.0);
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
Transform::from_xyz(-3.0, -3.0, 0.0),
|
Sprite::from_image(flashlights.flash_hold_4.clone()),
|
||||||
Sprite {
|
transform,
|
||||||
image: images.king.clone(),
|
RenderLayers::layer(STATIC_LAYER),
|
||||||
..default()
|
|
||||||
},
|
|
||||||
RenderLayers::layer(STATIC_LAYER),
|
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.spawn(Sprite::from_image(images.king.clone()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hide_cursor(mut windows: Query<&mut Window, With<PrimaryWindow>>) {
|
fn hide_cursor(mut windows: Query<&mut Window, With<PrimaryWindow>>) {
|
||||||
@@ -125,11 +134,20 @@ pub fn move_camera(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Clone, Copy, Eq, PartialEq, Hash, Reflect, Default)]
|
||||||
|
pub(crate) enum PlayerAction {
|
||||||
|
#[default]
|
||||||
|
Move,
|
||||||
|
Sprint,
|
||||||
|
Jump,
|
||||||
|
Interact,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_input(
|
pub fn handle_input(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
mut query: Query<(&Transform, &mut PlayerInput), With<Player>>,
|
mut query: Query<(&Transform, &mut PlayerInput, &mut PlayerAction), With<Player>>,
|
||||||
) {
|
) {
|
||||||
for (transform, mut input) in query.iter_mut() {
|
for (transform, mut input, mut action) in query.iter_mut() {
|
||||||
let forward = transform.forward();
|
let forward = transform.forward();
|
||||||
let right = transform.right();
|
let right = transform.right();
|
||||||
let mut movement_direction = Vec3::ZERO;
|
let mut movement_direction = Vec3::ZERO;
|
||||||
@@ -152,31 +170,32 @@ pub fn handle_input(
|
|||||||
if keyboard_input.pressed(KeyCode::ShiftLeft) {
|
if keyboard_input.pressed(KeyCode::ShiftLeft) {
|
||||||
movement_direction -= Vec3::Y;
|
movement_direction -= Vec3::Y;
|
||||||
}
|
}
|
||||||
|
if keyboard_input.pressed(KeyCode::KeyE) {
|
||||||
|
*action = PlayerAction::Interact
|
||||||
|
}
|
||||||
|
|
||||||
input.movement_direction = movement_direction.normalize_or_zero();
|
input.movement_direction = movement_direction.normalize_or_zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_player_movement(
|
pub fn apply_player_movement(mut player_query: Query<(&PlayerInput, &mut Velocity), With<Player>>) {
|
||||||
mut player_query: Query<(&PlayerInput, &mut Velocity), With<Player>>,
|
|
||||||
) {
|
|
||||||
const SPEED: f32 = 3.0;
|
const SPEED: f32 = 3.0;
|
||||||
const JUMP_FORCE: f32 = 4.0;
|
const JUMP_FORCE: f32 = 4.0;
|
||||||
|
|
||||||
for (input, mut velocity) in player_query.iter_mut() {
|
for (input, mut velocity) in player_query.iter_mut() {
|
||||||
let horizontal_movement = Vec3::new(
|
let horizontal_movement = Vec3::new(
|
||||||
input.movement_direction.x * SPEED,
|
input.movement_direction.x * SPEED,
|
||||||
0.0,
|
0.0,
|
||||||
input.movement_direction.z * SPEED,
|
input.movement_direction.z * SPEED,
|
||||||
);
|
);
|
||||||
|
|
||||||
velocity.linvel.x = horizontal_movement.x;
|
velocity.linvel.x = horizontal_movement.x;
|
||||||
velocity.linvel.z = horizontal_movement.z;
|
velocity.linvel.z = horizontal_movement.z;
|
||||||
|
|
||||||
if input.movement_direction.y > 0.0 {
|
if input.movement_direction.y > 0.0 {
|
||||||
velocity.linvel.y = JUMP_FORCE;
|
velocity.linvel.y = JUMP_FORCE;
|
||||||
} else if input.movement_direction.y < 0.0 {
|
} else if input.movement_direction.y < 0.0 {
|
||||||
velocity.linvel.y = -SPEED;
|
velocity.linvel.y = -SPEED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/player/toolbar.rs
Normal file
21
src/player/toolbar.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
use std::default::Default;
|
||||||
|
|
||||||
|
use crate::GameState;
|
||||||
|
|
||||||
|
use super::Player;
|
||||||
|
|
||||||
|
#[derive(Component, Default, Debug)]
|
||||||
|
pub struct Item(Option<Entity>);
|
||||||
|
|
||||||
|
impl Item {
|
||||||
|
pub fn none() -> Self {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn plugin(app: &mut App) {
|
||||||
|
app.add_systems(Update, show_toolbar.run_if(in_state(GameState::Playing)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_toolbar(player_tool_query: Query<&Item, With<Player>>) {}
|
||||||
24
src/util.rs
Normal file
24
src/util.rs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
macro_rules! single {
|
||||||
|
($query:expr) => {
|
||||||
|
match $query.get_single() {
|
||||||
|
Ok(q) => q,
|
||||||
|
_ => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! single_mut {
|
||||||
|
($query:expr) => {
|
||||||
|
match $query.get_single_mut() {
|
||||||
|
Ok(q) => q,
|
||||||
|
_ => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use single;
|
||||||
|
pub(crate) use single_mut;
|
||||||
Reference in New Issue
Block a user