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)
}
}
}
}
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.
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.