trigger system

This commit is contained in:
Jonas H
2026-03-05 15:05:49 +01:00
parent bab54b6f21
commit 350fddc2af
6 changed files with 134 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ pub mod noclip;
pub mod physics; pub mod physics;
pub mod rotate; pub mod rotate;
pub mod tree_instances; pub mod tree_instances;
pub mod trigger;
pub use camera::CameraComponent; pub use camera::CameraComponent;
pub use dissolve::DissolveComponent; pub use dissolve::DissolveComponent;
@@ -21,3 +22,4 @@ pub use movement::MovementComponent;
pub use physics::PhysicsComponent; pub use physics::PhysicsComponent;
pub use rotate::RotateComponent; pub use rotate::RotateComponent;
pub use tree_instances::TreeInstancesComponent; pub use tree_instances::TreeInstancesComponent;
pub use trigger::{TriggerComponent, TriggerEvent, TriggerEventKind, TriggerFilter, TriggerShape, TriggerState};

37
src/components/trigger.rs Normal file
View File

@@ -0,0 +1,37 @@
use crate::entity::EntityHandle;
pub enum TriggerShape
{
Sphere { radius: f32 },
}
pub enum TriggerFilter
{
Player,
}
pub enum TriggerState
{
Idle,
Inside,
}
pub struct TriggerComponent
{
pub shape: TriggerShape,
pub filter: TriggerFilter,
pub state: TriggerState,
}
pub enum TriggerEventKind
{
Entered,
Exited,
}
pub struct TriggerEvent
{
pub trigger_entity: EntityHandle,
pub activator_entity: EntityHandle,
pub kind: TriggerEventKind,
}

View File

@@ -41,6 +41,7 @@ use crate::systems::{
camera_follow_system, camera_input_system, camera_view_matrix, physics_sync_system, camera_follow_system, camera_input_system, camera_view_matrix, physics_sync_system,
player_input_system, render_system, rotate_system, snow_system, spotlight_sync_system, player_input_system, render_system, rotate_system, snow_system, spotlight_sync_system,
start_camera_following, state_machine_physics_system, state_machine_system, start_camera_following, state_machine_physics_system, state_machine_system,
trigger_system,
}; };
use crate::systems::camera::stop_camera_following; use crate::systems::camera::stop_camera_following;
use crate::utility::time::Time; use crate::utility::time::Time;
@@ -283,6 +284,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
PhysicsManager::physics_step(); PhysicsManager::physics_step();
physics_sync_system(&mut world); physics_sync_system(&mut world);
trigger_system(&mut world);
physics_accumulator -= FIXED_TIMESTEP; physics_accumulator -= FIXED_TIMESTEP;
} }

View File

