FPS Lock за HTML Canvas/Javascript

Опитвах се да направя анимация кадър по кадър със spritesheet, който направих на HTML уебсайт, и не можах да разбера как да заключа fps за анимацията. Проблемът е, че винаги се движи със светкавични скорости и искам да мога да го заключа на ~ 10-15 кадъра в секунда. Опитах да използвам метода Date.now() и метода setInterval, но изглежда не работи за момента.

Начинът, по който използвам тази анимация, също зависи от проверка на масив, за да се уверя, че трябва да се ангажира с анимирането на анимацията от 4 кадъра, която направих. Ето кода, който използвах.

function animateCharacter() {
    var canvas = document.getElementById("portrait");
    var context = canvas.getContext("2d");
    var character = new Image();
    character.src = "/assets/spritesheet.jpg";
    animate();
    function animate() {

        context.drawImage(character, shift, 0, width, height, 300, 0, width / 2, height / 2);

        if (currentFrame == totalFrames) {
            shift = 0;
            currentFrame = 0;
        }
        requestAnimationFrame(animate);

}

person Brain Meme    schedule 13.12.2017    source източник


Отговори (2)


Можете да опитате setTimeout

 function animate(){
// do your animation
//     workout your frame rate
  setTimeout(animate, 500);
 };
 animate();
person Fan Cheung    schedule 13.12.2017

Има няколко начина за решаване на това, но общата идея е да проверите за HighResTimeStamp, който имате във вашето rAF обратно извикване, и да актуализирате стойностите си според него.

Ето една фиктивна реализация, която ще се актуализира само ако е преминал поне един кадър и ще предаде time_delta на функцията update, така че да знае с колко трябва да мащабира своите скорости стойности.

const ctx = c.getContext('2d');

// we need to know when the last frame did trigger
let lastTick = performance.now();
function anim(time){
  const time_spent = time - lastTick,
    passed_frames = time_spent / (1000 / FPS.value);
  if(passed_frames >= 1){
    update(passed_frames);
    lastTick = time;
    draw();
  }
  requestAnimationFrame(anim);
}

let x = 0;
const speed = 5;
function update(time_delta){
  x = (x + (speed * time_delta)) % (c.width - 10);
}
function draw(){
  ctx.clearRect(0,0,c.width,c.height);
  ctx.fillRect(x, 50, 20, 20);
}

anim(performance.now());
<label>FPS: 1<input id="FPS" type="range" min="1" max="120">120</label><br>
<canvas id="c"></canvas>

Обърнете внимание, че това е само една от многото реализации, които могат да бъдат направени, може също да сме закръглили тази стойност на time_delta и/или дори да изпълним update в for цикъл, или...

person Kaiido    schedule 13.12.2017