generated from 2ndbeam/bevy-template
feat: Unchecked and untested plugin base
This commit is contained in:
parent
6eccecae37
commit
53778f0b33
5 changed files with 145 additions and 62 deletions
128
src/lib.rs
Normal file
128
src/lib.rs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
use bevy::math::bounding::IntersectsVolume;
|
||||
#[warn(missing_docs)]
|
||||
|
||||
use bevy::{math::bounding::{Aabb2d, BoundingCircle}, prelude::*};
|
||||
|
||||
// TODO: add more precise crate documentation
|
||||
// TODO: implement event emitting on collision
|
||||
/// Simple 2D collision system, inspired by Godot Engine.
|
||||
|
||||
#[derive(Component)]
|
||||
/// Enum of available shapes
|
||||
pub enum CollisionShape {
|
||||
/// Rectangle shape
|
||||
Aabb {
|
||||
/// The shape itself, tied to **global** position
|
||||
shape: Aabb2d,
|
||||
/// Start offset, used to calculate global position.
|
||||
offset: Vec2,
|
||||
/// Size of the shape, used to calculate global position.
|
||||
size: Vec2,
|
||||
},
|
||||
/// Circle shape
|
||||
Circle {
|
||||
/// The shape itself, tied to **global** position
|
||||
shape: BoundingCircle,
|
||||
/// Start offset, used to calculate global position
|
||||
offset: Vec2,
|
||||
},
|
||||
}
|
||||
|
||||
impl CollisionShape {
|
||||
/// Returns true if shapes intersect
|
||||
pub fn intersects(&self, other: &CollisionShape) -> bool {
|
||||
match self {
|
||||
Self::Aabb { shape: aabb, .. } => {
|
||||
match other {
|
||||
CollisionShape::Aabb { shape: other_aabb, .. } => aabb.intersects(other_aabb),
|
||||
CollisionShape::Circle { shape: circle, .. } => aabb.intersects(circle),
|
||||
}
|
||||
},
|
||||
Self::Circle{ shape: circle, .. } => {
|
||||
match other {
|
||||
CollisionShape::Aabb { shape: aabb, .. } => circle.intersects(aabb),
|
||||
CollisionShape::Circle { shape: other_circle, .. } => circle.intersects(other_circle),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
#[require(Transform)]
|
||||
/// Component, handling multiple collision shapes for single entity
|
||||
pub struct Collider {
|
||||
/// Shapes of the collider
|
||||
pub shapes: Vec<CollisionShape>,
|
||||
/// Bitmask of collider groups.
|
||||
/// Setting this to 0 makes collider invisible for others
|
||||
pub mask: usize,
|
||||
/// Bitmask of groups which will be checked for collision.
|
||||
/// Setting this to 0 makes collider ignorant to others
|
||||
pub check_mask: usize,
|
||||
}
|
||||
|
||||
impl Collider {
|
||||
#[inline]
|
||||
/// Returns true if any of self shapes intersect other's shapes, ignoring groups
|
||||
pub fn intersects_unchecked(&self, other: &Collider) -> bool {
|
||||
for shape in self.shapes.iter() {
|
||||
for other_shape in other.shapes.iter() {
|
||||
if shape.intersects(other_shape) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns true if any of self shapes intersect other's shapes, respecting groups.
|
||||
/// Wrapper around [intersects_unchecked](Self::intersects_unchecked)
|
||||
pub fn intersects(&self, other: &Collider) -> bool {
|
||||
if self.check_mask & other.mask == 0 {
|
||||
return false;
|
||||
}
|
||||
self.intersects_unchecked(other)
|
||||
}
|
||||
|
||||
/// Update shapes global position
|
||||
pub fn update_shapes_position(&mut self, global_position: &Vec2) {
|
||||
for shape in self.shapes.iter_mut() {
|
||||
match shape {
|
||||
CollisionShape::Aabb { shape, offset, size } => {
|
||||
shape.min.x = global_position.x + offset.x;
|
||||
shape.min.y = global_position.y + offset.y;
|
||||
shape.max.x = shape.min.x + size.x;
|
||||
shape.max.y = shape.min.y + size.y;
|
||||
},
|
||||
CollisionShape::Circle { shape, offset } => {
|
||||
shape.center.x = global_position.x + offset.x;
|
||||
shape.center.y = global_position.y + offset.y;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct UpdateShapes;
|
||||
|
||||
/// Update collider shapes to match new global transform
|
||||
pub fn update_collider_shapes(
|
||||
mut commands: Commands,
|
||||
colliders: Query<(&mut Collider, &GlobalTransform, Entity), With<UpdateShapes>>,
|
||||
) {
|
||||
for (mut collider, transform, entity) in colliders {
|
||||
collider.update_shapes_position(&transform.translation().xy());
|
||||
commands.entity(entity).remove::<UpdateShapes>();
|
||||
}
|
||||
}
|
||||
|
||||
/// Plugin that adds collision systems
|
||||
pub struct CollisionPlugin;
|
||||
|
||||
impl Plugin for CollisionPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(Update, update_collider_shapes);
|
||||
}
|
||||
}
|
||||
54
src/main.rs
54
src/main.rs
|
|
@ -1,54 +0,0 @@
|
|||
use bevy::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
struct Person;
|
||||
|
||||
#[derive(Component)]
|
||||
struct Name(String);
|
||||
|
||||
#[derive(Resource)]
|
||||
struct GreetTimer(Timer);
|
||||
|
||||
#[derive(Resource)]
|
||||
struct UpdateTimer(Timer);
|
||||
|
||||
pub struct HelloPlugin;
|
||||
|
||||
impl Plugin for HelloPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.insert_resource(GreetTimer(Timer::from_seconds(2.0, TimerMode::Repeating)));
|
||||
app.insert_resource(UpdateTimer(Timer::from_seconds(10.0, TimerMode::Once)));
|
||||
app.add_systems(Startup, add_people);
|
||||
app.add_systems(Update, (update_people, greet_people).chain());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn add_people(mut commands: Commands) {
|
||||
commands.spawn((Person, Name("Alkesey Mirnekov".to_string())));
|
||||
commands.spawn((Person, Name("Alkesey Mirnekov 2".to_string())));
|
||||
commands.spawn((Person, Name("Alkesey Mirnekov 3".to_string())));
|
||||
}
|
||||
|
||||
fn greet_people(time: Res<Time>, mut timer: ResMut<GreetTimer>, query: Query<&Name, With<Person>>) {
|
||||
if timer.0.tick(time.delta()).just_finished() {
|
||||
for name in &query {
|
||||
println!("hello {}!", name.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_people(time: Res<Time>, mut timer: ResMut<UpdateTimer>, mut query: Query<&mut Name, With<Person>>) {
|
||||
if timer.0.tick(time.delta()).just_finished() {
|
||||
for mut name in &mut query {
|
||||
name.0 = format!("{} II", name.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugins(HelloPlugin)
|
||||
.run();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue