2016-06-25 9 views
0

Итак, я создавал игру на холсте в HTML и Javascript. Я хотел сделать какую-то флип-птичью игру, но когда я нажимаю клавишу, анимация игрока выглядит заикающейся. Посмотрите:Smooth Animation in HTML5 Canvas

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 вызов возвращает идентификатор, который может быть использован для отмены события CallBack

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

Вы можете на самом деле назвать requestAnimationFrame более чем один раз за кадр. Пока все запросы могут отображаться в течение 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 

Хотя использование тогда и сейчас лучше.

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

  • Нет связанных вопросов^_^