CreateJS

Creating a Multiplayer Game with TogetherJS and CreateJS

Bubble Hell Duel is a multiplayer HTML5 dogfighting game. The object of the game is to dodge bubbles launched from your opponent while returning fire. This game was written mainly as a prototype for learning and the source code is available on GitHub. You can try the game out in single or multiplayer here. Currently the game does not contain any sound effects but uses CreativeJS and TogetherJS.

screenshot

In this post I would like to share some of my experiences when developing the game. Please share your thoughts in the comments if you agree or have other suggestions.

Game Engines

When developing a 2d game you can write you own engine or make use of some fantastic libraries that are available. After spending a few days looking at the various options available I decided to use CreateJS. As I have some experience with Flash, CreateJS made sense for my needs as there was not much of a learning curve. I also wanted to make use of some Flash animations and CreateJS supported this feature. I will elaborate a bit more on animations later in the article.

As I am a C++ developer I believe emscripten is also a good choice. It allows C/C++ code to be compiled to JavaScript, which can be executed in the browser. I am of the opinion that the static type checking and compile-time optimizations are great assets when developing large code bases. I have used emscripten before and it works very well, but for this project I wanted the fast and convenient prototyping capabilities of JavaScript. I also wanted to expand my JavaScript knowledge.

I’d like to mention a few other libraries that seem very interesting: Cocos2d-x is making an emscripten port and they already support HTML5 binding. I also like pixi.js as it provides a webGL renderer but also supports Canvas fallback when the browser does not support webGL.

C++ vs JavaScript

At first I was a little bit worried about the performance of JavaScript, and that was the reason my decision between using CreateJS or emscripten was difficult. Fortunately a simple benchmark showed that a naive collision detection algorithm with about 400 balls on screen could still reach 40+ fps, which was enough for my simple experiment.

As someone who has coded more in C++ than JavaScript I loved how quickly I could translate my thoughts into code and test them out on multiple browsers. On the other hand it was not very comfortable debugging my JavaScript. C++ compilers are quite good at pointing out misspellings and other mistakes that cause runtime issues. While the “use strict” directive and other mechanisms like closure compilers have their purpose they were not very helpful to me especially when variables became undefined. Rooting for the cause of errors can be somewhat difficult comparatively.

As an example of difficult debugging, I encountered the following issue. I was using float numbers for coordinates and other geometric values like angles. These values were passed to the other player using the TogetherJS.send method for synchronization:

var player = { x: 10.0, y: 10.0 };
TogetherJS.send({type:'sync',x:player.x,y:player.y});
TogetherJS.hub.on('sync', function(msg){
    enemy.x = msg.x;
    enemy.y = msg.y;
});

This worked, but lots of decimals were sent in this way, so I decided to relax the accuracy:

TogetherJS.send({type:'sync', x:Math.round(player.x), y:Math.round(player.y) });

Then I thought integers might not be accurate enough for collision detection, so I added more digits to the messages:

TogetherJS.send({type:'sync', x:player.x.toFixed(2), y:player.y.toFixed(2) });

While this seemed a reasonable solution, it actually induced a bug that was very hard to find and I did not notice it until I tested the game after implementing some more features. I noticed while playing the game the opponent would never move.

It took me hours in debugging before I could locate the cause. I do not think I would have made this mistake using C++.

If you would like to see this bug in action take a look at this jsFiddle project. Look at the three canvas tag outputs and you will notice the third canvas contains the bug. This issue occurs because toFixed returns a string representation.

I am not sure using a closure compiler would have avoided this issue, but I did find in another project that it definitely helps with optimizations.

Animation with Flash

As with most games I wanted to use a good deal of animation. I was very familiar with creating animations in Flash and found that CreateJS supported several ways of consuming the Flash animations and presenting them in HTML5. CreateJS is a set of libraries and tools used to create interactive HTML5 content. So by using CreateJS I could consume my animations as well as use the other libraries available for loop handling, resource management and in the future, sound manipulation. For a quick introduction to CreateJS take a look at this video.

CreateJS, which Mozilla now sponsors, offers great support for Flash animations.

There are two ways of using Flash animations in HTML5 with CreateJS. The first option is to directly export the Flash animation in a way that you can access all the elements in their original form, including paths, transformations and tweens. The advantage to this approach is that it produces smaller files, and CreateJS allows you to transfer them into a sprite sheet on the client side, for faster rendering. Adobe Flash CS6 offers the CreateJS Toolkit plugin that allows the designer to export all the content of an animation to HTML5 files. This generally results in a JavaScript file with all the graphics and tweens, an HTML file, and a set of image files. You can open up the HTML document in your browser and see the animation.

