Mobs
How can I make a mob of enemies that shoot projectiles at their nearest player?
To make mobs of enemies, Spawn an entity to represent each enemy,
and give it a behavior that finds the nearest player and shoots every tick.
Step 1: Spawn some mobs
In this example, our mobs of enemies are called Aliens.
We will define what an Alien does in the next step.
repeat 20 {
Spawn unit {
Alien
}
}
Step 2: Make mobs attack
To make our Alien attack,
we have simply given them a behavior that runs every few ticks and finds the nearest player to shoot at.
pub fn unit.Alien() {
// ...
on Tick(2.5s * Random) {
let enemy = QueryNearest(filter=Category:Hero)
if !enemy { continue }
Spawn projectile {
Bullet(heading=Angle(enemy.Pos - Pos), parent=unit)
}
}
}
- QueryNearest finds the nearest player.
- The
on Tick(2.5s * Random)means it will rerun this block somewhere between every0sand2.5s, chosen randomly
Full Code Listing
pub tangible category Category:Hero
pub tangible category Category:Alien
pub tangible category Category:Projectile
pub game fn World.Main() {
TopContent { "Arrow keys to move, click to fire" }
SpawnEachPlayer owner {
Spawn unit {
Hero
}
}
repeat 20 {
Spawn unit {
Alien
}
}
}
pub fn unit.Hero([owner]) {
use body=this, radius=1, shape=Circle
Body(pos=20*RandomVector)
PolygonSprite(ownerColor=true)
PolygonCollider(category=Category:Hero)
DecaySpeed(1)
DecayTurnRate(1)
on BeforePhysics {
Move(0.25 * Joystick)
}
// Shoot towards pointer on click
on ButtonDown(Click) {
Spawn projectile {
Bullet(heading=Angle(Pointer - Pos), parent=unit)
}
}
}
pub fn unit.Alien() {
use body=this, radius=1, shape=Equilateral(numPoints=4)
Body(pos=20*RandomVector)
PolygonSprite(color=#0f0)
PolygonCollider(category=Category:Alien)
DecaySpeed(1)
DecayTurnRate(1)
// Shoot towards nearest hero every so often
on Tick(2.5s * Random) {
let enemy = QueryNearest(filter=Category:Hero)
if !enemy { continue }
Spawn projectile {
Bullet(heading=Angle(enemy.Pos - Pos), parent=unit)
}
}
// Take 50 steps in a random direction every so often
on Tick(0.5s * Random) {
let step = 0.25 * RandomVector
repeat 50 {
Move(step)
await Tick
}
}
}
// Bullet flies towards a target with a speed of 30
pub fn projectile.Bullet(heading, parent) {
use body=this, radius=0.25, shape=Circle
Body(pos=parent.Pos, velocity=30*heading.Direction)
PolygonSprite(color=#fc0)
PolygonCollider(category=Category:Projectile, parent=)
on BeforeCollide that { Expire }
once Tick(1.5s) { Expire }
}