engine/examples/free_space/src/game.rs

180 lines
5.1 KiB
Rust
Raw Normal View History

2025-03-11 17:58:40 +00:00
use std::collections::HashMap;
2025-03-11 12:49:23 +00:00
use anyhow::Result;
use ecs::*;
2025-03-12 07:19:59 +00:00
use engine::prelude::{
cgmath::{Vector3, Vector4},
*,
};
2025-03-11 12:49:23 +00:00
2025-03-11 17:58:40 +00:00
#[derive(Clone, Copy, Debug)]
struct PlayerEntity(Entity);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Input {
Axis(u8),
Button(Button),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Button {
One,
}
#[derive(Clone, Copy, Debug)]
enum Control {
Throttle,
StrafeHorizontal,
StrafeVertical,
Yaw,
Pitch,
Roll,
PrimaryWeapon,
SecondaryWeapon,
}
#[derive(Clone, Debug)]
2025-03-12 07:19:59 +00:00
struct InputSettings {
2025-03-11 17:58:40 +00:00
mappings: HashMap<(String, Input), Control>,
}
2025-03-12 07:19:59 +00:00
impl Default for InputSettings {
2025-03-11 17:58:40 +00:00
fn default() -> Self {
Self {
mappings: [
(
2025-03-12 07:19:59 +00:00
("Joystick 1".to_string(), Input::Axis(0)),
2025-03-11 17:58:40 +00:00
Control::Throttle,
),
(
2025-03-12 07:19:59 +00:00
("Joystick 1".to_string(), Input::Axis(1)),
2025-03-11 17:58:40 +00:00
Control::StrafeHorizontal,
),
(
2025-03-12 07:19:59 +00:00
("Joystick 1".to_string(), Input::Axis(2)),
2025-03-11 17:58:40 +00:00
Control::StrafeVertical,
),
2025-03-12 07:19:59 +00:00
(("Joystick 1".to_string(), Input::Axis(3)), Control::Pitch),
2025-03-11 17:58:40 +00:00
(
2025-03-12 07:19:59 +00:00
("Joystick 1".to_string(), Input::Button(Button::One)),
2025-03-11 17:58:40 +00:00
Control::PrimaryWeapon,
),
2025-03-12 07:19:59 +00:00
(("Joystick 2".to_string(), Input::Axis(1)), Control::Yaw),
(("Joystick 2".to_string(), Input::Axis(0)), Control::Roll),
2025-03-11 17:58:40 +00:00
(
2025-03-12 07:19:59 +00:00
("Joystick 2".to_string(), Input::Button(Button::One)),
2025-03-11 17:58:40 +00:00
Control::SecondaryWeapon,
),
]
.into_iter()
.collect(),
}
}
}
2025-03-12 07:19:59 +00:00
impl InputSettings {
pub fn map_axis(&self, device_name: impl ToString, axis: u8) -> Option<Control> {
2025-03-11 17:58:40 +00:00
self.mappings
2025-03-12 07:19:59 +00:00
.get(&(device_name.to_string(), Input::Axis(axis)))
2025-03-11 17:58:40 +00:00
.map(|control| *control)
}
}
2025-03-11 12:49:23 +00:00
pub struct Game;
impl Game {
pub fn update(&mut self, _world: &mut World) -> Result<()> {
Ok(())
}
pub fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> {
2025-03-11 17:58:40 +00:00
let player = world.resources.get::<PlayerEntity>();
2025-03-12 07:19:59 +00:00
let (fighter_object, resources) = world.entity_resources(player.0)?;
2025-03-11 17:58:40 +00:00
2025-03-11 12:49:23 +00:00
match event {
2025-03-12 07:19:59 +00:00
EngineEvent::JoystickAxis(joystick, axis_index, value) => {
let normalized = value as f32 * (i16::MAX as f32).recip();
let input_settings = resources.get::<InputSettings>();
let player_control = fighter_object.get_component_mut::<FreeSpaceControl>()?;
if let Some(control) = input_settings.map_axis(joystick.name(), axis_index) {
match control {
Control::Throttle => player_control.set_throttle(normalized),
Control::StrafeHorizontal => {
player_control.set_left_right_strafe(normalized)
}
Control::StrafeVertical => player_control.set_up_down_strafe(normalized),
Control::Yaw => player_control.set_yaw(normalized),
Control::Pitch => player_control.set_pitch(normalized),
Control::Roll => player_control.set_roll(normalized),
Control::PrimaryWeapon => (),
Control::SecondaryWeapon => (),
}
}
2025-03-11 12:49:23 +00:00
}
2025-03-11 17:58:40 +00:00
2025-03-11 12:49:23 +00:00
_ => (),
}
Ok(())
}
}
impl Game {
pub fn setup_updates(world_builder: &mut WorldBuilder) -> Result<()> {
2025-03-11 17:58:40 +00:00
world_builder.add_update(
"player_rotation",
200,
Self::player_orientation,
EmptyFilter,
)?;
2025-03-12 07:19:59 +00:00
world_builder.add_update("camera_position", 1_000, Self::camera_update, EmptyFilter)?;
2025-03-11 17:58:40 +00:00
Ok(())
}
pub fn setup_scene(world: &mut World) -> Result<()> {
let mut fighter = AssetHandler::create(world).create_entity("fighter")?;
fighter.insert_component(FreeSpaceControl::new(FreeSpaceControlSettings::default()));
let player = PlayerEntity(world.add_entity(fighter)?);
world.resources.insert(player);
2025-03-12 07:19:59 +00:00
world.resources.insert(InputSettings::default());
2025-03-11 17:58:40 +00:00
world.commit_entity_changes()
}
}
// updates
impl Game {
fn player_orientation(
world: &mut World,
_entity: Entity,
draw: &mut Draw,
control: &mut FreeSpaceControl,
) -> Result<()> {
2025-03-12 07:19:59 +00:00
control.update(world.now());
draw.set_transform(control.transform())
}
2025-03-11 12:49:23 +00:00
2025-03-12 07:19:59 +00:00
fn camera_update(
world: &mut World,
_entity: Entity,
control: &mut FreeSpaceControl,
) -> Result<()> {
let scene = world.resources.get_mut::<Scene>();
let view = scene.view_mut();
view.camera_mut()
.set_center((control.translation() * Vector4::unit_w()).truncate());
view.camera_mut()
.set_eye_dir(control.rotation() * Vector3::unit_y());
view.update_buffer()
2025-03-11 12:49:23 +00:00
}
}