Collision_Systems - hpgDesigns/hpgdesigns-dev.io GitHub Wiki
(Wiki Note: This article could use some images.)
In game development, a collision occurs when two instances or shapes move to overlap each other (even if it's just 1-pixel overlap). This concept is useful for triggering a specific event. For instance, when a player is falling, and then comes into contact with a platform, he should stop. If he comes into contact with an enemy, he should either take damage or damage the enemy. To detect when something comes into contact with something else, you would use a collision event.
The exact specifics of when a collision occurs depend on the Mask settings and Collision system selected, but generally, we can say that a collision is deemed true when two things are overlapping or intersect by any amount.
Event
First, understand an event, and the difference between an object and an instance.
An object obj_0
will define an event with another object obj_1
(or
even the same object). When any instance of obj_0
comes into contact
with any instance of obj_1
, the event is fired inside of that instance
of obj_0
. If multiple instances are involved in collisions in one
step, they will all fire collision events. If obj_1
also has a
collision event with obj_0
, then both collision events will fire. If
you choose a collision event with the same object, then whenever any two
instances of that object collide, both of them will fire their collision
event.
A collision event will continue to occur every step for as long as the two objects continue to overlap. Because of this, in order to avoid repeatedly executing code (like constantly taking damage), it can be wise to, when a collision occurs, do something to make the collision stop happening. A few suggestions;
- Destroy one or both of the objects.
- Move one or both of the objects.
- Set a variable, and only execute the event if the variable is a certain value. You might consider setting an alarm to determine when to reset the variable.
For your convenience, within a collision event, the other variable can be used to refer to the other object in the collision. For DND users, many actions have an Applies to section at the top, with other listed as one of the options. Other can be used to execute some piece of code or action on the other object. For instance, collecting coins could be done as follows:
In obj_player's collision event with obj_coin:
Set the score relative to 1
For other object: Destroy the instance.
Formulas and Settings
The fundamental formulas for collision detection are rather complex, usually involving geometric polygon intersection algorithms, and even pixel-overlap algorithms for pixel-perfect collision. Fortunately, ENIGMA comes packed with several Collision Systems built in, and a default selected, so all you need to do is add collision events to the instances that you are interested in, and handle the event however you like. The selected collision system will decide when to trigger the event and execute the actions inside of it.
Using all defaults can quickly make your game feel very clunky, so once you are familiar with the basics of collisions, you can then move on to fine tuning the system. The sections below will provide you with the different levels of tuning your collisions.
Masks
The region of an object that determines which parts are "solid" and which parts are "air" is defined by the Mask. In the simplest sense, you can think of a mask as a silhouette of your object's sprite. The dark regions are solid, and the light regions are air. A collision occurs when the solid (dark) region of one object comes into contact with the solid region of another object.
The mask of an object is determined by selecting a sprite with the desired mask properties. By default, an object's mask is set equal to its Sprite. To alter properties for the object's mask, you can either alter the mask properties of the sprite, or select a separate mask for that object. Note that the mask is not visible in the game - only the sprite is drawn. The mask is only used to determine collisions.
The mask can be read/set programmatically in-game via the mask_index global local variable, or with the appropriate DND action.
The exact properties of a mask are determined by which Collision System you have selected. Please consult the respective Collision System's documentation, under their Mask section. Obviously, if one collision system's mask properties are insufficient for your game, you can select another collision system.
Collision System
The selected collision system employs the underlying formulas and algorithms to determine whether a collision occurs. It determines the exact behavior of collision functions, as well as the mask properties available. Since a collision event is determined by collision functions, the collision system then also determines when to trigger a collision event, based on the object's mask properties and coordinates.
Different systems behave very differently, so choose carefully. Generally, collision is a trade-off between efficiency (or calculation speed) and precision (or how accurate the collision seems to be). We try to select a default that is appropriate for the general case of most games - that is, a nice balance between efficiency and precision.
To select a collision system, go to ENIGMA Settings > API > Collisions, and select the desired system from the dropdown. Then click the green checkmark to submit your changes.
The following systems are currently available for selection:
- None - Collisions never occur. No collision functions are provided. Masks are meaningless. This is the most efficient system. It is useful for if you wish to handle collisions yourself, or do not intend to handle collisions at all.
- Bounding Box (Current Default) - The mask of every object is a rectangular region defined by the sprite's bounding box. Object-collisions are entirely rectangle-based. A basic set of geometric collision functions are provided. Very efficient, but entirely restricted to rectangular objects.
The following systems we hope to make available in the future:
- Circle/Sphere - The mask of every object is a circular region defined simply by an offset and a radius. Object-collisions are entirely point-distance based. A basic set of geometric collision functions are provided. Extremely efficient, but useless for more complex shapes.
- Polygon - The mask of every object is a polygon - a set of outline points selected by the user. Object-collisions are entirely polygon-intersect based. An advanced set of geometric collision functions are provided. Fairly efficient, with more precision available by adding more points (at the cost of a bit of efficiency).
- Pixel Perfect - The mask of every object is a bit map. Object-collisions are true if any solid bits overlap. An advanced set of geometric and pixel-perfect collision functions are provided. This is the most precise system, but is quite inefficient. Usually it is used in conjunction with the bounding box to rule out collisions in advance. This was the behavior that older versions of GM used.
- Shape - The mask of every object is selected as one of the above shapes. Object-collisions perform an additional check to decide which collision function to use between two objects, An advanced set of geometric and pixel-perfect collision functions are provided. Not very efficient, but very versatile, and as precise as the Mask dictates.
- Advanced Shape - Same as shape, but a simple bbox or distance-radius check is used first to determine whether the collision can be ruled out early. Because of this, it can be more efficient than Shape. On the other hand, if the additional check frequently doesn't rule out collisions, it can become less efficient, because it is an additional check. This is the behavior that GM uses (I think. Unless the shapes are just bit mapped).
(Wiki note: The above could probably be made into a table.)
Do it yourself
If none of the collision systems provided are suitable for your game, and you would like to handle your own collisions, consider one of the following:
- Select None for collision system, and then handle all collisions in-game using your own formula
- Select the closest collision system that will provide you with the best collision functions, not use collision events, and handle collisions in-game using the functions, or your own formulas where needed
- Code your own Collision System into ENIGMA, compile it into ENIGMA, and then select it. If you think other people may benefit from your collision system, you can share it, or submit it for inclusion into ENIGMA (must be license-compliant).