HTML and CSS Reference
In-Depth Information
The three following methods—
each
,
eachInvoke
, and
detect
—are the same as the ones described in
Chapter 2. They exist as helper methods to make it easier to perform operations on the items list. The difference
between
each
and
eachInvoke
is that the former takes an actual callback method, whereas the latter calls
a method stored as a property on the object. You'll notice each of these methods calls the
Function.call
method with exactly two parameters instead of
Function.apply
, which could support any number of para-
meters passed as an array. The reason for this is that to call
Function.apply
a new array object needs to be
created, which is something that any good HTML5 Engine should try to avoid wherever possible for methods
that are called frequently to limit the stutters caused by the garbage collector.
NOTE
As an HTML5 game programmer, you have only one real enemy: the garbage collector. JavaScript is
a garbage-collected language, which means that the developer doesn't need to worry about allocating and
freeing memory. The downside to this, however, is that at certain intervals JavaScript needs to clean up no-
longer-used pieces of memory itself by running a garbage collector. The collector can take some time to run,
sometimes more than 100ms, leading to a noticeable stutter in gameplay. The goal of any JavaScript engine
should be to create as few objects as possible over the course of a normal frame and save the creation of ob-
jects for situations where real game objects like sprites need to be created.
The functionality for adding and removing objects also works the same as in Chapter 2, with the
add
,
remove
, and
forceRemove
methods performing the same tasks as before with only the addition of a
call to the object's
destroy
method and some triggered events. There is also an additional index on the
id
of the object. If you remember the
Q.GameObject
code from Chapter 10, the
destroy
method also
calls
remove
, which could lead to an infinite recursive loop. This is the reason you added the
GameOb-
ject.destroyed
property, which allows you to remove an object by calling
GameObject.destroy()
or
Stage.remove(object)
and have the engine behave correctly either way.
To make it easier to look up objects on the stage by their
id
, the
stage
object keeps both the sorted items'
array as well as an object that is used as a hash to key objects to their
id
s.
The collision methods are also similar to what you saw in Chapter 2. The
overlap
method has been pulled
out and is placed as a method directly on
Q
primarily to make it easier to reach for scoping reasons. The primary
method for doing bounding box collisions—
Stage.collide
—calls a helper method called
_hitTest
that
uses the
Q.collide
method. The definition for
_hitTest
could have been embedded as an anonymous
function directly inside of
Q.collide
, but this would have led to the function definition being parsed on every
call, slowing down the engine slightly and adding to the garbage that needs to be collected.
Finally, the
step
and
draw
methods loop over each of the objects in the list and call the appropriate method
on each as well as trigger events before and after. The
draw
method also calls the optional sort function to
make sure objects are drawn in the correct z order.
Rounding Out the Scene Functionality
The last bit of code needed for scenes are some helper methods for staging, clearing, pausing, unpausing, and
looping the game. These utility methods are added directly onto the
Q
object instance.
Add the code in
Listing 11-9
to the bottom of the
Quintus.Scenes
module before the final closing curly
brace.
Listing 11-9:
Scene and stage utility methods