first_person/
first_person.rs1use macroquad::prelude::*;
2const 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 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 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}