<script>

window.onload = init;

function LoadSpriteset(names) {
    images = new Array(names.length);
    imagesloaded = 0;
    imagecount = 1 + names.length * 3;
    ext = ['a', 'p', 'z'];
    for (i = 0; i < names.length; i++) {
        images[i] = new Array(3);
        for (j = 0; j < 3; j++) {
            img = new Image();
            img.idi = i, img.idj = j;
            img.src = names[i] + '_' + ext[j] + ".png";
            img.onload = function() {
                context.drawImage(this, 0, 0);
                images[this.idi][this.idj] = context.getImageData(0, 0, 136, 384);
                delete this;
                if (++imagesloaded == imagecount) {
                    redraw = true;
                    setInterval(update, 16);
                }
            };
        }
    }
}

function init() {
    // capture keys
    left = 0;
    right = 0;
    up = 0;
    down = 0;

    window.onkeydown = function(evt) {
        if (evt.keyCode == 37) left = 1;
        if (evt.keyCode == 38) up = 1;
        if (evt.keyCode == 39) right = 1;
        if (evt.keyCode == 40) down = 1;
    };

    window.onkeyup = function(evt) {
        if (evt.keyCode == 37) left = 0;
        if (evt.keyCode == 38) up = 0;
        if (evt.keyCode == 39) right = 0;
        if (evt.keyCode == 40) down = 0;
    };
    // end capture keys

    // The game does not use true isometric projection because each tile is 128x64 (close), 64x32 (medium), or 32x16 (far)
    // which, when tilex or tiley is the hypotenuse, does not form a 30-60-90 triangle.
    // It's actually arctan(1/2)-arctan(2/1)-90. The image is compressed vertically a bit to allow for power-of-2 texture sizes.
    tilex = 0;
    tiley = 0;
    sin60 = 2.0/Math.sqrt(5); // sin(arctan(2)) or cos(arctan(1/2))
    sin30 = 1.0/Math.sqrt(5); // sin(arctan(1/2)) or cos(arctan(2))
    sqrt5120 = 32*Math.sqrt(5);

    debug = document.getElementById('debug');
    canvas = document.getElementById('draw');
    context = canvas.getContext('2d');

    background = new Image();
    background.src = "background.png";
    background.onload = function() {
        context.drawImage(this, 0, 0);
        delete this;
        background = context.getImageData(0, 0, 136, 384);
        if (++imagesloaded == imagecount) {
            redraw = true;
            setInterval(update, 16);
        }
    }
    LoadSpriteset(["Chair-Liv-Deco_large_front", "tower_large_ne"]);

    render = context.createImageData(136, 384);
}

function Blend(sourceid, soffset)
{
    sa = images[sourceid][0].data[soffset+0] / 255.0;
    if (sa == 0) return;
    sr = images[sourceid][1].data[soffset+0];
    sg = images[sourceid][1].data[soffset+1];
    sb = images[sourceid][1].data[soffset+2];
    if (sa == 255) {
        render.data[dest+0] = sr;
        render.data[dest+1] = sr;
        render.data[dest+2] = sr;
        return;
    }

    dr = render.data[dest+0];
    dg = render.data[dest+1];
    db = render.data[dest+2];
    da = 1.0 - sa;

    render.data[dest+0] = da * dr + sa * sr;
    render.data[dest+1] = da * dg + sa * sg;
    render.data[dest+2] = da * db + sa * sb;
}


function update() {
    if (!left && !right && !up && !down && !redraw) return;
    redraw = false;

    if (left == 1)  tilex -= 1;
    if (right == 1) tilex += 1;
    if (up == 1)    tiley += 1;
    if (down == 1)  tiley -= 1;

    screenx = Math.round((tilex + tiley)*sin60);
    screeny = Math.round((tilex - tiley)*sin30);
    z = screeny*1.5;

    for (y = 0; y < 384; y++) {
        for (x = 0; x < 136; x++) {
            dest = (y*136+x)*4;
            render.data[dest+0] = background.data[dest+0];
            render.data[dest+1] = background.data[dest+1];
            render.data[dest+2] = background.data[dest+2];
            render.data[dest+3] = 255;

            // Shift: read from the data so-many bytes ago. Subtract rather than add.
            if (y-screeny >= 0 && y-screeny < 384 && x-screenx >= 0 && x-screenx < 136) {
                source = ((y-screeny)*136 + x-screenx)*4;

                if (images[1][2].data[source] != 255 && images[1][2].data[source] - z < images[0][2].data[dest]) {
                    // Object 2 on top
                    Blend(0, dest);
                    Blend(1, source);
                } else {
                    // Object 1 on top
                    Blend(1, source);
                    Blend(0, dest);
                }
            } else {
                // Object 1 only
                Blend(0, dest);
            }
        }
    }

    context.putImageData(render, 0, 0);
    debug.innerHTML = "Tile x: " + tilex/sqrt5120 + "<br />Tile y: " + tiley/sqrt5120 + "<br />Screen x: " + screenx + "<br />Screen y: " + screeny + "<br />z: " + z;
}
</script>

<div id="debug"></div>
<canvas width="136" height="384" id="draw" style="border: 1px solid #888"></canvas>