Walls
How can I make walls that stop the player from moving through them?
This example shows how to create walls that stop the player from exiting the play area, but also create a little maze of walls inside the play area for the player to navigate around. The camera will be zoomed in so the player won't be able to see the whole map at once, creating a sense of exploration and discovery.
This is a 2D top-down view game, but with a side-view, the walls could become platforms that the player could jump onto and walk across. The same principles apply.
Step 1: Define a Wall entity
Walls are simply entities that have a collider that stops other bodies from walking through them.
The key thing is to add immovable=true so that no amount of force can move the wall.
pub fn wall.Wall(pos, width, height) {
use body=this, shape=Rectangle(width=, height=)
Body(pos=, immovable=true)
PolygonCollider(category=Category:Wall)
PolygonSprite(color=#000)
}
Step 2: Spawn walls around the edges of the screen
Spawn four walls around the edges of the screen to keep players from leaving the play area. Make them really thick so that even if the player is moving really fast, they will be unable to tunnel through the wall in a single physics tick.
Spawn wall { Wall(pos=@(100, 0), width=100, height=1000) }
Spawn wall { Wall(pos=@(-100, 0), width=100, height=1000) }
Spawn wall { Wall(pos=@(0, -100), width=1000, height=100) }
Spawn wall { Wall(pos=@(0, 100), width=1000, height=100) }
This spawns four walls with a thickness of 100 around the edges of the screen.
Step 3: Spawn some internal walls
In our example, we will just spawn the walls randomly inside the play area. You could also spawn them manually in a hand-designed pattern.
for row in RangeInclusive(-4, 4) {
for col in RangeInclusive(-4, 4) {
if row == 0 && col == 0 { continue } // clear spawn point
Spawn wall {
let pos = @(10*col, 10*row)
surprise {
Wall(pos=, width=2, height=10),
Wall(pos=, width=10, height=2),
}
}
}
}
Full Code Listing
pub tangible category Category:Wall
pub tangible category Category:Hero
pub game fn World.Main() {
TopContent { "Arrow keys to move" }
SolidBackground(#000)
// Boundaries are just big walls that prevent the player from leaving the play area.
Spawn wall { Wall(pos=@(100, 0), width=100, height=1000) }
Spawn wall { Wall(pos=@(-100, 0), width=100, height=1000) }
Spawn wall { Wall(pos=@(0, -100), width=1000, height=100) }
Spawn wall { Wall(pos=@(0, 100), width=1000, height=100) }
// Inner walls
for row in RangeInclusive(-9, 9) {
for col in RangeInclusive(-9, 9) {
if row == 0 && col == 0 { continue } // clear spawn point
Spawn wall {
let pos = @(5*col, 5*row)
surprise {
Wall(pos=, width=1, height=5),
Wall(pos=, width=5, height=1),
}
}
}
}
SpawnEachPlayer owner {
Subspawn unit {
Hero
}
}
}
pub fn wall.Wall(pos, width, height) {
use body=this, shape=Rectangle(width=, height=)
Body(pos=, immovable=true)
PolygonCollider(category=Category:Wall)
PolygonSprite(color=#322)
}
pub fn unit.Hero([owner]) {
use body=this, radius=0.5, shape=Circle
Body(pos=@(0, 0))
PolygonSprite(color=#fc0, bloom=5, luminous=1, layer=1)
PolygonCollider(category=Category:Hero)
Camera(radius=10, freeRadius=3)
on BeforePhysics {
let direction = @(0, 0)
if IsButtonDown(ArrowLeft) { direction += @(-1, 0) }
if IsButtonDown(ArrowRight) { direction += @(1, 0) }
if IsButtonDown(ArrowUp) { direction += @(0, -1) }
if IsButtonDown(ArrowDown) { direction += @(0, 1) }
if direction == @(0, 0) { continue }
Move(0.1 * direction)
}
}