generalize player into actor

This commit is contained in:
yuni 2024-03-17 23:49:50 +01:00
parent cef6e5cce7
commit f9e76921ec
5 changed files with 160 additions and 122 deletions

124
src/actor.rs Normal file
View file

@ -0,0 +1,124 @@
use bevy::prelude::*;
#[allow(unused)] pub const OXYGEN_USE_KG_PER_S: f32 = 1e-5;
#[allow(unused)] pub const OXY_S: f32 = OXYGEN_USE_KG_PER_S;
#[allow(unused)] pub const OXY_M: f32 = OXYGEN_USE_KG_PER_S * 60.0;
#[allow(unused)] pub const OXY_H: f32 = OXYGEN_USE_KG_PER_S * 60.0 * 60.0;
#[allow(unused)] pub const OXY_D: f32 = OXYGEN_USE_KG_PER_S * 60.0 * 60.0 * 24.0;
pub struct ActorPlugin;
impl Plugin for ActorPlugin {
fn build(&self, app: &mut App) {
app.add_systems(FixedUpdate, update);
}
}
#[derive(Component)]
pub struct Actor {
pub hp: f32,
pub m: f32, // mass
pub pos: Vec3, // position
pub v: Vec3, // velocity
// TODO: rotation
}
impl Default for Actor {
fn default() -> Self {
Self {
hp: 100.0,
m: 100.0,
pos: Vec3::ZERO,
v: Vec3::ZERO,
}
}
}
#[derive(Component)]
pub struct LifeForm {
pub adrenaline: f32,
pub adrenaline_baseline: f32,
pub adrenaline_jolt: f32,
}
impl Default for LifeForm { fn default() -> Self { Self {
adrenaline: 0.3,
adrenaline_baseline: 0.3,
adrenaline_jolt: 0.0,
}}}
#[derive(Component)]
pub struct Suit {
pub oxygen: f32,
pub power: f32,
pub oxygen_max: f32,
pub power_max: f32,
}
impl Default for Suit { fn default() -> Self { SUIT_SIMPLE } }
const SUIT_SIMPLE: Suit = Suit {
power: 1e5,
power_max: 1e5,
oxygen: OXY_D,
oxygen_max: OXY_D,
};
pub fn update(
time: Res<Time>,
mut query: Query<(&mut LifeForm, &mut Suit)>,
) {
let d = time.delta_seconds();
for (mut lifeform, mut suit) in query.iter_mut() {
if lifeform.adrenaline_jolt.abs() > 1e-3 {
lifeform.adrenaline_jolt *= 0.99;
}
else {
lifeform.adrenaline_jolt = 0.0
}
lifeform.adrenaline = (lifeform.adrenaline - 0.0001 + lifeform.adrenaline_jolt * 0.01).clamp(0.0, 1.0);
suit.oxygen = (suit.oxygen - OXY_S*d).clamp(0.0, 1.0);
}
}
#[derive(Component)]
pub struct Player;
//pub enum SuitSystemHandler {
// Heat,
// None,
//}
//#[derive(Component)]
//pub struct SuitSystem {
// pub name: String,
// pub active: bool,
// pub power: f32,
// pub handler: SuitSystemHandler,
//}
//
//impl Default for SuitSystem {
// fn default() -> Self {
// Self {
// name: "Untitled".to_string(),
// active: true,
// power: 0.0,
// handler: SuitSystemHandler::None,
// }
// }
//}
//pub fn setup(
// mut commands: Commands,
// settings: Res<settings::Settings>,
//) {
// commands.spawn((
// Player,
// SuitSystem {
// name: "HUD".to_string(),
// active: settings.hud_active,
// power: -0.05,
// ..default()
// },
// SuitSystem {
// name: "Heater".to_string(),
// handler: SuitSystemHandler::Heat,
// ..default()
// }
// ));
//}

View file

