Thursday, August 9, 2012

Writing a HTML5 Game Engine - UI Layout

Prologue

I will be starting a series of blog posts that will document my experience in creating a HTML5 game engine. First of all, what is the purpose of creating this game engine, aren't there already tons of game engines out there? Yes, surely there are already some great engines out there but I treat this more as an attempt to have a hands-on experience and experiment the inner workings of designing a game engine. This is both challenging and interesting to me so I hope to share my findings along the way that might help others as well.

The target platform for now is mainly desktop browsers. However, as HTML5 becomes more mature, there will be more and more hardware acceleration supported on mobile platforms as well (Testing HTML5 on different platform by Scirra). Typically people would talk about power consumption but I would argue that caching, bandwidth, latency are more of concern. But most of the time the display is what takes up the most energy anyways.

NOTE: None of the contents posted are conclusive so please judge based on your own needs  :)

1) UI Layout 

The first thing to consider is how we should define layout of game entities. Looking at other frameworks, this can either by through markup languages e.g. HTML, Microsoft's XAML, Adobe's MXML or just through code directly e.g. Cocos2D, C/C++. The choice in deciding on the architecture will be very tied into event handling and also rendering algorithm used. Markup languages allow programmers to quickly identify UI elements through scanning tree hierarchy.

<Div> Layout

In HTML5, we can obviously use DOM <div>'s to define our layout. There are several ways of doing this, one way is to do this using jQuery is $(document.body).append("<div class='new'/>");[2]. The issue with this is every time we would need to find the DOM and modify and re-render the HTML generated for it to work. The same applies to using CSS with selector strings. This isn't an efficient process as it requires to parse through the DOM element tree. This process can be slightly sped up with generating id's for each DOM to explicitly find the precise element. 

How about caching selectors? In the context of games, this will require a lot of dynamically DOM elements being injected and removed. For example, if a lot of elements are frequently being added/removed when monsters are being killed. Using the DOM would be slow regardless of caching selectors. 

MainGameContainer









<div id="mainPanel"> MainGameContainer
<div id="childPanel1">Left Panel</div>
<div id="childPanel2">Right Panel</div>
</div>

Left Panel
Right Panel

<style type="text/css">
#mainPanel {
background-color: White;
color: Black;
position:relative;
height:150px;
}
#childPanel1 {
background-color: Blue;
color: White;
position: absolute;
top: 20px;
left: 10px;
width: 30%;
height: 40px;
}
#childPanel2 {
background-color: Red;
color: White;
position: absolute;
top: 40px;
left: 20px;
width: 30%;
height: 60px;
}
</style>

Custom Node Tree

The alternative solution is to have our own custom node tree. Everything will be encapsulated in a object in javascript (equivalent of div) and we can make manipulations on it. It will have children just like DOM divs do. We will have to parse our own node tree to decide which children should appear on top of the other. Obviously this choice comes with great implementation cost but it will allow us to not touch the DOM at all. On the HTML side, it will just look like an embedded Flash application. It is arguable whether this tree traversal is faster than the browser traversing its DOM tree. However, this seems more of an implementation-specific issue for the browser and how you code the tree traversal in javascript.


This seems a lot of work but in later sections it may prove useful for controlling events and rendering. Another factor to consider is related to implementing a rendering engine for this. For the DOM model, we will have to rely on what the CSS styles support and positioning of elements which is sometimes hard to figure out or varies across different browsers. E.g. images may appear blurry on some browsers when u scale it using CSS but not if you specify the image width/height using canvas.context.drawImage [3]. Using your own custom tree will give you the full control in that aspect. You can use a single canvas to draw the entire game space for example.

Compared to the DOM model, the custom nodes we define in javascript will only contain the essentials of what's needed for us to render objects (a DOM object is much heavier [4]) in a game. So I decided to create this custom node tree first. Later I will discuss how this correlates to the rendering engine and UI event handling.