23
\$\begingroup\$

I'm in the process of building a JavaScript / HTML5 game (using Canvas) for mobile (Android / iPhone/ WebOS) with PhoneGap. I'm currently trying to design out how the UI and playing board should be built and how they should interact but I'm not sure what the best solution is. Here's what I can think of -

Build the UI right into the canvas using things like drawImage and fillText Build parts of the UI outside of the canvas using regular DOM objects and then float a div over the canvas when UI elements need to overlap the playing board canvas. Are there any other possible techniques I can use for building the game UI that I haven't thought of? Also, which of these would be considered the "standard" way (I know HTML5 games are not very popular so there probably isn't a "standard" way yet)? And finally, which way would YOU recommend / use?

Many thanks in advance!

\$\endgroup\$
3
  • \$\begingroup\$ Keep in mind that Canvas isn't supported in IE yet (IE9 allegedly will)... so that removes a huge market share for your game. There's a javascript patch that attempts to get it to work in IE, but it falls short of working well (SLOW as hell... not worth it). \$\endgroup\$
    – user4952
    Commented Jan 26, 2011 at 19:03
  • 1
    \$\begingroup\$ @Adam - See flashcanvas: flashcanvas.net \$\endgroup\$
    – ehsanul
    Commented Jan 26, 2011 at 21:02
  • \$\begingroup\$ I use dom elements as gui, mulitple floating divs as "windows" with one window containg canvas element (actual game). And there is always this option: developer.mozilla.org/en-US/docs/HTML/Canvas/… :) \$\endgroup\$
    – Kikaimaru
    Commented Mar 5, 2013 at 8:42

7 Answers 7

18
\$\begingroup\$

Both solutions (drawing on your canvas VS. traditional HTML/CSS) are totally valid and will work just fine. Some things to consider:

  • If you're already using a canvas-based library, your code may be cleaner/more organized by continuing to use canvas instead of having additional (DOM-based) methods for UI.
  • If your UI is extremely text-heavy (with dialogs etc.) then it may be simpler to implement via HTML/CSS. For instance, it's pretty trivial for text to flow in a DOM element (with stuff like wrapping and paragraph spacing) and comparatively difficult to implement in canvas.
  • Depending heavily on the library you're using, it could be much easier to implement click handling on DOM elements than within your canvas. For example if you want to detect a click on an "Ok" button, that's a trivial task in HTML/JS world. But in canvas you'd need to listen to the click on a different element and check its coordinates to see where the click took place.
  • Some user agents (especially mobile devices) can be tricky when using DOM elements containing text. For example, Mobile Safari may want to pop up a modal with the tools to copy/paste. Preventing this behavior might be difficult and would probably be easier in canvas land.

Some of this will be subjective; a developer I know always prefers using canvas since he just finds DOM to be ugly and verbose. Since either solution will work fine, I'd pick a simple single screen in your app, quickly develop it separately using both methods and see which one feels easier/better.

Best of luck!

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for your reply! Very good points. I'm actually building my own engine right now. Started it using Canvas but going to be modifying it a bit to test CSS3/WebKit stuff. Only reason I'm building my own is because the game is too 'simple' for a 'real' engine. We don't even really have a main game loop. The only reason it's even there is for animation, but considering how infrequently those happen we could probably just start/stop timers as needed :) \$\endgroup\$
    – Jason L.
    Commented Jan 6, 2011 at 0:00
5
\$\begingroup\$

I've been using easeljs for my canvas interaction.

It's pretty good and facilitates solid design. One of the key features that made me choose it was the facility to sync the position of your canvas objects and dom elements.

This makes it easy to do CSS speach bubbles and static UI elements like the hud frame and that kind of thing.

The advantage this has for browsers is that you get the rich canvas but you get to pawn off the smaller and static things to the dom to keep performance in check.

\$\endgroup\$
4
\$\begingroup\$

Canvas is slow on mobile platforms, at least mobile safari is anyway, so you'll want go use CSS based positioning of objects on those. Specifically use "translate3d" which will turn on the hardware accelerated rendering of objects.

Check out the CAAT library for canvas though, it's fast and you can use CSS backed "actors" and not change the game logic.

I cannot post links yet but here are some pseudo links http://labs.hyperandroid.com/animation