Another option is to export the animation into a sprite sheet, that is an image containing all the frames with a JavaScript file describing the position and size of each frame. These files can be easily integrated into HTML based games or applications via the SpriteSheet class in CreateJS. This is the approach I used for this game. To see the code where I use the SpriteSheet have a look at this link. If you want some more detail on this approach take a look at this video.

I should also note that you can use a tool called Zoë to export directly to a sprite sheet or a JSON file from a Flash Animation as well.

marisa

The above image is an example of a sprite sheet that I use in the game and was generated as described above. The original image came from the game Touhou Hisouten ~ Scarlet Weather Rhapsody, which is availabe at http://www.spriters-resource.com.

Multiplayer with TogetherJS

On my first iteration of the code the game was not multiplayer. Originally it was a single-player bullet hell game, with a boss foe randomly moving across the screen. I could not last more than 30 seconds before succumbing to withering fire. It was interesting enough that I thought multiplayer would be exciting.

I had heard of Together.js not long after it was released. The jsFiddle project is powered by Together.js and offers an impressive collaboration mode. This led me to using Together.js in my game. It is also very nice that Mozilla offers a default hub server simplifying the process of creating a multiplayer web based game. To learn more about Together.js be sure to check out this article.

It was easy and comfortable integrating Together.js into my game, as it works like other event dispatcher/listeners frameworks.

With Together.js, I was able to implement random match and invitation only multiplayer modes in the game. I did face a few design challenges that I had to overcome when designing the communication protocol.

First off, I did not put code in to prevent cheating with two-party communications and assumed a certain level of trust between players. In the game design currently all collision detection of a player is done locally. Theoretically if you block corresponding messages you can mask that you have taken damage.

Another area that I hacked a bit is that the bubbles of the enemy avatar are generated locally and randomly. This means that the bubbles seen from your character avatar are not necessarily the same as your opponent is seeing.

In practice neither of these shortcuts should ruin the fun of the game.
I did encounter a couple of issues or caveats with Together.JS.

  • I did not find a way to disable the cursor updating in Together.js. While this is useful in collaborative tools I did not need it in my game.
  • I am using Together.js in an asymmetric way, where both players see themselves as the red skirted Avatar (Reimu). This allows for easier placement of the player at the bottom of the screen and the opponent at the top. This also means that when you move the main player from an opponent’s view of the game your move is seen as the opponents move and vice versa.

The Fun of Making Mistakes

There are two visual effects in the game that came as unexpected surprises:

  • When a round finishes and the message ‘You Win’ or ‘You Lose’ appears, the time is frozen for a few seconds. This acts like a dramatic pause.
  • When a charge attack is released, the bullets are fixed and then gradually blown away toward the enemy.

Neither of these effects was designed in this way. I didn’t want the pause and I wanted the bullets to continue rotating around the player upon releasing. However I made mistakes, and the result seemed to be much better than I had planned, so they made the final cut.

Conclusion and Future Plans

It is always fun learning new things. I like the fact that I could prototype and visualize pretty quickly. In the future I might add more patterns for the bullet curtains, and a few sound effects. In addition I will probably also draw more background images or possibly animate them.

While developing the game I did realize in order to get a natural and intuitive feel required more effort than I expected. This is something I have always taken for granted while playing game.

The code is open source, so feel free to fork and play. Be sure to comment if you have any suggestions for improving the game or the existing code.

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

WebGL & CreateJS for Firefox OS

This is a guest post by the developers at gskinner. Mozilla has been working with the CreateJS.com team at gskinner to bring new features to their open-source libraries and make sure they work great on Firefox OS.

Here at gskinner, it’s always been our philosophy to contribute our solutions to the dev community — the last four years of which have been focused on web-standards in HTML and Javascript. Our CreateJS libraries provide approachable, modular, cross-browser-and-platform APIs for building rich interactive experiences on the open, modern web. We think they’re awesome.

For example, the CreateJS CDN typically receives hundreds of millions of impressions per month, and Adobe has selected CreateJS as their official framework for creating HTML5 documents in Flash Professional CC.

Firefox OS is a perfect fit for CreateJS content. It took us little effort to ensure that the latest libraries are supported and are valuable tools for app and game creation on the platform.

We’re thrilled to welcome Mozilla as an official sponsor of CreateJS, along with some exciting announcements about the libraries!

WebGL

