Recently I decided to build part of a game that used an isometric projection for displaying the game board using HTML5.
Dirty plagiarist that I am, I found an excellent (albeit very old) tutorial by Danko Kozar for doing this. However it was written in Actionscript. No bother – I just modified the code to work in HTML5. This meant I could more or less ignore the theory of how isometric projection works and just get down to the business of doing it. Porting the code was easy. As it says in the tutorial:
These tutorials can be used for programming an isometric game in many programming languages not just in Flash. They are more about game programming than about Flash programming.
Actionscript Code:
// isometric transformations
// author: Danko Kozar, DKOZAR.COM
// transforms x,y,z coordinates into Flash x coordinate
xFla = function (x, y, z) {
// cartesian coordinates
xCart = (x-z)*Math.cos(0.46365);
// flash coordinates
xI = xCart+xOrigin;
return (xI);
};
// transforms x,y,z coordinates into Flash y coordinate
yFla = function (x, y, z) {
// cartesian coordinates
yCart = y+(x+z)*Math.sin(0.46365);
// flash coordinates
yI = -yCart+yOrigin;
return (yI);
};
// --- drawing functions --------------------------------
style = function (a, b, c) {
// a: line width
// b: line color
// c: line alpha
lineStyle(a, b, c);
};
plot = function (x, y, z) {
moveTo(xFla(x, y, z), yFla(x, y, z));
};
draw = function (x, y, z) {
lineTo(xFla(x, y, z), yFla(x, y, z));
};
boxFilled = function (x, y, z, a, b, c, color, fill) {
beginFill(fill);
style(1, color, 100);
plot(x, y, z);
draw(x+a, y, z);
draw(x+a, y+b, z);
draw(x, y+b, z);
draw(x, y, z);
plot(x, y+b, z);
draw(x+a, y+b, z);
draw(x+a, y+b, z+c);
draw(x, y+b, z+c);
draw(x, y+b, z);
plot(x, y, z);
draw(x, y+b, z);
draw(x, y+b, z+c);
draw(x, y, z+c);
draw(x, y, z);
endFill();
};
// --- initialisation --------------------------------
xScreenSize = 400;
yScreenSize = 300;
xOrigin = xScreenSize/2;
yOrigin = yScreenSize-30;
// --- main ------------------------------------------
// left wall
boxFilled(0, 0, 200, 200, 80, 0, "0xEE0000", "0xAA0000");
// right wall
boxFilled(200, 0, 0, 0, 80, 200, "0xEE0000", "0xAA0000");
// floor
boxFilled(0, 0, 0, 200, 0, 200, "0x00BB00", "0x00BB00");
// left door
boxFilled(80, 0, 200, 40, 60, 0, "0xCCCCCC", "0x999999");
// right door
boxFilled(200, 0, 80, 0, 60, 40, "0xCCCCCC", "0x000000");
// blue box
boxFilled(100, 0, 130, 30, 60, 30, "0x0000FF", "0x0000AA");
// grey box
boxFilled(80, 0, 80, 30, 30, 30, "0xAAAAAA", "0x555555");
// yellow box
boxFilled(60, 0, 70, 20, 20, 20, "0xFFFF00", "0xAAAA00");
// purple box
boxFilled(60, 0, 20, 30, 20, 40, "0xFF00FF", "0xAA00AA");
HTML5/Javascript Code:
// isometric transformations
// author: Christo, mightystuff.net
// transforms x,y,z coordinates into canvas x coordinate
xFla = function (x, y, z) {
// cartesian coordinates
xCart = ( x - z ) * Math.cos(0.46365);
// canvas coordinates
xI = xCart + xOrigin;
return (xI);
};
// transforms x,y,z coordinates into canvas y coordinate
yFla = function (x, y, z) {
// cartesian coordinates
yCart = y + ( x + z) * Math.sin(0.46365);
// canvas coordinates
yI = -yCart + yOrigin;
return (yI);
};
// --- drawing functions --------------------------------
style = function (a, b, c) {
// a: line width
// b: line color
// c: line alpha
context.lineWidth = a;
context.strokeStyle = b;
};
plot = function (x, y, z) {
move(xFla(x, y, z), yFla(x, y, z));
};
draw = function (x, y, z) {
line(xFla(x, y, z), yFla(x, y, z));
};
line = function(x,y) {
context.lineTo(x, y);
}
boxFilled = function (x, y, z, a, b, c, strokeColour, fillColour) {
context.strokeStyle = strokeColour;
context.fillStyle = fillColour;
context.beginPath();
plot(x, y, z);
draw(x + a, y, z);
draw(x + a, y + b, z);
draw(x, y + b, z);
draw(x, y, z);
context.closePath();
context.stroke();
context.fill();
context.beginPath();
plot(x, y + b, z);
draw(x + a, y + b, z);
draw(x + a, y + b, z + c);
draw(x, y + b, z + c);
draw(x, y + b, z);
context.closePath();
context.stroke();
context.fill();
context.beginPath();
plot(x, y, z);
draw(x, y + b, z);
draw(x, y + b, z + c);
draw(x, y, z + c);
draw(x, y, z);
context.closePath();
context.stroke();
context.fill();
};
// --- initialisation --------------------------------
var xScreenSize = 400; // isometric grid parameters
var yScreenSize = 300;
var xOrigin = xScreenSize/2;
var yOrigin = yScreenSize-30;
function drawElements() {
// --- main ------------------------------------------
// left wall
boxFilled(0, 0, 200, 200, 80, 0, "#EE0000", "#AA0000");
// right wall
boxFilled(200, 0, 0, 0, 80, 200, "#EE0000", "#AA0000");
// floor
boxFilled(0, 0, 0, 200, 0, 200, "#00BB00", "#00BB00");
// left door
boxFilled(80, 0, 200, 40, 60, 0, "#CCCCCC", "#999999");
// right door
boxFilled(200, 0, 80, 0, 60, 40, "#CCCCCC", "#000000");
// blue box
boxFilled(100, 0, 130, 30, 60, 30, "#0000FF", "#0000AA");
// grey box
boxFilled(80, 0, 80, 30, 30, 30, "#AAAAAA", "#555555");
// yellow box
boxFilled(60, 0, 70, 20, 20, 20, "#FFFF00", "#AAAA00");
// purple box
boxFilled(60, 0, 20, 30, 20, 40, "#FF00FF", "#AA00AA");
}
jQuery(document).ready(function($) {
init();
});
var canvas; // Reference to the canvas element
var context;
function init() {
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
drawElements();
}
Pretty similar huh? This is just the tip of the iceberg and not everything is as easy as this when porting from Flash to HTML 5 (specifically the canvas element). In my (so far limited) experience the canvas element is a bitch to hook up events to, handy libraries notwithstanding.
As usual, other people have already thought about these things in depth: tackling the essentials of drawing and benchmarking the differences between flash and html5.

Great stuff man!!! ^_^
Glad my tutorial helped. And didn’t know that canvas is so similar…
One thing: be sure to replace stuff like “Math.cos(0.46365);” with constants (numbers) (or calculate the value at the application start), because there’s no point in overloading the processor in each frame.
Cheers!