\$\endgroup\$
4
  • \$\begingroup\$ I think the repo link on CAAT's page is pointing to the old one so make sure you use this one instead! repo: github.com/hyperandroid/CAAT \$\endgroup\$ Commented Jan 5, 2011 at 8:43
  • \$\begingroup\$ (sorry i can only add one link per post currently) Here is a demo I created of which contains a hello-world template for CAAT - onedayitwillmake.com/CAATCirclePack \$\endgroup\$ Commented Jan 5, 2011 at 8:45
  • \$\begingroup\$ Thanks for the links, I'll def. check it out. I have heard rumblings of Canvas being slow but I'm one who usually has to see things himself :) I should also note that the game I'm creating is VERY light on the animations. Never more than one or two running at the same and at intervals of once every 5-10 seconds for a minute at a time. Nothing crazy. Also, to verify, are you suggesting not using Canvas at all but using plain old DOM objects with CSS/translate3d? \$\endgroup\$
    – Jason L.
    Commented Jan 5, 2011 at 12:55
  • \$\begingroup\$ To be honest, I can't say for your specific scenario or not. However if you want to target mobile-safari specfically then imo yeah you would want to use CSS with divs. It's very fast at doing that compared redrawing the canvas from my experience. I was able to easily get 45 image based sprites moving around at 30FPS using 'translate3d' to move them into place. Be sure to place this in the CSS for the objects you plan on moving with 'transform3d', otherwise webkit will animate those objects to where specified instead of placing. -webkit-transition: transform3d 0s linear; \$\endgroup\$ Commented Jan 5, 2011 at 16:29
2
\$\begingroup\$

Have to agree about canvas slowness on iPhone 4. Pretty sure safari canvas is not being backed by GL. My cheezy game runs fast on iPhone 3GS and android but on iPhone 4 I think the retina display has too many pixels, or if canvas isn't riding on GL, this would explain why it drags. I like the canvas development model, haven't tried the css translate3d option yet. In particular I used GWT and the gwt-g2d canvas wrapper (optimization/obfuscation). http://www.photonjunky.com/shootout.html

\$\endgroup\$
1
\$\begingroup\$

I would suggest keeping your controls as html elements such as menu and command for accessibility reasons. Using a bit of CSS you can display elements over a canvas, and not lose out on the pre-built functionality of HTML.

\$\endgroup\$
1
\$\begingroup\$

I know this is an old question, but today (March 2013) we know better. I decided to answer in case someone else stumbled in here like I did. I have to disagree with most of the other answers. They are probably valid for web browser development, but not for mobile. It makes a great difference which path you choose (DOM or canvas animation). The Android webview is completely useless (slow, stuttering) in itself, which makes Phonegap useless for Android game development, unless you can apply hardware acceleration, which is currently only possible using canvas animation and a suitable framework. For more info, see this reply.

\$\endgroup\$
0
\$\begingroup\$

You can do it a million ways. However you feel most comfortable and your engineers feel most confident.

If you're looking for inspiration or a code example then, here's one way that I do it. I have a function that repeatedly draws a menu until a button is pressed. When the button is pressed, the game loads and the old menu click event listeners are removed and new game click event listeners are added. I also end the old draw loop of the menu and start a new game draw loop. Here's some selected snippets to give you the idea of how its done:

Game.prototype.loadMenu = function() {
  var game = this;
  var can = this.canvas;

  // now we can use the mouse for the menu
  can.addEventListener('click', game.menuClickEvent, false);
  can.addEventListener('touchstart', game.menuClickEvent, false);

  // draw menu
  this.loop = setInterval(function() { game.drawMenu() }, 30);
};

Game.prototype.drawMenu = function() {
  // ... draw the menu
}

Game.prototype.loadLevel = function(levelstring) {
  // unload menu
  var can = this.canvas;
  var game = this;
  can.removeEventListener('click', game.menuClickEvent, false);
  can.removeEventListener('touchstart', game.menuClickEvent, false);

  if (this.loop) clearInterval(this.loop);

  // ... other level init stuff


  // now we can press keys for the game
  //can.addEventListener('click', game.gameClickEvent, false);
  can.addEventListener('touchstart', game.gameClickEvent, false);
  can.addEventListener('keydown', game.gameKeyDownEvent, false);

  this.loop = setInterval(function() { game.tick() }, 30);
}

// called from tick()
Game.prototype.draw = function(advanceFrame) {
  // ...
}

This way I'm able to separate out game drawing and game events from menu drawing and menu events. It also gives me leeway to use game/animation elements in my menus should I want to make them look real pretty.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .