HTML5 动画在持续刷新的画布上

发布于 2024-11-05 10:04:18 字数 5187 浏览 1 评论 0原文

大家哟!

我已经在 HTML5/Canvas 中开发等距平铺游戏引擎一段时间了,并且我已经有了一个完整的工作游戏。今天早些时候,我回顾了我的代码并想:“嗯,让我们尝试顺利地制作这个动画......”

从那时起,这就是我所做的一切。

问题
我希望角色实际上从一个图块“滑动”到另一个图块 - 但画布重绘不允许这样做 - 有人有任何想法......?下面的代码和小提琴...

摆弄它! 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>  

编辑:
请...?

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 & canvas support on this 'ere electronic machine!<sub>This game, jus' plain ol' won't work!</sub></h1>
    </canvas>
</body> 
</html>  

Edit:
Please...?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吲‖鸣 2024-11-12 10:04:18

要使用画布制作动画,您必须每帧重新绘制整个受影响的部分,否则您的对象将在其后面留下痕迹。每个动画帧,在精灵移动之前,您必须重新绘制他身后的三到四个图块。

我建议在绘图函数中添加一些额外的状态,以便对于每一帧,更新一些临时距离并重新绘制相关的图块和精灵。全局变量会在动画运行时阻止按键输入。

我懒得自己写了,不过你应该没问题。玩得开心!

To animate with canvas, you have to redraw the whole affected section each frame, or your objects will leave a trail behind them. Each animation frame, before the sprite moves, you have to redraw the three or four tiles just behind him.

I'd suggest adding some extra states to your drawing function so that for each frame, some temporary distances are updated and the relevant tiles and sprite are redrawn. A global variable would block key input while the animation was running.

I'm too lazy to write it myself, but you should be fine. Have fun!

隱形的亼 2024-11-12 10:04:18

这是一个示例。 它不太准确,因为我做得很快。

基本上,当用户按下按钮时,您想要启动倒计时,时钟的每个连续滴答都会将其(+1,+2)等移动到其目标。经过一定数量的滴答声后,它停止移动。

编辑以使用尼克的修改示例。见评论。

Here's an example. It isn't too accurate because I made it real quick.

Basically when a user pressed a button you want to initiate a countdown where each successive tick of the clock moves it (+1,+2) etc towards its goal. After some number of ticks it stops moving.

Edited to use Nick's modified example. See comments.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文