In this part of the tutorial, we will learn how to move our spaceship! 🚀
You will:
Learn how to send messages to components
Learn how to code a wrap effect using modulo
Learn how to move an object in a direction with cos and sin
Learn how to get a direction from an angle"
Check the video below to see the final result of this section:
Let's start by adding the variables we need in our init function.
The speed variable will define the speed of our spaceship, as its name suggests.
The velocity variable, which is a vector, will represent the spaceship’s velocity.
As you can see here I only wrote vmath.vector3() instead of vmath.vector3(0,0,0) they are exactly the same.
Perfect! Now, go back to the update function and add the code below right after the part that handles the spaceship’s rotation.
This code will allow us to move the spaceship in the direction it is facing.
We declare a local variable direction, which will be a vector3. Then, we need to retrieve the x and y direction values.
For x, we use math.cos, which takes the angle in radians as a parameter. For y, we use math.sin, which also takes the angle in radians.
This is how we convert our angle into a direction vector. Finally, we scale our direction by the movement speed, and just like that, our velocity vector is ready!
Now that we have our velocity vector, all that’s left is to apply it to the game object's position.
So, add the code below right after this step.
We simply retrieve the spaceship’s position using go.get_position(), which is a function for game objects.
Then, we just need to add self.velocity to our position, multiplying everything by delta time to keep the movement proportional to the frame rate.
Finally, we apply the new position to our game object using go.set_position(), which, of course, takes the updated position as a parameter.
Now, if you launch the game, your spaceship should start moving right away. If you press a key, the spaceship should change direction.
Alright, I admit we don’t have full control yet. We want the spaceship to move only when we press the Up key.
So, let's go back to the on_input function to handle the Up action press.
If the Up key press is detected, then input.y will be set to 1.
Now, let’s go back to the update function to take input.y into account and add a condition so that the spaceship moves only if input.y equals 1.
We wrap the code that moves the spaceship with an if statement.
Let’s launch our game!
So now, our spaceship doesn't move right away. We can rotate it and move it forward, but the movement isn't very smooth.
We will add acceleration and deceleration effects so that our spaceship accelerates smoothly and then decelerates gently.
Let’s go back to our init function, and declare the speed variable as 0. Then, add a variable called maxAcceleration, which will be set to 600. This will be the maximum speed of our spaceship.
Now, go to the update function and remove the following code.
Indeed, now we will adjust the speed if we press the Up key on the keyboard.
What we want to do now is increase the spaceship’s speed when we press a key. Then, if no key is pressed but the spaceship’s speed is greater than zero, we will decrement it. This is what we do in the code below.
I check if input.y equals 1. If that's the case, I increase the speed, taking delta time into account, and so on.
Now, launch the game, and the movement should be much smoother! Feel free to decrease or increase maxAcceleration to see the difference.
So?! Have you noticed that our spaceship ends up going way too fast if we keep holding the Up key?
We’ll fix this with a vmath function by using clamp. This function allows us to restrict a value within a defined range.
The first parameter of clamp is the value to restrict, the second is the minimum value, and the third is the maximum value.
If you launch the game again, the spaceship should no longer accelerate indefinitely.
To finish the movement of our spaceship, what if we added a wrap effect? This means ensuring our spaceship is always visible on the screen. If our spaceship goes off the right side, it will reappear on the left. If it goes off the bottom, it will reappear at the top of the screen.
You might think we could use the clamp function from vmath, but no, it won’t work because clamp only restricts a value. So, our spaceship wouldn’t be able to go beyond the limits.
How can we do this then? There are certainly other ways, but we will use the modulo method!
We will do this by creating a function that updates the spaceship's position if it exceeds the width or height of the screen.
Here, we declare at the top of our script a local function, meaning this function only exists within this script.
It takes a position as a parameter, and this function returns a position.
Now, we need to know the height and width of the screen. We can find this information in the game.project file, under the display section.
In our script, we will declare two variables—one for the width and the other for the height.
These variables are constants, meaning that these values should not change.
Now, in the function, write the code below.
We simply calculate the x position modulo the screen width, and similarly for the y position.
If you didn't know how modulo works, I'll explain it simply in my way. And if, even after my explanation, you still don't understand, I encourage you to do your own research.
Modulo returns the remainder of a division. For example, 10 % 3 equals 1 because you can fit 3 into 10 three times (3x3 = 9), and if you subtract 9 from 10, you're left with 1.
Now, if I have x and a maximum value of 10 that x should not exceed: x % 10.
If x is 1, the remainder is 1.
If x is 5, the remainder is 5 because I can't fit 10 into 5.
If x is 10, the remainder is 0 because I've fit 10 into 10, so we return to zero.
If x is 11, the remainder is 1 because I've fit 10 into 11.
Thanks to modulo, you can easily cap values. The formula is simple: initial value % maximum value. However, this works only if you want to cap values to positive numbers.
Now, let's use our function in our script. Go back to the update function and add the following code:
Before passing the new position to the game object, we update the position variable by calling our wrapPosition function and passing the pos variable as a parameter.
Launch your game and admire what you've created!
Now, we will turn off the engine if the player is not moving the spaceship. Go back to the init function and create a new variable.
This variable will allow us to know if the engine is on.
Now, using Defold's messaging system, we can send messages to components to disable them. At the beginning of your init function, add the following code.
We send a message via msg.post to the component effect_spr, and the message is disable.
If you launch your game, you no longer see a trail behind the spaceship. Now, we want to activate it, and we will do this by creating a function. So, declare a new function at the beginning of your script:
This function takes two parameters: the first one is self, which represents the variables specific to our script, and the second one is enable, which will be a boolean variable.
Now let's write the code that will allow us to enable or disable our effect.
We write the following condition: If enable is true but our engine is off, we turn it on. We set self.engineOn to true and send a message to our component. Otherwise, we do the opposite.
Do not launch the game yet, we need to use this function now. Go back to the update function and find the part of the code following the input handling. Then, add the following code.
Indeed, if input.y == 1, it means the player is pressing the key, so we activate the engine. And if it's not the case, we deactivate the engine.
Finally, launch your game once more to see your work in action.
That's the end of this first module! If you've made it this far, give yourself a pat on the back for the effort you've put in. You’ve created a game! And by making this game, you've taken your first steps in Defold!
In the next module, we'll mainly focus on how to us factory and the Defold's collision system. So let's do that in the next lesson.