generated from 2ndbeam/bevy-template
feat: Collision groups and states
This commit is contained in:
parent
f6022d84b2
commit
88a73275ff
8 changed files with 108 additions and 3 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
|
@ -591,6 +591,7 @@ dependencies = [
|
||||||
"bevy_rapier2d",
|
"bevy_rapier2d",
|
||||||
"leafwing-input-manager",
|
"leafwing-input-manager",
|
||||||
"petgraph",
|
"petgraph",
|
||||||
|
"seldom_state",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -4816,6 +4817,23 @@ dependencies = [
|
||||||
"tiny-skia",
|
"tiny-skia",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "seldom_state"
|
||||||
|
version = "0.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5db0767975eeb39d99493b23adc55b14d7106c333c06dd85774fa2cb909b79d5"
|
||||||
|
dependencies = [
|
||||||
|
"bevy_app",
|
||||||
|
"bevy_derive",
|
||||||
|
"bevy_ecs",
|
||||||
|
"bevy_log",
|
||||||
|
"bevy_math",
|
||||||
|
"bevy_utils",
|
||||||
|
"either",
|
||||||
|
"leafwing-input-manager",
|
||||||
|
"variadics_please",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "self_cell"
|
name = "self_cell"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ bevy = { version = "0.18.0", features = ["bevy_remote"] }
|
||||||
bevy_rapier2d = "0.33.0"
|
bevy_rapier2d = "0.33.0"
|
||||||
leafwing-input-manager = "0.20.0"
|
leafwing-input-manager = "0.20.0"
|
||||||
petgraph = { version = "0.8.3" }
|
petgraph = { version = "0.8.3" }
|
||||||
|
seldom_state = { version = "0.16.0", features = ["leafwing_input"] }
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 1
|
opt-level = 1
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ use std::time::Duration;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rapier2d::prelude::*;
|
use bevy_rapier2d::prelude::*;
|
||||||
|
|
||||||
|
use crate::{GROUP_ATTACK, GROUP_INTERACTIVE, GROUP_STATIC};
|
||||||
|
|
||||||
/// Contains logic for attack-related calculations
|
/// Contains logic for attack-related calculations
|
||||||
#[derive(Component, Clone, Debug, Reflect)]
|
#[derive(Component, Clone, Debug, Reflect)]
|
||||||
#[reflect(Component, Clone, Debug)]
|
#[reflect(Component, Clone, Debug)]
|
||||||
|
|
@ -33,6 +35,7 @@ impl AttackArea {
|
||||||
max_distance,
|
max_distance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns attack area bundle with everything needed
|
/// Returns attack area bundle with everything needed
|
||||||
pub fn bundle(
|
pub fn bundle(
|
||||||
damage: f32,
|
damage: f32,
|
||||||
|
|
@ -41,6 +44,7 @@ impl AttackArea {
|
||||||
position: Vec2,
|
position: Vec2,
|
||||||
half_area: Vec2,
|
half_area: Vec2,
|
||||||
facing_left: bool,
|
facing_left: bool,
|
||||||
|
affinity: Group,
|
||||||
) -> impl Bundle {
|
) -> impl Bundle {
|
||||||
let origin_x = if facing_left { position.x - half_area.x } else { position.x + half_area.x };
|
let origin_x = if facing_left { position.x - half_area.x } else { position.x + half_area.x };
|
||||||
(
|
(
|
||||||
|
|
@ -49,6 +53,10 @@ impl AttackArea {
|
||||||
|
|
||||||
// Collision
|
// Collision
|
||||||
Transform::from_xyz(position.x, position.y, 0.),
|
Transform::from_xyz(position.x, position.y, 0.),
|
||||||
|
CollisionGroups::new(
|
||||||
|
GROUP_ATTACK,
|
||||||
|
GROUP_STATIC | GROUP_INTERACTIVE | affinity,
|
||||||
|
),
|
||||||
Collider::cuboid(half_area.x, half_area.y),
|
Collider::cuboid(half_area.x, half_area.y),
|
||||||
|
|
||||||
// AttackAreaOrigin
|
// AttackAreaOrigin
|
||||||
|
|
@ -73,3 +81,12 @@ impl AttackArea {
|
||||||
self.damage * EaseFunction::QuinticOut.sample_unchecked(total_multiplier)
|
self.damage * EaseFunction::QuinticOut.sample_unchecked(total_multiplier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// System that updates AttackArea timers and despawns those who timed out
|
||||||
|
pub fn update_attack_areas(mut commands: Commands, time: Res<Time>, areas: Query<(Entity, &mut AttackArea)>) {
|
||||||
|
for (area_id, mut area) in areas {
|
||||||
|
if area.tick(time.delta()) {
|
||||||
|
commands.entity(area_id).despawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,25 @@
|
||||||
//! This module contains core concepts of the combat system
|
//! This module contains core concepts of the combat system
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub mod attack;
|
pub mod attack;
|
||||||
|
|
||||||
|
/// Combat health component
|
||||||
|
#[derive(Component, Clone, Copy, PartialEq, Debug, Default, Reflect)]
|
||||||
|
#[reflect(Component, Clone, PartialEq, Debug, Default)]
|
||||||
|
pub struct Health {
|
||||||
|
/// Current health value
|
||||||
|
pub current: f32,
|
||||||
|
/// Maximum health value
|
||||||
|
pub max: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Health {
|
||||||
|
/// Constructs new health component
|
||||||
|
pub fn new(max: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
current: max,
|
||||||
|
max,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
13
src/lib.rs
13
src/lib.rs
|
|
@ -10,14 +10,27 @@ pub mod graph;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
pub mod plugin;
|
pub mod plugin;
|
||||||
|
pub mod states;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use bevy_rapier2d::prelude::*;
|
||||||
|
|
||||||
use crate::{player::Player, timer::BpmTimer};
|
use crate::{player::Player, timer::BpmTimer};
|
||||||
|
|
||||||
const PIXELS_PER_METER: f32 = 16.;
|
const PIXELS_PER_METER: f32 = 16.;
|
||||||
|
|
||||||
|
/// Collision group for static entities (walls, floors, etc)
|
||||||
|
pub const GROUP_STATIC: Group = Group::GROUP_1;
|
||||||
|
/// Collision group for interactive entities (doors, buttons, etc)
|
||||||
|
pub const GROUP_INTERACTIVE: Group = Group::GROUP_2;
|
||||||
|
/// Collision group for player and player-related entities
|
||||||
|
pub const GROUP_FRIENDLY: Group = Group::GROUP_3;
|
||||||
|
/// Collision group for enemy-related entities
|
||||||
|
pub const GROUP_ENEMY: Group = Group::GROUP_4;
|
||||||
|
/// Collision group for attack-related entities
|
||||||
|
pub const GROUP_ATTACK: Group = Group::GROUP_5;
|
||||||
|
|
||||||
/// Returns pixel measurement for given length in meters
|
/// Returns pixel measurement for given length in meters
|
||||||
#[inline(always)] pub const fn meters(length: f32) -> f32 { PIXELS_PER_METER * length }
|
#[inline(always)] pub const fn meters(length: f32) -> f32 { PIXELS_PER_METER * length }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,10 @@ use bevy_rapier2d::prelude::*;
|
||||||
use leafwing_input_manager::prelude::*;
|
use leafwing_input_manager::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
meters,
|
GROUP_ATTACK, GROUP_ENEMY, GROUP_FRIENDLY, GROUP_INTERACTIVE, GROUP_STATIC, input::{
|
||||||
input::{
|
|
||||||
DefaultInputMap,
|
DefaultInputMap,
|
||||||
PlayerInput,
|
PlayerInput,
|
||||||
}
|
}, meters
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod systems;
|
pub mod systems;
|
||||||
|
|
@ -51,11 +50,19 @@ impl Player {
|
||||||
RigidBody::KinematicPositionBased,
|
RigidBody::KinematicPositionBased,
|
||||||
KinematicCharacterController::default(),
|
KinematicCharacterController::default(),
|
||||||
ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_STATIC,
|
ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_STATIC,
|
||||||
|
CollisionGroups::new(
|
||||||
|
GROUP_FRIENDLY,
|
||||||
|
GROUP_STATIC | GROUP_INTERACTIVE | GROUP_ENEMY | GROUP_ATTACK,
|
||||||
|
),
|
||||||
Collider::cuboid(meters(0.3), meters(0.9)),
|
Collider::cuboid(meters(0.3), meters(0.9)),
|
||||||
ActiveEvents::COLLISION_EVENTS,
|
ActiveEvents::COLLISION_EVENTS,
|
||||||
Sleeping::disabled(),
|
Sleeping::disabled(),
|
||||||
|
|
||||||
|
// State
|
||||||
|
crate::states::Free,
|
||||||
|
|
||||||
Children::spawn((
|
Children::spawn((
|
||||||
|
// Camera
|
||||||
Spawn((
|
Spawn((
|
||||||
Name::new("Player camera"),
|
Name::new("Player camera"),
|
||||||
Camera2d,
|
Camera2d,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rapier2d::prelude::*;
|
use bevy_rapier2d::prelude::*;
|
||||||
use leafwing_input_manager::prelude::*;
|
use leafwing_input_manager::prelude::*;
|
||||||
|
use seldom_state::prelude::*;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
|
@ -18,6 +19,8 @@ impl Plugin for GamePlugin {
|
||||||
|
|
||||||
InputManagerPlugin::<input::PlayerInput>::default(),
|
InputManagerPlugin::<input::PlayerInput>::default(),
|
||||||
InputManagerPlugin::<input::DebugInput>::default(),
|
InputManagerPlugin::<input::DebugInput>::default(),
|
||||||
|
|
||||||
|
StateMachinePlugin::default(),
|
||||||
))
|
))
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, (
|
.add_systems(Update, (
|
||||||
|
|
|
||||||
24
src/states.rs
Normal file
24
src/states.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
//! Commonly used entity states
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
/// Entity is not doing anything special
|
||||||
|
#[derive(Component, Clone, Copy, PartialEq, Eq, Debug, Default, Reflect)]
|
||||||
|
#[reflect(Component, Clone, PartialEq, Debug, Default)]
|
||||||
|
pub struct Free;
|
||||||
|
|
||||||
|
/// Entity is acting and cannot do something else
|
||||||
|
#[derive(Component, Clone, Copy, PartialEq, Eq, Debug, Default, Reflect)]
|
||||||
|
#[reflect(Component, Clone, PartialEq, Debug, Default)]
|
||||||
|
pub struct Acting {
|
||||||
|
/// How much time left before action ends
|
||||||
|
pub beats_remaining: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Entity is awaiting a specific set of actions
|
||||||
|
#[derive(Component, Clone, Copy, PartialEq, Eq, Debug, Default, Reflect)]
|
||||||
|
#[reflect(Component, Clone, PartialEq, Debug, Default)]
|
||||||
|
pub struct ActionWindow {
|
||||||
|
/// How much time left before window ends
|
||||||
|
pub beats_remaining: u32,
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue