3
\$\begingroup\$

Yo everyone!

I have been working on an Isometric Tile Game Engine in HTML5/Canvas for a little while now and I have a complete working game. Earlier today I looked back over my code and thought: "hmm, let's try to get this animated smoothly..."

And since then, that is all I have tried to do.

The problem
I would like the character to actually "slide" from tile to tile - but the canvas redrawing doesn't allow this - does anyone have any ideas....? Code and fiddle below...

Fiddle with it! http://jsfiddle.net/neuroflux/n7VAu/

<html>  
<head>
<title>tileEngine - Isometric</title>
<style type="text/css">
* { margin: 0px; padding: 0px; font-family: arial, helvetica, sans-serif; font-size: 12px; cursor: default; }
</style>
<script type="text/javascript">
var map = Array( //land
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]],
    [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]
);
var tileDict = Array("http://www.wikiword.co.uk/release-candidate/canvas/tileEngine/land.png");
var charDict = Array("http://www.wikiword.co.uk/release-candidate/canvas/tileEngine/mario.png");
var objectDict = Array("http://www.wikiword.co.uk/release-candidate/canvas/tileEngine/rock.png"); //last is one more
var objectImg = new Array();

var charImg = new Array();
var tileImg = new Array();

var loaded = 0;
var loadTimer;
var ymouse;
var xmouse;
var eventUpdate = 0;

var playerX = 0;
var playerY = 0;

function loadImg(){ //preload images and calculate the total loading time
    for(var i=0;i<tileDict.length;i++){ 
        tileImg[i] = new Image();
        tileImg[i].src = tileDict[i];
        tileImg[i].onload = function(){
            loaded++;
        }
    }
    i = 0;
    for(var i=0;i<charDict.length;i++){
        charImg[i] = new Image();
        charImg[i].src = charDict[i];
        charImg[i].onload = function(){
            loaded++;
        }
    }
    i = 0;
    for(var i=0;i<objectDict.length;i++){
        objectImg[i] = new Image();
        objectImg[i].src = objectDict[i];
        objectImg[i].onload = function(){
            loaded++;
        }
    }
}

function checkKeycode(event) { //key pressed
    var keycode;
    if(event == null) {
        keyCode = window.event.keyCode;
    } else {
        keyCode = event.keyCode;
    }
    switch(keyCode) {
        case 38: //left
            if(!map[playerX-1][playerY][1] > 0){
                playerX--;
            }
            break;
        case 40: //right
            if(!map[playerX+1][playerY][1]  > 0){
                playerX++;
            }
            break;
        case 39: //up
            if(!map[playerX][playerY-1][1]  > 0){
                playerY--;
            }
            break;
        case 37: //down
            if(!map[playerX][playerY+1][1]  > 0){
                playerY++;
            }
            break;
        default:
            break;
    }
}

function loadAll(){ //load the game
    if(loaded == tileDict.length + charDict.length + objectDict.length){
        clearInterval(loadTimer);
        loadTimer = setInterval(gameUpdate,100);
    }
}

function drawMap(){ //draw the map (in intervals)
    var tileH = 25;
    var tileW = 50;
    mapX = 80;
    mapY = 10;
    for(i=0;i<map.length;i++){
        for(j=0;j<map[i].length;j++){
            var drawTile= map[i][j][0];
            var xpos = (i-j)*tileH + mapX*4.5;
            var ypos = (i+j)*tileH/2+ mapY*3.0;
            ctx.drawImage(tileImg[drawTile],xpos,ypos);

            if(i == playerX && j == playerY){
                you = ctx.drawImage(charImg[0],xpos,ypos-(charImg[0].height/2));
            }
        }
    }
}

function init(){ //initialise the main functions and even handlers
    ctx = document.getElementById('main').getContext('2d');
    loadImg();
    loadTimer = setInterval(loadAll,10);
    document.onkeydown = checkKeycode;
}

function gameUpdate() { //update the game, clear canvas etc
    ctx.clearRect(0,0,904,460); 
    ctx.fillStyle = "rgba(255, 255, 255, 1.0)"; //assign color
    drawMap();
}
</script>
</head> 
<body align="center" style="text-align: center;" onload="init()">   
    <canvas id="main" width="904" height="465">
        <h1 style="color: white; font-size: 24px;">I'll be damned, there be no HTML5 &amp; canvas support on this 'ere electronic machine!<sub>This game, jus' plain ol' won't work!</sub></h1>
    </canvas>
</body> 
</html>  
\$\endgroup\$

2 Answers 2

8
\$\begingroup\$

You can animate your character by interpolating from the initial position to the target position.

You would have to update the position of the player inside your gameUpdate method, before calling drawMap();. To avoid strange movements, you'll have to lock/ignore player input for that period of time. This can be done easily by setting a flag isAnimating to true and simply ignoring key-input when isAnimating == true.

If your game gets more fleshed out, your game code will increase. If that's the case it's probably a good idea to separate your code into classes (I know, not so easy with JavaScript) and also implement a proper game-loop: Tips for writing the main game loop?

\$\endgroup\$
2
  • \$\begingroup\$ Thank you for the response, is there any chance you could edit my JSFiddle example with an idea of which direction to go in? I'm so confused. \$\endgroup\$ Commented May 9, 2011 at 10:53
  • \$\begingroup\$ There you go: jsfiddle.net/n7VAu/2 Although this doesn't incorporate any best practices.. for example the movement calculation shouldn't be in the draw method.. but it's just an example. \$\endgroup\$
    – bummzack
    Commented May 9, 2011 at 11:32
3
\$\begingroup\$

I think it would be best if your tiles are on a separate canvas. This would make what you want really easy - you just clear the top canvas on each frame, while the background remains. As bummzack said, you might have to lock controls during the animation.

Otherwise you could clear only the origin and destination tiles and redraw them on each frame, but this seems like more (unnecessary) work.

Btw using the arrow keys on a 45 degree isometric map makes controls very difficult for me. Better use some of the letter keys, as they are laid out in a 'hex' pattern, making diagonal movements more intuitive.

\$\endgroup\$
1
  • \$\begingroup\$ Hi RecencyEffect. :) No need to worry about late replies to old questions. It's perfectly acceptable here. \$\endgroup\$ Commented Oct 11, 2012 at 13:39

You must log in to answer this question.

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