在画布的glitchy动画 [英] Glitchy Animation on Canvas

查看:192
本文介绍了在画布的glitchy动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的主底层玩家移动和电梯移动我使用这个帧速率:

  var requestAnimFrame = window。 requestAnimationFrame || 
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback){
window.setTimeout(callback,1000/60);
};

当播放器死亡时,我将此帧速率用于爆炸动画。

  var requestAnimFrameExplode = function(callback){
window.setTimeout(callback,1000/15);
};

现在所有这些都工作正常,但是在我的一个级别我有电梯上下移动等使用主底层帧速率,但是当播放器死亡爆炸帧速率播放器(使事情更慢,所以你可以看到动画1秒),这使电梯减慢1秒,使它看起来毛病。 p>

在我的游戏循环我有:

  if )
{
requestAnimFrameExplode(Loop); //调用循环但慢但是动画爆炸显示
DrawSpawnAnimation(); // this drawing the explode animation
}

else
{
requestAnimFrame(Loop); //当死亡为假时,它以正常快速帧速率调用玩家移动等
}

我的问题是如何阻止这个故障?

解决方案

如果电梯和其他东西在循环中运行, >这是一个使用requestAnimationFrame和setTimeout的动画插图。



使用RAF驱动两个动画会更加高效,



此RAF动画循环将运行您的电梯,如下所示:

  var fps1 = 60; 
function runElevator(){
setTimeout(function(){

//请求另一个循环
raf1 = requestAnimFrame(runElevator);
$ b b //更新电梯属性(当前Y和直线)
elevatorY + = elevatorSpeed * elevatorDirection;
if(elevatorY + elevatorHeight> canvasB.height || elevatorY< 30){
elevatorDirection = - elevatorDirection;
}

//调用绘制电梯框架的函数
drawElevator(elevatorX,elevatorY,elevatorWidth,elevatorHeight)

},1000 / fps1); setTimeout动画循环运行你的爆炸,如下所示:

  var fps2 = 30; 
function runExplosion(){

//更新爆炸属性(当前爆炸半径)
explosionRadius + = 1.5;

//检查爆炸是否完成
if(explosionRadius< explosionMaxRadius){

//爆炸未完成,绘制另一个爆炸框架
drawExplosion(explosionX,explosionY,explosionRadius);

//并请求另一个循环
setTimeout(runExplosion,1000 / fps2);

} else {

//爆炸完成,清除顶部画布,我们在这里!
ctxT.clearRect(0,0 ,canvasT.width,canvasT.width);
}

}

这里是代码和小提琴: http://jsfiddle.net/m1erickson/YzqUF/

 <!doctype html> 
< html>
< head>
< link rel =stylesheettype =text / cssmedia =allhref =css / reset.css/> <! - reset css - >
< script type =text / javascriptsrc =http://code.jquery.com/jquery.min.js>< / script>

< style>
body {background-color:ivory; padding:20px;}
#container {position:relative;}
canvas {border:1px solid red; position:absolute; top:0; left:0}
< / style>

< script>
$(function(){

var canvasT = document.getElementById(canvasTop);
var ctxT = canvasT.getContext(2d); var canvasB = document.getElementById(canvasBottom);
var ctxB = canvasB.getContext(2d);

window.requestAnimFrame =(function(callback){
返回window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback,1000/60)
};
})();


var elevatorX = 30;
var elevatorY = 30;
var elevatorWidth = 40;
var elevatorHeight = 60;
var elevatorSpeed = 2;
var elevatorDirection = 1;

ctxT.strokeStyle =orange;
var explosionX = 100;
var explosionY = 200;
var explosionStartingRadius = 10;
var explosionEndingRadius = 25;
var explosionRadius = explosionStartingRadius;

var raf1;
var raf2;

runElevator();


function explode(x,y,maxRadius){

explosionX = x;
explosionY = y;
explosionMaxRadius = maxRadius
explosionRadius = 10;

ctxT.clearRect(0,0,canvasB.width,canvasB.height);
ctxT.beginPath();
ctxT.arc(x,y,explosionRadius,0,Math.PI * 2,false)
ctxT.closePath();
ctxT.fillStyle =yellow
ctxT.fill();
ctxT.stroke();
ctxT.fillStyle =orange;
runExplosion();

}

var fps1 = 60;
function runElevator(){
setTimeout(function(){
raf1 = requestAnimFrame(runElevator);

elevatorY + = elevatorSpeed * elevatorDirection;
if电梯Y +电梯高度> canvasB.height ||电梯Y< 30){
elevatorDirection = -elevatorDirection;
}

drawElevator(elevatorX,elevatorY,elevatorWidth,elevatorHeight)

},1000 / fps1);
}

