2016-06-25 119 views
0

所以我在HTML和Javascript的画布上创建了一个游戏。我想做出某种飞扬的鸟类游戏,但是当我按下一个键时,玩家的动画看起来确实很滑稽。请看:HTML5画布中的流畅动画

body { 
 
    overflow: hidden; 
 
}
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <link rel="stylesheet" href="Style.css"/> 
 
</head> 
 
<body onload="startgame()"> 
 
    <canvas id="canvas"></canvas> 
 
<script> 
 
    canvas.height=window.innerHeight; 
 
    canvas.width=window.innerWidth; 
 

 
function startgame() { 
 
    var c = document.getElementById("canvas"); 
 
    var ctx = c.getContext("2d"); 
 
    
 
    var x = 900; 
 
    var y = 300; 
 
    var w = 25; 
 
    var h = 500; 
 
    var yperson = 20; 
 
    var xperson = 200; 
 
    
 
    document.addEventListener("keydown", function() { 
 
     yperson -= 150; 
 
    }); 
 
    
 
    function updateperson() { 
 
     yperson = yperson; 
 
    } 
 
    
 
    setInterval(createobject, 10); 
 
    function createobject() { 
 
     ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
     
 
     x -= 1; 
 
     yperson += 0.5; 
 
     yperson *= 1.003; 
 
     
 
     ctx.fillStyle = "#009999"; 
 
     ctx.fillRect(x,y,w,h); 
 
     
 
     ctx.fillStyle = "black"; 
 
     ctx.fillRect(xperson,yperson,30,30); 
 
     
 
     if (x <= 50) { 
 
      if (yperson < 280 && xperson === x-30) { 
 
       x -= 1; 
 
      } else if (yperson > 280){ 
 
       x += 1; 
 
      } 
 
     } 
 
     
 
     
 
    } 
 
} 
 
</script> 
 
</body> 
 
</html>

我希望它有一个流畅的动画了。我看到一些人说应该使用requestanimationframe来完成,但我不知道如何使用它。

在此先感谢。

+0

看起来不错,但是'requestAnimationFrame'会稍微平滑,因为它更新显示。 –

+0

我知道。 @SpencerWieczorek但是当你按下某个键时,这个人真的很快没有动画。 –

+0

你只是直接将位置向上移动150像素。如果你想要动画你想向上施加一个力量,而不是直接向上翻译;在这种情况下,它们之间没有动画。 –

回答

0

requestAnimationFrame

有关详情请参阅MDN window.requestAnimationFrame

由于以前的答案是缺乏一些资料,在这里被标注示例的基本用法。

// A flag to indicate that the animation is over 
var stop = false; // when true the animation will stop 

// define main loop update 
// the callback that is the main loop 
// the browser treats this function as special in terms of display items including 
// the canvas, and all DOM items. 
// It will ensure that any changes you make to the page are synced to the display 
function update(time){ // time is the time since load in millisecond 1/1000th 
         // time is high precision and gives the time down to 
         // microseconds (1/1,000,000) as fraction 0.001 is one microsecond 

    // you can stop the animation by simply not calling the request 
    // so if the flag stop is true stop the animation 
    if(!stop){ 
     requestAnimationFrame(update); // request the next frame 
    } 
} 

requestAnimationFrame(update); // request the very first frame 
// or you can start it with a direct call. But you will have to add the time 
update(0); 

更新功能每秒最多可调用60次。如果代码无法跟上(即,它需要超过1/60秒的渲染时间),那么更新功能将等待下一帧,从而有效地将帧速率降低到1/30。如果渲染速度慢,它将继续跳帧。

由于无法控制帧速率,因此可以执行以下操作将动画放慢至所需的帧速率。

const FRAMES_PER_SECOND = 30; // Valid values are 60,30,20,15,10 
// set the mim time to render the next frame 
const FRAME_MIN_TIME = (1000/60) * (60/FRAMES_PER_SECOND) - (1000/60) * 0.5; 
var lastFrameTime = 0; // the last frame time 
function update(time){ 
    if(time-lastFrameTime < FRAME_MIN_TIME){ //skip the frame if the call is to early 
     requestAnimationFrame(update); 
     return; // return as there is nothing to do 
    } 
    lastFrameTime = time; // remember the time of the rendered frame 
    // render the frame 
    requestAnimationFrame(update); 
} 

如果您将焦点更改为另一个选项卡,则浏览器将不再调用请求,直到焦点返回到选项卡。

像其他计时器事件调用requestAnimationFrame返回一个可用于取消回调事件

var id = requestAnimationFrame(update); 
// to cancel 
cancelAnimationFrame(id); 

实际上,你可以调用requestAnimationFrame超过每帧一次ID。只要所有请求都可以在1/60秒内呈现,他们都将同时同步并呈现给显示器。但是你必须小心,因为如果渲染时间太长,它们可能不同步。

RequestAnimationFrame通过双重缓冲更改防止闪烁(当渲染未完成时显示画布)。与显示器硬件同步并防止剪切(当显示器在画面中途更新时引起,并且显示器的上半部分显示旧画面,底部显示新帧)。取决于浏览器有更多好处。

0

这是我建立了我的游戏:

// DEFINE OBJECTS UP HERE 

var update = function(modifier) { 
    // update all the object properties 
    // multiply values that depend on time (like speeds) by modifier 
}; 
var render = function() { 
    // draw everything 
}; 
var main = function() { 
    var now = Date.now(); 
    var change = now - then; 

    update(change/1000); // update based on frame rate, change in milliseconds/second 
    render(); 
    then = now; 
    requestAnimationFrame(main); 
}; 

// ADD EVENT LISTENERS HERE 

requestAnimationFrame = window.requestAnimationFrame 
       || window.webkitRequestAnimationFrame 
       || window.msRequestAnimationFrame 
       || window.mozRequestAnimationFrame; 
// ABOVE CODE GIVES CROSS-BROWSER COMPATIBILITY 

    var then = Date.now(); 
    main(); 

requestAnimationFrame告诉执行基于帧速率的循环浏览器。就我个人而言,我不明白它是如何工作的,尽管如果有人在这里,我会对知道更多知识感兴趣。 setInterval允许您设置循环运行的速度,但最佳速率取决于浏览器。 “then”和“now”变量用于确定自从上次执行循环以来经过了多长时间。这个值可以被传递到更新的功能和用于依赖于帧速率计算,虽然有时候你不需要它,可以只使用:

var update = function() { 
     //STUFF 
}; 

// if using that variation just ignore then and now and call: 
update(); 
//in your main 

虽然使用当时和现在是更好的。