Tutorial (Godot Engine v3 - GDScript) - Collision Detection!

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@sp33dy·
0.000 HBD
Tutorial (Godot Engine v3 - GDScript) - Collision Detection!
# ![Godot Engine Logo v3 (Competent).png](https://steemitimages.com/DQmenztXPYjpJLwd6Y1rTfWEUX9g5tsYMEhty5PzaKmaFcZ/Godot%20Engine%20Logo%20v3%20(Competent).png)   Tutorial

![](https://steemit-production-imageproxy-thumbnail.s3.amazonaws.com/DQmeRXYK5hTURHD9TqUuGi4vPsockATFzcKFZdawUYpq24B_1680x8400) ...learn how to add Collision Detection!

# What Will I Learn?
This tutorial builds on the last, which explained how to add [Bullets](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-bullets).

In this article, you will learn how to add collisions to the game; allowing for the Invaders and the Player to kill or be killed!
<center>
![Correct Behaviour.gif](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520013622/fogjqchbmnvb5icstklb.gif)
</center>
<centre>Note: the recording method doesn't do justice to the smoothness of this</center>

### Assumptions
> * You have installed [Godot Engine v3.0](https://steemit.com/gamedev/@sp33dy/installing-godot-engine-v3-0-windows)
> * You've completed the previous tutorials
> * You should be familiar with [Scenes](http://docs.godotengine.org/en/3.0/getting_started/step_by_step/scene_tree.html?highlight=scene), [Nodes](http://docs.godotengine.org/en/3.0/getting_started/step_by_step/scenes_and_nodes.html?highlight=nodes), [creating instances](vhttp://docs.godotengine.org/en/3.0/getting_started/step_by_step/instancing.html?highlight=instances) and a basic grasp of [GDScript syntax and documentation](http://docs.godotengine.org/en/3.0/getting_started/scripting/gdscript/index.html?highlight=gdscript)

### You will

* Learn about Collisions (an overview)
* Add a Collision Area to the _Player_ Ship
* Add a Collision Area to the _Invader_ 
* Add a Collision Area to the _Laser_ 
* Learn to connect the Signals!
* Rename Area2D's for object checking
* Learn to enable Debug option to see Collision Areas

# Requirements

You must have installed [Godot Engine v3.0](https://steemit.com/gamedev/@sp33dy/installing-godot-engine-v3-0-windows).

All the code from this tutorial will be provided in a [GitHub repository](https://github.com/sp33dy/Godot-v3-Tutorials-Beginner). I'll explain more about this, towards the end of the tutorial.

----

# Collisions (an overview)

Collisions in Godot Engine are very simple to implement, but requires a lot of practice!

For our game, we are going to utilise the [Area2D](http://docs.godotengine.org/en/3.0/classes/class_area2d.html?highlight=area2d) class, which is designed to be used for 2D collisions. With this, we are going to attach a [CollisionShape2D](http://docs.godotengine.org/en/3.0/classes/class_collisionshape2d.html?highlight=collisionshape2d). 

The shape is defined as an area, not seen, which overlaps an object on the screen; i.e. a Sprite is a great candidate!

The shape can be one of many different shapes, i.e. Circle, Box, Concave, Convex, etc.

<center>
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520007748/mudjsy3wynffg1uhjcnd.png)
</center>

As the object (i.e. Sprite) moves, the Shape remains positioned to it. For example, in the above diagram, the _Player_ Sprite has a triangular Collision Shape assigned to it. As the ship moves, the Shape follows, as it is attached to the child.

> The Shape is NEVER seen; unless it is enabled in debug mode (see the debug section below).

<center>
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520007919/klsjsovwnh10wkeowuql.png)
</center>

When two objects with CollisionShape2D's overlap, a collision is detected and a signal is raised. These are hooked to code, which in turn, responds; such as destroy the _Player_ ship because the _Invader's_ shape (the red circle) enters the _Players_!

Consult the [Godot Area2D documentation](http://docs.godotengine.org/en/3.0/classes/class_area2d.html?highlight=area2d#signals) for a list and description of all the signals available; we're only going to use the 'area_entered'.

# Add a Collision Area to the _Player_ ship
Let's begin by adding a collision shape to the _Player_ ship.

> * Open the _Player_ Scene
> * Create an Area2D node as a child to the root _Player_ sprite:
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520008325/onsp0scdwscdlv1inezs.png)
> You'll note a Yellow triangle appears
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520008362/j1hgzcj4qix25xanust7.png)

> Hover over it and you will see a pop-up informing you that you need to add a Shape!
> * Create a CollisionShape2D as a child to the Area2D:
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520008444/adwgdwbanyfjswfog8kv.png)

> A yellow triangle will show next to the new CollisionShape2D because we need to define the shape itself! Look in the inspector, when you select the CollisionShape2D. Its value will be a null shape
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520008567/wnlk7kylccm0cvqdhpfq.png)

> You need to click on this and select a New Convex Shape (look at the icon to the left of the option, it shows a box with a hat on it)
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520008635/fzerdb5okswg7le2suvp.png)