var fps2 = 30;
function runExplosion(){

explosionRadius + = 1.5;

if(explosionRadius< explosionMaxRadius){
drawExplosion(explosionX,explosionY,explosionRadius);
setTimeout(runExplosion,1000 / fps2);
} else {
ctxT.clearRect(0,0,canvasT.width,canvasT.width);
}

}

function drawElevator(x,y,width,height){
ctxB.clearRect(0,0,canvasB.width, canvasB.height);
ctxB.beginPath()
ctxB.moveTo(x + width / 2,0);
ctxB.lineTo(x + width / 2,y);
ctxB.rect(x,y,width,height);
ctxB.stroke();
ctxB.fill();
}

function drawExplosion(x,y,radius){
ctxT.beginPath();
ctxT.arc(x,y,radius,0,Math.PI * 2,false);
ctxT.closePath()
ctxT.stroke();
}

$(#explode)click(function(){explode(150,150,75);});


}); // end $(function(){});
< / script>

< / head>

< body>
< button id =explode>分解< / button>
< div id =container>
< canvas id =canvasTopwidth = 300 height = 300>< / canvas>
< canvas id =canvasBottomwidth = 300 height = 300>< / canvas>
< / div>

< / body>
< / html>


On my main bottom layer where the player moves and elevators move I use this frame rate:

var requestAnimFrame =  window.requestAnimationFrame || 
                        window.webkitRequestAnimationFrame || 
                        window.mozRequestAnimationFrame || 
                        window.msRequestAnimationFrame  ||  
                        window.oRequestAnimationFrame   || 
                        function(callback) {
                        window.setTimeout(callback, 1000/60);
                        };

When the player dies I use this frame rate for the explosion animation.

var requestAnimFrameExplode = function(callback) {
                        window.setTimeout(callback, 1000/15);
                        };

Now all this works fine, however on one of my levels I have elevators moving up and down etc that use the main bottom layer frame rate, but when the player dies the explosion frame rate players(makes things slower so you can see the animation for 1 sec) so this makes the elevators slow down for 1 sec and makes it look glitchy.

In my game Loop I have:

if(Death ==true)
{
requestAnimFrameExplode(Loop); //calls loop again but slower so animation explode shows
DrawSpawnAnimation(); //this draws the explode animation
}

else
{
requestAnimFrame(Loop); //when Death is false it calls at normal fast framerate for player movement etc
}

My question is how to stop this glitching? How can I Make the elevators and other thing sin the loop run the same time even if the animation is playing?

解决方案

Here’s an animation illustration that uses both requestAnimationFrame and setTimeout.

It would be more performant to use RAF to drive both animations, but both are presented here for illustration purposes.

This RAF animation loop runs your elevator and looks like this:

var fps1 = 60;
function runElevator() {
    setTimeout(function() {

        // request another loop
        raf1=requestAnimFrame(runElevator);

        // update the elevator properties (current Y and directon)
        elevatorY+=elevatorSpeed*elevatorDirection;
        if(elevatorY+elevatorHeight>canvasB.height || elevatorY<30){
            elevatorDirection= -elevatorDirection;
        }

        // call the function that draws the elevator frame
        drawElevator(elevatorX,elevatorY,elevatorWidth,elevatorHeight)

    }, 1000 / fps1);
}

