Camera and user input
If you are familiar with how WGPU works you might know this, but in case you don't, we have been working with 3D! I've tried to simplify some functions to work with 2D but when it comes to the camera I thought it was better to leave some control for developers so they can work with 3D if they want. If you want to go in depth with how the camera works I suggest going through those chapters in Learn WGPU. However, in here I'll just leave it at telling you that our FRUG instance has a property called camera
which is a struct. Such struct contains some properties but the ones you can use to get started are the eye
(a 3D point that defines where the camera is located) and the target
(another 3D point which defines where our camera is looking at).
In this section we'll take a look at how we can move our camera using the arrow keys, for this we'll use the second property that appears in the definition of our update function called input
.
input
is actually WGPU's Input Helper. Check it out if you wish learn more about such functions.
For this let's start by checking if our right key is being held inside our update function and before all the rendering-related lines.
#![allow(unused)] fn main() { let update_function = move |instance: &mut frug::FrugInstance, input: &frug::InputHelper| { // Checking our input if input.key_held(frug::VirtualKeyCode::Right) { // 1. // 2. We'll write something to move our camera in here } // Rendering instance.clear(); instance.add_tex_rect(-0.25, 0.0, 0.5, 0.5, frog_text_idx); instance.update_buffers(); }; }
-
You surely noticed that we wrote something saying
VirtualKeyCode
. FRUG has some components that help use work with theinput
struct, in this case we use that enum to check for the right key. Later on we'll do the same for the left key. -
In there we'll write the code to move our camera
Now, like I mentioned before, our camera struct has the eye
and target
properties, which we'll use to move our camera. Since we want to keep this as 2D as possible we will move both the eye
and target
properties of the camera in the same part and at the same rate. In this case we'll want to move things horizontally, so we'll use the x
property of both of them with the following lines:
#![allow(unused)] fn main() { instance.camera.eye.x -= 0.01; instance.camera.target.x -= 0.01; }
If you run your project you'll notice that when you press the right key our image nicely moves to the right side of the screen. This means that the camera is moving, not the frog itself, yet it creates the illusion that the frog is moving.
Now lets do the same thing for the left, shall we?
#![allow(unused)] fn main() { else if input.key_held(frug::VirtualKeyCode::Left) { instance.camera.eye.x += 0.01; instance.camera.target.x += 0.01; } }
If you run this you'll notice that we now can move things to either side (horizontally), yet you'll probably notice that if you press both of them it moves towards the right side of the screen. This is because we did things in a poor manner. You could implement your own version of this to avoid this, or if you want you can check it out in the platformer example, where things will be a bit better, yet we'll leave it like that for the sake of simplicity in this example.
As always, here's the whole version of the code you should have up until now (don't forget that you should use your own image for the texture!).
use frug; fn main() { let (mut frug_instance, event_loop) = frug::new("My Window"); let img_bytes = include_bytes!("frog.png"); let frog_text_idx = frug_instance.load_texture(img_bytes); let update_function = move |instance: &mut frug::FrugInstance, input: &frug::InputHelper| { // Checking our input if input.key_held(frug::VirtualKeyCode::Right) { instance.camera.eye.x -= 0.01; instance.camera.target.x -= 0.01; } else if input.key_held(frug::VirtualKeyCode::Left) { instance.camera.eye.x += 0.01; instance.camera.target.x += 0.01; } // Rendering instance.clear(); instance.add_tex_rect(-0.25, 0.0, 0.5, 0.5, frog_text_idx); instance.update_buffers(); }; frug_instance.run(event_loop, update_function); }
Now let's check out how to draw custom shapes, shall we?