Skip to content
Download

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.

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 is 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).
  • flipX mirrors the drawing and the collision box around the origin.
  • onCollide runs after the movement of the step, once for each T touched.
  • An instance that is already touching when it is created fires onTouchStart on the first step.
  • An onCollide registered 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.

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