Spline Barriers
Demo + Lesson on how to use curved barriers in your games.
Introduction
Lesson
Spline Barriers
A SplineBarrier is a curved wall you can place anywhere in your scene. Unlike a normal rectangle Barrier, a SplineBarrier follows a smooth curve defined by a list of control points — letting you build slopes, arches, winding paths, and organic terrain boundaries.
How It Works
1 Defining the Curve with Control Points
When you create a SplineBarrier, you pass in a splinePoints
array — a list of { x, y } coordinates that act as
anchors along the path:
jsconst barrier = new SplineBarrier({
id: 'cliff_edge',
color: '#8B4513',
lineWidth: 5,
splinePoints: [
{ x: 50, y: 400 },
{ x: 200, y: 300 },
{ x: 400, y: 350 },
{ x: 600, y: 200 },
]
}, gameEnv);
These points are not connected with straight lines. Instead, the barrier computes a smooth curve through them using Catmull-Rom spline interpolation.
2 Catmull-Rom Interpolation
The magic behind the smooth curve is the catmullRom() static method. It
generates a point on the curve between two anchors (P1 → P2),
using their neighbors (P0, P3) as tension guides:
t = 0.0 → start of segment (at P1)
t = 1.0 → end of segment (at P2)
By sampling this function many times per segment (default: 50 samples),
getCurvePoints() builds a dense array of positions that forms the rendered and
collidable curve. The more segments, the smoother and more collision-accurate the barrier.
3 Rendering
Each SplineBarrier owns its own dedicated <canvas>
element, layered above the game background (z-index: 15). On every
frame, draw() clears that canvas and redraws the full curve using the computed
points.
This is intentionally separate from the main game canvas so the barrier doesn’t
interfere with other rendering layers and can be toggled via visible. This is
for debugging purposes — you can set visible: false to hide the curve
while keeping its collision active.
4 Collision Detection
SplineBarrier does not use the engine’s standard rectangular
hitbox. Both collisionChecks() and isCollision() are
overridden to do nothing — rectangular collision is irrelevant for a curved boundary.
Instead, update() runs its own proximity check every frame:
- Finds the
Playerobject ingameEnv.gameObjects - Gets the player’s center position
- Iterates over all curve points
- If the player is within 20 pixels of any curve point, a collision is triggered
On collision, the player is pushed away from the nearest curve point along the vector between them:
push direction = normalize(playerCenter − collisionPoint) × pushStrengthThis gives the illusion of a solid wall without needing a polygon collider.
Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
splinePoints |
Array<{x,y}> | simple fallback curve | The control points defining the path |
color |
string | '#8B4513' |
Stroke color of the rendered curve |
lineWidth |
number | 5 |
Width of the rendered line in pixels |
visible |
boolean | true |
Whether the curve is drawn each frame |
id |
string | 'spline_barrier' |
Canvas element ID |