first_person/
first_person.rs

1use macroquad::prelude::*;
2// use glam::vec3;
3
4const MOVE_SPEED: f32 = 0.1;
5const LOOK_SPEED: f32 = 0.1;
6
7fn conf() -> Conf {
8    Conf {
9        window_title: String::from("Macroquad"),
10        window_width: 1260,
11        window_height: 768,
12        fullscreen: false,
13        ..Default::default()
14    }
15}
16
17#[macroquad::main(conf)]
18async fn main() {
19    let mut x = 0.0;
20    let mut switch = false;
21    let bounds = 8.0;
22
23    let world_up = vec3(0.0, 1.0, 0.0);
24    let mut yaw: f32 = 1.18;
25    let mut pitch: f32 = 0.0;
26
27    let mut front = vec3(
28        yaw.cos() * pitch.cos(),
29        pitch.sin(),
30        yaw.sin() * pitch.cos(),
31    )
32    .normalize();
33    let mut right = front.cross(world_up).normalize();
34    let mut up = right.cross(front).normalize();
35
36    let mut position = vec3(0.0, 1.0, 0.0);
37    let mut last_mouse_position: Vec2 = mouse_position().into();
38
39    let mut grabbed = true;
40    set_cursor_grab(grabbed);
41    show_mouse(false);
42
43    loop {
44        let delta = get_frame_time();
45
46        if is_key_pressed(KeyCode::Escape) {
47            break;
48        }
49        if is_key_pressed(KeyCode::Tab) {
50            grabbed = !grabbed;
51            set_cursor_grab(grabbed);
52            show_mouse(!grabbed);
53        }
54
55        if is_key_down(KeyCode::Up) {
56            position += front * MOVE_SPEED;
57        }
58        if is_key_down(KeyCode::Down) {
59            position -= front * MOVE_SPEED;
60        }
61        if is_key_down(KeyCode::Left) {
62            position -= right * MOVE_SPEED;
63        }
64        if is_key_down(KeyCode::Right) {
65            position += right * MOVE_SPEED;
66        }
67
68        let mouse_position: Vec2 = mouse_position().into();
69        let mouse_delta = mouse_position - last_mouse_position;
70
71        last_mouse_position = mouse_position;
72
73        if grabbed {
74            yaw += mouse_delta.x * delta * LOOK_SPEED;
75            pitch += mouse_delta.y * delta * -LOOK_SPEED;
76
77            pitch = if pitch > 1.5 { 1.5 } else { pitch };
78            pitch = if pitch < -1.5 { -1.5 } else { pitch };
79
80            front = vec3(
81                yaw.cos() * pitch.cos(),
82                pitch.sin(),
83                yaw.sin() * pitch.cos(),
84            )
85            .normalize();
86
87            right = front.cross(world_up).normalize();
88            up = right.cross(front).normalize();
89
90            x += if switch { 0.04 } else { -0.04 };
91            if x >= bounds || x <= -bounds {
92                switch = !switch;
93            }
94        }
95
96        clear_background(LIGHTGRAY);
97
98        // Going 3d!
99
100        set_camera(&Camera3D {
101            position: position,
102            up: up,
103            target: position + front,
104            ..Default::default()
105        });
106
107        draw_grid(20, 1., BLACK, GRAY);
108
109        draw_line_3d(
110            vec3(x, 0.0, x),
111            vec3(5.0, 5.0, 5.0),
112            Color::new(1.0, 1.0, 0.0, 1.0),
113        );
114
115        draw_cube_wires(vec3(0., 1., -6.), vec3(2., 2., 2.), GREEN);
116        draw_cube_wires(vec3(0., 1., 6.), vec3(2., 2., 2.), BLUE);
117        draw_cube_wires(vec3(2., 1., 2.), vec3(2., 2., 2.), RED);
118
119        // Back to screen space, render some text
120
121        set_default_camera();
122        draw_text("First Person Camera", 10.0, 20.0, 30.0, BLACK);
123
124        draw_text(
125            format!("X: {} Y: {}", mouse_position.x, mouse_position.y).as_str(),
126            10.0,
127            48.0 + 18.0,
128            30.0,
129            BLACK,
130        );
131        draw_text(
132            format!("Press <TAB> to toggle mouse grab: {grabbed}").as_str(),
133            10.0,
134            48.0 + 42.0,
135            30.0,
136            BLACK,
137        );
138
139        next_frame().await
140    }
141}