Try out our latest games now! →
iconSUPERMATRIX STUDIO
ProjectsToolsGuidesBlogNewsPlay Now!
iconSUPERMATRIX STUDIO
Play Now!
  • Home
  • Projects
  • Tools
  • About
  • Blogs
  • News

Socials

  • Twitter
  • GitHub
  • LinkedIn

Procedural Pipe Generation and Collision Detection

Procedural Pipe Generation and Collision Detection
Instructor

NoFace

Mentor

Welcome to the third lesson. A scrolling background is great, but we need actual gameplay. In this module, we will create the iconic green pipes, spawn them continuously at randomized heights, and detect when the bird successfully navigates through them.


1. Designing the Obstacle Scene#

First, we need to create the pipe object that we will clone (instance) repeatedly via code.

  1. Create a new scene with a Node2D as the root and name it PipeSet.
  2. Add two StaticBody2D nodes as children. Name one TopPipe and the other BottomPipe.
  3. For each StaticBody2D, add a Sprite2D and a CollisionShape2D (use a RectangleShape2D). Position them so there is a gap in the middle for the bird to fly through.

Creating the Score Zone#

We need to know when the player successfully passes a pipe.

  1. Add an Area2D node to the PipeSet root and name it ScoreZone.
  2. Add a CollisionShape2D to it, covering the empty gap between the top and bottom pipes.
  3. Connect the body_entered signal of the ScoreZone to the PipeSet script to emit a custom scored signal.

Adding Game Juice: To make scoring feel rewarding, add a CPUParticles2D node to the ScoreZone. Set it to emit briefly (One Shot) when the bird passes through. CPU particles are highly performant for 2D UI and simple effects like bursting confetti or stars upon scoring.


2. The Spawner Script#

Now, head back to your Main scene. We need a system to generate these PipeSet scenes at regular intervals.

  1. Add a Timer node to the Main scene. Name it SpawnTimer, set its Wait Time to 1.5 seconds, and check Autostart.
  2. Create a new Marker2D node named SpawnPosition. Place it just outside the right edge of your viewport (e.g., x: 520).

Attach a script to your Main node to handle the logic:

gdscript
extends Node2D

@export var pipe_scene: PackedScene
@onready var spawn_timer: Timer = $SpawnTimer
@onready var spawn_position: Marker2D = $SpawnPosition

func _ready() -> void:
	# Connect the timer's timeout signal
	spawn_timer.timeout.connect(_on_spawn_timer_timeout)

func _on_spawn_timer_timeout() -> void:
	var new_pipe = pipe_scene.instantiate()
	
	# Randomize the Y position for varied gameplay
	var random_y = randf_range(200.0, 600.0)
	new_pipe.position = Vector2(spawn_position.position.x, random_y)
	
	# Add the pipe to the scene tree
	add_child(new_pipe)

3. Memory Management#

If we keep spawning pipes infinitely, our game will eventually crash from memory exhaustion. We must delete pipes once they leave the screen.

  1. Open your PipeSet scene.
  2. Add a VisibleOnScreenNotifier2D node.
  3. Stretch its bounding box to cover the entire pipe structure.
  4. Connect its screen_exited signal to the PipeSet script and call queue_free().
gdscript
extends Node2D

# ... score logic ...

func _on_visible_on_screen_notifier_2d_screen_exited() -> void:
	queue_free() # Safely deletes the pipe from memory

Your game now endlessly generates obstacles and cleans them up automatically!

PreviousInfinite Scrolling Environment with ShadersNextUI Integration, Game Over State, and Score Tracking

Explore More Lessons

Project Setup and 2D Physics Foundation

Completed

Infinite Scrolling Environment with Shaders

Completed

Procedural Pipe Generation and Collision Detection

Current Lesson

UI Integration, Game Over State, and Score Tracking

Up Next

Game Polish: Audio, Screen Shake, and Main Menu

Up Next

Supermatrix Studio

Building immersive, neon-drenched worlds.

Social
© 2026 Supermatrix Studio. All rights reserved.