KiwiJS v1.2.0 – Kiwi.Log Debug System

Hello, and welcome to a new feature in KiwiJS v1.2.0! Today we’re looking at debugging – a vital part of any development cycle, and one which is much more powerful in this release.

It’s time to put console.log to bed. Say hello to Kiwi.Utils.Log, a more powerful way to manage your debug output.

An Introduction to the Console

If you have never developed with a console before, now’s the time to start. The browser console is a place where you can see messages and execute code.

The console is located in a different place in each browser, so you may have to go looking. On my desktop, Chrome provides it in the menu “View->JavaScript Console” or by clicking the menu button and selecting “More tools->JavaScript Console”; Firefox has it under “Tools->Web Developer->Web Console” or by clicking the menu button and selecting “Developer->Web Console”; and Safari has it under “Develop->Show Error Console”.

Not only does the console show you messages and logs from your code, it can also accept code input directly. This is very useful for tweaking behavior on the fly, looking up properties of objects, etc.

This article continues on the assumption that you understand the basics of the console.

Aliases

Debug logging is inherently messy. You’ll probably want to insert debug code into many lines, and it should be as fast to type as possible.

We’ve added a convenient alias to Kiwi.Utils.Log. You can access everything via Kiwi.Log, and in fact that’s what we do in KiwiJS itself.

If you want to go even faster, add this at the start of your game:

Basic Output

Based on console methods, Kiwi.Log has three ways to output messages. You can log, warn, and error.

Logs

Logs are simple feedback messages. In most modern browsers, they will report the source file and line number on which that log was executed. You should use this for most purposes.

Warnings

Warnings should appear differently in the console. Most browsers will put a warning sign next to them. In Chrome, they are conveniently yellow, which stands out against other logs.

Errors

Errors are more significant messages. They usually appear red. In addition, they will typically report a stack trace. This is a very useful output, which tells you not only what line was executed, but the line of every function that took it to that point. Errors and stack traces are excellent tools for figuring out exactly where you are in your logic flow.

An error will not interrupt your program. It’s just a special kind of log.

Concatenated Output

You can supply any number of arguments to output methods.

Using Tags

