Chapter 1. Introduction To Impact
Impact is a JavaScript game framework created by Dominic Szablewski. Impact takes advantage of the modern browser’s Canvas element in order to create high-performance 2D games on the Web and even mobile. One of the biggest advantages of using Impact is that it is easy to pick up, comes with very good code examples, has an active community, and has a very robust level editor called Weltmeister. The only barrier of entry is the licensing fee for the software, since it is not open source. After purchasing a license, you do get the full source code, the Weltmeister level editor, and free current major version updates (1.x). While there are other open source and free JavaScript game frameworks out there, Impact has an extra level of polish I haven’t seen with anything else so far.
Why Use Impact?
Perhaps one of the most appealing factors of buying Impact is the inclusion of a sample Objective-C project that allows you to compile your Web game into a native iOS app. This enables your game to take advantage of OpenGL for graphics and OpenAL for sound instead of the Canvas and Audio elements in the mobile Safari browser. This solution gives your game almost native-like performance on iOS, and it can be packaged up and sold in the Apple Store just like a native app.
Here are some links to help you learn more about Impact and examples of it in action:
Tools you will need:
- PHP
For saving levels created with Weltmeister.
- Apache
For locally hosting and testing your game.
- IDEs
Impact has no IDE dependencies; you can create your games with any simple text editor. I prefer to use WebStorm or PHPStorm since these IDEs, which are made by JetBrains, offer code hinting, project management, refactoring, and debugging.
- Browsers
Impact works very well on WebKit browsers, especially Chrome, but any modern browser with support for Canvas and the Audio tag should also work.
Setting Up a Local Environment
Before getting started, we are going to have to set up a simple Web development environment in order to take full advantage of Impact and its level editor. Plus, by setting up a local development environment, we can simulate what it will be like to host the game in a production environment. Let’s take a look at configuring Apache, the IDE, and Impact itself.
Install WebStorm/PHPStorm
While you can use any basic text editor, I prefer to use an IDE that offers a more robust set of features such as code hinting, refactoring, project management, version control integration, and a debugger. JetBrains has two IDEs that both handle JavaScript/HTML5 development. If you only plan on doing JavaScript development, I would suggest using WebStorm. If you need to do HTML5 and PHP development (which comes in handy since Impact’s level editor uses PHP) you should look at PHPStorm.
Installing these applications is straightforward. Here are URLs for each IDE:
Each IDE has a 30-day trial and after the trial costs $99 for a license. There are a lot of resources out there on how to use each IDE, so I am not going to cover it here.
Install Apache/PHP/MySQL
There are many guides for installing Apache and PHP on your operating system of choice. Here are some simple one-click solutions to help get you up and running as quickly as possible:
- Mac
For Mac, you should use an all-in-one solution such as MAMP. This is a free one-click solution for getting Apache, PHP, and MySQL set up on your Mac. Likewise, you can also use the built-in version of PHP that comes with OS X, but you will need to do some manual configuration of Apache to get it working. Simply do a search for “Enabling PHP in Mac OS X” in order to find instructions.
- PC
Just like on Mac, there are some excellent one-click solutions for setting up Apache, PHP, and MySQL. I have used XAMP in the past, and have had excellent success with it.
Other Hosting Options
If you prefer not to work on a LAMP (Linux, Apache, MySQL, PHP) stack you can check out the following projects that allow you to run Impact on different hosting environments:
- Node.js
Conner Petzold made a Node.js module that allows Impact to run on a Node HTTP server. His Node-Impact module is on GitHub.
- .NET
You can run Impact on IIS and .NET thanks to Mike Hamilton’s ImpactJS-IIS-.NET-API project.
- Ruby
Chris Darroch put together a Sinatra backend for Impact. Just remove the .php extensions for the API calls in your
lib/weltmeister/config.js
and fire upimpact.rb
.- Python
Joe Esposito has a GitHub project that implements a backend server in Python for Impact to let you develop multiple games at once.
Setting Up a New Impact Project
Impact is a self-contained project. Each game you create will require you to copy the default Impact project folder (which you get once you buy a license) into a new location on your server and start from scratch. Impact is set up so you can easily do all your work from your local host.
To get started, copy the Impact project into your local host. You should see the following files (Figure 1-1).
As you can see, I have renamed my impact
folder residentraver
, which is the name of the game we
are going to create in this book. Here is a quick breakdown of everything
in the folder:
- index.html
This is the main .html file that runs your game.
- lib
This is the core code for Impact and where you will store your own game-specific JS files. This also contains the source code for Weltmeister.
- media
This is the assets directory, and where all game art and sound files will go.
- tools
This directory contains .php scripts to minify your game’s JS files and make it harder for people to have access to the game’s source code. This is part of the license and is important so you don’t accidentally distribute the source code.
- weltmeister.html
This is the level editor’s .html file.
You should now have everything you need to run your first game. If you open your browser and navigate to http://localhost/residentraver[1] you should see the following page (Figure 1-2).
Before moving on, I just wanted to take a quick moment to look at the index.html file and how it is set up. Open it up in your editor and you should see the following HTML code:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Impact Game</title> 5 <style type="text/css"> 6 html,body { 7 background-color: #000; 8 color: #fff; 9 font-family: helvetica, arial, sans-serif; 10 margin: 0; 11 padding: 0; 12 font-size: 12pt; 13 } 1415 #canvas { 16 position: absolute; 17 left: 0; 18 right: 0; 19 top: 0; 20 bottom: 0; 21 margin: auto; 22 border: 1px solid #555; 23 } 24 </style> 25 26 <script type="text/javascript" src="lib/impact/impact.js"></script> 27 <script type="text/javascript" src="lib/game/main.js"></script> 28 </head> 29 <body> 30 <canvas id="canvas"></canvas> 31 </body> 32 </html>
Outside of the style
tag, you may
notice there isn’t a lot of code actually embedded in the page. We have
two script
tags that load in the
impact.js
framework and our main.js
JavaScript file. Finally the only tag in
body
is the Canvas element.
Note
The Canvas element is part of the HTML5 spec and is what actually allows Impact to run in the browsers. Think of the canvas as an image that we can draw bitmap data into. Impact takes care of all the underlying code we would have had to write in order to display game graphics to the screen. You can learn more about how the Canvas tag works at the whatwg.org Canvas page. It’s also important to note that the Canvas element only works in modern browsers such as Chrome 13+, Safari 3.2+, Firefox 6+ and IE 9+. For a full list of browsers that support the Canvas element, go to http://caniuse.com/#search=canvas.
You can also add your own HTML code around the Canvas element and
design this page to look like any other HTML file. Just keep in mind that
we use the canvas
id
in our game in order to tell impact where to render our game’s graphics
to, so don’t change it unless you update your game’s initialization
logic.
Now we are ready to learn more about the Impact framework.
Modules
Impact’s source code is organized into modules. Since JavaScript
itself does not have an include()
function that can load other JavaScript source files into an object,
Impact has its own system. A module typically looks like this:
1 ig.module( 2 'game.my-file' 3 ) 4 .requires( 5 'impact.game', 6 'impact.image', 7 'game.other-file' 8 ) 9 .defines(function(){ 10 // code for this module 11 });
The first block defines the module name 'game.my-file
', which directly corresponds to the
file name. Modules and their dependencies typically reside in the lib/
folder of your Impact project directory, and subdirectories are included
in a path to these files using object-model dot syntax. Therefore, the
my-file.js
file sits in the lib/game/my-file.js
.
The second block defines any additional files that will be loaded at
runtime. Since JavaScript itself does not have an established way to load
other JavaScript source files into an object, Impact has its own system.
The modules listed in the .requires()
method will be loaded from the lib/impact/game.js
, lib/impact/image.js
, and lib/game/other-file.js
project directory,
respectively. These required files will be loaded before the module’s body
and before the last block of the above module example is executed.
The last step the module takes is to execute the function passed to
the .defines()
method. This linear
process allows you to control when code is loaded and run. It’s important
to follow Impact’s file naming and location structure since it will try to
automatically load these resources for you during the pre-load phase.
Next, we’ll talk a little more about classes in Impact and how they
work.
How Classes Work
In JavaScript, there is no real notion of a traditional class structure like you have in other OOP languages. In JavaScript, everything is an Object. While this allows JavaScript to be incredibly flexible, it also makes it difficult to structure your code in a reusable way. To solve this issue, Impact has a pseudo-class object, which is the basis of every class we will create in our game.
Note
Impact’s class object is based on John Resig’s simple JavaScript inheritance code (http://ejohn.org/blog/simple-javascript-inheritance), but it is extended with deep copying of properties and static instantiation.
Here is an example of how we can create a new person class by building off of Impact’s core Class object:
1 // Create a new class "Person" 2 var Person = ig.Class.extend({ 3 name: '', 4 init: function( name ) { 5 this.name = name; 6 } 7 }); 8 9 // Instantiate an object of the first class 10 var e = new Person('John Doe'); 11 e.name; // => John Doe
You may have noticed that we actually extend the functionality of
the ig.Class
object via the .extend()
method.
Note
In traditionally class based languages, the extends keyword allows us to copy over the existing functionality of another class. This is what will allow us to infuse additional functionality into all of our game classes without having to actually duplicate code all over the place.
In addition to extending off of ig.Class
, you can actually extend off of any
custom class you create. Again, in order to extend another class you
simply use the .extend()
functionality.
Here we are going to extend off of our person class to create a new zombie
class:
1 // Create another class by extending the "Person" class 2 var Zombie = Person.extend({ 3 init: function( name ) { 4 this.parent( 'Zombie: ' + name ); 5 } 6 }); 7 8 // Instantiate an object of the second class 9 var p = new Zombie('John Doe'); 10 p.name; // => Zombie: John Doe
All classes that are created with .extend()
will also have an .extend()
method that can be used for further
subclassing. When working inside of extended classes, you can use .this
and .parent
for scope. You will see later on how
splitting up core logic into individual classes will help expostulate
functionality and make our game code easier to maintain while we develop
it.
Core Classes
Impact is made up of several core classes that revolve around the
game framework and all the necessary systems such as rendering, maps,
sounds, and more. All the classes are in the ig
namespace, which is set up by the core class.
Here is a list of the main classes used in Impact along with a short
description of what they do:
- ig Core
The
ig
object provides the module definition and loading capabilities as well as some utility functions.- Animation
An
ig.Animation
object takes care of animating an entity or BackgroundMap tiles. Frames from anAnimationSheet
—an image with all animation frames—are drawn as specified by the animation’sframeTime
and sequence.- AnimationSheet
ig.AnimationSheet
is a thin wrapper around anig.Image
object. It specifies thewidth
andheight
properties for each animation frame in the sheet. It is used by theig.Animation
class.- BackgroundMap
An
ig.BackgroundMap
draws tiles from a Tileset, as indicated by its 2D data array.- CollisionMap
An
ig.Collision
takes a 2D TileMap and allows tracing against it for collisions.- Entity
Interactive objects in the game world are typically subclassed from this base entity class. It provides animation, drawing, and basic physics. Subclassing your entities from
ig.Entity
ensures that it can be added to the game world, react to the CollisionMap along with other entities, and be added to a level within Weltmeister.- Font
An
ig.Font
object loads a specially formatted font image and allows you to draw text with it.- Game
ig.Game
is the main hub for your game. It hosts all currently active entities, BackgroundMaps, and a CollisionMap. You can subclass your own game class fromig.Game
.- Image
ig.Image
is a wrapper around image resources (.png, .gif, .jpeg). It takes care of loading and scaling the source image. You can draw the whole image by calling.draw()
or just one tile of it by calling.drawTile()
.- Input
ig.Input
handles all keyboard and mouse input.- Loader
ig.Loader
is the default pre-loader for all images and sounds that the game needs. By default, it displays a white progress bar on a black background.- Map
ig.Map
is the base class forig.BackgroundMap
andig.CollisionMap
. It only provides basic access to the tiles in the map data.- Music
ig.Music
offers the ability to play a list of background music in order or randomly.- Sound
An instance of
ig.Sound
represents a sound file to be used as background music or game sound.- SoundManager
The SoundManager takes care of loading sounds and providing them for
ig.Music
andig.Sound
instances. An instance of the SoundManager is automatically created atig.soundManager
by theig.main()
function.- System
ig.System
takes care of starting and stopping the run loop and calls the.run()
method on the current game object. It also does the housekeeping forig.Input
and provides some utility methods.- Timer
The
ig.Timer
has two distinct modes of operation. You can either get the difference by calling.delta()
between the current time and the timer’s target time (as set by the constructor or.set()
) or just get the current tick—the time since the last call to.tick()
.
You can learn more about each of these classes and their methods on Impact’s website under the documentation section at http://impactjs.com/documentation.
How Inner Classes Work
In traditional class-based languages, you usually have the option to put a class inside of another class’s package structure. These are called inner classes. Impact has its own version of this, which allows us to add more than one class to a single module file.
Creating an inner class is similar to making a normal class, with the exception that you will be adding it to the end of the main class’s module. These inner classes also support inheritance as well. Here is a quick example of two classes in the same module:
1 ig.module( 2 game.entities.myclass' 3 ) 4 .requires( 5 'impact.entity' 6 ) 7 .defines(function(){ 8 EntityMyClass = ig.Entity.extend({ 9 //Properties and methods go here 10 }); 11 12 EntityMyInnerClass = ig.Entity.extend({ 13 //Properties and methods go here 14 }); 15 });
This technique is incredibly helpful when it comes to keeping your code organized, as you will see later in the book.
Level Editor
One of the best features of Impact is its level editor called
Weltmeister. It is located in the libs/weltmeister
folder inside the Impact
project. We will go through using this editor in the next chapter, but I
wanted to take some time to highlight its features and how to use
it.
You can pull up the level editor anytime by navigating to the root
of your project’s domain and loading the weltmeister.html
file. You will be presented
with this screen:
When you load the editor for the first time, you are presented with
an empty untitled.js
map file. Along the top are
your main controls such as Save, Save As, New, and Load. Reload Images
allows you to make visual tweaks to your map without having to do a hard
refresh. Finally, on the far right, you will see a large arrow that
shows/hides the layers, and below that are your map’s layers. By default,
there is an entities layer, which is where your player, monster, and other
in-game elements will go. You can add new layers at any time by pressing
the plus sign on the right of the Layers label.
Note
Layers simply allow you to draw level tiles onto the stage just as you would use a stamp tool in a painting program. If your game’s level is incredibly detailed, you may want to break out parts of the level’s tiles into a background, middle ground, and foreground layers as well as creating other layers for collision detection and additional details. Anything that moves in the game will go into the entities layer.
Before we can start making levels for our game, we need to create some graphics. Let’s take a look at the asset pipeline, and more importantly, how to create graphics for Impact projects.
[1] Based on how Apache is set up on your computer, you may have a different URL for your localhost. If you are using MAMP, it may be http://localhost:8888, or with XAMP it is http://localhost. Refer to your Apache documentation for the correct URL.
Get Building HTML5 Games with ImpactJS now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.