Previous topic

Next topic

This Page

Quick search

Turbulenz is an HTML5 game engine and server-side APIs available in JavaScript and TypeScript for building and distributing 2D and 3D games that run on platforms that support HTML5 features such as modern browsers without the need for plugins.

The aim of this guide is to familiarize developers with the SDK,
quickly allowing them to start creating great games for the Turbulenz
platform. We give a brief introduction to some important concepts and
tools, and describe the process of writing, building and running a
simple Turbulenz application.

To learn the basics of how to use Turbulenz APIs read the next section.
If you are comfortable with how to use a basic Turbulenz JavaScript APIs, for example to draw an image to the screen, you can skip this section and move on to the finding the best way to structure a Turbulenz application.

The <canvas> tag is where Turbulenz will draw the game. Think of this as the game window, in this case we’ll make it 640x480 pixels.
Loading the Turbulenz libraries are done by including scripts in the HTML before your game code is executed.

To get started begin by using the core TurbulenzEngine and the GraphicsDevice library to change the background color of the canvas element.
Add the following script tags after the section marked as “Script includes go here”:

The TurbulenzEngine variable will allow you to create instances of the low-level modules such as GraphicsDevice, SoundDevice, NetworkDevice, InputDevice and PhysicsDevice.
You can usually assume the existence of TurbulenzEngine and debug variables because they are automatically added by the Turbulenz build tools when you get to creating Turbulenz apps. In this example we will declare them manually.
To create a graphics module instance add the following code:

vargraphicsDevice=TurbulenzEngine.createGraphicsDevice({});

These creation functions take parameters with construct options (An object literal with properties).
In this case just use an empty object to denote no options.
Now the graphicsDevice is created and the <canvas> element can be cleared with a color.

Now initialize a color array for background color to be set:

varr=1.0,g=1.0,b=0.0,a=1.0;varbgColor=[r,g,b,a];

The bgColor is a 4-dimensional vector specified by [red, green, blue, alpha], where each value is from 0.0 to 1.0.
In this example the color will be yellow.

Having declared the function and passed it to setInterval function of TurbulenzEngine, this will attempt to call the function at the interval specified in milliseconds.
In this case 1/60th of a second or 60 frames-per-second (fps).
Now add this code inside the update function to clear the <canvas> element, which will happen every frame:

This will prepare the frame by calling beginFrame and if successful will clear the screen with the bgColor, then finish the frame.
Now you have function that will attempt to clear the screen yellow at 60fps.
To run the JavaScript code in the browser, navigating to the page by opening the file directly from your filesystem with the default browser or drag and drop the HTML file into the browser of your choice.
If you want to reload the code, refresh the page.
You should now see a yellow box, which from this point will be your game window.

This will create a rectangle with coordinates (x1, y1) and (x2, y2) where (0, 0) is the top left of the screen.
The rectangle will start 50px from the edges of the canvas and will be colored red.
To draw this rectangle with Draw2D add the following code between the clear() and the endFrame() in the update loop:

draw2D.begin();draw2D.draw(drawObject);draw2D.end();

If you refresh the page, you should now see the red rectangle.
The draw2D.draw function is an easy way to just draw an object, but for more flexibility and control, drawing a sprite is better.
Construct a simple sprite by using the Draw2DSprite function, do this under the drawObject declaration:

These will be the initial properties of the sprite.
To draw it, use the drawSprite function and put it after the draw2D.draw function:

draw2D.drawSprite(sprite);

Reload the example and you should see a white diamond in the center of the screen.
Sprite values can be changed via methods such as getColor & setColor.
For a sprite, position can be changed by directly accessing the property on the sprite object.
Define the following angles to use for rotating the sprite below the sprite declaration:

varPI2=Math.PI*2;varrotateAngle=Math.PI/32;

To rotate the sprite add the following in the update function after the code that modifies the background color:

The next step is to start using assets such as images to make the sprite more interesting.
To do this you will need to start hosting the files on a web server.
There are many ways to do this, since you have Python installed as part of the setup, you can start a basic webserver from the command-line in the current directory using the following command:

# For Python 2.7 use
python -m SimpleHTTPServer

Run the command from the same directory as your .html file and navigate your browser to 127.0.0.1:8000 or localhost:8000 you will see a list of files in that directory.
Click on the .html to view the file, it should run as before.
Now you can start loading image files as textures for the sprite.
Start by creating a texture using the GraphicsDevice, after the sprite creation:

To create a texture this way the src image can be a png, jpg, dds or tga.
You can test what a browser supports using the graphicsDevice.isSupported function.
Calling createTexture will cause the JavaScript to request the image.
The onload function will be called when the image has been retrieved and will return the texture object if successful or null if not.
Passing the loaded texture object to the sprite and setting the textureRectangle to use the width and height of the texture will allow the code to start drawing the image.
If you are seeing only a white sprite then check the following notes below:

Note

Draw2D requires the texture to have “power-of-2” dimensions i.e. 16x16, 64x32, 128x512, etc and also to have mipmaps turned on in this example.
The example file complies with these requirements. If you use your own image you need to make sure it does too.

Note

If you are trying to use a file hosted on a different server, that server will need to allow CORS. corsproxy.com will allow you to test it out with images if you do http://www.corsproxy.com/www.website.com/img/name.png for example, otherwise you should do host the files on your own server.

To use a transparent image you will need to change how it is rendered.
In this example move the drawSprite call to its own draw2D.begin and end and set the draw mode to be “additive” which will make dark colors transparent for the particle_spark. It should now look like this:

Once you are familiar with how the Turbulenz APIs can be used you can start creating games against those APIs yourself.
To help you better structure your first app, Turbulenz provides a range of tools, examples and features to make supporting modern and older browsers easier.
These come in the form of file/API servers, code/asset processing tools, build configurations and more.

This section will start to introduce you to these tools and explain some of the terminology Turbulenz use when describing apps.
Code written for the Turbulenz engine can run in several configurations.

Canvas Mode:

Using only the in-built features of the browser. This is
referred to as canvas mode (named after the HTML <canvas>
tag through which modern browsers expose accelerated rendering
features). As well as accelerated graphics capabilities, modern
browsers often allow access to a range of low-level functionality
including sound playback, input events and more.

In canvas mode, the Turbulenz Engine will determine which APIs
are available and use the most suitable of these to provide
functionality to the game. Games using this mode require
sufficiently modern browsers, but end-users with such browsers are
not required to enable any extensions.

With Browser Extensions:

To provide games with a fixed set of features and performance
characteristics on a wider range of browsers, Turbulenz supplies a
small binary plugin that exposes a some native functionality to
JavaScript. Games targeting this configuration will require the
end user to install these extensions. Using the plugin guarantees
that the game will support the full range of popular browsers
across multiple operating systems.

The Turbulenz extensions to the browser include native support for
several features that are not yet available in browsers (such as
physics simulation or rendering to multiple color buffers). Also
included is a JavaScript engine selected and optimized for the
execution of game code. This means that game code will have more
predictable performance characteristics but still have full access
to all the APIs and data, just as the code that drives the rest of
the HTML page.

The set of built-in functionality in modern browsers is continually
increasing, and canvas mode is now a viable option for many games.

The majority of the code that makes up the Turbulenz engine is shared
between both configurations, and similarly games can usually be built
for either configuration without change to the code. We suggest that
developers test and compare the performance of the two configurations
from an early stage. Depending on the support provided by the
browser, there may still be limitations in canvas mode. However the
gap is narrowing all the time.

Note

EXPERIMENTAL
Introduced in SDK 0.25.0 Turbulenz has added support for writing games
in TypeScript. The TypeScript compiler allows developers to write code
in syntax similar to JavaScript with additional type checking and code
verification to help them confidently develop large applications.
More information about TypeScript can be found
here.

The Turbulenz SDK comes with build tools that are run on the game code
before it is executed. These tools can perform several optimization
functions, and also automatically generate the appropriate html code
to load and run the game. The tools support several build ‘modes’:

plugin

A release version of the game (suitable for deployment), using
the browser extensions plugin to provide low level access. The
maketzjs tool is used to bundle JavaScript code and all referenced
libraries into a single .tzjs file that the Turbulenz engine can
load with one request to the server. Code will be executed by the
JavaScript engine embedded in the browser plugin.

