Cocos Creator Tutorial: The Cannon 2, Part 2

Shooting Rocks

Philip Shen
7 min readJun 24, 2018

Introduction

Welcome to part 2 of my tutorial on Cocos Creator! In part 1 I covered creating nodes, enabling physics, enabling collisions, and hooking user input. In this part I’m going to cover spawning meteors and having the cannon shoot bullets at them. Let’s get started!

Shooting Bullets

Creating the Prefab

Prefab is short for prefabrication; as the name suggests, it is a resource that is loaded prior to the game running. They are very handy and we’ll use them a lot in this tutorial.

The first thing we’re going to do is create a bullet prefab for our game. The way to do that in Cocos is very simple:

  1. Drag your bullet resource into the scene editor so that it shows up in the node tree
  2. Drag it from the node tree back to your file navigator
  3. That’s it! Once you’ve dragged the prefab into your file navigator, it should appear like this:

Then you can go ahead and delete the bullet from the node tree.

We also need the bullets to collide with other physics colliders. To begin editing it, just double click the prefab in the file navigator so that it appears in the scene editor, and then just we can begin editing it as if it were any other node.

So, as I mentioned earlier, what we need for this bullet is for it to be a physics collider. Go ahead and give it a RigidBody component, and then a PhysicsBoxCollider component––you know the drill.

One thing to note is that while the “bullet” checkbox in the RigidBody component may seem very fitting for our prefab, it’s not necessary. What we do want to do though is to set the “Type” property to “Kinematic” so that it won’t be affected by gravity.

Creating the Bullet Script

Create a Bullet.ts file, add it to our bullet prefab, and let’s get going on that. It’s going to be a very simple file and do nothing except destroy our bullet after a certain amount of time has passed. Here’s the entire file:

Which I don’t think you’ll need any help digesting. Two nice, useful Cocos functions used here are cc.isValid() and node.destroy() , which are pretty self explanatory (read more here).

Instantiating Bullets in Code

Now we’re going to make our cannon actually shoot these bullet prefabs. First, open up Game.ts and let’s add a property for these bullets of ours:

As you can see, we’re declaring it as type cc.Prefab .

Then, add some more math utility functions:

Cocos uses degrees to measure angles, while Javascript’s Math uses radians; these functions should save us some time.

Now we have everything we need to begin making some bullets. In Game.ts, create a function called “createBullet” and make it look something like this:

  1. We use cc.instantiate() to get a node from a prefab
  2. Something a little funky about Cocos is that you use the setPosition() method to set the position, but for the rotation you just change the rotation property. I’m not sure why that is.
  3. This line is important, and it demonstrates how we get the separate components from a node. What it does is get the RigidBody component of the bullet––which, if you recall, we created using the Cocos Creator editor––and allows us to modify it. Here, we set the velocity of the bullet to be relative to the angle and velocity provided.
  4. Finally, we display our node in the game using the addChild() method on the Game node.

All that’s left for you to do now is to make sure the “bullet” property is set to your bullet prefab. Go over to the Cocos editor and do that.

Actually Shooting Bullets

Now, all that’s left to do is shoot the bullets out of the cannon! To do that, we’re going to go back to Cannon.ts and hook more input!

What we’re going to first need to do in Cannon.ts is get a reference it’s parent Game so that it can access the createBullet() method. Doing that is quite simple: (note: I only included the relevant parts of our Cannon.ts file. Don’t go deleting everything else we put into Cannon.ts)

Note 1: you don’t need to import “Game” at the top of the file there in order to make this work; that’s really just a stylistic preference because I like my properties statically typed.

Note 2: Doing this––putting the createBullet() in Game and calling it from Cannon––is pretty ugly. Please don’t take this tutorial as a guide on methodology or anything like that; I’m just trying to show how to do things in Cocos Creator.

Note 3: The cc.find() method searches through the node tree. Make sure you have rename your root node––which may be named “canvas”––to “Game”

Ok, now that Cannon.ts contains a reference to our game, we can access its methods. Let’s begin shooting bullets by calling createBullet() when the spacebar is pressed:

  1. This first part is where we get the position of the end of the barrel, which is where we want to start spawning bullets from. The barrel.getPosition() function gets the position of the barrel’s anchor point (which we set to the base of the barrel, where it meets the cannon body); therefore in order to get the position of the end of the barrel, we have to do the trigonometry above.
  2. This second part introduces an important principle in Cocos: node space vs world space. Simply put, the coordinates of a node in world space are its location on the entire scene (with the origin at the center), which can vary wildly. The coordinates of a node in node space are its location relative to, well itself, with the anchor point serving as the origin. We are trying to create the bullet with its position in respect to the Game node; therefore we must first convert the position of the end of our barrel––which is currently in node space coordinates with respect to the barrel––to world space coordinates.
  3. Then, we convert those world space coordinates back to node space, this time with respect to the Game node. It’s a little confusing, but what we’re essentially doing is using the world space––which is the same for every node––to convert between different node spaces.
  4. Finally, we create the bullet using the position of the end of the barrel as the position, a velocity of 400 (you can make this whatever you want), and an angle equal to the angle of the barrel to make sure the bullet is oriented correctly. You should now be firing bullets!
bang!

Creating Meteors

The next step is to get some meteors on the screen. So that’s what we’re going to do.

Create the Meteor Prefab

We’re going to create the Meteor prefab in the same way we created the bullet prefab, rigid body and physics collider and all. I’ll leave you to do that, but make sure you leave in the following properties:

  1. Check the RigidBody checkbox Enable Contact Listeners so we can trigger callback functions when collisions are detected
  2. Keep the RigidBody type at “Dynamic,” but change the Gravity Scale to 0 so it’s not affected by gravity. This will make it so when the meteor collides with our cannon, it doesn’t push the cannon around.

Then create a Meteor.ts script and add it to our meteor. We can now begin setting coding up our meteor.

Creating Meteors

Now we need to spawn meteors. We’re going to do this in very much the same way as we spawned bullets, excepts rather than setting the position to a known point (i.e. the end of the barrel) we’re going to give the meteors a random position and a random velocity, and them spawn at random time intervals. To do that, add the following code to your Game.ts file:

This code is all pretty straightforward and you should be able to read it by now. First we add all the properties we need for our meteor: the prefab property, minimum and maximum values for our random properties, and so forth. the scheduleCreateMeteor() function sets a random time interval that spawns a meteor after every iteration. Call this method in the start() lifecycle callback function, and meteors should now be spawning!

But as you can see, when the meteors are shot they just get pushed now. We want to destroy those meteors. For that, we’re going to have to edit the Meteor.ts script.

Coding the Meteor Part 1: Self Destruct

We need our meteor to self-destruct after a time interval so that we don’t have a bunch of zombie meteors flying around and taking up memory off screen. Insert the following self-destruct code, which is the same as what we wrote for our bullet, into Meteor.ts:

Coding the Meteor Part 2: Handling Collisions

Next, we need to make sure that when the meteor is shot by a bullet, it gets destroyed. To do that, we’ll be using the collision callbacks.

Remember back to when we made our meteor prefab, and we checked the option Enable Contact Listeners? Well, what that did was trigger callback functions when collisions were detected. These callback functions are going to allow us to destroy the meteor (and the bullet that hits it) when they collide. Add this to your Meteor.ts file:

Pretty simple! That’s all we need to do. You should now be destroying meteors:

Conclusion

That about does it for part 2. We covered prefab creation and instantiation, collision callbacks, and a few other things. In part 3, we’ll touch up our project a bit and make it look nice.

You can view the full code for these tutorials on Github here.

--

--