@@ -9,6 +9,7 @@ pub mod snow;
pub mod spotlight_sync; pub mod spotlight_sync;
pub mod state_machine; pub mod state_machine;
pub mod tree_dissolve; pub mod tree_dissolve;
pub mod trigger;
pub use camera::{ pub use camera::{
camera_follow_system, camera_input_system, camera_noclip_system, camera_view_matrix, camera_follow_system, camera_input_system, camera_noclip_system, camera_view_matrix,
@@ -21,3 +22,7 @@ pub use rotate::rotate_system;
pub use snow::snow_system; pub use snow::snow_system;
pub use spotlight_sync::spotlight_sync_system; pub use spotlight_sync::spotlight_sync_system;
pub use state_machine::{state_machine_physics_system, state_machine_system}; pub use state_machine::{state_machine_physics_system, state_machine_system};
pub use tree_dissolve::{
tree_dissolve_update_system, tree_instance_buffer_update_system, tree_occlusion_system,
};
pub use trigger::trigger_system;

82
src/systems/trigger.rs Normal file
View File

@@ -0,0 +1,82 @@
use glam::Vec3;
use crate::components::trigger::{TriggerEvent, TriggerEventKind, TriggerFilter, TriggerShape, TriggerState};
use crate::entity::EntityHandle;
use crate::world::World;
pub fn trigger_system(world: &mut World)
{
world.trigger_events.clear();
let trigger_entities: Vec<EntityHandle> = world.triggers.all();
let mut pending_events: Vec<TriggerEvent> = Vec::new();
for trigger_entity in trigger_entities
{
let trigger_pos = match world.transforms.get(trigger_entity)
{
Some(t) => t.position,
None => continue,
};
let candidate_entities: Vec<EntityHandle> = match world.triggers.get(trigger_entity)
{
Some(trigger) => match &trigger.filter
{
TriggerFilter::Player => world.player_tags.all(),
},
None => continue,
};
let activator_positions: Vec<(EntityHandle, Vec3)> = candidate_entities
.into_iter()
.filter_map(|e| world.transforms.get(e).map(|t| (e, t.position)))
.collect();
let overlapping = match world.triggers.get(trigger_entity)
{
Some(trigger) => activator_positions.iter().any(|(_, pos)| match &trigger.shape
{
TriggerShape::Sphere { radius } => (trigger_pos - *pos).length() < *radius,
}),
None => continue,
};
let first_activator = activator_positions.first().map(|(e, _)| *e);
if let Some(trigger) = world.triggers.get_mut(trigger_entity)
{
match (&trigger.state, overlapping)
{
(TriggerState::Idle, true) =>
{
trigger.state = TriggerState::Inside;
if let Some(activator_entity) = first_activator
{
pending_events.push(TriggerEvent {
trigger_entity,
activator_entity,
kind: TriggerEventKind::Entered,
});
}
}
(TriggerState::Inside, false) =>
{
trigger.state = TriggerState::Idle;
if let Some(activator_entity) = first_activator
{
pending_events.push(TriggerEvent {
trigger_entity,
activator_entity,
kind: TriggerEventKind::Exited,
});
}
}
_ =>
{}
}
}
}
world.trigger_events.extend(pending_events);
}

View File

@@ -4,6 +4,7 @@ use crate::components::dissolve::DissolveComponent;
use crate::components::follow::FollowComponent; use crate::components::follow::FollowComponent;
use crate::components::lights::spot::SpotlightComponent; use crate::components::lights::spot::SpotlightComponent;
use crate::components::tree_instances::TreeInstancesComponent; use crate::components::tree_instances::TreeInstancesComponent;
use crate::components::trigger::{TriggerComponent, TriggerEvent};
use crate::components::{ use crate::components::{
CameraComponent, InputComponent, JumpComponent, MeshComponent, MovementComponent, CameraComponent, InputComponent, JumpComponent, MeshComponent, MovementComponent,
PhysicsComponent, RotateComponent, PhysicsComponent, RotateComponent,
@@ -86,6 +87,8 @@ pub struct World
pub rotates: Storage<RotateComponent>, pub rotates: Storage<RotateComponent>,
pub tree_instances: Storage<TreeInstancesComponent>, pub tree_instances: Storage<TreeInstancesComponent>,
pub names: Storage<String>, pub names: Storage<String>,
pub triggers: Storage<TriggerComponent>,
pub trigger_events: Vec<TriggerEvent>,
} }
impl World impl World
@@ -110,6 +113,8 @@ impl World
rotates: Storage::new(), rotates: Storage::new(),
tree_instances: Storage::new(), tree_instances: Storage::new(),
names: Storage::new(), names: Storage::new(),
triggers: Storage::new(),
trigger_events: Vec::new(),
} }
} }
@@ -136,6 +141,7 @@ impl World
self.rotates.remove(entity); self.rotates.remove(entity);
self.tree_instances.remove(entity); self.tree_instances.remove(entity);
self.names.remove(entity); self.names.remove(entity);
self.triggers.remove(entity);
self.entities.despawn(entity); self.entities.despawn(entity);
} }