Optionally, the code can also be compacted to obfuscate it and
make it as small and fast as possible.

canvas

Equivalent to plugin, except that the browser extensions plugin
is not used. Instead, the platform libraries make use of
functionality built into the browser.

In this mode, code is still bundled into a single file and can be
compacted as in plugin mode. However, the code bundle is a single .js
file, since it must be loaded and run by the browsers own
JavaScript engine.

canvas-debug

Intended for debugging during development. In these modes there
is very little transformation of the JavaScript code. A single
command (using the makehtml tool) takes a .js
template file, and optionally a .html file, as
input and produces a .html file that loads the game. In these
modes the code always runs using the browsers JavaScript engine,
allowing standard web development tools to be used to debug the
code (see Debugging).

The Turbulenz SDK comes with a small server (referred to as the
local development server), intended to be
run on the developer’s machine. This local development server is
capable of serving files, emulating the Turbulenz online services,
recording metrics about the game code and data as well as managing and
deploying game projects.

While it is sometimes possible to launch games directly from the file
system, we recommend that developers use the local development server
to run and test during development. Most browsers require that
applications are run from a server, especially in canvas modes.

Use the plus button on the left of the page to create a new
project, and fill in the ‘Game Directory’ text box with the path of
the directory created in step 1. Click ‘CONFIRM’ in the drop down
box. Add a title e.g. “My First App”. The rest can be left as default for now.

Note

In the game directory field, you must specify the full path. Do not use ~/ to replace /Users/*USERNAME*/

There should now be a manifest.yaml file in your applications
directory.

Create a new file myfirstapp.js in your applications directory
with the following contents:

A file myfirstapp.canvas.debug.html should have been created in the
current directory.

Note

On Linux, the SDK only supports running in canvas mode. Use the command
for canvas-debug below in order to run the app on Linux browsers.

Back in your browser, click on the Play button for your newly
created project. The page should list the file just created
myfirstapp.debug.html. Click on this file to open and run the
application. You will see the default development HTML page
containing an instance of your application (for now just a blank
area).

Try changing the value passed to gd.clear in the code (the
components represent Red, Green, Blue and Alpha values). Re-run the
build step (5) and click reload in the browser.

This example shows the makehtml tool being used to build the
application in canvas-debug mode referred to above. The other modes
can be built as follows.

plugin

For plugin (and canvas mode), a .tzjs code bundle is built using
the maketzjs tool, and then makehtml is used to create
an HTML page to load and run it:

This application simply clears the screen each frame, but it
illustrates the process of building and running code with the
Turbulenz tools. Run either of the above tools with the -h flag
to get a list of available options. In particular, the
maketzjs tool provides support for compacting and obfuscating
JavaScript code.

The Engine requires that the game define an entry point and assign it
to TurbulenzEngine.onload, to be called at load time. In general
the game will use this entry point function to perform some minimal
initialization and schedule asynchronous operations (such as screen
updates and loading) before returning control to the browser.

The TurbulenzEngine global object exposes the
low-level API functionality of the engine. Here the code uses it to
create a GraphicsDevice (through which
graphics API calls are made), before defining the tick function.
Next, the TurbulenzEngine is used again, this
time to schedule the newly defined tick function to be called 60
times per second.

tick uses the GraphicsDevice (via the
gd variable created in the scope of the onloadFn entry point)
to clear the back buffer and display it to the browser window.

Code in other .js files can be imported using markup understood by the
Turbulenz build tools. The majority of the Turbulenz Engine is made
up of JavaScript library code, contained in the jslib directory
that can be imported in this way. When starting a new project we
recommend that developers take a copy of this directory and
immediately submit the unchanged versions to their revision control
system.

Copy the jslib folder from the install path to
C:\dev\myfirstapp (or the location you chose for the simple
example above).

Re-run the commands above to build the .html (and .tzjs) files and
open them in the browser.

JavaScript library code referenced using the technique above is
handled in one of two ways depending on the build mode. In
canvas-debug mode, the html created by makehtml contains
<script> tags that cause the code to be loaded directly into the
page. When using plugin and canvas modes, the .js files are
concatenated into one self-contained file that can be loaded with a
single request to the server.

