Skip to main content

pfx_bench/
game.rs

1use pfx_core::clock::Tick;
2use pfx_input::{ActionSpec, Binding, Input, Key};
3use pfx_load::scene::{Camera, Matrix};
4use pfx_play::{Game, SceneGame, World};
5
6pub const MOVE_SPEED: f32 = 2.0;
7pub const TURN_SPEED: f32 = 60.0;
8
9pub fn actions() -> Vec<ActionSpec> {
10    vec![
11        ActionSpec::axis("walk").key(Binding::keys(Key::S, Key::W)),
12        ActionSpec::axis("strafe").key(Binding::keys(Key::A, Key::D)),
13        ActionSpec::axis("lift").key(Binding::keys(Key::Q, Key::E)),
14        ActionSpec::axis("turn").key(Binding::keys(Key::Left, Key::Right)),
15        ActionSpec::axis("tilt").key(Binding::keys(Key::Down, Key::Up)),
16    ]
17}
18
19fn add(a: [f32; 3], b: [f32; 3], scale: f32) -> [f32; 3] {
20    [
21        a[0] + b[0] * scale,
22        a[1] + b[1] * scale,
23        a[2] + b[2] * scale,
24    ]
25}
26
27fn forward(yaw: f32, pitch: f32) -> [f32; 3] {
28    let (sy, cy) = yaw.sin_cos();
29    let (sp, cp) = pitch.sin_cos();
30    [cp * sy, sp, -cp * cy]
31}
32
33pub struct BenchGame {
34    scene: SceneGame,
35    camera: Option<String>,
36    yaw: f32,
37    pitch: f32,
38}
39
40impl BenchGame {
41    pub fn new(camera: Option<String>) -> Self {
42        Self {
43            scene: SceneGame,
44            camera,
45            yaw: 0.0,
46            pitch: 0.0,
47        }
48    }
49
50    fn aim(&mut self, world: &World) {
51        let camera = world.camera;
52        let (direction, _, _) = camera.axes();
53        self.yaw = direction[0].atan2(-direction[2]);
54        self.pitch = direction[1].clamp(-1.0, 1.0).asin();
55    }
56
57    fn look(&self, world: &mut World) {
58        let at = world.camera.at;
59        world.camera.look_at = add(at, forward(self.yaw, self.pitch), 1.0);
60    }
61}
62
63fn placed(model: Matrix, base: Camera) -> Camera {
64    let at = [model[3][0], model[3][1], model[3][2]];
65    let ahead = [-model[2][0], -model[2][1], -model[2][2]];
66    let up = [model[1][0], model[1][1], model[1][2]];
67    Camera {
68        at,
69        look_at: add(at, ahead, 1.0),
70        up,
71        ..base
72    }
73}
74
75impl Game for BenchGame {
76    fn actions(&self) -> Vec<ActionSpec> {
77        actions()
78    }
79
80    fn start(&mut self, world: &mut World) {
81        self.scene.start(world);
82        if let Some(id) = self.camera.as_deref().and_then(|name| world.object(name)) {
83            world.camera = placed(world.model(id), world.camera);
84        }
85        self.aim(world);
86    }
87
88    fn tick(&mut self, world: &mut World, tick: &Tick, input: &Input) {
89        self.scene.tick(world, tick, input);
90        let dt = tick.dt;
91        let walk = input.action("walk").value;
92        let strafe = input.action("strafe").value;
93        let lift = input.action("lift").value;
94        let turn = input.action("turn").value;
95        let tilt = input.action("tilt").value;
96        if walk == 0.0 && strafe == 0.0 && lift == 0.0 && turn == 0.0 && tilt == 0.0 {
97            return;
98        }
99        self.yaw += (turn * TURN_SPEED * dt).to_radians();
100        self.pitch = (self.pitch + (tilt * TURN_SPEED * dt).to_radians()).clamp(-1.5, 1.5);
101        let (ahead, right, _) = {
102            let mut aimed = world.camera;
103            aimed.look_at = add(aimed.at, forward(self.yaw, self.pitch), 1.0);
104            aimed.axes()
105        };
106        let mut at = world.camera.at;
107        at = add(at, ahead, walk * MOVE_SPEED * dt);
108        at = add(at, right, strafe * MOVE_SPEED * dt);
109        at = add(at, world.camera.up, lift * MOVE_SPEED * dt);
110        world.camera.at = at;
111        self.look(world);
112    }
113
114    fn stop(&mut self) {
115        self.scene.stop();
116    }
117}