Skip to main content

Energon Boom

We are going to give the aliens the most interesting weapon in the game - an Energon Boom. It will be a slow moving cube of energy that targets the player's position and explodes, destroying everything within a large area. This will force the player to move quickly to avoid the explosion.

Creating the projectile

The explosion is simply going to be a collider that only lasts for one tick. This means we need to create a category for it.

Select your categories.easel file. Insert the following highlighted code underneath your other categories:

pub tangible category Category:Ship
pub tangible category Category:Asteroid
pub tangible category Category:Projectile
pub tangible category Category:Shield
pub tangible category Category:Powerup
pub tangible category Category:Alien
pub tangible category Category:Explosion

Now we need to define the behavior of the projectile, which we will do in a new EnergonBoom function.

Create a new file called energonBoom.easel and fill it with the following code at the bottom of your file:

pub fn projectile.EnergonBoom(ship, target) {
use body=projectile
use speed=12, radius=0.5, turnRate=0.1rev
use color=#ffcc00, luminous=1, layer=-5
use aoe=6
use lifetime=3s

Body(
pos = ship.Pos,
velocity = speed * Direction(target - pos),
bullet=true,
)
PolygonSprite(shape=Equilateral(numPoints=4), glare=0.7, bloom=3)
PolygonCollider(
shape=Circle, category=Category:Projectile,
collideWith = Category:Ship | Category:Projectile,
)

once Tick(lifetime) { Expire }

once BeforeCollide that {
Strobe(shine=1, dissipate=0.5s)
repeat 5 { Spark(shine=0.5, splatter=1, dissipate=0.5s) }
Expire
}

once BeforeDespawn {
Spark(radius=aoe, dissipate=0.5s, shine=0.2, bloom=3, feather=1, glare=0.3)

Spawn explosion {
use body=explosion

Body(pos=projectile.Pos, immovable=true)
PolygonCollider(shape=Circle(aoe), category=Category:Explosion, sense=Category:Tangible)

once AfterPhysics { Expire }
}
}
}

Next we need to get the aliens to fire the Energon Boom. We will make them fire upon the nearest player ship every 7 seconds.

Select your alien.easel file. Insert the following code at the bottom of your Alien function:

pub fn ship.Alien {
// ...

on Tick(7s) {
let hero = QueryNearest(filter=Category:Ship)
if (hero) {
Spawn projectile {
EnergonBoom(ship=, target=hero.Pos)
}
}
}
}
info

The QueryNearest function is used to find the nearest entity that matches the given criteria. It might return nothing if it can't find anything. That is why we check if we do have a hero before firing the Energon Boom.

Finally, we have to make sure our hero ship gets destroyed by the explosion.

Select your ship.easel file. Modify the following code in your Ship function:

pub fn ship.Ship([owner]) {
// ...

on BeforeCollide that {
if that.Category.Overlaps(Category:Asteroid | Category:Alien | Category:Explosion) {
// ...
}
}
}

Click Preview to enter your game. You should find that, every 7 seconds, the aliens will fire an Energon Boom at you. If you are good enough at aiming, you should find you can shoot down an Energon Boom with your Plasma Bolt. Finally, if you get caught in the explosion, your ship should be destroyed.

The current entity this, revisited

Let's take another moment to understand an additional rule to one of the most concepts in Easel - the current entity.

Something interesting is happening in our EnergonBoom function. Below is the relevant part of the code from energonBoom.easel. Open up energonBoom.easel so you can follow along.

pub fn projectile.EnergonBoom(ship, target) {
// ...

once BeforeDespawn {
// ...

Spawn explosion {
use body=explosion

Body(pos=projectile.Pos, immovable=true)
PolygonCollider(shape=Circle(aoe), category=Category:Explosion, sense=Category:Tangible)

once AfterPhysics { Expire }
}
}
}

First, how does this work? Using Spawn explosion, we are creating a new entity that represents the explosion. We want to create a PolygonCollider that is the same size as the explosion, so that other entities can detect when they have been hit by the explosion and react accordingly.

The problem is, we need our new PolygonCollider component to become part of the explosion entity, not the projectile entity, because the projectile is just about to despawn. (How do we know this? We are inside its once BeforeDespawn block!) If we mistakenly attached the new collider to the projectile, it would not live long enough to have an effect.

Previously we told you this simple rule for Easel components: Whenever you create a component in Easel, by default it becomes part of the current entity, What is the current entity here? Previously we told you to look at the function signature fn projectile.EnergonBoom, which tells us that the current entity is projectile. This is the wrong entity, we want explosion.

However, the reason our code works is because of one more special rule. Within the subblock of a function that spawns a new entity (like Spawn or Subspawn) the current entity is the entity that was just spawned. That is why our new PolygonCollider component gets attached to the explosion entity and not the projectile. PolygonCollider is inside the Spawn explosion subblock, and so explosion is the current entity within that subblock.

tip

Whenever you create a component in Easel, by default it becomes part of the current entity.

Normally, the current entity can be found by looking for the parameter before the . in the function signature. For example fn projectile.EnergonBoom means the current entity is projectile. However, within the subblock of a function that spawns a new entity (like Spawn or Subspawn) the current entity is the entity that was just spawned. For example, components created inside a Spawn explosion { ... } block would become part of the explosion entity instead.

This special rule helps give Easel its hierarchical style, which is often a good match with how games are structured, and can allow for games to be expressed more logically.

Indicating the explosion

It is a good idea to give the player some indication of where the explosion is going to happen so they can get out of the way.

Select your energonBoom.easel file. Insert the following highlighted line into your EnergonBoom function.

pub fn projectile.EnergonBoom(ship, target) {
// ...

PolygonSprite(shape=Equilateral(numPoints=4), glare=0.7, bloom=3)
PolygonSprite(shape=Circle(aoe), crater=0.85, color=color.Fade(0.95))
PolygonCollider(
shape=Circle, category=Category:Projectile,
collideWith = Category:Ship | Category:Projectile,
)

// ...
}

Click Preview to enter the game. When the aliens fire an Energon Boom, you should see a circle appear where the explosion is going to happen.

Targeting the player

We want the Energon Boom to explode when it reaches the player's position. This forces the player to move out of the way. We will do this by modifying the lifetime of the Energon Boom so that it explodes when enough time has passed for it to have reached the player.

In energonBoom.easel, find your previous lifetime=3s declaration and replace it with the highlighted snippet below:

pub fn projectile.EnergonBoom(ship, target) {
use body=projectile
use speed=12, radius=0.5, turnRate=0.1rev
use color=#ffcc00, luminous=1, layer=-5
use aoe=6
use lifetime = 1s * Distance(ship.Pos, target) / speed

// ...
}

Click Preview to enter the game. You should find that the Energon Boom explodes when it reaches your ship's position, and so you must get out of the way to stay alive. This encourages the player to keep moving and adds a new challenge to the game.