@ -1,12 +1,12 @@
use crate::{settings, player}; use crate::{settings, actor};
use bevy::prelude::*; use bevy::prelude::*;
use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}; use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin};
const HUD_REFRESH_TIME: f32 = 0.5; const HUD_REFRESH_TIME: f32 = 0.5;
const FONT: &str = "tmp/fonts/NotoSansSC-Thin.ttf"; const FONT: &str = "tmp/fonts/NotoSansSC-Thin.ttf";
pub struct OutFlyHudPlugin; pub struct HudPlugin;
impl Plugin for OutFlyHudPlugin { impl Plugin for HudPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Startup, setup); app.add_systems(Startup, setup);
app.add_systems(Update, (update, handle_input)); app.add_systems(Update, (update, handle_input));
@ -115,11 +115,14 @@ fn setup(
fn update( fn update(
diagnostics: Res<DiagnosticsStore>, diagnostics: Res<DiagnosticsStore>,
time: Res<Time>, time: Res<Time>,
playervars:Res<player::PlayerVars>, player: Query<(&actor::Suit, &actor::LifeForm), With<actor::Player>>,
mut timer: ResMut<FPSUpdateTimer>, mut timer: ResMut<FPSUpdateTimer>,
mut query: Query<&mut Text, With<GaugesText>>, mut query: Query<&mut Text, With<GaugesText>>,
) { ) {
if timer.0.tick(time.delta()).just_finished() { if timer.0.tick(time.delta()).just_finished() {
let player = player.get_single();
if player.is_ok() {
let (suit, lifeform) = player.unwrap();
for mut text in &mut query { for mut text in &mut query {
if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) { if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
if let Some(value) = fps.smoothed() { if let Some(value) = fps.smoothed() {
@ -127,15 +130,17 @@ fn update(
text.sections[1].value = format!("{value:.0}"); text.sections[1].value = format!("{value:.0}");
} }
} }
let power = playervars.power; let power = suit.power;
text.sections[3].value = format!("{power:}Wh"); text.sections[3].value = format!("{power:}Wh");
let oxygen = playervars.oxygen * 100.0; let oxy_percent = suit.oxygen / suit.oxygen_max * 100.0;
text.sections[5].value = format!("{oxygen:.1}%"); let oxy_total = suit.oxygen * 1e6;
let adrenaline = playervars.adrenaline * 990.0 + 10.0; text.sections[5].value = format!("{oxy_percent:.1}% [{oxy_total:.0}mg]");
let adrenaline = lifeform.adrenaline * 990.0 + 10.0;
text.sections[7].value = format!("{adrenaline:.0}pg/mL"); text.sections[7].value = format!("{adrenaline:.0}pg/mL");
} }
} }
} }
}
fn handle_input( fn handle_input(
keyboard_input: Res<ButtonInput<KeyCode>>, keyboard_input: Res<ButtonInput<KeyCode>>,

View file

@ -1,9 +1,9 @@
mod audio; mod audio;
mod player;
mod camera; mod camera;
mod world; mod world;
mod settings; mod settings;
mod hud; mod hud;
mod actor;
use bevy::window::{Window, WindowMode, PrimaryWindow, CursorGrabMode }; use bevy::window::{Window, WindowMode, PrimaryWindow, CursorGrabMode };
use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}; use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
@ -14,29 +14,24 @@ fn main() {
.add_systems(Startup, ( .add_systems(Startup, (
setup, setup,
audio::setup, audio::setup,
player::setup,
world::setup, world::setup,
)) ))
.add_systems(Update, ( .add_systems(Update, (
handle_input, handle_input,
player::handle_input,
audio::toggle_bgm, audio::toggle_bgm,
world::asset_loaded.after(world::load_cubemap_asset), world::asset_loaded.after(world::load_cubemap_asset),
)) ))
.add_systems(FixedUpdate, (
player::drain_resources,
))
.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
.add_plugins(( .add_plugins((
camera::CameraControllerPlugin, camera::CameraControllerPlugin,
hud::OutFlyHudPlugin, hud::HudPlugin,
actor::ActorPlugin,
)) ))
.add_plugins(( .add_plugins((
FrameTimeDiagnosticsPlugin, FrameTimeDiagnosticsPlugin,
LogDiagnosticsPlugin::default(), LogDiagnosticsPlugin::default(),
)) ))
.insert_resource(settings::Settings::default()) .insert_resource(settings::Settings::default())
.insert_resource(player::PlayerVars::default())
.run(); .run();
} }

