Collision
Collision uses the sprite’s collision box, adjusted in the sprite editor. Two instances collide when the boxes overlap; just touching edges doesn’t count. Instances without a sprite don’t collide, and angle is ignored.
| Function | What it does | Example |
|---|---|---|
void onCollide<T>(std::function<void(T&)> callback) |
Registers a function called on every step in which this instance touches a T. Register it in onSpawn. |
onCollide<Coin>([](Coin& c) { c.destroy(); }); |
void onTouchStart<T>(std::function<void(T&)> callback) |
Like onCollide, but runs once, when the contact starts. Good for coins, doors and flags. |
onTouchStart<Coin>([](Coin& c) { c.destroy(); }); |
void onTouchEnd<T>(std::function<void(T&)> callback) |
Runs once, when the contact ends. It doesn’t fire for a destroyed instance. | onTouchEnd<Water>([this](Water&) { gravity = 0.25f; }); |
bool collidesAt<T>(float atX, float atY) |
true if this instance would touch a T if it were at (atX, atY). |
if (!collidesAt<Wall>(x + 2, y)) x += 2; |
T* findAt<T>(float atX, float atY) |
The first instance of T touched at that position, or nullptr. |
if (Enemy* e = findAt<Enemy>(x, y + 1)) e->destroy(); |
bool placeFree(float atX, float atY) |
true if no solid instance would be touched at that position. |
if (placeFree(x, y + 1)) vspeed += 0.3f; |
To move while stopping at walls, see moveAndStop in Movement.
By the object’s name
Section titled “By the object’s name”All these functions also take the object’s name in quotes in place of the <T>. That is how you react to an object without code. The callback receives an Entity&.
| Function | Example |
|---|---|
Entity* touching(std::string_view object) |
if (touching("Espinho")) restart(); |
bool collidesAt(std::string_view object, float atX, float atY) |
if (collidesAt("Chao", x, y + 1)) ... |
Entity* findAt(std::string_view object, float atX, float atY) |
if (Entity* e = findAt("Caixa", x + 1, y)) e->x += 1; |
void onCollide(std::string_view object, std::function<void(Entity&)> callback) |
onCollide("Lava", [this](Entity&) { destroy(); }); |
void onTouchStart(std::string_view object, std::function<void(Entity&)> callback) |
onTouchStart("Espinho", [this](Entity&) { restart(); }); |
void onTouchEnd(std::string_view object, std::function<void(Entity&)> callback) |
onTouchEnd("Agua", [this](Entity&) { gravity = 0.25f; }); |
Mask and mirroring
Section titled “Mask and mirroring”maskis the name of a sprite. When set, the collision box comes from it, not from the current sprite: changing the animation doesn’t change the box. In the editor, it is the object’s Máscara (mask).flipXmirrors the drawing and the collision box around the origin.
onCollideruns after the movement of the step, once for eachTtouched.- An instance that is already touching when it is created fires
onTouchStarton the first step. - An
onCollideregistered inside another one can already fire on the same step. - Sólido (solid) is checked in the object’s Inspector, or in the code with
solid = true.
Older functions
Section titled “Older functions”These still work:
| Function | What it does |
|---|---|
T* touching<T>() |
The first instance of T touched right now, or nullptr. |
T* touching<T>(float atX, float atY) |
The same, at a position. |
std::vector<T*> touchingAll<T>() |
All the instances of T touched right now. |
std::optional<Rect> collisionBox() const |
The collision box in the world, at the current position. |
std::optional<Rect> collisionBoxAt(float atX, float atY) const |
The box if the instance were at (atX, atY). |
