In a place where your fantasy can roam free, there won't be any boundaries to what your imagination can create.
Misha’s Tech Playground
graphics, fun and code play
I'm crazy - but who cares? My ideas are constantly dwelling and this is the place for them to pour out and form into something good. Only active participation will ultimately make this place come to life.
Choosing the right Graphics Technique for a Browser Based Game
Whether if you are doing a puzzle game, a tricky jump 'n run or a full fledged mmorpg, be it a simply casual or a long term persistent browser based game, you'll certainly need one thing: images and animations.
As mentioned in last weeks article, you have the choice of implementing the right drawing technique. However, there are vast performance differences. So there is no technique that fits them all, merely you'll need to decide on a case by case basis what you are going to use.
Since trying out everything only to realize that there were some tiny details you weren't aware of in the first place isn't actually fun, I am providing an in depth review of each technique.
We'll go into detail about each techniques pro's and con's and you'll learn how you would go about animating your game graphics in the technique of your choice.
At the end of this article you'll also find a matrix containing the most important facts from this review.
A Short side-note for Those Looking to Create Flash Games:
This article won't include information about Flash or Actionscript. There are already a lot of really great tutorials and articles on this topic out there. I don't think I need to be making another tutorial containing the same information. Have a look at GotoAndPlay.it which is an awesome source for anyone interested in making Flash games.
(X)HTML Image Nodes
Pros
- Compatibility generally good
- Drawing handled completely by the browser
- Depth sorting integrated (style.zIndex)
Cons
- Slow for lots of animations
- No image transformations beside translation and scale
- No integrated path animation
- Only rectangular shapes (see Text)
Details
Using (X)HTML to display your game graphics, means basically sticking to good old image nodes:
-
<img src="images/myImage.gif">
Nowadays we all have more or less modern browsers that support css, which is a good thing. With css you can display images without using image nodes while gaining a little bit more control over how they are displayed.
The big advantage of this technique is that you get results blazingly fast. You put an image node or a block element into your markup, you set a few style properties and there you go.
Of course, if you are to make a dynamic game, you would append your game graphics programmatically with JavaScript.
If you are going to have sprites and collision detection, you might want to stick each sprite into a container that you use for the actual position on screen and the collision detection itself. The advantage of this is that you'll save a few calculations while calculating intersections and positioning. The disadvantage is clearly that the browser has one node per sprite more to take care of. If you are going to have sprites animated by JavaScript, then you'll need even another node extra, acting as the mask for it.
Using nothing but HTML and it's DOM alone leaves you also to rectangular 2d shapes and images, although there is a nice example of a 3d maze utilizing css borders. You won't be able to use rotations or skewing which somewhat diminishes your possibilities.
This is one of the reasons that this technique isn't the best for highly dynamic games containing lots of animations or effects. However, it is well suited for puzzles and adventure games as these naturally don't have too much action.
Although HTML isn't the fastest solution when it comes to animation, it is the most flexible. You have 3 major possibilities to have your sprites come to life. Each one has good and bad sides of it's own.
Animation Via elm.scrollTop
Pros
- Fastest for DOM animation in Safari and Opera
- Good for animating many images at once
- Very fast on Safari and Opera
Cons
- Can be slow in Firefox < 3.0
- Needs extra node as mask
- Slow for many individual
How to
-
//sprite classes for scrollTop / scrollLeft
-
-
CGE.Sprite = new AJS.Class({
-
box: null, // for tiles this is the tile container, pos is relative to it
-
img: null,
-
spriteH: 0,
-
spriteW: 0,
-
// get x and y directly from object, faster for anim
-
z: 0,
-
frames: null,
-
init: function(url, pos, size, parent, useBox) {
-
this.img = AJS.IMG({src: url});
-
if(useBox)
-
this.box = AJS.DIV({className: CGE.STYLE_SPRITE}, this.img);
-
if(pos)
-
this.setPos(pos);
-
if(size)
-
this.setSize(size);
-
if(parent)
-
AJS.ACN(parent, this.box);
-
},
-
get: function() {
-
return this.img.src;
-
},
-
set: function(url, size) {
-
this.img.src = url;
-
},
-
getPos: function() {
-
return [this.box.offsetLeft, this.box.offsetTop];
-
},
-
setFrame: function(name, n) {
-
this.box.scrollTop = this.frames[name][n][CGE.Y];
-
this.box.scrollLeft = this.frames[name][n][CGE.X];
-
},
-
setPos: function(pos) {
-
AJS.setLeft(this.box, pos[CGE.X]);
-
AJS.setTop(this.box, pos[CGE.Y]);
-
AJS.setDepth(this.box, pos[CGE.Y]);
-
},
-
setSize: function(size) {
-
this.spriteH = size[CGE.HEIGHT];
-
this.spriteW = size[CGE.WIDTH];
-
AJS.setHeight(this.box, this.spriteH);
-
AJS.setWidth(this.box, this.spriteW);
-
}
-
});
-
CGE.AnimSprite = CGE.Sprite.extend({
-
isPlaying: false,
-
isMirrored: true,
-
sign: true, // true=add, false = substract
-
frames: null,
-
key: null,
-
init: function(url, pos, size, parent, isPlaying) {
-
this.parent(url, pos, size, parent, true);
-
this.key = {name: "base",num: 0}
-
this.isPlaying = (isPlaying);
-
this.frames = {base: [[0,0],[32,0],[64,0],[96,0],[128,0],[160,0]]};
-
},
-
getFrame: function() {
-
return this.key;
-
},
-
setFrame: function(name, n) {
-
if(n>= this.frames[name].length)
-
n = 0;
-
this.parent(name, n)
-
this.key = {name: name, num: n};
-
},
-
next: function() {
-
if(this.isPlaying)
-
this.setFrame(this.key.name, ++this.key.num);
-
},
-
pause: function() {
-
this.isPlaying = false;
-
},
-
play: function(name) {
-
if(name)
-
this.key.name = name;
-
this.isPlaying = true;
-
},
-
stop: function() {
-
this.pause();
-
this.setFrame("base", 0);
-
}
-
});
Example
animating an elements scroll property with Javascript
Animation Via elm.style.backgroundPosition
Pros
- Fastest for DOM animation in Firefox
- No extra node needed as mask
- very well suited for sprite sheets
Cons
- Slowest DOM animation in Safari and Opera
- Setting image url or position involves string modifications
- Slow for lots of sprites
How to
-
// sprite classes for backgroundPosition
-
-
CGE.Sprite = new AJS.Class({
-
box: null, // for tiles this is the tile container, pos is relative to it
-
img: null,
-
spriteH: 0,
-
spriteW: 0,
-
// get x and y directly from object, faster for anim
-
z: 0,
-
frames: null,
-
init: function(url, pos, size, parent, useBox) {
-
this.img = AJS.DIV({style: "background:url("+url+")"});
-
if(useBox)
-
this.box = AJS.DIV({className: CGE.STYLE_SPRITE}, this.img);
-
if(pos)
-
this.setPos(pos);
-
if(size)
-
this.setSize(size);
-
if(parent)
-
AJS.ACN(parent, this.box);
-
},
-
get: function() {
-
return this.img.src;
-
},
-
set: function(url, size) {
-
this.img.src = url;
-
},
-
getPos: function() {
-
return [this.box.offsetLeft, this.box.offsetTop];
-
},
-
setFrame: function(name, n) {
-
this.img.style.backgroundPosition = -this.frames[name][n][CGE.X]+"px "+ (-this.frames[name][n][CGE.Y])+"px";
-
//this.box.scrollLeft = this.frames[name][n][CGE.X];
-
},
-
setPos: function(pos) {
-
AJS.setLeft(this.box, pos[CGE.X]);
-
AJS.setTop(this.box, pos[CGE.Y]);
-
AJS.setDepth(this.box, pos[CGE.Y]);
-
},
-
setSize: function(size) {
-
this.spriteH = size[CGE.HEIGHT];
-
this.spriteW = size[CGE.WIDTH];
-
AJS.setHeight(this.box, this.spriteH);
-
AJS.setWidth(this.box, this.spriteW);
-
AJS.setHeight(this.img, this.spriteH);
-
AJS.setWidth(this.img, this.spriteW);
-
}
-
});
-
CGE.AnimSprite = CGE.Sprite.extend({
-
isPlaying: false,
-
isMirrored: true,
-
sign: true, // true=add, false = substract
-
frames: null,
-
key: null,
-
init: function(url, pos, size, parent, isPlaying) {
-
this.parent(url, pos, size, parent, true);
-
this.key = {name: "base",num: 0}
-
this.isPlaying = (isPlaying);
-
this.frames = {base: [[0,0],[32,0],[64,0],[96,0],[128,0],[160,0]]};
-
},
-
getFrame: function() {
-
return this.key;
-
},
-
setFrame: function(name, n) {
-
if(n>= this.frames[name].length)
-
n = 0;
-
this.parent(name, n)
-
this.key = {name: name, num: n};
-
},
-
next: function() {
-
if(this.isPlaying)
-
this.setFrame(this.key.name, ++this.key.num);
-
},
-
pause: function() {
-
this.isPlaying = false;
-
},
-
play: function(name) {
-
if(name)
-
this.key.name = name;
-
this.isPlaying = true;
-
},
-
stop: function() {
-
this.pause();
-
this.setFrame("base", 0);
-
}
-
});
Example
animating an elements backgroundPosition with Javascript
Animation Via elm.style.top/elm.style.left
Pros
- Fast for DOM animation
- Very well suited for sprite sheets
Cons
- Setting image url or position involves string modifications
- Needs extra node as mask
- Slow for lots of sprites
How to
-
// sprite classes for style.*
-
-
CGE.Sprite = new AJS.Class({
-
box: null, // for tiles this is the tile container, pos is relative to it
-
img: null,
-
spriteH: 0,
-
spriteW: 0,
-
// get x and y directly from object, faster for anim
-
z: 0,
-
frames: null,
-
init: function(url, pos, size, parent, useBox) {
-
this.img = AJS.IMG({src: url});
-
if(useBox)
-
this.box = AJS.DIV({className: CGE.STYLE_SPRITE}, this.img);
-
if(pos)
-
this.setPos(pos);
-
if(size)
-
this.setSize(size);
-
if(parent)
-
AJS.ACN(parent, this.box);
-
},
-
get: function() {
-
return this.img.src;
-
},
-
set: function(url, size) {
-
this.img.src = url;
-
},
-
getPos: function() {
-
return [this.box.offsetLeft, this.box.offsetTop];
-
},
-
setFrame: function(name, n) {
-
this.img.style.top = -this.frames[name][n][CGE.Y]+"px";
-
this.img.style.left = -this.frames[name][n][CGE.X]+"px";
-
},
-
setPos: function(pos) {
-
AJS.setLeft(this.box, pos[CGE.X]);
-
AJS.setTop(this.box, pos[CGE.Y]);
-
AJS.setDepth(this.box, pos[CGE.Y]);
-
},
-
setSize: function(size) {
-
this.spriteH = size[CGE.HEIGHT];
-
this.spriteW = size[CGE.WIDTH];
-
AJS.setHeight(this.box, this.spriteH);
-
AJS.setWidth(this.box, this.spriteW);
-
}
-
});
-
-
CGE.AnimSprite = CGE.Sprite.extend({
-
isPlaying: false,
-
isMirrored: true,
-
sign: true, // true=add, false = substract
-
frames: null,
-
key: null,
-
init: function(url, pos, size, parent, isPlaying) {
-
this.parent(url, pos, size, parent, true);
-
this.key = {name: "base",num: 0}
-
this.isPlaying = (isPlaying);
-
this.frames = {base: [[0,0],[32,0],[64,0],[96,0],[128,0],[160,0]]};
-
},
-
getFrame: function() {
-
return this.key;
-
},
-
setFrame: function(name, n) {
-
if(n>= this.frames[name].length)
-
n = 0;
-
this.parent(name, n)
-
this.key = {name: name, num: n};
-
},
-
next: function() {
-
if(this.isPlaying)
-
this.setFrame(this.key.name, ++this.key.num);
-
},
-
pause: function() {
-
-
-
-
this.isPlaying = false;
-
},
-
play: function(name) {
-
if(name)
-
this.key.name = name;
-
this.isPlaying = true;
-
},
-
stop: function() {
-
this.pause();
-
this.setFrame("base", 0);
-
}
-
});
Example
animating an images style.* with Javascript
SVG Shapes and Images
Pros
- Filters
- Define symbols for later use
- Can utilize style sheets
- Portability
- Scalable graphics (vector art)
- 3d vector graphics
- Sub-Pixel Accuracy
- Integrated path animation
- Depth sorting integrated (style.zIndex)
Cons
- Level of Implementation vastly different between browsers
- Compatibility (only through Plugins for IE)
- Very slow rendering
- Declarative Animation (as of now) only available in Opera and ASV
- Sub-Pixel-Accuracy causes artifacts during animation: (image)
Details
Scalable Vector Graphics (SVG) is primarily (as the name suggests) a format for vector art. It's main advantage is therefore obviously its seamless scalability. The format is already mature and boasts a lot of useful treats that online game developers could leverage.
The main problem here is that the standard, despite it's maturity is not very well supported by most of todays browsers. A notable exception is Opera which supports almost 90% of the current SVG 1.1 Standard. Firefox and Safari are up close, but lack most of font and all of the declarative animation features.
Internet Explorer, as usual, has no integrated support at all but relies on third party plugins. The most prominent being Adobe SVG Viewer (ASV).
While scalability is it's strength, speed or efficiency certainly isn't. Doing animation in SVG is a real resource hog, be it scripted or declarative — redrawing lots of splines or images with subpixel accuracy takes it's toll, not to forget the xml tree parsing that is involved as well anytime you change a property of a single node.
In my opinion, SVG could potentially be a big player for puzzle games, adventures with less action. It is very well suited for high quality, low bandwidth interface design that is nearly impossible with raster images. Take a look at the examples to see some interface widgets in action.
Declarative Animation
Pros
- Trigger event driven animation without JavaScript
- Easy to define
- Time based, not frame based
Cons
- Currently only available in Opera (and plugins)
- Very slow
How to
-
<!-- svg animation node -->
-
<animateTransform attributeName="transform" additive="sum" type="translate"
-
dur="60s" values="0 0;0 50;50 50;50 0;0 0" repeatCount="indefinite"/>
Example
W3C SVG animation specification and examples
Animation Via elm.x/elm.y
Pros
- Compatibility, works with plugins and browsers with native SVG support
Cons
- Very slow
How to
-
//sprite classes for scripted SVG animation
-
-
CGE.SvgSprite = new AJS.Class({
-
pat: null,
-
sym: null,
-
img: null,
-
-
dH: 32,
-
dW: 32,
-
dX: 0,
-
dY: 0,
-
-
sH: 32,
-
sW: 32,
-
sX: 0,
-
sY: 0,
-
-
init: function(patId, symId, pos) {
-
var def = AJS.$("def");
-
var svgGrp = AJS.$("svgGrp");
-
var unique = (new Date().getTime());
-
-
-
this.pat = AJS.$(patId).cloneNode(true);
-
this.pat.setAttribute("id", patId + unique);
-
-
this.sym = AJS.$(symId).cloneNode(true);
-
this.sym.setAttribute("id", symId + unique);
-
this.sym.firstChild.nextSibling.setAttribute("fill", "url(#"+patId + unique+")");
-
-
def.appendChild(this.pat);
-
def.appendChild(this.sym);
-
-
this.img = document.createElementNS("http://www.w3.org/2000/svg", "use");
-
this.img.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#"+symId + unique);
-
this.img.setAttribute("x", pos[CGE.X]);
-
this.img.setAttribute("y", pos[CGE.Y]);
-
-
svgGrp.appendChild(this.img);
-
-
this.dX = pos[CGE.X];
-
this.dY = pos[CGE.Y];
-
},
-
paint: function() {
-
this.pat.firstChild.nextSibling.setAttribute("x", -this.sX);
-
this.pat.firstChild.nextSibling.setAttribute("y", -this.sY);
-
-
this.img.setAttribute("x", this.dX);
-
this.img.setAttribute("y", this.dY);
-
},
-
-
});
-
-
CGE.SvgAnimSprite = CGE.SvgSprite.extend({
-
goFwd: true,
-
isPlaying: false,
-
numFrames: 6,
-
showFrame: 0,
-
-
init: function(patId, symId, pos) {
-
this.parent(patId, symId, pos);
-
},
-
-
next: function() {
-
var frm = this.showFrame;
-
frm = (++frm) % this.numFrames;
-
-
this.sX = frm * this.sW;
-
this.paint();
-
}
-
});
Example
Canvas drawing
Pros
- Compact API
- Composite operations (Filters)
- Canvas can be used as image buffer or texture
- Image transformations including rotation and skew
Cons
- No integrated depth management (depth determined by drawing order)
- No image masking (beside image alpha channel)
- No integrated path animation
Details
Last but surely not least let's look at Canvas. Originally proposed by Apple and integrated into Webkit for usage in their Dashboard client and Safari Browser, for some time already it is also adapted by Gecko Browsers (i.e. Firefox) and Opera.
Opera even now even sports a 3d extension to canvas, though this is considered highly questionable as it's API seems very immature and isn't backed by any standard.
Microsoft (as usual) is slow in the following, but there is a workaround code from Google available to get your canvas application to also work in IE.
Canvas though doesn't have any convenience features built in, such as path animation, depth sorting, stylesheet support or animation. Which doesn't necessarily mean that you can't add most of these features on your own.
Animation is an easy task as you would just have to redraw each modified element once you changed any of it's parameters - something that is done implicitly with DOM or SVG. But this is exactly the feature you can leverage to build extremely efficient (at least in relation) animations with canvas.
- Draw your static background to a canvas object that is not visible
- Draw your static foreground to a canvas object that is not visible
- Now, while you periodically repaint the visible canvas, paint in this order:
background → dynamic content → foreground
This, for example, saves you from having to repaint or adjust thousands of floor tiles anytime you move through your game world - something that more or less happens when you were to use DOM animation.
Talking of floor tiles – canvas makes it really easy to draw only those parts you really need. Just paint all your tiles to a non-displayed canvas object and access this later on as an image.
-
var sX = yourAnimatedValueX;
-
var sY = yourAnimatedValueY;
-
var sW = realCanvas.width;
-
var sH = realCanvas.height;
-
-
var dX = 0;
-
var dY = 0;
-
var dW = realCanvas.width;
-
var dH = realCanvas.height;
-
realCanvasContext.drawImage(mapCanvas, sX, sY, sW, sH, dX, dY, dW, dH);
You basically don't move your map around inside your canvas but move the visible mask over your map. I haven't tested this with real life size maps yet, but I suppose filling a canvas with a somewhat larger map, even though not visible, might get problematic.
Keep in mind that if you use 40 × 40 pixel small tiles, you will get a 40.000 × 40.000 pixel large map if you have an array of just 100 tiles squared.
Build Your Own Animation
Pros
- Fast! (magnitudes faster than HTML or SVG for sprites)
- Textured 3d vector graphics
- Compatibility (already widely adopted)
- Much faster than HTML or SVG for large or lots of animations
Cons
- Not yet a sanctioned standard by the W3C (though most likely in HTML 5)
- Compatibility (though there is a google fix for IE)
How to
-
//sprite classes for canvas animation
-
CGE.Gfx = new AJS.Class({
-
context: null,
-
image: null,
-
-
// destination coords
-
dH: 0,
-
dW: 0,
-
dX: 0,
-
dY: 0,
-
-
// source coords
-
sH: 0,
-
sW: 0,
-
sX: 0,
-
sY: 0,
-
-
// current frame number to show
-
showFrame: 0,
-
// member of the frame object to use
-
useFrame: null,
-
-
init: function (url, pos, size, ctx, frm) {
-
this.dX = pos[0];
-
this.dY = pos[1];
-
this.dH = size[1];
-
this.dW = size[0];
-
this.sH = size[1];
-
this.sW = size[0];
-
this.context = ctx;
-
this.useFrame = frm;
-
-
this.set(url);
-
this.paint();
-
},
-
-
paint: function () {
-
//this.context.clearRect(this.dX, this.dY, this.dW, this.dH);
-
this.context.drawImage(this.image,
-
this.sX, this.sY, this.sW, this.sH,
-
this.dX, this.dY, this.dW, this.dH);
-
},
-
-
get: function () {
-
return this.image.src;
-
},
-
-
set: function (url) {
-
if(typeof url != "string") {
-
this.image = url;
-
} else if(!this.image) {
-
this.image = new Image();
-
} else {
-
this.image.src = url;
-
}
-
},
-
-
getframe: function () {
-
return this.showFrame;
-
},
-
-
setFrame: function (n) {
-
this.showFrame = n;
-
}
-
});
-
-
CGE.AnimSprite = CGE.Gfx.extend({
-
isPlaying: false,
-
numFrames: 0,
-
-
init: function (url, pos, size, ctx, frm, numFrm, play) {
-
this.parent(url, pos, size, ctx, frm);
-
this.numFrames = numFrm;
-
this.isPlaying = (play == true);
-
-
},
-
-
next: function () {
-
var frm = this.showFrame;
-
frm = (++frm) % this.numFrames;
-
-
this.sX = this.useFrame[frm][0];
-
this.sY = this.useFrame[frm][1];
-
this.showFrame = frm;
-
this.paint();
-
}
-
});
Example
animating inside Canvas with Javascript
The End? Finally!
You've made it! We are now at the end of this in depth review of the different animation and Graphics display techniques for browser based games. I hope this article was helpful in one way or the other.
A note for those intending to use my code. I used the AJS framework to define my classes, however with a little modification the code can easily work standalone too.
If you liked this article or have critique, questions or suggestions, let me know.
Tags: code performance, game engine, Games, JavaScript Library, tile graphics
16 Responses to “Choosing the right Graphics Technique for a Browser Based Game”
Leave a Reply
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
Hey, all I can say is wowa, some really good reading there :D, just a quick question about how your 'Animation Via elm.style.top/elm.style.left' works, I've been looking into somthing simular to this, but using pre coded css .classes, that i can quickly switch within the DOM. To make each of the .classes as reusable as possible i have a class="tileset tile#" implementation.
For example I have
#world .grass {background:url('GRS2ROC.bmp');}
#world .tile01{background-position: -40px -81px;}
#world .tile02{background-position:-120px -81px;}
#world .tile03{background-position:-200px -81px;}
#world .tile04{background-position:-280px -81px;}
From the few tests that i have done it looked quicker to only alter the class bit of a DIV tag, rarther than editing the background position, this could be due to needed less text to select which sprite to use.
As you only need
rarther than
But this could be due to my implementation, from the looks of it you have done far more research into this problem than myself.
Thanks for the compliment.
I can cook up a quick test later today to try out your technique and see how it matches up with all the others.
I suspect the class approach to be slightly less effective than the backgroundPosition approach, due to the double lookup of the properties.
You need to change the class, which in turn changes the background-position. If you ever happen to have multiple classes assigned to your tiles, it might also get pretty messy real quick. Because then you start evaluating strings and replacing specific patterns (regex?!) which might get slow for many items.
Generally I am leaning towards canvas anyhow, I have a test cooking right now which animates 250 individually animated sprites over a moving tiled background at about 50-90% CPU (depending on browser). Try to do that with css animation
Ah cool would be intersting to see your results, I am really tempted to jump ship over to using Canvas rarther than HTML, and 250 animated objects on a moving background sounds mighty tempting
Does possibily losing a large % of the possible customer base worry you? As alot of people are still using IE for everything. Also Googles canvas code isnt going to allow anywhere near 250 animated objects, from what a college tells me its horrificly slow even when trying to do simple tasks 
I would really love to say I don't care about IE...
Although personally I do, from a developer standpoint, I have to take it into consideration.
In my engine I'll provide automatic fallback to DOM sprites when canvas is not available, though most of the animations will most likely be turned off then. I mean, come on... I need to give IE users incentive to upgrade to a real browser
I am also going to use SVG to a certain degree for interface stuff at a later point. So definitely IE users will get the worse experience in any case...
If you're interested, look at my bug tracker to see information on the roadmap and planned features. The project name is Brimstone.
The canvas route certainly looks impressive and fun, but I'm very concerned about the browser compatibility.
It's not always the case that a given user doesn't want to move away from IE, sometimes they don't have a choice. If they are using a computer in an Internet Cafe, or in an educational institution that is still using IE as default, they might simply not have access to any other browser.
Thats a good point, and it might be valid in a number of countries. But at least here in Germany educational institutions are mainly using Firefox, much as they had been using Netscape before.
Network admins there really do care about their network security.
I also think that while still providing compatibility a web-game developer could still advocate the use of a standards compliant and more secure web browser on their sites...
And as said before, I am providing a fallback solution for those mediocre browsers that don't support proper w3c standards (not trying to imply that canvas is one yet, though).
Okay, I tried the elm.className approach this afternoon. It really is 10-15% faster(relative to backdropPosition) which evaluates to 1% CPU usage less than the fastest dom method previously.
I put an example online too.
Though it might result in a huge stylesheet for lots of tiles. Anyways... I'll investigate further and let you know the outcome...
Hey, just had a look at your example, looks good. I do think its quicker because altering HTML using JS is slow, hell any text based manipulation is, and pushing as much text into css rules reduces the amount of text that needs to change.
On a complete tangent and off topic(delete if you'd rarther not talk about this stuff), have you looked into how your going to handle path finding, i've been looking into A* implementations and movement validation between the server and client. The current method that i am considering is to generate a path using JS, as its just math it should be quick, and parse the endpoint and distance to a php script which will validate the move and send the ok if everything is alright. Is this how you were considering movement, or were you going for the pure server side validation?
Erp, sorry about spam... Also if you adopt the tileset - tile# system, you have LESS css, as all your tiles are going to be the same size, for example 40px-40px. You can have one tile# document so you can make lots of div's each using different tilesets, for example 'div class="grass t01"', 'div class="grass t02"' 'div class="stone t01"' 'div class="wood t01"'. The t01, t02... code doesnt change only the tileset
Regarding the tile# system:
I think that is exactly the point where it will start to get slow. Now that you have more than one class name, you need to evaluate the class name and then change only that part which you want to update - i.e. grass t01 changed to grass t03. Though I was wrong before so I might as well do a test-case to prove my thesis
And changing the style attribute doesn't change html, it changes an object property, though you first need to create it as string and then the browser will evaluate that to floats.
Right now I'd like to avoid the stylesheet as only the dom method benefits from it. SVG and Canvas need either a different stylesheet or completely different implementation.
And then there's the problem when I change the tilesets/sprites, I need tp update my objects to the new sizes as well. Parsing the css then is a mess and having the numbers in both JS and CSS is prone to errors.
So it really need to do some investigation here before I can actually decide if I go the class or the bg route...
Regarding the pathfinding:
There are some awesome tutorials available for Flash which I think can almost directly be translated for JS.
TonyPa's Tile Game Tutorials
gotoAndPlay's tutorials (choose pathfinding as topic)
And no, I'm not planning to et the server involved in pathfinding. My aim is to make the game work completely offline. I'll probably go a mixed route with A*, Waypoints and BestFirst.
We'll see when this actually becomes current. Pathfinding is slated for sometime around v0.70, right now I am working on v0.10 so probably ask again after the coming summer
Ah thanks for the links, they look dead handy, I've got some basic path finding done, but its in PHP atm, once i finish getting it working ill port it to JS.
http://horrain.com/httpMMO/aStar.php
The main reasion for this is that i am used to debugging in php, and am relativly new to jS.
So if you're that new to JS, you might still need these Firefox extensions to make your development and debugging life a whole lot easier.
http://chrispederick.com/work/web-developer/
http://www.getfirebug.com/
The both work in FF3 already.
I'll check out your code later, first I'll need to get some work done here
Nice pathfinder you've got there horrain. It even makes diagonals! Though since it's php I can't sy anything about the code. I suppose an offline version might be even faster since the request lag is probably the where the majority of time is spent.
Hey, thanks, once i finish implementing all of the features that i need ill port it over to JS. Atm the class is returning a whole set of points, im going to try and optimise the return, so less data needs to be stored and transmitted, mainly because client CPU is free where as bandwidth isnt
If you wish i can send you a link to the code, onces it all nicly finished, so you can see how i've done bits and bobs.
Client CPU and Bandwidth are also the most uncertain variables in any online gaming equation.
You'll just never know what you're audience will have and planning for multiplayer you'll even need to consider that two people in the same session will have vastly different specs.
But on the other hand, isn't it exactly this what makes it so exciting
Anyways, yes, I'd like to look at the code once you're ready. I think it can only help looking at other peoples work. You'll never get dumber from reading...
Though, I am planning to move a bit away from PHP. I do Java for a living and the game(s) here should get a Python backend. So there's not too much time to keep up with php as well, though I am doing a little job here and there involving that as well.
But if I'll spend any more time with computers than I do right now anyway, my wife's probably chopping my hands off
- no hands, no typing 
Scripted Image Mosaics...
Here's another useful tidbit.
I already wrote a lot of posts about Javascript Sprites, how to animate them and how they perform. What I neglected so far is how they actually get on the stage or the page to use the correct term. Another fact is also th...