Now we have all the pieces we need to create our game, let’s update the GameScene to populate it with both the Player class as well as enemies. While we are at it, we are going to add a camera so we can scroll off screen!
But first, we are going to add a simple HUD, which is a 2D interface that is drawn over the top of our game display. We will simply display the total kill count in the top right corner.
To create the HUD, create a new CanvasLayer node, parented to the GameSceneRoot node and rename it HUD. Add a label to the newly created HUD, rename it Kills, and set the text to Kills:0. We also configure the Font as we did earlier when creating the Stage label.
Your Node hierarchy should now look like:
And the HUD should now look like:
Now we add the following code:
extends Node2D
enum GameState { Loading, Running, GameOver }
onready var State = GameState.Loading
onready var enemyObj = preload("res://Enemy/Enemy.tscn")
var Player = null
var cam = null
func _ready():
var labelText = "Stage " + str(globals.currentStage)
$Label.set_text(labelText)
$AnimationPlayer.play("Stage Display")
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
$HUD/Kills.set_text("Kills:" + str(globals.kills))
pass
func _input(event):
if(State == GameState.GameOver):
if(event.is_action("PLAYER_SHOOT")):
get_tree().change_scene("TitleScene/TitleScene.tscn")
func startAnimationDone():
$Label.visible = false
Player = load("res://Player/Player.tscn").instance()
Player.position = Vector2(300,720/2)
cam = Camera2D.new()
cam.position.x = 360
cam.make_current()
Player.add_child(cam)
add_child(Player)
SpawnEnemies()
State = GameState.Running
func _on_Area2D_area_entered(area):
#Did we hit the trigger to queue boss fight?
if(area.get_collision_layer_bit(4)):
if(State == GameState.Running):
Player.speed = 0
globals.currentStage = globals.currentStage + 1
get_tree().reload_current_scene()
func PlayerDied():
for i in Player.get_children():
i.queue_free()
remove_child(Player)
State = GameState.GameOver
$Label.set_text("Game Over")
$Label.visible = true
$Label.set_position(Vector2(1280/2 - 200, 720/2))
func SpawnEnemy(x,y):
var enemy = enemyObj.instance()
enemy.set_position(Vector2(x,y))
add_child(enemy)
func SpawnEnemies():
randomize()
# One extra plane per stage
for i in range(0,10+globals.currentStage):
SpawnEnemy(700 + randi()%5000,randi()%int(get_viewport_rect().size.y))
func SpawnBossWave():
for i in range(0,10):
SpawnEnemy(3800 + randi()%220, randi()%720)
Now we’ve got a game! One thing you will notice is the game continues to run past the end of the level. To get around this, we are going to create an Area2D that tells the game we are at the end of the level. We already implemented the code, _on_Area2D_area_entered()… now we just need to implement an area on our map.
Create a new node parented to the root node called triggers, then inside this node create an Area2D. Finally, create a CollisionShape of type Rectangle 30 wide and 360 high, and draw this half a screen (1280/2) from the end of the level, like so:
Then wire up the area_entered() signal to call _on_Area2D_area_entered() when we hit this code. Finally, let’s set up the Area2D collisions like so:
