Lesson 27

Pit Runner

Cross the pits, grab every coin, and make three lives last. Assembles Platformer Movement, Collect Coins, and Lives System.

Loading the game engine. This takes a moment the first time.

Platformer only

This is a project, not a lesson: nothing in this folder is new. Cross the pits, collect every coin, and make three lives last the whole way.

BUILD IT FROM

  1. Platformer Movement: the running, jumping player.
  2. Collect Coins and Items: the coins, emitting on the bus.
  3. Lives System: the pits, the respawn, and the counting.

WHAT THE GLUE DOES

The signal chain from the Lives System lesson runs unchanged: kill zone emits life_lost, this file subtracts and emits lives_updated, the HUD redraws. All this file adds is a second way for the round to end, collecting every coin, and a flag so the two endings cannot overlap.

The scenes

■ UI node · ■ 2D node · % unique name · .tscn instanced scene

game.tscn
  • Game Node2D game.gd
  • Player CharacterBody2D player.tscn
  • HUD CanvasLayer hud.tscn
  • Ground Node2D
  • Ground1 StaticBody2D block.tscn
  • Ground2 StaticBody2D block.tscn
  • Ground3 StaticBody2D block.tscn
  • Platform1 StaticBody2D block.tscn
  • Platform2 StaticBody2D block.tscn
  • Platform3 StaticBody2D block.tscn
  • Coins Node2D
  • Coin1 Area2D coin.tscn
  • Coin2 Area2D coin.tscn
  • Coin3 Area2D coin.tscn
  • Coin4 Area2D coin.tscn
  • Coin5 Area2D coin.tscn
  • Coin6 Area2D coin.tscn
  • KillZone Area2D kill_zone.gd
  • CollisionShape2D
coin.tscn
  • Coin Area2D coin.gd
  • Polygon2D
  • CollisionShape2D
hud.tscn
  • HUD CanvasLayer hud.gd
  • MarginContainer
  • HBoxContainer
  • LivesLabel Label %
  • ScoreLabel Label %
  • ResultLabel Label %
player.tscn
  • Player CharacterBody2D player.gd
  • Sprite2D
  • CollisionShape2D
block.tscn
  • Block StaticBody2D
  • Polygon2D
  • CollisionPolygon2D

FileSystem

  • game.tscn
  • game.gd
  • coin.tscn
  • coin.gd
  • hud.tscn
  • hud.gd
  • player.tscn
  • player.gd
  • block.tscn
  • kill_zone.gd

game_events.gd

Switch it on once, under Project > Project Settings, on the Globals tab. Not made yet? Press Create Script to make it right there. Already made it? Press Select Script/Scene, pick it, and press Add. Its Name column should say GameEvents, which Godot fills in for you. That's the name your code uses.

The code

extends Node2D

## How many lives the player begins with.
@export var starting_lives: int = 3
## How many coins are in the scene. Change this if you add coins!
@export var total_coins: int = 6

var lives: int
var collected: int = 0
var round_over: bool = false

@onready var player: Player = $Player

func _ready() -> void:
	lives = starting_lives
	# kill_zone.gd emits "life_lost", the exact chain from Lives System.
	GameEvents.life_lost.connect(_on_life_lost)
	GameEvents.coin_collected.connect(_on_coin_collected)

func _on_life_lost() -> void:
	if round_over:
		return
	lives -= 1
	# hud.gd connects to "lives_updated" and redraws the number.
	GameEvents.lives_updated.emit(lives)
	if lives <= 0:
		round_over = true
		player.set_physics_process(false)
		# hud.gd shows Game Over.
		GameEvents.player_died.emit()
		_restart_soon()

func _on_coin_collected(_value: int) -> void:
	if round_over:
		return
	collected += 1
	if collected >= total_coins:
		round_over = true
		player.set_physics_process(false)
		# hud.gd shows the win message.
		GameEvents.goal_reached.emit()
		_restart_soon()

func _restart_soon() -> void:
	var timer: SceneTreeTimer = get_tree().create_timer(2.0)
	timer.timeout.connect(_on_restart_timeout)

func _on_restart_timeout() -> void:
	get_tree().reload_current_scene()