It is very important in a game that you detect collisions properly. Nobody is going to play a game where things start exploding even when they are many pixels apart. Besides the graphics and sounds, this is one more thing that you should try to keep as accurate as possible.
In this tutorial, you will learn about detecting and debugging collisions in detail.
Detecting and Ignoring Hits
Before you can detect any collisions, you need to add the Collision
component to an entity. This component will successfully detect a collision between any two convex polygons. This component has two events: HitOn
and HitOff
. The HitOn
event is triggered when a collision occurs. It will not be triggered again unless collisions of that specific type cease. The HitOff
event is triggered when a collision ceases.
If you are checking for collision with multiple components and all these collisions occur simultaneously, each collision will fire its own HitOn
event. The data received from a collision event is only valid as long as the collision is still occurring.
You can use the .checkHits()
method to perform collision checks against all entities with a specified component. Calling this method multiple times will not result in multiple redundant checks.
Keep in mind that hit checks are performed upon entering each new frame. Let's say there are two objects which have not yet collided when the hit check is performed. Now, if one of the objects moves to a new location and overlaps with the second object later in the same frame, the hit events will not be fired until a collision check is performed again in the next frame.
If you have to detect only the first collision between different entities, you can use the .ignoreHits(String componentList)
method. The componentList
variable is a comma-separated list of components with which you no longer want to detect collisions. When no arguments are provided, it will stop collision detection with all entities. Here is an example:
littleBox.bind("HitOn", function(hitData) { Crafty("Obstacle").color('red'); this.ignoreHits('Obstacle'); });
You can see that Crafty not only starts detecting the HitOn
event but also the HitOff
event. That's why the color of the big box does not change back to black.
Another similar method called .resetHitChecks(String componentList)
can be used to re-check for collision between specific components. This method will keep firing the HitOn
event again and again as long as the collision is still happening.
Debugging Collisions
When entities are moving continuously, it is very hard to see if the collisions are being fired at the right time. In the above demo, it looks as if the HitOn
event is firing slightly before the actual event. Crafty gives you the option of drawing hit boxes around entities so that you can actually see what's going on.
There are two components that you can use for debugging purposes. These are WiredHitBox
and SoldHitBox
.
The first component will allow you to use the .debugStroke([String strokeColor])
method, which will draw an outline around the entity with a given color. When no color is provided, the color red is used to draw the outline.
Similarly, the second component is used to fill the entities with a given color using the .debugFill([String fillStyle])
method. When no color is provided, the color red is used. Here is a demo with the .debugStroke()
method.
Creating a Custom Hit Box
You can also create a custom hit box for collision detection. This is helpful when you are using image sprites in your game that are not rectangular. The .collision()
method that you can use to create a custom hit area accepts a single parameter that is used to set the coordinates of the new hit box.
These coordinates can be supplied in the form of a polygon object, an array of x,y coordinate pairs, or a list of x,y coordinate pairs. The points of the polygon are marked in a clockwise manner, and they are positioned relative to the unrotated state of our entity. The custom hit area will automatically rotate itself when the entity rotates.
There are a few things that you should keep in mind when using custom hit areas. The hit area that you define should form a convex polygon for the collision detection to work properly. For those who are unfamiliar with the term, a convex polygon is a polygon with all of the interior angles less than 180°. You might also see slight performance degradation when the hit area that you defined lies outside the entity itself.
The custom hit area that you defined won't have any effect unless you add the Collision
component to every entity with which your hit area needs to detect a collision.
littleBox.collision(80, 0, 100, 100, 50, 100) .debugStroke('green') .checkHits('Obstacle');
In the above demo, we have defined a custom hit box that lies outside the orange box. As you can see, the big block turns blue only when it collides with the triangle. The position of the orange box doesn't matter.
Let's take a look at another example which uses a spaceship by Gumichan01. The default hit box for the spaceship is the boundary of the sprite itself. In the current scenario, the top right corner of the spaceship touches the block first, but that space is actually empty. For users who are playing your game, this is a case of bad collision detection.
What you can do here is define your own hit area using a triangular shape like the following code. The custom hit box polygon that you define can have as many sides as you want. Just make sure that it is still a convex polygon.
spaceShip.collision(8, 0, 0, 48, 70, 48);
Conclusion
After completing all these tutorials, you should now be able to create your own little games with great graphics, nice sound effects, scenes, and collision detection. I should remind you that I have used Crafty version 0.7.1 in this tutorial, and the demos might not work with other versions of the library.
JavaScript has become one of the de-facto languages of working on the web. It’s not without it’s learning curves, and there are plenty of frameworks and libraries to keep you busy, as well. If you’re looking for additional resources to study or to use in your work, check out what we have available in the Envato marketplace.
If you have any questions, let me know in the comments.
No comments:
Post a Comment