second key and fence
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2820,6 +2820,7 @@ dependencies = [
|
||||
"bevy_sprite3d",
|
||||
"bevy_trenchbroom",
|
||||
"nil",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -17,3 +17,4 @@ bevy-tnua-avian3d = "0.2.0"
|
||||
bevy_dolly = { version = "0.0.5", default-features = false }
|
||||
bevy_asset_loader = "0.22.0"
|
||||
bevy_sprite3d = "4.0.0"
|
||||
rand = "0.8.5"
|
||||
|
||||
1162
assets/maps/map1.map
1162
assets/maps/map1.map
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@ enum CutsceneState {
|
||||
None,
|
||||
Playing {
|
||||
timer: Timer,
|
||||
name: String,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -21,37 +22,39 @@ pub fn plugin(app: &mut App) {
|
||||
|
||||
fn on_start_cutscene(
|
||||
trigger: Trigger<StartCutscene>,
|
||||
cutscenes: Query<(&Transform, &CutsceneCamera), Without<Camera>>,
|
||||
mut res: ResMut<DebugVisuals>,
|
||||
mut cutscene_state: ResMut<CutsceneState>,
|
||||
mut cam: Query<&mut Transform, With<Camera>>,
|
||||
) {
|
||||
let cutscene = trigger.event().0.clone();
|
||||
|
||||
let Some((t, _)) = cutscenes
|
||||
.iter()
|
||||
.find(|(_, cutscene_camera)| cutscene == cutscene_camera.name)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
res.cam_follow = false;
|
||||
|
||||
*cam.single_mut() = *t;
|
||||
|
||||
*cutscene_state = CutsceneState::Playing {
|
||||
timer: Timer::from_seconds(2.0, TimerMode::Once),
|
||||
name: cutscene,
|
||||
};
|
||||
}
|
||||
|
||||
fn update(
|
||||
mut res: ResMut<DebugVisuals>,
|
||||
mut cutscene_state: ResMut<CutsceneState>,
|
||||
cutscenes: Query<(&Transform, &CutsceneCamera), Without<Camera>>,
|
||||
mut cam: Query<&mut Transform, With<Camera>>,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
if let CutsceneState::Playing { timer, .. } = &mut *cutscene_state {
|
||||
if let CutsceneState::Playing { timer, name } = &mut *cutscene_state {
|
||||
res.cam_follow = false;
|
||||
timer.tick(time.delta());
|
||||
|
||||
let Some((t, _)) = cutscenes
|
||||
.iter()
|
||||
.find(|(_, cutscene_camera)| name == &cutscene_camera.name)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
*cam.single_mut() = *t;
|
||||
|
||||
if timer.finished() {
|
||||
res.cam_follow = true;
|
||||
*cutscene_state = CutsceneState::None;
|
||||
|
||||
60
src/gates.rs
60
src/gates.rs
@@ -1,38 +1,46 @@
|
||||
use crate::{cutscene::StartCutscene, keys::KeyCollected, movables::TriggerMovableEvent};
|
||||
use bevy::{prelude::*, utils::hashbrown::HashSet};
|
||||
|
||||
#[derive(Resource)]
|
||||
enum GatesState {
|
||||
Init,
|
||||
GateOpen1,
|
||||
}
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.insert_resource(GatesState::Init);
|
||||
app.add_observer(on_key);
|
||||
}
|
||||
|
||||
fn on_key(
|
||||
_trigger: Trigger<KeyCollected>,
|
||||
mut commands: Commands,
|
||||
mut state: ResMut<GatesState>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
if matches!(*state, GatesState::Init) {
|
||||
*state = GatesState::GateOpen1;
|
||||
commands.trigger(StartCutscene("fence_01".to_string()));
|
||||
fn on_key(trigger: Trigger<KeyCollected>, mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
match trigger.event().0.as_str() {
|
||||
"fence_gate" => {
|
||||
commands.trigger(StartCutscene("fence_01".to_string()));
|
||||
|
||||
//TODO: put into a sound effects system
|
||||
commands.spawn((
|
||||
AudioPlayer::new(asset_server.load("sfx/effects/gate.ogg")),
|
||||
PlaybackSettings::DESPAWN,
|
||||
));
|
||||
//TODO: put into a sound effects system
|
||||
commands.spawn((
|
||||
AudioPlayer::new(asset_server.load("sfx/effects/gate.ogg")),
|
||||
PlaybackSettings::DESPAWN,
|
||||
));
|
||||
|
||||
let entities: HashSet<_> = vec!["fence_01", "fence_02"]
|
||||
.into_iter()
|
||||
.map(|s| String::from(s))
|
||||
.collect();
|
||||
let entities: HashSet<_> = vec!["fence_01", "fence_02"]
|
||||
.into_iter()
|
||||
.map(|s| String::from(s))
|
||||
.collect();
|
||||
|
||||
commands.trigger(TriggerMovableEvent(entities));
|
||||
commands.trigger(TriggerMovableEvent(entities));
|
||||
}
|
||||
"fence_shaft" => {
|
||||
commands.trigger(StartCutscene("fence_02".to_string()));
|
||||
|
||||
//TODO: put into a sound effects system
|
||||
commands.spawn((
|
||||
AudioPlayer::new(asset_server.load("sfx/effects/gate.ogg")),
|
||||
PlaybackSettings::DESPAWN,
|
||||
));
|
||||
|
||||
let entities: HashSet<_> = vec!["fence_shaft"]
|
||||
.into_iter()
|
||||
.map(|s| String::from(s))
|
||||
.collect();
|
||||
|
||||
commands.trigger(TriggerMovableEvent(entities));
|
||||
}
|
||||
_ => {
|
||||
error!("unknown key logic: {}", trigger.event().0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
src/keys.rs
36
src/keys.rs
@@ -4,14 +4,14 @@ use bevy::prelude::*;
|
||||
use std::f32::consts::PI;
|
||||
|
||||
#[derive(Event, Reflect)]
|
||||
pub struct KeySpawn(pub Vec3);
|
||||
pub struct KeySpawn(pub Vec3, pub String);
|
||||
|
||||
#[derive(Component, Reflect)]
|
||||
#[reflect(Component)]
|
||||
struct Key;
|
||||
struct Key(pub String);
|
||||
|
||||
#[derive(Event, Reflect)]
|
||||
pub struct KeyCollected;
|
||||
pub struct KeyCollected(pub String);
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.add_systems(Update, collect_key);
|
||||
@@ -19,17 +19,17 @@ pub fn plugin(app: &mut App) {
|
||||
}
|
||||
|
||||
fn on_spawn(trigger: Trigger<KeySpawn>, mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
let KeySpawn(position) = trigger.event();
|
||||
let KeySpawn(position, id) = trigger.event();
|
||||
|
||||
//TODO: randomize
|
||||
let spawn_dir = Quat::from_rotation_y(PI / 2.) * Vec3::new(0.5, 0.6, 0.).normalize();
|
||||
let angle = rand::random::<f32>() * PI * 2.;
|
||||
let spawn_dir = Quat::from_rotation_y(angle) * Vec3::new(0.5, 0.6, 0.).normalize();
|
||||
|
||||
let mesh = asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/key.glb"));
|
||||
|
||||
commands
|
||||
.spawn((
|
||||
Name::new("key"),
|
||||
Key,
|
||||
Key(id.clone()),
|
||||
Transform::from_translation(*position),
|
||||
Visibility::default(),
|
||||
Collider::sphere(1.5),
|
||||
@@ -50,21 +50,21 @@ fn collect_key(
|
||||
) {
|
||||
for CollisionStarted(e1, e2) in collision_event_reader.read() {
|
||||
let collectable = if query_player.contains(*e1) && query_collectable.contains(*e2) {
|
||||
Some(*e2)
|
||||
*e2
|
||||
} else if query_player.contains(*e2) && query_collectable.contains(*e1) {
|
||||
Some(*e1)
|
||||
*e1
|
||||
} else {
|
||||
None
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(collectable) = collectable {
|
||||
commands.spawn((
|
||||
AudioPlayer::new(asset_server.load("sfx/effects/key_collect.ogg")),
|
||||
PlaybackSettings::DESPAWN,
|
||||
));
|
||||
let key = query_collectable.get(collectable).unwrap();
|
||||
|
||||
commands.trigger(KeyCollected);
|
||||
commands.entity(collectable).despawn_recursive();
|
||||
}
|
||||
commands.spawn((
|
||||
AudioPlayer::new(asset_server.load("sfx/effects/key_collect.ogg")),
|
||||
PlaybackSettings::DESPAWN,
|
||||
));
|
||||
|
||||
commands.trigger(KeyCollected(key.0.clone()));
|
||||
commands.entity(collectable).despawn_recursive();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ fn trigger(
|
||||
target,
|
||||
start_time: time.elapsed_secs(),
|
||||
//TODO: make this configurable
|
||||
duration: 1.,
|
||||
duration: 2.,
|
||||
};
|
||||
|
||||
commands.entity(e).insert(platform);
|
||||
@@ -75,6 +75,7 @@ fn move_active(
|
||||
let t = (elapsed - active.start_time) / active.duration;
|
||||
transform.rotation = active.start.rotation.lerp(active.target.rotation, t);
|
||||
} else {
|
||||
info!("movable done");
|
||||
*transform = active.target;
|
||||
|
||||
commands.entity(e).remove::<(ActiveMovable, Movable)>();
|
||||
|
||||
@@ -37,8 +37,8 @@ fn on_hit(
|
||||
if hp.0 <= 0 {
|
||||
commands.entity(trigger.entity()).despawn_recursive();
|
||||
|
||||
if enemy.has_key {
|
||||
commands.trigger(KeySpawn(transform.translation));
|
||||
if !enemy.key.is_empty() {
|
||||
commands.trigger(KeySpawn(transform.translation, enemy.key.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ pub struct CutsceneCamera {
|
||||
#[model({ "path": "models/alien_naked.glb" })]
|
||||
pub struct EnemySpawn {
|
||||
pub head: String,
|
||||
pub has_key: bool,
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
impl EnemySpawn {
|
||||
|
||||
@@ -72,11 +72,7 @@
|
||||
@PointClass base(transform) model({ "path": "models/alien_naked.glb" }) = enemy_spawn
|
||||
[
|
||||
head(string) : "head" : "" : ""
|
||||
has_key(choices) : "has_key" : "false" : "" =
|
||||
[
|
||||
"true" : "true"
|
||||
"false" : "false"
|
||||
]
|
||||
key(string) : "key" : "" : ""
|
||||
]
|
||||
|
||||
@SolidClass base(transform, target) = movable
|
||||
|
||||
Reference in New Issue
Block a user