Making things Explode

Now we want the enemies to explode when they are hit. Time to create an Explosion class. Create a new Scene, save it as Explosion.tscn, then create the following node hierarchy.

Explosion-Nodes in Godot Screenshot

Select the Sprite and drag the file /assets/graphics/explosion/explosion.png over to the Texture field of the sprite. You will notice that this is actually a sprite sheet, containing multiple frames of animation in a single file. Set Vframes and Hframes to 3 each, giving us 9 frames of animation to work with.

Explosion-frames in Godot Screenshot

Next, select the AnimationPlayer node, then create a new animation just like we did back when we created a bullet. We create an animation named Explode with the following keys and tracks configured:

Explosion-key-frames-and-tracks in Godot Screenshot

Here we created 3 tracks, a Property track that changes the frame property of Sprite over time, advancing through our animation. We also created a Method call track that calls queue_free() at the end of the animation. Finally, we added an Audio Playback Track that plays the file Explosion.wav available in /assets/audio/explode/explode.wav.

When creating the Audio Playback Track, select the AudioStreamPlayer when prompted. Then create a new key, and set Explode.wav as the Stream, like so:

Set-audio-key

Now open up Enemy.gd and add the following code:

onready var explode = preload("res://Explosion.tscn").instance()

func _on_Area2D_area_entered(area):
  #Hit by bullet
  if(area.get_collision_layer_bit(3)):
  
    explode.set_position(self.get_position())
    get_parent().add_child(explode)
    globals.kills = globals.kills + 1
    queue_free()

This invokes our newly created Explosion object. Basically, when the Enemy is hit, we check to see if the thing that hit us was on the Bullet layer, if it was, we create an explosion, set it to our current position, increment the global kills count and then remove us from the scene.

And finally, we need to make the Player explode if they collide with an enemy. Our Player.gd script now consists of:

extends Node2D


var speed = 150
var verticalMovement = 0
const MAX_VERTICAL_MOVEMENT = 200
var bulletObj = null
const RATE_OF_FIRE = 3.0
var dying = false


onready var shotCooldown = $Timer
onready var explode = preload("res://Explosion.tscn").instance()


func _ready():
  bulletObj = load("res://Bullet.tscn")
  shotCooldown.wait_time = 1.0/RATE_OF_FIRE
  shotCooldown.one_shot = true
  

func _process(delta):
  move_local_x(speed*delta)
  if(self.position.y > 1  && self.position.y <= get_viewport_rect().size.y):
    move_local_y(verticalMovement*delta)
  else:
    if(self.position.y < 1): 
      move_local_y(10) #Bounce off top
      verticalMovement = 0
    if(self.position.y > get_viewport_rect().size.y): 
      move_local_y(-10) #Bounce off bottom
      verticalMovement = 0
  if(dying == true):
    if(shotCooldown.time_left == 0):
      get_node("/root/GameSceneRoot").PlayerDied()
      queue_free()
      print("Dead")
  
func stop():
  speed = 0

func explode():
  explode.set_position(self.get_position())
  get_parent().add_child(explode)
  globals.kills = globals.kills + 1
  shotCooldown.wait_time = 2.5
  shotCooldown.start()
  $PlayerSprite.visible = false
  dying = true


func _input(event):
  if(event.is_action("PLAYER_UP")):
    if(verticalMovement >= -MAX_VERTICAL_MOVEMENT):
      verticalMovement-=10
  if(event.is_action("PLAYER_DOWN")):
    if(verticalMovement <= MAX_VERTICAL_MOVEMENT):
      verticalMovement+=10
  if(event.is_action("PLAYER_SHOOT")):
    if(shotCooldown.time_left == 0):
      var bullet = bulletObj.instance()
      bullet.position = self.get_position()
      bullet.position.y = bullet.position.y + 20
      get_node("/root/GameSceneRoot").add_child(bullet)
      shotCooldown.start()



func _on_Area2D_area_entered(area):
  #Layer 2 is another enemy
  if(area.get_collision_layer_bit(2)):
    explode()

Again be sure that the area_entered() signal has been connected. In this code, we reuse the shot timer (this has the advantage of preventing shots while dying) to delay removing the object from the scene until after the explosion animation is done. In the meanwhile, while waiting to be destroyed, we set our sprite to be invisible.

 

Scroll to Top