> Click on the option again and the menu will list an Edit option, select that
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520008686/ixrhgxjxu3jiq2tvcjjd.png)

> Click on the Vector Points option, because we need to set our Vector points 

> (The little right arrow, as highlighted in yellow)
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520008820/zohay4nixgeep4vm7yhy.png)

> Now specify Array Size 3 with the values [(-6,7),(0,-7),(6,7)]
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520009219/qqnbtatv3opbhurubo5f.png)

> As can be seen in the diagram above, you set the Vector array as three points on a Triangle (it is odd that Godot doesn't have a built in a triangle shape in my opinion!). On the left, you can see what should be in your 2D view. The Shape will be seen over your Sprite, even though in the game it is hidden because it is ONLY used to detect collisions with other areas.

Congratulations, you've now added a Collision Area to your _Player_ ship, let's move on and do the same with the _Invader_ and the _Laser_ bullet

## Add a Collision Area to the _Invader_ 
> * Open the _Invader_ Scene
> * Add an Area2D and CollisionShape2D. 
> * This  time, add a Capsule Shape to the _Invader:
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520009745/bvwyvpdgoxv7zqmxpkvp.png)

> As can be seen, the Shape is smaller than the _Invader, therefore we need to resize it! 

> _Note: you may wonder why I chose the Capsule type over a Circular one. We want the shape to fit as snuggly as possible. The _Invader_ sprite is wide and short, thus, the Capsule works best for this sprite._

> Before we change the size, please find the Node2D>Transform>Rotation Degree option of the CollisionShape2D and set it to 90 degrees, thereby placing the curved ends sideways:
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520009953/zncuhk7rr1gz0dgivxnc.png)

> Next, edit the Capsule Shape, setting it to a Radius of 28 and Height of 25 (I only found these by experimenting!)
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520010067/x82urjolyunxfeqoy6gv.png)

> The Shape should now be perfectly placed over your _Invader_ Sprite, like so:
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520010108/nj75vm9gqg6zgumqs2q5.png)

## Add Collision Area to the _Laser_ 
> * Open the _Laser_ Scene
> * Add an Area2D and CollisionShape2D. 
> * Add a rectangle Shape to the _Invader_:
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520010273/osh5kxj2afuwitmarmb0.png)

> As can be seen, the Shape is a lot wider than the _Laser_ but shorter; therefore we need to resize it! 
> Edit the rectangle, setting it to x=5 and y=15:
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520010361/g3vt41xtscoparxo9qhg.png)

> We could have used a Capsule Shape, but the number of points in the shape determines performance! For our purposes, this really isn't relevant, but if we had hundreds of thousands, then it  it might! 

Try running the game now! What happens???

... Did you expect that?

# Connecting the Signals!
Nothing happened! The game played as it did before. 

For those with a good memory, I mentioned earlier that the collisions are detected and a signal is fired! Without us changing the behaviour of our actors to use the signals, nothing happens!

Let's add the first simple case.

> * Open the _Player_ Scene
> * Open the _Player_ script
> * Add the following line to the top of the _ready_ function

    $Area2D.connect("area_entered", self, "hit")

> This locates the child Area2D and tells it to connect the signal to a function; as described in the parameters. 

> 1. The first parameter is the "area_entered" signal that is called by the Collision.
> 2. The second parameter states where to find the third parameter, as a function; i.e. in the same (self) script.
> 3. The name of the function to call

> Thus, when any other Area2D enters the _Players_ Area2D child area, an 'area_entered' signal is triggered which is wired to our _hit_ function. 

> Which has to be added:

    func hit(object):
        	modulate.a = 0.2

> This simply receives the object that was detected hitting the Area2D (not that we use it... yet!).

>  For now, we'll set the alpha of the sprite, thereby dimming it

> _We'll change this code shortly, but for now, this is the easiest way for me to demonstrate the process._

The code looks like this in the editor:

![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520011043/n7silvcfeytzbn1gu75d.png)

Try running it, but do not touch the Spacebar; if you do, you'll notice a bug!

Eventually, the _Invader_ reaches the _Player_ and when one touches, the ship becomes transparent:

![alien to player collision.gif](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520011294/bupr4pxv6xiew2jaih5o.gif)

Did you notice what happens when you press the Spacebar? 

This is the type of issue that will often confuse beginners. It works, but not as expected! 

![press fire.gif](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520011454/qr7izsusnqurtaspcfd8.gif)

As soon as the _Laser_ appears, its Shape collides with the _Player_ ship, because it is launched by it! We need a mechanism to ignore the _Laser_!

## Rename the _Laser_ Area2D
Not the best solution, but one approach is to use the name of the object to determine whether it should be ignored or not. 

I.E. The object passed to the _hit_ function of the _Player_ ship will be the Area2D that collided. If we rename the _Laser's_  Area2D to something unique (rather the generic Area2D name), we can check for its name and ignore it!

