Move continously
Description
The current camera controls move by a fixed amount each time you press a key. This lets us change the view, but is far from a smooth experience.
This change will continue moving the camera while a key is pressed. Rather than updating the camera position directly on each key event, it sets the camera velocity. The velocity will update the position every frame as long as the user is holding down the key. We now listen for key release events to know when to reset the velocity.
One important change is the control flow for the event loop. Previously, we would only do react if an event came in (e.g. a key press). Now we need to update the camera position every frame, even if the keyboard state hasn't changed.
Changing the control flow to polling means if there are no events, we'll
receive MainEventsCleared. Here we can run world.update
to update
the camera position and redraw the frame.
Note that the RedrawRequested event is still used when the window is resized, so we'll keep that handler and adjust the viewport and aspect ratio when it happens.
Also, since we're continously redrawing we no longer need to explicitly request a redraw action.
Screenshot
Commands
git clone git@github.com:atsheehan/iridium
cd iridium
git checkout d203fcb11b7d43725a376d7f60aa21152b530ae4
cargo run --release
Code Changes
Modified src/main.rsGitHub
@@ -5,7 +5,7 @@55 use render::Renderer;
66 use winit::{
77 event::{ElementState, Event, KeyEvent, WindowEvent},
8- event_loop::EventLoop,
8+ event_loop::{ControlFlow, EventLoop},
99 keyboard::{KeyCode, PhysicalKey},
1010 };
1111 use world::World;
@@ -18,6 +18,7 @@1818
1919 let mut world = World::new(20, 20);
2020
21+ event_loop.set_control_flow(ControlFlow::Poll);
2122 event_loop
2223 .run(move |event, window_target| match event {
2324 Event::WindowEvent {
@@ -40,25 +41,57 @@4041 window_id,
4142 } if window_id == renderer.window_id() => {
4243 match (state, physical_key) {
43- (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyW)) => world.move_forward(),
44- (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyS)) => world.move_backward(),
45- (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyA)) => world.move_left(),
46- (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyD)) => world.move_right(),
47- (ElementState::Pressed, PhysicalKey::Code(KeyCode::Space)) => world.move_up(),
48- (ElementState::Pressed, PhysicalKey::Code(KeyCode::ControlLeft)) => world.move_down(),
44+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyW)) => {
45+ world.start_moving_forward()
46+ }
47+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyS)) => {
48+ world.start_moving_backward()
49+ }
50+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyA)) => {
51+ world.start_moving_left()
52+ }
53+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyD)) => {
54+ world.start_moving_right()
55+ }
56+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::Space)) => {
57+ world.start_moving_up()
58+ }
59+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::ControlLeft)) => {
60+ world.start_moving_down()
61+ }
62+ (ElementState::Released, PhysicalKey::Code(KeyCode::KeyW)) => {
63+ world.stop_moving_forward()
64+ }
65+ (ElementState::Released, PhysicalKey::Code(KeyCode::KeyS)) => {
66+ world.stop_moving_backward()
67+ }
68+ (ElementState::Released, PhysicalKey::Code(KeyCode::KeyA)) => {
69+ world.stop_moving_left()
70+ }
71+ (ElementState::Released, PhysicalKey::Code(KeyCode::KeyD)) => {
72+ world.stop_moving_right()
73+ }
74+ (ElementState::Released, PhysicalKey::Code(KeyCode::Space)) => {
75+ world.stop_moving_up()
76+ }
77+ (ElementState::Released, PhysicalKey::Code(KeyCode::ControlLeft)) => {
78+ world.stop_moving_down()
79+ }
4980 (ElementState::Pressed, PhysicalKey::Code(KeyCode::Escape)) => {
5081 window_target.exit();
5182 }
5283 _ => {}
5384 };
54-
55- renderer.redraw();
5685 }
5786 Event::WindowEvent {
5887 event: WindowEvent::RedrawRequested,
5988 window_id,
6089 } if window_id == renderer.window_id() => {
6190 renderer.set_viewport();
91+ }
92+ Event::AboutToWait => {
93+ world.update();
94+
6295 renderer.set_camera(world.camera());
6396 renderer.clear();
6497
@@ -5,7 +5,7 @@5 use render::Renderer;
6 use winit::{
7 event::{ElementState, Event, KeyEvent, WindowEvent},
8- event_loop::EventLoop,
9 keyboard::{KeyCode, PhysicalKey},
10 };
11 use world::World;
@@ -18,6 +18,7 @@18
19 let mut world = World::new(20, 20);
20
21 event_loop
22 .run(move |event, window_target| match event {
23 Event::WindowEvent {
@@ -40,25 +41,57 @@40 window_id,
41 } if window_id == renderer.window_id() => {
42 match (state, physical_key) {
43- (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyW)) => world.move_forward(),
44- (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyS)) => world.move_backward(),
45- (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyA)) => world.move_left(),
46- (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyD)) => world.move_right(),
47- (ElementState::Pressed, PhysicalKey::Code(KeyCode::Space)) => world.move_up(),
48- (ElementState::Pressed, PhysicalKey::Code(KeyCode::ControlLeft)) => world.move_down(),
49 (ElementState::Pressed, PhysicalKey::Code(KeyCode::Escape)) => {
50 window_target.exit();
51 }
52 _ => {}
53 };
54-
55- renderer.redraw();
56 }
57 Event::WindowEvent {
58 event: WindowEvent::RedrawRequested,
59 window_id,
60 } if window_id == renderer.window_id() => {
61 renderer.set_viewport();
62 renderer.set_camera(world.camera());
63 renderer.clear();
64
@@ -5,7 +5,7 @@5 use render::Renderer;
6 use winit::{
7 event::{ElementState, Event, KeyEvent, WindowEvent},
8+ event_loop::{ControlFlow, EventLoop},
9 keyboard::{KeyCode, PhysicalKey},
10 };
11 use world::World;
@@ -18,6 +18,7 @@18
19 let mut world = World::new(20, 20);
20
21+ event_loop.set_control_flow(ControlFlow::Poll);
22 event_loop
23 .run(move |event, window_target| match event {
24 Event::WindowEvent {
@@ -40,25 +41,57 @@41 window_id,
42 } if window_id == renderer.window_id() => {
43 match (state, physical_key) {
44+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyW)) => {
45+ world.start_moving_forward()
46+ }
47+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyS)) => {
48+ world.start_moving_backward()
49+ }
50+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyA)) => {
51+ world.start_moving_left()
52+ }
53+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::KeyD)) => {
54+ world.start_moving_right()
55+ }
56+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::Space)) => {
57+ world.start_moving_up()
58+ }
59+ (ElementState::Pressed, PhysicalKey::Code(KeyCode::ControlLeft)) => {
60+ world.start_moving_down()
61+ }
62+ (ElementState::Released, PhysicalKey::Code(KeyCode::KeyW)) => {
63+ world.stop_moving_forward()
64+ }
65+ (ElementState::Released, PhysicalKey::Code(KeyCode::KeyS)) => {
66+ world.stop_moving_backward()
67+ }
68+ (ElementState::Released, PhysicalKey::Code(KeyCode::KeyA)) => {
69+ world.stop_moving_left()
70+ }
71+ (ElementState::Released, PhysicalKey::Code(KeyCode::KeyD)) => {
72+ world.stop_moving_right()
73+ }
74+ (ElementState::Released, PhysicalKey::Code(KeyCode::Space)) => {
75+ world.stop_moving_up()
76+ }
77+ (ElementState::Released, PhysicalKey::Code(KeyCode::ControlLeft)) => {
78+ world.stop_moving_down()
79+ }
80 (ElementState::Pressed, PhysicalKey::Code(KeyCode::Escape)) => {
81 window_target.exit();
82 }
83 _ => {}
84 };
85 }
86 Event::WindowEvent {
87 event: WindowEvent::RedrawRequested,
88 window_id,
89 } if window_id == renderer.window_id() => {
90 renderer.set_viewport();
91+ }
92+ Event::AboutToWait => {
93+ world.update();
94+
95 renderer.set_camera(world.camera());
96 renderer.clear();
97
Modified src/math.rsGitHub
@@ -3,6 +3,20 @@33 #[derive(Debug, Copy, Clone)]
44 pub(crate) struct Vec3(pub(crate) f32, pub(crate) f32, pub(crate) f32);
55
6+ impl Vec3 {
7+ pub(crate) fn set_x(&self, new_x: f32) -> Vec3 {
8+ Self(new_x, self.1, self.2)
9+ }
10+
11+ pub(crate) fn set_y(&self, new_y: f32) -> Vec3 {
12+ Self(self.0, new_y, self.2)
13+ }
14+
15+ pub(crate) fn set_z(&self, new_z: f32) -> Vec3 {
16+ Self(self.0, self.1, new_z)
17+ }
18+ }
19+
620 impl Add<Vec3> for Vec3 {
721 type Output = Vec3;
822
@@ -3,6 +3,20 @@3 #[derive(Debug, Copy, Clone)]
4 pub(crate) struct Vec3(pub(crate) f32, pub(crate) f32, pub(crate) f32);
5
6 impl Add<Vec3> for Vec3 {
7 type Output = Vec3;
8
@@ -3,6 +3,20 @@3 #[derive(Debug, Copy, Clone)]
4 pub(crate) struct Vec3(pub(crate) f32, pub(crate) f32, pub(crate) f32);
5
6+ impl Vec3 {
7+ pub(crate) fn set_x(&self, new_x: f32) -> Vec3 {
8+ Self(new_x, self.1, self.2)
9+ }
10+
11+ pub(crate) fn set_y(&self, new_y: f32) -> Vec3 {
12+ Self(self.0, new_y, self.2)
13+ }
14+
15+ pub(crate) fn set_z(&self, new_z: f32) -> Vec3 {
16+ Self(self.0, self.1, new_z)
17+ }
18+ }
19+
20 impl Add<Vec3> for Vec3 {
21 type Output = Vec3;
22
Modified src/render.rsGitHub
@@ -187,10 +187,6 @@187187 self.cube_program
188188 .set_uniform_vec3("camera_position", camera.position());
189189 }
190-
191- pub(crate) fn redraw(&mut self) {
192- self.window.request_redraw();
193- }
194190 }
195191
196192 struct ProgramId(GLuint);
@@ -187,10 +187,6 @@187 self.cube_program
188 .set_uniform_vec3("camera_position", camera.position());
189 }
190-
191- pub(crate) fn redraw(&mut self) {
192- self.window.request_redraw();
193- }
194 }
195
196 struct ProgramId(GLuint);
@@ -187,10 +187,6 @@187 self.cube_program
188 .set_uniform_vec3("camera_position", camera.position());
189 }
190 }
191
192 struct ProgramId(GLuint);
Modified src/world.rsGitHub
@@ -1,6 +1,6 @@11 use crate::math::Vec3;
22
3- const MOVE_DISTANCE: f32 = 0.5;
3+ const MOVE_SPEED: f32 = 0.5;
44
55 pub(crate) struct World {
66 x_width: u32,
@@ -12,6 +12,7 @@1212 pub(crate) fn new(x_width: u32, z_depth: u32) -> Self {
1313 let camera = Camera {
1414 position: Vec3(0.0, 0.0, 0.0),
15+ velocity: Vec3(0.0, 0.0, 0.0),
1516 };
1617
1718 Self {
@@ -21,6 +22,10 @@2122 }
2223 }
2324
25+ pub(crate) fn update(&mut self) {
26+ self.camera.position = self.camera.position + self.camera.velocity;
27+ }
28+
2429 pub(crate) fn block_positions(&self) -> impl Iterator<Item = Vec3> {
2530 let x_start = 0;
2631 let x_end = self.x_width;
@@ -31,28 +36,52 @@3136 .flat_map(move |x| (z_start..z_end).map(move |z| Vec3(x as f32, -2.0, z as f32)))
3237 }
3338
34- pub(crate) fn move_forward(&mut self) {
35- self.camera.position = self.camera.position + Vec3(0.0, 0.0, MOVE_DISTANCE);
39+ pub(crate) fn start_moving_forward(&mut self) {
40+ self.camera.velocity = self.camera.velocity.set_z(MOVE_SPEED);
41+ }
42+
43+ pub(crate) fn stop_moving_forward(&mut self) {
44+ self.camera.velocity = self.camera.velocity.set_z(0.0);
45+ }
46+
47+ pub(crate) fn start_moving_backward(&mut self) {
48+ self.camera.velocity = self.camera.velocity.set_z(-MOVE_SPEED);
49+ }
50+
51+ pub(crate) fn stop_moving_backward(&mut self) {
52+ self.camera.velocity = self.camera.velocity.set_z(0.0);
53+ }
54+
55+ pub(crate) fn start_moving_left(&mut self) {
56+ self.camera.velocity = self.camera.velocity.set_x(-MOVE_SPEED);
57+ }
58+
59+ pub(crate) fn stop_moving_left(&mut self) {
60+ self.camera.velocity = self.camera.velocity.set_x(0.0);
61+ }
62+
63+ pub(crate) fn start_moving_right(&mut self) {
64+ self.camera.velocity = self.camera.velocity.set_x(MOVE_SPEED);
3665 }
3766
38- pub(crate) fn move_backward(&mut self) {
39- self.camera.position = self.camera.position + Vec3(0.0, 0.0, -MOVE_DISTANCE);
67+ pub(crate) fn stop_moving_right(&mut self) {
68+ self.camera.velocity = self.camera.velocity.set_x(0.0);
4069 }
4170
42- pub(crate) fn move_left(&mut self) {
43- self.camera.position = self.camera.position + Vec3(-MOVE_DISTANCE, 0.0, 0.0);
71+ pub(crate) fn start_moving_up(&mut self) {
72+ self.camera.velocity = self.camera.velocity.set_y(MOVE_SPEED);
4473 }
4574
46- pub(crate) fn move_right(&mut self) {
47- self.camera.position = self.camera.position + Vec3(MOVE_DISTANCE, 0.0, 0.0);
75+ pub(crate) fn stop_moving_up(&mut self) {
76+ self.camera.velocity = self.camera.velocity.set_y(0.0);
4877 }
4978
50- pub(crate) fn move_up(&mut self) {
51- self.camera.position = self.camera.position + Vec3(0.0, MOVE_DISTANCE, 0.0);
79+ pub(crate) fn start_moving_down(&mut self) {
80+ self.camera.velocity = self.camera.velocity.set_y(-MOVE_SPEED);
5281 }
5382
54- pub(crate) fn move_down(&mut self) {
55- self.camera.position = self.camera.position + Vec3(0.0, -MOVE_DISTANCE, 0.0);
83+ pub(crate) fn stop_moving_down(&mut self) {
84+ self.camera.velocity = self.camera.velocity.set_y(0.0);
5685 }
5786
5887 pub(crate) fn camera(&self) -> &Camera {
@@ -62,6 +91,7 @@6291
6392 pub(crate) struct Camera {
6493 position: Vec3,
94+ velocity: Vec3,
6595 }
6696
6797 impl Camera {
@@ -1,6 +1,6 @@1 use crate::math::Vec3;
2
3- const MOVE_DISTANCE: f32 = 0.5;
4
5 pub(crate) struct World {
6 x_width: u32,
@@ -12,6 +12,7 @@12 pub(crate) fn new(x_width: u32, z_depth: u32) -> Self {
13 let camera = Camera {
14 position: Vec3(0.0, 0.0, 0.0),
15 };
16
17 Self {
@@ -21,6 +22,10 @@21 }
22 }
23
24 pub(crate) fn block_positions(&self) -> impl Iterator<Item = Vec3> {
25 let x_start = 0;
26 let x_end = self.x_width;
@@ -31,28 +36,52 @@31 .flat_map(move |x| (z_start..z_end).map(move |z| Vec3(x as f32, -2.0, z as f32)))
32 }
33
34- pub(crate) fn move_forward(&mut self) {
35- self.camera.position = self.camera.position + Vec3(0.0, 0.0, MOVE_DISTANCE);
36 }
37
38- pub(crate) fn move_backward(&mut self) {
39- self.camera.position = self.camera.position + Vec3(0.0, 0.0, -MOVE_DISTANCE);
40 }
41
42- pub(crate) fn move_left(&mut self) {
43- self.camera.position = self.camera.position + Vec3(-MOVE_DISTANCE, 0.0, 0.0);
44 }
45
46- pub(crate) fn move_right(&mut self) {
47- self.camera.position = self.camera.position + Vec3(MOVE_DISTANCE, 0.0, 0.0);
48 }
49
50- pub(crate) fn move_up(&mut self) {
51- self.camera.position = self.camera.position + Vec3(0.0, MOVE_DISTANCE, 0.0);
52 }
53
54- pub(crate) fn move_down(&mut self) {
55- self.camera.position = self.camera.position + Vec3(0.0, -MOVE_DISTANCE, 0.0);
56 }
57
58 pub(crate) fn camera(&self) -> &Camera {
@@ -62,6 +91,7 @@62
63 pub(crate) struct Camera {
64 position: Vec3,
65 }
66
67 impl Camera {
@@ -1,6 +1,6 @@1 use crate::math::Vec3;
2
3+ const MOVE_SPEED: f32 = 0.5;
4
5 pub(crate) struct World {
6 x_width: u32,
@@ -12,6 +12,7 @@12 pub(crate) fn new(x_width: u32, z_depth: u32) -> Self {
13 let camera = Camera {
14 position: Vec3(0.0, 0.0, 0.0),
15+ velocity: Vec3(0.0, 0.0, 0.0),
16 };
17
18 Self {
@@ -21,6 +22,10 @@22 }
23 }
24
25+ pub(crate) fn update(&mut self) {
26+ self.camera.position = self.camera.position + self.camera.velocity;
27+ }
28+
29 pub(crate) fn block_positions(&self) -> impl Iterator<Item = Vec3> {
30 let x_start = 0;
31 let x_end = self.x_width;
@@ -31,28 +36,52 @@36 .flat_map(move |x| (z_start..z_end).map(move |z| Vec3(x as f32, -2.0, z as f32)))
37 }
38
39+ pub(crate) fn start_moving_forward(&mut self) {
40+ self.camera.velocity = self.camera.velocity.set_z(MOVE_SPEED);
41+ }
42+
43+ pub(crate) fn stop_moving_forward(&mut self) {
44+ self.camera.velocity = self.camera.velocity.set_z(0.0);
45+ }
46+
47+ pub(crate) fn start_moving_backward(&mut self) {
48+ self.camera.velocity = self.camera.velocity.set_z(-MOVE_SPEED);
49+ }
50+
51+ pub(crate) fn stop_moving_backward(&mut self) {
52+ self.camera.velocity = self.camera.velocity.set_z(0.0);
53+ }
54+
55+ pub(crate) fn start_moving_left(&mut self) {
56+ self.camera.velocity = self.camera.velocity.set_x(-MOVE_SPEED);
57+ }
58+
59+ pub(crate) fn stop_moving_left(&mut self) {
60+ self.camera.velocity = self.camera.velocity.set_x(0.0);
61+ }
62+
63+ pub(crate) fn start_moving_right(&mut self) {
64+ self.camera.velocity = self.camera.velocity.set_x(MOVE_SPEED);
65 }
66
67+ pub(crate) fn stop_moving_right(&mut self) {
68+ self.camera.velocity = self.camera.velocity.set_x(0.0);
69 }
70
71+ pub(crate) fn start_moving_up(&mut self) {
72+ self.camera.velocity = self.camera.velocity.set_y(MOVE_SPEED);
73 }
74
75+ pub(crate) fn stop_moving_up(&mut self) {
76+ self.camera.velocity = self.camera.velocity.set_y(0.0);
77 }
78
79+ pub(crate) fn start_moving_down(&mut self) {
80+ self.camera.velocity = self.camera.velocity.set_y(-MOVE_SPEED);
81 }
82
83+ pub(crate) fn stop_moving_down(&mut self) {
84+ self.camera.velocity = self.camera.velocity.set_y(0.0);
85 }
86
87 pub(crate) fn camera(&self) -> &Camera {
@@ -62,6 +91,7 @@91
92 pub(crate) struct Camera {
93 position: Vec3,
94+ velocity: Vec3,
95 }
96
97 impl Camera {