The setTimeout animation loop runs your explosion and looks like this:

var fps2 = 30;
function runExplosion() {

    // update the explosion properties (the current radius of the explosion)
    explosionRadius+=1.5;

    // check if the explosion is done
    if(explosionRadius<explosionMaxRadius){

        // the explosion is not done, draw another explosion frame
        drawExplosion(explosionX,explosionY,explosionRadius);

        // and request another loop 
        setTimeout(runExplosion, 1000/fps2);

    }else{

        // the explosion is done,  clear the top canvas and "we’re outta here!"
        ctxT.clearRect(0,0,canvasT.width,canvasT.width);
    }

}

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/YzqUF/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; padding:20px;}
    #container{position:relative;}
    canvas{border:1px solid red; position:absolute; top:0; left:0}
</style>

<script>
    $(function(){

        var canvasT=document.getElementById("canvasTop");
        var ctxT=canvasT.getContext("2d");
        var canvasB=document.getElementById("canvasBottom");
        var ctxB=canvasB.getContext("2d");

        window.requestAnimFrame = (function(callback) {
          return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
          function(callback) {
            window.setTimeout(callback, 1000 / 60);
          };
        })();


        var elevatorX=30;
        var elevatorY=30;
        var elevatorWidth=40;
        var elevatorHeight=60;
        var elevatorSpeed=2;
        var elevatorDirection=1;

        ctxT.strokeStyle="orange";
        var explosionX=100;
        var explosionY=200;
        var explosionStartingRadius=10;
        var explosionEndingRadius=25;
        var explosionRadius=explosionStartingRadius;

        var raf1;
        var raf2;

        runElevator();


        function explode(x,y,maxRadius){

            explosionX=x;
            explosionY=y;
            explosionMaxRadius=maxRadius
            explosionRadius=10;

            ctxT.clearRect(0,0,canvasB.width,canvasB.height);
            ctxT.beginPath();
            ctxT.arc(x,y,explosionRadius,0,Math.PI*2,false)
            ctxT.closePath();
            ctxT.fillStyle="yellow"
            ctxT.fill();
            ctxT.stroke();
            ctxT.fillStyle="orange";
            runExplosion();

        }

        var fps1 = 60;
        function runElevator() {
            setTimeout(function() {
                raf1=requestAnimFrame(runElevator);

                elevatorY+=elevatorSpeed*elevatorDirection;
                if(elevatorY+elevatorHeight>canvasB.height || elevatorY<30){
                    elevatorDirection= -elevatorDirection;
                }

                drawElevator(elevatorX,elevatorY,elevatorWidth,elevatorHeight)

            }, 1000 / fps1);
        }

        var fps2 = 30;
        function runExplosion() {

            explosionRadius+=1.5;

            if(explosionRadius<explosionMaxRadius){
                drawExplosion(explosionX,explosionY,explosionRadius);
                setTimeout(runExplosion, 1000/fps2);
            }else{
                ctxT.clearRect(0,0,canvasT.width,canvasT.width);
            }

        }

        function drawElevator(x,y,width,height){
            ctxB.clearRect(0,0,canvasB.width,canvasB.height);
            ctxB.beginPath();
            ctxB.moveTo(x+width/2,0);
            ctxB.lineTo(x+width/2,y);
            ctxB.rect(x,y,width,height);
            ctxB.stroke();
            ctxB.fill();
        }

        function drawExplosion(x,y,radius){
            ctxT.beginPath();
            ctxT.arc(x,y,radius,0,Math.PI*2,false);
            ctxT.closePath()
            ctxT.stroke();
        }

        $("#explode").click(function(){ explode(150,150,75); });


    }); // end $(function(){});
</script>

</head>

<body>
<button id="explode">Explode</button>
<div id="container">
<canvas id="canvasTop" width=300 height=300></canvas>
<canvas id="canvasBottom" width=300 height=300></canvas>
</div>

</body>
</html>

这篇关于在画布的glitchy动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