You can add tags to your logs to aid in filtering. It’s simple: just add a string starting with a hash (#). Any such string in the arguments of a log method will be recorded as a tag.

Note that a tag must start with the hash. Only that character is checked.

Showing Logs

Logs are recorded. You can go back and access the records using various techniques.

Filtering with Tags

Any show method can take tags, just like an output method. This will restrict its return to only those messages that include that tag.

If your game contains lots of debug messages, tags are a great way to filter through the mess.

Stack Trace Warning

When accessing recorded logs, stack traces are no longer accurate. This is because they are no longer being executed in their actual place in the code. You should always consult errors in-situ.

Methods for Showing Logs

You can use the following methods to show logs:

  • showAll() displays the entire log.
  • showLogs() displays all messages logged with log().
  • showWarnings() displays all messages logged with warn().
  • showErrors() displays all messages logged with error().
  • showLast() displays the last message logged. If you specify tags, it will display the last message logged with that tag.
  • showTimePeriod() displays all messages logged within a certain time range. This uses a Unix time, measured in milliseconds since 1970-01-01T00:00. This is currently 1.422 trillion, which is a difficult number to handle. We recommend you specify the time range as milliseconds before now, for example Kiwi.Log.showTimePeriod( Date.now() - 10000, Date.now() - 5000 ) to show all logs from 5 to 10 seconds ago.

Configuring Output

Logs are useful during development, but they have little purpose after the product ships. You should probably remove all debug code for your release build. However, if there are good reasons to maintain it, you can at least prevent it from clogging up the console.

Set Kiwi.Log.display = false to mute all output. The log will still be recorded, but it won’t be displayed in the browser console.

Set Kiwi.Log.record = false to disable recording. The log will still be displayed, but it won’t add any more records.

Set Kiwi.Log.enable = false to disable the log entirely. You can still access records, but messages will not be printed to the console, and the log will not record anything more.

Be careful with logs. Your game updates some 60 times per second, and logs can very rapidly become very large. It’s trivially easy to push so much data into your console that the whole browser freezes. By configuring your output, you can avoid this inconvenience.

Game Designer’s Log, Supplemental

We hope you find this new tool to be useful. It’s a big step forward for controlling and recalling your debug process. Now set course for the undiscovered country of future productivity – second star on the right, and straight on til morning.

That’s it for KiwiJS v1.2.0. We’ve covered all the cool new bits. But as always, there’s plenty more on the horizon! Stay tuned for the next great adventure.

New Tagging System and Object Selection, Part I (Kiwi.js v1.1.0)

Hello, and welcome to the fourth in a series of in-depth articles about Kiwi.js v1.1.0, now available for use at www.kiwijs.org. Today we’ll be talking about object selection, and how the new tagging system can help you manage complex scenes. I’m Ben Richards, and we’ll be exploring object selection together. Unlike other articles in this series, I wasn’t part of the development team for these features. But I do sit next to the current team. His name is also Ben. (Ben Harding.)

Who Needs to Read This Post?

Most users. If you’re managing a scene with lots of content, you’ll find these methods useful for quickly accessing specific objects. You’ll also learn something about the scene graph.

Scene Graph

Kiwi.js uses a scene graph. This is a powerful tool for organising your scenes.

Scene Order: First In First Out

When you add game objects to a State, you do so in the order they are drawn. For example, consider the following scene:

  1. Landscape (StaticImage)
  2. Wreckage (StaticImage)
  3. Alien Warrior (Sprite)
  4. Player (Sprite)
  5. Rain (ParticleEffect)

This will draw the landscape first, then draw obstacles and characters on top of that, and finally draw rain on top of everything. This makes sense. You wouldn’t want to draw the landscape over the characters.

Groups: Building A Tree

To organise your scenes, you can add objects to Groups. A Group simply holds a series of objects. When it comes to render order, groups are replaced by their contents, preserving their order.

Groups are also objects, and can be added to other groups. This can quickly lead to very complex scenes. For example, if you add the following objects to a game:

  1. Background
  2. Group Alexander
  3. Group Byron

The groups will not render, but they will be considered in the order they are added.

Now add objects to these groups:

  1. Add Alien Warrior X to Group Byron.
  2. Add Group Cicero to Group Alexander.
  3. Add Alien Warrior Y to Group Alexander.
  4. Add Alien Warrior Z to Group Cicero.

What order will they render in?

The answer is ZYX, even though we added them in order XYZ. How can this be? Let’s look at the new scene graph, indicating the numeric order in which objects will render.

  • (1) Background
  • Group Alexander
    • Group Cicero
      • (2) Alien Warrior Z
    • (3) Alien Warrior Y
  • Group Byron
    • (4) Alien Warrior X

As you can see, it just goes top to bottom.

Use this functionality to preserve order in your scenes.

Note that groups are not rendered objects. They are simply a structure that tells the game to render their children in order. While you can set their visibility and transform them, you cannot change the alpha of a group. You must change the alpha of its children instead.

States Are Groups

Under the hood, a State is just a fancy Group with some extra abilities. When you add children to the State, you’re really just populating a root group. It would be more accurate to represent the scene thus:

  • State
    • (1) Background
    • Group Alexander
      • Group Cicero
        • (2) Alien Warrior Z
      • (3) Alien Warrior Y
    • Group Byron
      • (4) Alien Warrior X

Tools to Preserve Order

We’re already seeing some complicated structures in these examples. But imagine how complex it would become to manage a scene with thirty aliens. How do you access them all – or acquire sub-groups?

Members and Tracking Lists

States and groups maintain membership lists.

Groups have a list called members. This is simply an array of all children on the object. It is not exactly the same thing as all children beneath the object; if a child is a group with its own children, members will only record the group. You can access the members of a group through standard array access methods, e.g.

States are a kind of group, so they already have a members array. You may access this in the same way.

States also have a secret _trackingList array. This is not intended for user access, so try not to touch it or something might break. Internally, it tracks every object that was created while the state was active, which is very close to the set of members of the state and all its sub-members.

You’ll note that this does not make it very easy to access components of a complex scene graph. For example, if you want to check every alien against your player’s position, but the aliens are stored in several different groups, how might you go about this?

Note: It’s confusing to swap between “members” and “children” all the time. We’re planning to deprecate “members” in favour of “children” in the near future.

Identifying Objects

There are three main ways to identify objects: names, IDs, and tags.

Names

Objects are named when you create them. You may name a Group on creation by passing it a string after specifying its state, e.g. new Kiwi.Group(state, "groupName"). Groups without a specific name are called “”. Other game objects are named after the name you gave their texture atlas; for example, consider the following declaration:

The value of background.name is "background", because this is what you named the texture.

Names are not at all guaranteed to be unique. For example, any object you create using the “background” texture will also be named “background”. In general, assume that names are unreliable identifiers.

IDs

Objects are assigned a UUID upon creation. The UUID is a Universally Unique Identifier. It’s a long string that looks a bit like "2816f873-c232-4746-b81e-d89aa3332c32".

Unlike names, UUIDs are practically unique. Think of them as random numbers. It is theoretically possible for two UUIDs to be generated with the same value, but the odds are significantly lower than you being struck by a meteorite. For all intents and purposes, a UUID is effectively unique.

Tags

Groups and renderable objects can be tagged using new methods in Kiwi.js v1.1.0. A tag is a simple string, and an object can have any number of tags.

You can add a tag to an object using addTag as follows:

It’s pretty simple – you don’t need to create a list or anything, just supply one or more tags.

You can remove a tag from an object using removeTag as follows:

You can check for tags using hasTag as follows:

Tags are very useful for identifying and collecting broad categories of items without having to write your own arcane code to probe the scene. Tags don’t do anything you couldn’t do another way, but they are very handy for common tasks. For example, you might tag several types of object with “enemy”.

We’ll explain how to use this information in part II.

In Review

Today we’ve learned about the scene graph and object identifiers.

Next Time

In the next article, we’ll look at ways to use this information.

Benjamin D. Richards