4. Enemies
Create the objects
Section titled “Create the objects”-
Create the object
Enemy(Novo objeto…, new object, in theobjectsfolder). In the Inspetor (Inspector), choose the spriteinimigo. In the Camadas (layers) panel, create one more Instâncias layer, calledInimigos, and drag it belowTiros. Then clickInstanciasagain. -
Create the object
Spawnerand leave it without a sprite. It doesn’t show up in the game: its only job is to create enemies. -
Drag
Spawnerinto the roomMain. Anywhere is fine; in the editor it shows up as a little square.Enemydoes not go in the room: the one that creates the enemies isSpawner.
The enemy
Section titled “The enemy”Open Enemy.hpp, delete the examples and write:
#pragma once#include <brasa/brasa.hpp>
// Enemy that falls from the top of the screen.class Enemy : public brasa::Entity {public: BRASA_VARS(Enemy)
void onSpawn() override; void onUpdate() override;};And Enemy.cpp:
#include "Enemy.hpp"
using namespace brasa;
void Enemy::onSpawn() { animSpeed = 0.1f; // random(a, b) picks a number between a and b: each enemy falls at a different speed. vspeed = random(0.8f, 1.6f); // When a Bullet touches me, the shot and I are destroyed. // The other objects (Bullet, Player...) are already known here, with no #include. onCollide<Bullet>([this](Bullet& bullet) { bullet.destroy(); destroy(); });}
void Enemy::onUpdate() { // roomHeight() is the height of the screen; past it (with some slack), the enemy got away. if (y > static_cast<float>(roomHeight()) + 16.0f) destroy();}
BRASA_ENTITY(Enemy);random(0.8f, 1.6f)picks a number between 0.8 and 1.6. Each enemy falls at a different speed, which makes the game less predictable.onCollide<Bullet>(...)says: “when I touch aBullet, do this”. Brasa checks the collision boxes on every step and calls the lambda. The shot that hit arrives asbullet, and both are destroyed.- In
onUpdate, the enemy that passed the bottom of the screen is destroyed.
The Spawner
Section titled “The Spawner”Open Spawner.hpp, delete the examples and write:
#pragma once#include <brasa/brasa.hpp>
// Creates enemies at the top of the screen, faster and faster.class Spawner : public brasa::Entity {public: BRASA_VARS(Spawner)
void onSpawn() override;
private: void scheduleNext(); // schedules the next enemy int spawned_ = 0;};Spawner has a function of its own, scheduleNext, and counts how many enemies it has created in spawned_.
Now Spawner.cpp:
#include "Spawner.hpp"
#include <algorithm>
using namespace brasa;
// The Spawner needs no onUpdate: it schedules the next enemy with after(),// which calls the function after N steps (at 60 steps per second).void Spawner::onSpawn() { scheduleNext(); }
void Spawner::scheduleNext() { // The interval shrinks little by little (from 1 s down to a minimum of 0.25 s): the game gets harder. const int interval = std::max(15, 60 - spawned_ * 2); after(interval, [this] { ++spawned_; const float margin = 16.0f; spawn<Enemy>(random(margin, static_cast<float>(roomWidth()) - margin), -16.0f, "Inimigos"); scheduleNext(); // schedules the next one });}
BRASA_ENTITY(Spawner);How it works:
- When
Spawneris created,onSpawncallsscheduleNext(). scheduleNextcomputes an interval: 60 steps (1 second) at the start, 2 steps fewer for each enemy, down to a minimum of 15.std::max(15, ...)guarantees that minimum.after(interval, ...)waits that long and creates anEnemyat a randomxposition, just above the screen (y = -16).- Then it calls
scheduleNext()again, and the cycle goes on forever.
Test it now
Section titled “Test it now”Press Play. The enemies start falling, faster and faster. Shoot them: shot and enemy go away together. For now, touching the ship does nothing; that comes in the next part.
What you learned
Section titled “What you learned”- An object without a sprite can have an invisible job, like
Spawner. random(a, b)picks numbers. See Random numbers.onCollide<Object>(...)reacts when two objects touch. See Collisions.- A function that schedules itself again with
aftercreates a repetition with a varying interval.
Next part: 5. Score and lives →