As WebGL becomes more widely supported in browsers, we’re proud to announce that after working in collaboration with Mozilla, a shiny new WebGL renderer for EaselJS is now in early beta! Following research, internal discussions, and optimizations, we’ve managed to pump out a renderer that draws a subset of 2D content anywhere from 6x to 50x faster than is currently possible on the Canvas 2D Context. It’s fully supported in both the browser and in-app contexts of Firefox OS.

We thought about what we wanted to gain from a WebGL renderer, and narrowed it down to three key goals:

  1. Very fast performance for drawing sprites and bitmaps
  2. Consistency and integration with the existing EaselJS API
  3. The ability to fall back to Context2D rendering if WebGL is not available

Here’s what we came up with:

SpriteStage and SpriteContainer

Two new classes, SpriteStage and SpriteContainer, enforce restrictions on the display list to enable aggressively optimized rendering of bitmap content. This includes images, spritesheet animations, and bitmap text. SpriteStage is built to automatically make additional draw calls per frame as needed, avoiding any fixed maximum on the number of elements that can be included in a single draw call.

These new classes extend existing EaselJS classes (Stage and Container), so creating WebGL content is super simple if you’re familiar with EaselJS. Existing content using EaselJS can be WebGL-enabled with a few keystrokes.

Layering Renderers

This approach allows WebGL and Context2D content to be layered on screen, and mouse/touch interactions can pass seamlessly between the layers. For example, an incredibly fast game engine using WebGL rendering can be displayed under a UI layer that leverages the more robust capabilities of the Context2D renderer. You can even swap assets between a WebGL and Context2D layer.

Finally, WebGL content is fully compatible with the existing Context2D renderer. On devices or browsers that don’t support WebGL, your content will automatically be rendered via canvas 2D.

While it took some work to squeeze every last iota of performance out of the new renderer, we’re really happy with this new approach. It allows developers to build incredibly high performance content for a wide range of devices, and also leverage the extremely rich existing API and toolchain surrounding CreateJS. Below, you’ll find a few demos and links that show off its capabilities.

Example: Bunnymark

A very popular (though limited) benchmark for web graphics is Bunnymark. This benchmark simply measures the maximum number of bouncing bunny bitmap sprites (try saying that 5 times fast) a renderer can support at 60fps.

Bunnymark

The following table compares Bunnymark scores using the classic Context2D renderer and the new WebGL renderer. Higher numbers are better.

Environment Context2D WebGL Change
2012 Macbook Pro, Firefox 26 900 46,000 51x
2012 Macbook Pro, Chrome 31 2,300 60,000 26x
2012 Win 7 laptop, IE11 (x64 NVIDIA GeForce GT 630M, 1 GB VRAM) 1,900 9,800 5x
Firefox OS 1.2.0.0-prerelease (early 1.2 device) 45 270 6x
Nexus 5, Firefox 26 225 4,400 20x
Nexus 5, Chrome 31 230 4,800 21x

Since these numbers show maximum sprites at 60fps, the above numbers can increase significantly if a lower framerate is allowed. It’s worth noting that the only Firefox OS device we have in house is an early Firefox OS 1.2 device (has a relatively low-powered GPU), yet we’re still seeing significant performance gains.

Example: Sparkles Benchmark

This very simple demo was made to test the limits of how many particles could be put on screen while pushing the browser to 24fps.

Sparkles

Example: Planetary Gary

We often use the Planetary Gary game demo as a test bed for new capabilities in the CreateJS libraries. In this case, we retrofitted the existing game to use the new SpriteStage and SpriteContainer classes for rendering the game experience in WebGL.

Planetary Gary

This was surprisingly easy to do, requiring only three lines of changed or added code, and demonstrates the ease of use, and consistency of the new APIs. It’s a particularly good example because it shows how the robust feature set of the Context2D renderer can be used for user interface elements (ex. the start screen) in cooperation with the superior performance of the WebGL renderer (ex. the game).

Even better, the game art is packaged as vector graphics, which are drawn to sprite sheets via the Context2D renderer at run time (using EaselJS’s SpriteSheetBuilder), then passed to the WebGL renderer. This allows for completely scaleable graphics with minimal file size (~85kb over the wire) and incredible performance!

Roadmap

We’ve posted a public preview of the new WebGL renderer on GitHub to allow the community to take it for a test drive and provide feedback. Soon it will be included it in the next major release.

Follow @createjs and @gskinner on twitter to stay up to date with the latest news and let us know what you think — thanks for reading!

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)