2013-07-05 4 views
0

На моем главном нижнем слое, где игрок перемещается и лифты двигаются я использую эту частоту кадров: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 секунды и делает его выглядящим glitchy.

В моей игре Loop у меня есть:

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 
} 

Мой вопрос заключается в том, чтобы остановить это обнаружение сбоя? Как я могу заставить лифты и другие вещи грешить цикл одновременно, даже если анимация играет?

ответ

1

Вот анимация иллюстрация, которая использует как requestAnimationFrame и SetTimeout.

Было бы более удобно использовать RAF для управления обеими анимациями, но оба они представлены здесь для иллюстративных целей.

Этот цикл анимации RAF работает ваш лифт и выглядит следующим образом:

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); 
} 

Цикл анимации SetTimeout запускает свой взрыв, и выглядит следующим образом:

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); 
    } 

} 

Вот код и 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> 
+0

Можете ли вы объяснить, почему один не переопределяет другого? Как если бы вы потратили время на 1 секунду, разве это не изменило бы другую анимацию? – Sam

+0

Конечно, рад объяснить :) SetTimeout является асинхронным, что означает, что когда вы запрашиваете setTimeout кода ** внутри **, таймаут будет запускаться после указанного таймаута, но код ** после ** таймаут будет запускаться немедленно (без таймаута). Поэтому нет никакой задержки для любого кода, который после setTimeout, и ваша анимация лифта будет продолжать работать бесперебойно ... аккуратно, да? – markE

+0

Хорошо, но этот тайм-аут, скажем, полсекунды, в то время как это работает, не означает ли это, что вся пауза программы, как она рассчитана на время? следовательно, глючное действие с лифтами? – Sam

0

Похоже, вы пытаетесь контролировать скорость своей анимации, контролируя частоту кадров. Я рекомендую рефакторинг, чтобы частота кадров не зависела от скорости анимации.

Другими словами, не замедляйте ваш взрыв, опустив частоту кадров. Вы должны замедлить его, сделав пламя/мусор меньше, чем каждый кадр.

Это говорит, замедляя весь уровень вниз (лифты и все), когда вы умираете звуки как своего рода аккуратный эффект;)

+0

Звучит неплохо, но это слишком смутно, может быть, оно идет назад d, то вперед снова может быть прохладным. Тем не менее, хотя я недостаточно опытен в программировании, чтобы разобраться в этом сам :( – Sam

Смежные вопросы