> * Open the _Lazer_ Scene
> * Rename the Area2D to _LaserArea_

![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520011912/rlmwvhphwvp9wwf6jhsr.png)

Let's now modify the _Player_ script _hit_ function:

        func hit(object):
        	if object.name != 'LaserArea':
        		modulate.a = 0.2

The function will only change the alpha of the Sprite if something, other than the LaserArea hits it.

Try rerunning! You should find that you can fire at will! Allow the Alien to touch and you will see that they WILL kill the _Player_:

![bullets ok.gif](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520012140/c0v53ilfp6xqplwem72x.gif)

## Connect the _Invader_ to a hit signal!
Let's do the same for the _Invader_ as we did for the _Player_

> * Open the _Invader_ Scene
> * Open the _Invader_ script
> * Add the new _ready_ and _hit_ functions:
    func _ready():
    	$Area2D.connect("area_entered", self, "hit")

    func hit(object):
    	queue_free()

> The _ready_ function connects the _Invader_ child _Area2D_ to this script and wires the 'area_entered' signal to the _hit_ function
> The _hit_ function instructs Godot Engine to remove the Instance from the tree before the next frame (i.e. remove it from the screen and game)!

You can now dispatch those pesky _Invaders_:

![destroying invaders.gif](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520012781/rl5llmyhj5xik52jjdow.gif)

... BUT, that was WAY too easy... Why???

## Set the _Laser_ signal processing!
The _Laser_ bullet didn't stop when it hit the first _Invader_! It continues to wipe out anything else that it hits before going off the screen! This is bad but can be easily fixed. Can you think how???

Before adding the code to the _Laser_ script, we need to think:

> * When the _Laser_ is fired by the _Player_ ship it will detect it
> * The _Laser_ node should only be removed when it hits an _Invader_

Given this, we need to modify the name of the Area2D of the _Invader_, so that the _Laser_ script can use its name (much like we did with the _Player_ and _Laser_)

> * Open the _Invader_ Scene
> * Rename the Area2D to InvaderArea:
![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520013034/a8exoakrliv29nfy7f40.png)
> * By changing the Area2D, you will need to open the _Invader_ script and modify the _ready_ method:

    func _ready():
    	$InvaderArea.connect("area_entered", self, "hit")

> Previously, the connect was on the $Area2D, but this has now been renamed to $InvaderArea! See how making changes to the Nodes in the Scene Tree can affect your code!

> * Open the _Laser_ script and add the following two new functions:

    func _ready():
     	$LaserArea.connect("area_entered", self, "hit")

    func hit(object):
     	if object.name == 'InvaderArea':
     		queue_free()

> The _ready_ function finds the child _LaserArea_ and connects its "area_entered" signal to the scripts _hit_ function
> The _hit_ function checks whether the object that is touching is an _InvaderArea_, freeing itself from the tree and the game if true.

The behaviour is now correct:
![Correct Behaviour.gif](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520013622/fogjqchbmnvb5icstklb.gif)


# Finally

That concludes this issue. My next article will address colour selections! 

Don't forget to check out the game on [itch.io](https://sp33dy.itch.io/alien-invaders). I'm publishing the game in advance of tutorials, so it is worth you checking it out periodically! You'll be able to guess what is coming up in my posts!

Please do comment and ask questions! I'm more than happy to interact with you.

# Sample Project

I hope you've read through this Tutorial, as it will provide you with the hands-on skills that you simply can't learn from downloading the sample set of code. 

However, for those wanting the code, please download from [GitHub](https://github.com/sp33dy/Godot-v3-Tutorials-Beginner).

You should then Import the "Space Invaders (part 7)" folder into Godot Engine.

# Other Tutorials

#### Beginners

> * [Install Godot Engine 3.0](https://steemit.com/gamedev/@sp33dy/installing-godot-engine-v3-0-windows)
> * [Installing your First Demo](https://steemit.com/gamedev/@sp33dy/first-demo-godot-engine-v3-0)
> * [Your first Sprite!](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-your-first-moving-sprite)
> * [Move your first Sprite!](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-move-your-sprite)
> * [Create lots of Sprites!](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-create-lots-of-sprites)
> * [Sprite formations!](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-sprite-formations)
> * [Smooth Movement!](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-smooth-movement#comments)
> * [Invader Graphics!](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-invader-graphics)
> * [Player Ship!](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-player-ship)
> * [Bullets](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-bullets)

#### Competent

> * [Custom TileMaps](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-custom-tilemap)
> * [Custom TileMap Scrolling](https://steemit.com/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-custom-tilemap-scrolling)

<br /><hr/><em>Posted on <a href="https://utopian.io/utopian-io/@sp33dy/tutorial-godot-engine-v3-gdscript-collision-dectection">Utopian.io -  Rewarding Open Source Contributors</a></em><hr/>
👍 , , , , , , , , , , , , ,