PhoneGap Legends – A Sample Game App

Next week I’ll be representing Adobe at GDC 2013, and demonstrating how Adobe Creative CloudPhoneGap, and PhoneGap Build can be great tools for building casual gaming experiences. In preparation, I’ve been working on a gaming sample application that shows off the potential of HTML games packaged with PhoneGap.

…and now I’d like to introduce you to PhoneGap Legends. PhoneGap Legends is a fantasy/RPG themed demo that leverages HTML DOM animation techniques and targets webkit browsers. I was able to get some really outstanding performance out of this example, so be sure to check out the video and read the details below. The name “PhoneGap Legends” doesn’t mean anything; I just thought it sounded videogame-ish and appropriately fitting.

PhoneGap Legends

PhoneGap Legends

This game demo is an infinitely-scrolling top-view RPG themed game that is implemented entirely in HTML, CSS, and JavaScript. There is a scrolling background, enemy characters, HUD overlays, and of course, our “protagonist” hero – all that’s missing is a story, and general game mechanics like interacting with sprites.

Again, I was able to get some *really outstanding performance* out of this sample, so I wanted to share, complete with source code, which you’ll find further in this post (and I encourage you to share it too). Take a look at the video below to see the game in action on a variety of devices. Every single bit of this is rendered completely with HTML, CSS, and JavaScript – there are no native portions of the application.

Update 3/24:  If you’d like to test this out on your own devices, you can now access it online at http://tricedesigns.com/portfolio/phonegap_legends/   However, it will still only work on webkit browsers (Chrome, Safari, Android, iOS, etc…), and is optimized for small-device screens.  If you attempt to use this on a very large screen, you’ll probably see some sprite clipping.

Disclaimer: This sample app is by no means a complete game or complete game engine. I’ve implemented some techniques for achieving great performance within a PhoneGap application with game-themed content, but it still needs additional game mechanics. I also wrote this code in about 2 days – it needs some additional cleanup/optimization before use in a real-world game.

Source

Full source code for this demo application is available on GitHub. This code is provided as-is: https://github.com/triceam/PhoneGap-Legends. I will be making a few updates over the next few days in preparation for GDC next week, but for the most part, it is stable.

Development Approach

The PhoneGap Legends application was built following the performance tips that I posted earlier this month. The game is built so that it uses a game loop based upon requestAnimationFrame to perform all UI updates. This gives it a scheduled interval that is in sequence with the browser’s redraw cycle.

In general, the DOM is as shallow as possible for achieving the desired experience. All “sprites”, or UI elements are basic DOM nodes with a fixed position and size.  All DOM elements have an absolute position at 0,0 and leverage translate3d for their x/y placement.  This is beneficial for 2 reasons: 1) It is hardware accelerated, and 2) there are very, very few reflow operations.  Since all the elements are statically positioned and of a fixed size, browser reflow operations are at an extreme minimum.

The background is made up a series of tiles that are repeated during the walk/movement sequence:

Sprite Sheet for Background Tiles

In the CSS styles, each tile is 256×256 square, with a background style that is defined for each “type” of tile:

.tile{
    width: 256px;
    height:256px;
    overflow: hidden;
    position: absolute;
    top:0px;
    left:0px;
    background-repeat: repeat;
    background-clip:border-box;
}
.tile_0 {      background: url('../images/background_tiles.png');     background-position: 0px 0px;}
.tile_1 {      background: url('../images/background_tiles.png');     background-position: 256px 0px;}
.tile_2 {      background: url('../images/background_tiles.png');     background-position: 512px 0px;}
.tile_3 {      background: url('../images/background_tiles.png');     background-position: 0px 256px;}
.tile_4 {      background: url('../images/background_tiles.png');     background-position: 256px 256px;}

The content displayed within each of the “sprite” DOM elements is applied using sprite sheets and regular CSS background styles. Each sprite sheet contains multiple images, the background for a node is set in CSS, and the position for each image is set using the “background-position” css style.  For example, the walking animation for the hero character is applied just by changing the CSS style that is applied to the “hero” <div> element.

Sprite Sheet for Hero

There is a sequence of CSS styles that are used to define each state within the walking sequence:

.hero_0_0{ background: url('../images/rpg_sprite_walk.png'); background-position:0px 0px;}
.hero_0_1{ background: url('../images/rpg_sprite_walk.png'); background-position:0px 96px;}
.hero_0_2{ background: url('../images/rpg_sprite_walk.png'); background-position:0px 192px;}
.hero_0_3{ background: url('../images/rpg_sprite_walk.png'); background-position:0px 288px;}
...

This game demo extensively uses translate3d for hardware accelerated composition.  However, note that the 3d transforms are all applied to relatively small elements, and are not nested. All of the “textures” are well below the max texture size across all platforms (1024×1024), and since it uses sprite sheets and reusable CSS styles, there are relatively few images to load into memory or upload to the GPU.

Attribution

The following Creative Commons assets were used in the creation of this sample app and the accompanying video:

Image – Grass Texture: http://opengameart.org/content/grass-with-moss
Image - Trees/Bushes: http://opengameart.org/content/lots-of-hyptosis-tiles-organized
Image - Main Character: http://opengameart.org/content/2d-rpg-character-walk-spritesheet
Image - Enemies: http://opengameart.org/content/rpg-enemies-11-dragons
Image - Compass Rose: http://en.wikipedia.org/wiki/File:Compass_rose_en_04p.svg

Font – Avalon Quest: http://www.ffonts.net/Avalon-Quest.font
Note: I used a free/open licensed font that could be embedded in the app for offline usage. This font was converted to a web-font package that can be embedded in the PhoneGap application using http://www.fontsquirrel.com/