Although JavaScript is a garbage collected language, it is important
to perform certain shutdown operations manually. In particular, the
online APIs should be explicitly shutdown to notify the server that
the game session is finishing. Explicit shutdown also helps to
guarantee that objects are destroyed in the correct order.

Game code can set the onunload
property of the TurbulenzEngine object to a callback which will be
invoked when the engine is about to be shut down. The game should use
this mechanism to shutdown any libraries and attempt to clear
references. For example, the shutdown callback for the simple
application above might look something like:

This code does several things. It first defines variables
technique and shader which will be set later once the
shader has been loaded. Next it creates a RequestHandler object which is used to load the shader
(note the onload callback which parses the shader data and
creates a runtime shader from it).

Once the shader has loaded and the onload callback has created
it, technique will no longer be null and the contents of the
if statement will be invoked. The code calculates a rotation
angle based on the current time, calculates a suitable
world-view-projection matrix based on the projection matrix from
the camera, sets the loaded shader technique and parameter and then
renders the vertex buffer using that shader.

Build this code and reload the resulting HTML file in your browser.
You should see a rotating cube appear in the scene.

Note

For brevity this code contains no error checking. Production code
should check at least that each object is created correctly and
that the request for the shader succeeds.

It is highly recommended that developers check the return values from
calls to the Turbulenz engine API, particularly during creation of
high-level objects such as the GraphicsDevice
and the SoundDevice where failure to create the
object may indicate that the browser does not support the required
APIs, or the client machine does not have the required capabilities.

The onerror property of the
TurbulenzEngine object can be set to a user-defined callback that will
be invoked when the engine detects a problem. This can catch bugs
such as invalid arguments passed to the API, and so we recommend that
this be set during development:

