Compare commits
7 commits
6926a0f4f9
...
70c83295ca
Author | SHA1 | Date | |
---|---|---|---|
70c83295ca | |||
d856c8487a | |||
afeba6b63d | |||
71259431eb | |||
624de181ce | |||
4b37bc1043 | |||
df9c6e9c05 |
8 changed files with 135 additions and 3 deletions
BIN
assets/models/marker_race.glb
Normal file
BIN
assets/models/marker_race.glb
Normal file
Binary file not shown.
BIN
src/blender/marker_race.blend
Normal file
BIN
src/blender/marker_race.blend
Normal file
Binary file not shown.
|
@ -924,10 +924,11 @@
|
||||||
- Yep, that's space for you.
|
- Yep, that's space for you.
|
||||||
- You have a couple of options to help with that though.
|
- You have a couple of options to help with that though.
|
||||||
- First, make sure your Augmented Reality is on. [press TAB]
|
- First, make sure your Augmented Reality is on. [press TAB]
|
||||||
- Then, boost the light amplification setting. [press ESC]
|
- Then, boost the Night Vision setting. [press ESC]
|
||||||
- Sometimes the flashlight can help too. [press F]
|
- Sometimes the flashlight can help too. [press F]
|
||||||
- But space is empty, so unless you point the flashlight at something, it won't do much.
|
- But space is empty, so unless you point the flashlight at something, it won't do much.
|
||||||
- "You can boost its brightness, but careful: It may drain more power than your reactor generates."
|
- "You can boost its brightness, but careful: It may drain more power than your reactor generates."
|
||||||
|
- If you ever run out of power, just hop into a vehicle, their reactors generate more than you'll need.
|
||||||
- goto: generic_questions
|
- goto: generic_questions
|
||||||
- Tell me about life in space.:
|
- Tell me about life in space.:
|
||||||
- Sure, what do you want to know?
|
- Sure, what do you want to know?
|
||||||
|
|
|
@ -1136,7 +1136,7 @@ fn spawn_scenes(
|
||||||
state.ar_models.push("suit_ar_chefhat".to_string());
|
state.ar_models.push("suit_ar_chefhat".to_string());
|
||||||
|
|
||||||
// command: wants lookat PLAYERCAMERA
|
// command: wants lookat PLAYERCAMERA
|
||||||
state.wants_tolookat_id = Some("PLAYERCAMERA".to_string());
|
state.wants_tolookat_id = Some(ID_SPECIAL_PLAYERCAM.to_string());
|
||||||
|
|
||||||
// command: pronoun he
|
// command: pronoun he
|
||||||
state.pronoun = Some("he".to_string());
|
state.pronoun = Some("he".to_string());
|
||||||
|
|
123
src/game.rs
123
src/game.rs
|
@ -11,16 +11,19 @@
|
||||||
// This module handles player input, and coordinates interplay between other modules
|
// This module handles player input, and coordinates interplay between other modules
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use actor::PlayerCamera;
|
||||||
use bevy::color::palettes::css;
|
use bevy::color::palettes::css;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::scene::SceneInstance;
|
use bevy::scene::SceneInstance;
|
||||||
use bevy::window::{PrimaryWindow, Window, WindowMode};
|
use bevy::window::{PrimaryWindow, Window, WindowMode};
|
||||||
use bevy_xpbd_3d::prelude::*;
|
use bevy_xpbd_3d::prelude::*;
|
||||||
|
use fastrand;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub const CHEAT_WARP_1: &str = "pizzeria";
|
pub const CHEAT_WARP_1: &str = "pizzeria";
|
||||||
pub const CHEAT_WARP_2: &str = "busstopclippy2";
|
pub const CHEAT_WARP_2: &str = "busstopclippy2";
|
||||||
pub const CHEAT_WARP_3: &str = "busstopclippy3";
|
pub const CHEAT_WARP_3: &str = "busstopclippy3";
|
||||||
|
pub const RACE_TARGET_RADIUS: f64 = 5.0;
|
||||||
|
|
||||||
pub struct GamePlugin;
|
pub struct GamePlugin;
|
||||||
impl Plugin for GamePlugin {
|
impl Plugin for GamePlugin {
|
||||||
|
@ -48,12 +51,14 @@ impl Plugin for GamePlugin {
|
||||||
.run_if(on_event::<AchievementEvent>()),
|
.run_if(on_event::<AchievementEvent>()),
|
||||||
);
|
);
|
||||||
app.add_systems(Update, check_achievements.run_if(game_running));
|
app.add_systems(Update, check_achievements.run_if(game_running));
|
||||||
|
app.add_systems(Update, handle_race.run_if(game_running));
|
||||||
app.insert_resource(Id2Pos(HashMap::new()));
|
app.insert_resource(Id2Pos(HashMap::new()));
|
||||||
app.insert_resource(Id2V(HashMap::new()));
|
app.insert_resource(Id2V(HashMap::new()));
|
||||||
app.insert_resource(JupiterPos(DVec3::ZERO));
|
app.insert_resource(JupiterPos(DVec3::ZERO));
|
||||||
app.insert_resource(var::AchievementTracker::default());
|
app.insert_resource(var::AchievementTracker::default());
|
||||||
app.insert_resource(var::Settings::default());
|
app.insert_resource(var::Settings::default());
|
||||||
app.insert_resource(var::GameVars::default());
|
app.insert_resource(var::GameVars::default());
|
||||||
|
app.insert_resource(RaceState::default());
|
||||||
app.insert_resource(AchievementCheckTimer(Timer::from_seconds(
|
app.insert_resource(AchievementCheckTimer(Timer::from_seconds(
|
||||||
1.0,
|
1.0,
|
||||||
TimerMode::Repeating,
|
TimerMode::Repeating,
|
||||||
|
@ -74,6 +79,16 @@ pub struct Id2V(pub HashMap<String, DVec3>);
|
||||||
pub struct JupiterPos(pub DVec3);
|
pub struct JupiterPos(pub DVec3);
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct AchievementCheckTimer(pub Timer);
|
pub struct AchievementCheckTimer(pub Timer);
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
pub struct RaceState {
|
||||||
|
pub initialized: bool,
|
||||||
|
pub started: bool,
|
||||||
|
pub start_countdown: f64,
|
||||||
|
pub timeout: f64,
|
||||||
|
pub score: u64,
|
||||||
|
}
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct RaceTarget;
|
||||||
|
|
||||||
#[derive(Event)]
|
#[derive(Event)]
|
||||||
pub enum AchievementEvent {
|
pub enum AchievementEvent {
|
||||||
|
@ -155,13 +170,35 @@ impl Cycle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(mut settings: ResMut<Settings>, prefs: ResMut<var::Preferences>) {
|
pub fn setup(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut settings: ResMut<Settings>,
|
||||||
|
prefs: ResMut<var::Preferences>,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
) {
|
||||||
settings.hud_active = prefs.augmented_reality;
|
settings.hud_active = prefs.augmented_reality;
|
||||||
settings.radio_mode = prefs.radio_station;
|
settings.radio_mode = prefs.radio_station;
|
||||||
settings.set_noise_cancellation_mode(prefs.noise_cancellation_mode);
|
settings.set_noise_cancellation_mode(prefs.noise_cancellation_mode);
|
||||||
settings.third_person = prefs.third_person;
|
settings.third_person = prefs.third_person;
|
||||||
settings.shadows_sun = prefs.shadows_sun;
|
settings.shadows_sun = prefs.shadows_sun;
|
||||||
settings.ar_avatar = prefs.avatar;
|
settings.ar_avatar = prefs.avatar;
|
||||||
|
|
||||||
|
// Setup Race
|
||||||
|
let mut entitycmd = commands.spawn((
|
||||||
|
RaceTarget,
|
||||||
|
actor::OrbitsJupiter,
|
||||||
|
bevy::pbr::NotShadowCaster,
|
||||||
|
bevy::pbr::NotShadowReceiver,
|
||||||
|
Position::default(),
|
||||||
|
actor::WantsToLookAt(cmd::ID_SPECIAL_PLAYERCAM.to_string()),
|
||||||
|
LinearVelocity::default(),
|
||||||
|
SpatialBundle {
|
||||||
|
transform: Transform::from_scale(Vec3::splat(RACE_TARGET_RADIUS as f32)),
|
||||||
|
visibility: Visibility::Hidden,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
));
|
||||||
|
load_asset("marker_race", &mut entitycmd, &*asset_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_game_event(
|
pub fn handle_game_event(
|
||||||
|
@ -678,3 +715,87 @@ fn handle_window_focus(
|
||||||
*local_paused = paused;
|
*local_paused = paused;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_race(
|
||||||
|
mut commands: Commands,
|
||||||
|
time: Res<Time>,
|
||||||
|
mut log: ResMut<hud::Log>,
|
||||||
|
mut settings: ResMut<Settings>,
|
||||||
|
mut race: ResMut<RaceState>,
|
||||||
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
|
q_player: Query<(&Position, &LinearVelocity, &Transform), With<PlayerCamera>>,
|
||||||
|
mut q_racetarget: Query<
|
||||||
|
(Entity, &mut Position, &mut LinearVelocity, &mut Visibility),
|
||||||
|
(With<RaceTarget>, Without<PlayerCamera>),
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
let mut deinitialize = false;
|
||||||
|
if !settings.race_active {
|
||||||
|
if race.initialized {
|
||||||
|
log.warning(format!("Stopped race! Final score: {}", race.score));
|
||||||
|
deinitialize = true;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (player_pos, player_v, player_trans) = if let Ok(val) = q_player.get_single() {
|
||||||
|
val
|
||||||
|
} else {
|
||||||
|
error!("No player found in handle_race!");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let (target_entity, mut target_pos, mut target_v, mut target_vis) =
|
||||||
|
if let Ok(val) = q_racetarget.get_single_mut() {
|
||||||
|
val
|
||||||
|
} else {
|
||||||
|
error!("No race target entity found in handle_race!");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if !deinitialize {
|
||||||
|
let mut spawn_target = false;
|
||||||
|
|
||||||
|
if !race.initialized {
|
||||||
|
log.warning("Time Trial Race START!".to_string());
|
||||||
|
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Honk));
|
||||||
|
race.score = 0;
|
||||||
|
race.initialized = true;
|
||||||
|
spawn_target = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if player_pos.distance(target_pos.0) < RACE_TARGET_RADIUS {
|
||||||
|
race.score += 1;
|
||||||
|
spawn_target = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if spawn_target {
|
||||||
|
race.timeout = time.elapsed_seconds_f64() + 5.0;
|
||||||
|
let difficulty = 2.0 * race.score as f64;
|
||||||
|
let mut delta = DVec3::new(0.0, 0.0, 100.0);
|
||||||
|
delta = (player_trans.rotation * delta.as_vec3()).as_dvec3();
|
||||||
|
delta += DVec3::new(
|
||||||
|
(fastrand::f64() - 0.5) * difficulty,
|
||||||
|
(fastrand::f64() - 0.5) * difficulty,
|
||||||
|
(fastrand::f64() - 0.5) * difficulty,
|
||||||
|
);
|
||||||
|
*target_pos = Position(player_pos.0 + delta);
|
||||||
|
*target_v = *player_v;
|
||||||
|
*target_vis = Visibility::Inherited;
|
||||||
|
commands.entity(target_entity).insert(RigidBody::Kinematic);
|
||||||
|
}
|
||||||
|
|
||||||
|
if race.timeout <= time.elapsed_seconds_f64() {
|
||||||
|
log.warning(format!("GAME OVER! Final score: {}", race.score));
|
||||||
|
deinitialize = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if deinitialize {
|
||||||
|
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::PowerDown));
|
||||||
|
race.initialized = false;
|
||||||
|
settings.race_active = false;
|
||||||
|
*target_vis = Visibility::Hidden;
|
||||||
|
commands.entity(target_entity).remove::<RigidBody>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ pub fn asset_name_to_path(name: &str) -> &'static str {
|
||||||
"whale" => "models/whale.gltf#Scene0",
|
"whale" => "models/whale.gltf#Scene0",
|
||||||
"marker_satellites" => "models/marker_satellites.glb#Scene0",
|
"marker_satellites" => "models/marker_satellites.glb#Scene0",
|
||||||
"marker_planets" => "models/marker_planets.glb#Scene0",
|
"marker_planets" => "models/marker_planets.glb#Scene0",
|
||||||
|
"marker_race" => "models/marker_race.glb#Scene0",
|
||||||
"point_of_interest" => "models/point_of_interest.glb#Scene0",
|
"point_of_interest" => "models/point_of_interest.glb#Scene0",
|
||||||
"metis" => "models/metis.gltf#Scene0",
|
"metis" => "models/metis.gltf#Scene0",
|
||||||
"thebe" => "models/thebe.gltf#Scene0",
|
"thebe" => "models/thebe.gltf#Scene0",
|
||||||
|
|
|
@ -66,6 +66,7 @@ pub enum DeathScreenEvent {
|
||||||
|
|
||||||
pub const MENUDEF: &[(&str, MenuAction, MenuType)] = &[
|
pub const MENUDEF: &[(&str, MenuAction, MenuType)] = &[
|
||||||
("✆ Phone", MenuAction::PhoneCall, MenuType::Always),
|
("✆ Phone", MenuAction::PhoneCall, MenuType::Always),
|
||||||
|
("⊙ Time Trial", MenuAction::Race, MenuType::Always),
|
||||||
("✯ Map\n", MenuAction::ToggleMap, MenuType::Always),
|
("✯ Map\n", MenuAction::ToggleMap, MenuType::Always),
|
||||||
("", MenuAction::ToggleAR, MenuType::Always),
|
("", MenuAction::ToggleAR, MenuType::Always),
|
||||||
("", MenuAction::ChangeARAvatar, MenuType::AROnly),
|
("", MenuAction::ChangeARAvatar, MenuType::AROnly),
|
||||||
|
@ -98,6 +99,7 @@ pub enum MenuType {
|
||||||
pub enum MenuAction {
|
pub enum MenuAction {
|
||||||
ToggleMap,
|
ToggleMap,
|
||||||
ToggleAR,
|
ToggleAR,
|
||||||
|
Race,
|
||||||
ChangeARAvatar,
|
ChangeARAvatar,
|
||||||
ChangePointer,
|
ChangePointer,
|
||||||
ModLightAmp,
|
ModLightAmp,
|
||||||
|
@ -784,6 +786,11 @@ pub fn handle_input(
|
||||||
ew_game.send(GameEvent::SetMenu(Turn::Off));
|
ew_game.send(GameEvent::SetMenu(Turn::Off));
|
||||||
ew_updatemenu.send(UpdateMenuEvent);
|
ew_updatemenu.send(UpdateMenuEvent);
|
||||||
}
|
}
|
||||||
|
MenuAction::Race => {
|
||||||
|
settings.race_active ^= true;
|
||||||
|
ew_game.send(GameEvent::SetMenu(Turn::Off));
|
||||||
|
ew_updatemenu.send(UpdateMenuEvent);
|
||||||
|
}
|
||||||
MenuAction::ResetSettings => {
|
MenuAction::ResetSettings => {
|
||||||
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::PowerDown));
|
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::PowerDown));
|
||||||
*settings = Settings::default();
|
*settings = Settings::default();
|
||||||
|
|
|
@ -104,6 +104,7 @@ pub struct Settings {
|
||||||
pub shadows_sun: bool,
|
pub shadows_sun: bool,
|
||||||
pub shadows_pointlights: bool,
|
pub shadows_pointlights: bool,
|
||||||
pub shadowmap_resolution: usize,
|
pub shadowmap_resolution: usize,
|
||||||
|
pub race_active: bool,
|
||||||
pub large_moons: bool,
|
pub large_moons: bool,
|
||||||
pub key_selectobject: MouseButton,
|
pub key_selectobject: MouseButton,
|
||||||
pub key_zoom: MouseButton,
|
pub key_zoom: MouseButton,
|
||||||
|
@ -251,6 +252,7 @@ impl Default for Settings {
|
||||||
shadows_sun: true,
|
shadows_sun: true,
|
||||||
shadows_pointlights: false,
|
shadows_pointlights: false,
|
||||||
shadowmap_resolution: 2048,
|
shadowmap_resolution: 2048,
|
||||||
|
race_active: false,
|
||||||
large_moons: false,
|
large_moons: false,
|
||||||
key_selectobject: MouseButton::Left,
|
key_selectobject: MouseButton::Left,
|
||||||
key_zoom: MouseButton::Right,
|
key_zoom: MouseButton::Right,
|
||||||
|
|
Loading…
Add table
Reference in a new issue