In this part, we’ll make the ship fire in the direction it’s facing, and make bullets automatically disappear after a short time.
You will learn how to:
Refactor code in Defold
Create separate game object files
Use the factory component to spawn game objects
Create editable properties that can be set in the editor or passed through a factory
First, let’s refactor our project.
Previously, I showed you how to create a game object directly in a collection.
Now, I’ll show you that it’s also possible to create a game object as a separate file in the file tree.
In the main folder, right-click and choose:
New → Game Object
Name the file "ship" and click Create Game Object.
A new file should appear, named "ship.go".
Now go back to the main.collection, select all the components of the spaceship,
right-click and choose Copy.
You can now open the ship.go file. In the Game Object outline, right-click and choose Paste to insert the copied components.
And that’s it! Our Game Object is ready, we just need to add it back into the main collection.
Go back to the main collection and delete the old ship Game Object.
Now right-click on collection and choose Add Game Object File.
Select your ship.go file (the only Game Object file you created), then click OK.
Finally, we need to place it back at position X: 480 and Y: 320.
Open the main atlas file again and add the file laser.png. Create a game object named "laser" and also create a script named "laser".
Now, open the laser game object.
Reduce the sprite’s scale on both the X and Y axes to 0.5, and adjust its rotation on the Z axis to -90 degrees.
Now that our laser game object is ready, it’s time to make use of it.
We want to instantiate a laser shot each time the player presses the space key.
To instantiate game objects in Defold, you need to use the Factory component.
A Factory component allows you to create game objects dynamically during the game’s runtime.
This is useful, for example, to:
Spawn enemies during gameplay
Generate projectiles when the player shoots
Procedurally create decorative objects
Start by opening the ship game object, then add a Factory component to it.
Click the box next to the Prototype section, select the file laser.go, and click OK.
Finally, name the component laser_factory.
👆 By the end, your configuration should look like this.
Now it’s time to use our factory.
To instantiate an object, you need to use the method factory.create().
This method takes several arguments:
The first argument is mandatory, it’s the URL of our component, which is "#laser_factory".
The second argument is optional, it specifies the position where you want to instantiate the object.
There are other arguments as well, but we’ll cover those later.
At the end of your init function, write the following line:
Now, run the game and watch the laser appear at the ship’s position.
What we want is to create the laser in front of the ship, not at its center.
Delete the call to factory.create and instead create a shoot function before the init function.
This way, we can perform the calculations we need and then call the shoot function inside init.
Now, let’s modify the function so that our laser appears in front of the ship.
Take a moment to read through, then write the following code:
Here’s a summary of what our function does:
Retrieve ship information
We get its position (go.get_position()) and the size of its sprite (go.get("#ship_spr", "size")) to know where to place the laser.
Calculate direction
The ship’s angle is converted to radians using math.rad(self.angle) to perform the necessary trigonometric calculations. This is the same calculation we used for moving the ship.
Determine laser position
The laser is generated slightly in front of the ship, at a distance equal to half its height (distance = size_sprite.y / 2), in the direction indicated by its angle.
Create the laser
Finally, we use factory.create() to create the laser game object at the calculated position.
Now run the game, the laser should appear in front of the ship when the application starts.
Now it would be great if we could shoot whenever we press the space key and that’s exactly what we’re going to do!
Open the Input Bindings file and add a new entry for the space key.
Name the action "shoot".
Then, open the script and add the following code:
👆 Note here, in the second if statement, the use of action.pressed.
This ensures that our shoot function is only called once, when the key is initially pressed.
Run the game and shoot as many times as you want.
However, the lasers don’t move yet!
Let’s take care of that problem right away!
Open the laser.script file.
We’re going to declare two new properties using the go.property() method.
This method takes two parameters: the name of the property, and its type.
The allowed data types are:
number, boolean, hash, vector3, vector4, quaternion, and url.
Now go ahead and write the following code:
As you’ve probably noticed, we’ve declared a property for the speed and one for the direction.
If you go back to the game object editor and click on the laser script, you should see the speed and direction properties listed.
What’s great is that we can also modify these properties directly from our factory.create() call.
Now, add an update function and let’s finally code the laser’s movement:
That's great, but we still need to make a few adjustments. We now have to change the direction property when creating our laser.
But what is the purpose of the direction property?
This direction property simply defines the direction in which we want our laser to go.
I'll let you write the following code:
Here we are creating a direction vector. We then get the direction using cos and sin, as usual.
We’ll also make sure to apply the correct rotation to the ship, although this is mainly to introduce you to the vmath.quat_rotation_z() method.
This method simply takes an angle in radians, and that’s it! It returns the correct rotation to apply to our object.
Next, we declare a props table, for the speed and direction, and pass it to our factory.
If you run your game, you'll now be able to shoot in all directions!
That's cool, but there's a problem...
What happens to our bullets? Well, they just float off screen and are never deleted.
So let's take care of that!
Add an init function at the beginning of our script, and create a variable called self.life_time.
This variable will serve as a timer before deleting our bullet.
Now, at the beginning of the update function, add the following code:
Here, we simply decrease our timer using the delta time, and as soon as it is less than or equal to zero, we call the method go.delete().
If you’d like, you can use Defold’s final() function, it’s called just before the object is completely deleted.
You can add something like print("delete") inside it to check in the console each time an object is removed.
And there you go, our ship is now firing in all directions, and the lasers are being properly removed!
Feel free to increase or decrease the life_time if you like.
Great! Now that our ship is able to shoot, in the next Part 2 we’ll learn how to use the collision system and add asteroids that the ship can destroy.