TurbulenzEngine.onerror=functiongameErrorFn(msg){// Handle the error, using msg to inform the developer// what went wrong.window.alert(msg);};

Note

In canvas mode, error checking in the Turbulenz engine is often
omitted for performance reasons. We recommend that developers
regularly run both the plugin and canvas versions of their games
in order to catch as many coding errors as possible.

Turbulenz recommends Chrome using canvas builds as a debugging and
testing environment, although it is worth experimenting with the
debugging features offered by each of the main browsers. Note that in
some cases the debug modes are simply not supported on a given
browser.

A working debug environment should allow you to set breakpoints, step
through code and view the values of variables.

There are many issues related to processing and loading of assets
which can have an effect on performance and load times. The section
Assets deals with this in more detail, covering topics such as
caching and best practices for asset pipelines.

The Turbulenz SDK comes with a series of tools for converting various
asset types into JSON files. Modern browsers have optimized native
support for parsing JSON, and it is trivial to add custom data to a
JSON file. Browsers generally also support image formats such as PNG
and JPEG for use in textures. Compressed images are fully supported
when running with the Turbulenz browser extensions, but in canvas mode
may require manual decompression in JavaScript.

The Turbulenz tools are provided as a set of standalone command-line
programs. This allows developers to easily integrate them into
existing pipelines or wrap them in their own custom scripts.

Some examples of useful tools for asset creation include:

dae2json:

Converts Collada formatted data into a JSON format understood by
the TurbulenzEngine. It can be instructed to extract only
specific data types, for example animation or physics data, giving
the developer full control over how data is divided and at what
frequency it should be loaded.

The output from this tool is understood by the Scene object and can be passed directly to it at runtime.

The -j flag can be used to force this tool to write JSON in a
human-friendly (but less optimal) format. See the full
description or invoke the tool with the -h flag to
see the full set of options.

cgfx2json:

Reads in .cgfx files, extracts the programs, techniques and
parameters and into the format used by the low-level
createShader method. Thus,
no data transformation is required at runtime to create a shader
from this object.

The full list of tools and their descriptions is given in the Section
Tools.

At runtime, assets are loaded into the game by sending requests to the
server (using the TurbulenzEngine.request function). These requests are carried out
asynchronously, with data or error codes being passed to the
application via callbacks.

To simplify the process of making such requests, handling errors and
dealing with the subtle differences between browsers, the Turbulenz
engine provides some higher level objects such as RequestHandler. Objects such as The Scene Object implement
functionality that developers may find useful for loading and managing
assets at runtime.

The scene_loading sample and the sampleapp application in the SDK
provides examples of asset loading.

The browsers caching mechanisms can have a great effect on load times
for data that is successfully cached. HTTP servers can provide hints
to the browser to tell how which data can be cached and for how long
(although the browser is free to ignore these and potentially use
other criteria to make caching decisions).

The Turbulenz servers consider the staticmax directories to
contain data that changes extremely infrequently. If your game
project contains a staticmax directory then any data loaded from
it will be served with HTTP headers that tell the browser that it can
be cached for a long period of time.

This means that changes to data in the staticmax directories may not
be reflected in your game until the browser cache clears. To avoid
this situation we recommend encoding a hash of the data contents into
the name of the built asset on disk. When the contents changes, the
file name of the asset will no longer appear in the browser cache and
will therefore be reloaded.

Mapping Tables

Since a strategy such as this can make it very difficult to keep track
of which file corresponds to a given source file, Turbulenz recommends
the use of a mapping table, generated when assets are built. This
mapping table is loaded (uncached) by the game to be used to look up
the staticmax file corresponding to a given source file. In this
way, game code can refer to source assets such as myshader.cgfx and
loader code can request the latest version from the server, hopefully
using caching in an optimal way.

The number of individual browser requests can also have an influence
on loading times. Each request carries data overhead due to the HTTP
protocol, and there can be significant latency associated with an
individual request. Grouping data according to when it must be loaded
can help reduce the number of individual requests your game makes to
the server. See the section Add Assets to an Archive for one
method of grouping data.

Check the compiler by running the following command in the root Turbulenz SDK directory:

tsctslib/debug.ts

This command will generate the JavaScript for the camera object in the same directory (tslib).
If the compiler worked, the command should complete with no errors and you can delete the output file after reading it.

If you are using Sublime Text 2 as your default IDE, there are a number of TypeScript projects for Sublime at various stages of development.
The syntax highlighting can be downloaded from the Microsoft page or easily installed from Sublime Package Control

The commands specified in this section were written for use with tsc version 0.9.1. For the latest commands, see the latest project information

Basic compilation

To compile a .ts file to JavaScript simply type:

tscfilename.ts

This will output filename.js and any errors will be listed on the command line.
The output JavaScript file will be located in the same directory as the source file.
To specify a different filename/location, use the –out command e.g.

tsc--outnew_dir/new_filename.jsfilename.ts

Compiling a TypeScript application against Turbulenz

To build a TypeScript app that uses Turbulenz you will need the TypeScript declarations located in jslib-modular and implementation from jslib.
You will need the following directories:

jslib

jslib-modular

The jslib-modular directory has groups of definitions for the following:

SDK 0.25.0

jslib-modular

aabbtree.d.ts: AABB tree used by the scene

base.d.ts: Declarations to augment lib.d.ts

canvas.d.ts: Turbulenz implementation of canvas API

debug.d.ts: Debug functionality

fontmanager.d.ts: Font rendering

jsengine.d.ts: Engine core

jsengine_base.d.ts: Fundamental shared classes in high-level engine

jsengine_debug.d.ts: Extra debug functionality for high-level engine

jsengine_deferredrendering.d.ts: Additions for DeferredRendering

jsengine_forwardrendering.d.ts: Additions for ForwardRendering

jsengine_simplerendering.d.ts: Additions for SimpleRendering

physics2d.d.ts: 2d physics

servicedatatypes.d.ts: References used by services

services.d.ts: Turbulenz online services API

turbulenz.d.ts: Low-level platform API (plugin engine API)

tzdraw2d.d.ts: 2d rendering functionality

utilities.d.ts: Low level shared functions

vmath.d.ts: Turbulenz Math library implementation

webgl.d.ts: Additional declarations for the GraphicsDevice

Added SDK 0.26.0

jlib-modular

capturedevices.d.ts: Declarations for the CaptureDevice

Added SDK 0.27.0

jlib-modular

spatialgrid.d.ts: SpacialGrid implementation

svg.d.ts: SVG rendering declarations

Added SDK 0.28.0

jlib-modular

particlesystem.d.ts: Components of the GPU Particle System

Using this method you will generate JavaScript files for your application, which you can use in conjunction with jslib.
To explain how to do this, we will convert SampleApp to TypeScript and combine it with the jslib-modular declarations.
You will need to start by doing the following:

Create a new folder in SDK_DIR/apps/sampleapp/tsscripts

Copy the following files to the folder structure

SDK_DIR/apps/sampleapp/scripts/sampleappmain.js -> SDK_DIR/apps/sampleapp/tsscripts/sampleappmain.ts (NOTE: Keep the contents of the original file, but change the extension)

SDK_DIR/apps/sampleapp/scripts/sampleappmain.js -> SDK_DIR/apps/sampleapp/scripts/sampleappmain.js.bk (NOTE: Make a backup of the original file)

The declarations in this example require additional declaration files.
If you move the location of jslib-modular, make sure to include all files.

Note

In Visual Studio, the IDE will warn you which classes it can’t find references for and underline them in red.
If you run the TypeScript compiler directly, it will list them in the output.
Once all references have been satisfied, there will be no additional messages.

The output is similar to the original sampleappmain.js file, but the formatting is slightly different.
This command will overwrite the original sampleappmain.js
If you wish to run the release version, you must rebuild the app.

Run the app from the local server and open the debugger.
The source code for the sampleapp should be the TypeScript generated output.
You can breakpoint and step through the code like regular JavaScript in the debug build.

This is the most basic of conversions, but now you are able to start adding TypeScript specific code to the app.

Sometimes when learning how to use Turbulenz features you might want to try changing an existing application to try a new function or different arguments.
Depending which file(s) you change you there are certain files you may or may not have to rebuild.
Changes to this pattern of files require rebuilding the following:

In samples the majority of the example code is located in the template file, hence you will likely need to rebuild all configurations for most changes:

Note

The commands must be run with the Turbulenz Environment enabled from the SDK/samples directory

Assumed variables:

SAMPLENAME - The name of the sample to rebuild e.g. 2dcanvas, animation etc.

TYPESCRIPTNAME - The name of the specific TypeScript file you want to rebuild e.g. debugphysics, morph, sceneloader etc.

JSLIBMODULARDEP - The name of each jslib-modular file the sample depends on e.g. jsengine_base, turbulenz, physics2d etc.
Generally the samples list what they require in the templates file. See jslib-modular.

OTHERDEP - Any other files that the sample requires.

SAMPLESCRIPT - These are the shared scripts that a sample requires to run e.g. morph, motion, sceneloader etc.

[file.ts ..] - Refers to a list of files. You should replace this with the files you require. Do not include the [ and ..].

TypeScript Only:

To rebuild sample helper scripts (shared across samples), you must know their dependencies and include them via the declarations files.
Samples use the jslib and jslib-modular for their TypeScript files.
If not all dependencies are met, the command will display errors and TYPESCRIPTNAME.d.ts will not be generated.

To rebuild sample templates (per sample), you must know what the sample uses and include dependencies via the *.d.ts files in jslib-modular.
The SAMPLESCRIPT files will includes things like the shared scripts that the sample needs.

Apps are structured slightly differently from Samples because the majority of code is located in scripts files, not the main template.
For that reason, making simple changes usually requires less to rebuild for the sake of testing debug configurations:

Note

The commands must be run with the Turbulenz Environment enabled from the SDK/apps/APPNAME directory

Assumed variables:

APPNAME - The name of the app you wish to rebuild e.g. multiworm, sampleapp etc.

APPFILE - The name of any files that make up the app e.g. appscene, wormapp etc.

TYPESCRIPTNAME - The name of the specific TypeScript file you want to rebuild e.g. sampleappmain, inputapp, wormapp.

JSLIBMODULARDEP - The name of each jslib-modular file the app depends on e.g. jsengine_base, turbulenz, physics2d. See jslib-modular.

OTHERDEP - Any other files that the sample requires.

[file.ts ..] - Refers to a list of files. You should replace this with the files you require. Do not include the [ and ..].

TypeScript Only:

To rebuild app scripts, you must know their dependencies and reference them either via the *.d.ts definition files or via *.ts directly.