View file

@ -1,91 +1,6 @@
use crate::settings;
use bevy::prelude::*; use bevy::prelude::*;
use bevy::window::PrimaryWindow; use bevy::window::PrimaryWindow;
#[derive(Component)]
pub struct Player {
pub hp: f32,
pub pos: Vec3,
pub v: Vec3,
}
impl Default for Player {
fn default() -> Self {
Self {
hp: 100.0,
pos: Vec3::ZERO,
v: Vec3::ZERO,
}
}
}
pub enum SuitSystemHandler {
Heat,
None,
}
#[derive(Component)]
pub struct PlayerEntity;
#[derive(Component)]
pub struct SuitSystem {
pub name: String,
pub active: bool,
pub power: f32,
pub handler: SuitSystemHandler,
}
impl Default for SuitSystem {
fn default() -> Self {
Self {
name: "Untitled".to_string(),
active: true,
power: 0.0,
handler: SuitSystemHandler::None,
}
}
}
#[derive(Resource)]
pub struct PlayerVars {
pub oxygen: f32,
pub adrenaline: f32,
pub adrenaline_jolt: f32,
pub power: f32,
}
impl Default for PlayerVars {
fn default() -> Self {
Self {
oxygen: 0.1984,
adrenaline: 0.1,
adrenaline_jolt: 0.5,
power: 6200.0,
}
}
}
pub fn setup(
mut commands: Commands,
settings: Res<settings::Settings>,
) {
commands.spawn(Player::default());
commands.spawn((
PlayerEntity,
SuitSystem {
name: "HUD".to_string(),
active: settings.hud_active,
power: -0.05,
..default()
},
SuitSystem {
name: "Heater".to_string(),
handler: SuitSystemHandler::Heat,
..default()
}
));
}
pub fn handle_input( pub fn handle_input(
keyboard_input: Res<ButtonInput<KeyCode>>, keyboard_input: Res<ButtonInput<KeyCode>>,
mut windows: Query<&mut Window, With<PrimaryWindow>>, mut windows: Query<&mut Window, With<PrimaryWindow>>,
@ -104,15 +19,3 @@ pub fn handle_input(
} }
} }
pub fn drain_resources(
mut playervars:ResMut<PlayerVars>,
) {
if playervars.adrenaline_jolt.abs() > 1e-3 {
playervars.adrenaline_jolt *= 0.99;
}
else {
playervars.adrenaline_jolt = 0.0
}
playervars.adrenaline = (playervars.adrenaline - 0.0001 + playervars.adrenaline_jolt * 0.01).clamp(0.0, 1.0);
playervars.oxygen = (playervars.oxygen - 0.000001).clamp(0.0, 1.0);
}

View file

@ -1,4 +1,4 @@
use crate::camera; use crate::{actor, camera};
use bevy::prelude::*; use bevy::prelude::*;
use bevy::core_pipeline::Skybox; use bevy::core_pipeline::Skybox;
use bevy::asset::LoadState; use bevy::asset::LoadState;
@ -22,6 +22,17 @@ pub fn setup(
mut ambient_light: ResMut<AmbientLight>, mut ambient_light: ResMut<AmbientLight>,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
) { ) {
// Add player
commands.spawn((
actor::Player,
actor::Actor::default(),
actor::LifeForm::default(),
actor::Suit {
oxygen: actor::OXY_M,
..default()
}
));
// Add skybox // Add skybox
let skybox_handle = asset_server.load(CUBEMAP_PATH); let skybox_handle = asset_server.load(CUBEMAP_PATH);
commands.spawn(( commands.spawn((