Audio – Monster: http://www.freesound.org/people/Erdie/sounds/167890/
Audio – Music: http://www.freesound.org/people/rap2h/sounds/115261/

Source

Again, in case you missed it above, Full source code for this demo application is available on github. This code is provided as-is: https://github.com/triceam/PhoneGap-Legends.

  • jesse

    awesome work!

  • skeddio

    Thanks for this very interesting article.

    But are you sure PhoneGap is the best way for creating 2D mobile games, while Adobe is providing amazing tools like Gaming SDK, Starling, Scout, etc. with AIR?

    I understand it’s a of Proof of Concepts. You showed that HTML5 can achieve great performances. It’s just a bit pity to not use the right tool for the right task…

    • http://www.tricedesigns.com Andrew

      Adobe has several strategies for building games, including AIR and the gaming platform. I primarily focus on HTML/JS & PhoneGap, not Flash/AIR,and will be representing PhoneGap at GDC. There will be other Adobe staff there to promote Flash platform tools. PhoneGap is a great solution for casual games or “companion apps” to accompany console or pc games. I’d argue that AIR is better for more complicated gaming experiences.

  • Pingback: Using Creative Cloud and CSS Translate3D to Create an 8 Way Character Animation - Renaun Erickson | Renaun Erickson

  • http://cubicmushroom.co.uk Toby G

    Great demo, & great to see such good performance from purely HTML/CSS/JS apps.

    Also spotted a minor error… the link to your character sprite & trees & bushes sprites are the wrong way round.

    • http://www.tricedesigns.com Andrew

      Thanks, it’s fixed!

  • Petar

    Awesome really. I like clean and optimized code and yours really looks that way even if it is a must because of webview’s slower performance. Great job with the demo and phonegap! I’m a native android developer but I have used phonegap in two projects and I have one more underway so I follow your blogs and I find them very interesting.

  • Puja

    This article is very informative. Gives some very useful/helpful insights/ tips how one can improve the overall performance of HTML5 app .

    We have developed a phoneGap based HTML5 game for iOS and the speed and everything is very good. Now, when we are trying to run the same code on Android using phonegap, the speed is very very slow. Did you ever come across such a problem? It would help if you could share some tips/ insights.

    • http://www.tricedesigns.com Andrew

      It all depends on the version of Android that you are trying to target, and whether you are performing DOM animations or Canvas animations. The system web view in Android is notoriously slow. DOM animations perform decently if you use translate3d transformations to force GPU rendering. However, on older versions of Android, it has problems too. If you are using HTML5 Canvas, it is going to be slow. I don’t think any Android devices have a hardware accelerated canvas implementation.

  • Stu

    This look’s great. I would like to get into game development for apps and hopefully looking through what you have here will help be get a sense of what is required

    • http://www.tricedesigns.com Andrew

      Hi Stu,
      This is just a demo app, not a full fledged game. Building a full game would be more complex than this, but hopefully will get you in the right direction. Good luck!

  • Romulo

    Congratulations!
    The engine for moving was really amazing!
    I’m new Phonegap developer and I’m very happy because your sample game.
    Thank you for sharing.

  • sairam

    this is not working, showing blank screen in android and also not working in browser, pls guide me properly…

    • http://www.tricedesigns.com Andrew

      Can you provide any additional details? Were there any error messages? What version of Android, What kind of device, etc…?

  • Eric Berg

    This is really nice! Does the native build of the app run with the same performance as the web version?

  • Part Time Crazy

    really impressed with what you’ve done there! I’ve been looking at attempting a phonegap game (just for the challenge) and I’ve noticed that when i use css3 animations they run and different speeds on an iphone compared to an ipad. Is this something you have noticed and do you know of any way to keep everything at the same frame rate?

    I know I can switch it to jquery animate but I thought css3 animations would be better for the app.

  • http://ghita.org/ Serban Ghita

    Wow, I read this with great curiosity. It seems that you are not using drawImage() at all. In my simple game, I’m using drawImage() for both sprite animation and player placement (X, Y) on canvas.

    I’m curious on running some performance tests, but meanwhile I want to ask you if you think the CSS technique might cause future problems in detecting collisions with other objects? Can you describe any future downsides of this cool technique?

    • http://tricedesigns.com/ Andrew Trice

      With the DOM/CSS technique, you have to manage all of the collision detection & geometries yourself. You can’t just test if the pixels are a certain value. It gives great performance, but is kind of a hack-ish workaround. I think in the future, the HTML canvas will be a better solution. HTML5 Canvas is great on iOS now, but is not as great on other platforms, especially in the Android system web view.

  • carl lindberg

    thanks for a great article/work. Cool! If one would publish this with a start screen and some collision and life/score thing on the iOS app store, would it be approved for the app store you think? I know that some poor performance stuff gets declined. Anyhow I will check more about using the html5 canvas.. i’m about to decide wether to make some 2d platform gravity/running around games with unity, corona … or (the most awesome) html5 via phonegap so it can be used on more platforms.

  • kamesh

    im begginer to android development and my task is to develop android app using
    HTML5 and css.. i dont find any basic code in web .. wil you plz give any link to study html,css and javascript… plz

  • gardenofwine

    I just found this neat proof of concept. Kudos. I’ve tried loading it into an ios phonegap application, but all I get is a blank screen (phonegap/cordova 3.4). Any ideas why that might be happening or what can I do to solve this issue?

  • Tomás Ofen

    Amazing demo. As “gardenofwine” says, i have try to upload the demo to adobe phonegap build to test with new versions of phonegap (3.3.0 at this moment in this platform), and the app doesn’t work. However, if i test it with the minimum available version there (2.5.0) it works like a charm. It would be great if you could make a version with improved code for this new versions of phonegap, so newbies can learn better. Again, cooool demo!