帆布迷宫游戏流畅的动画

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了帆布迷宫游戏流畅的动画相关的知识,希望对你有一定的参考价值。

我正在构建一个基于this教程的迷宫游戏。只要按住箭头键,我就成功地让玩家矩形继续移动。当你第一次开始游戏时,动画真的很好而且很快,但似乎在玩游戏几秒后动画变得越来越慢。任何人都可以帮我弄清楚为什么会这样吗?

我已经创建了一个代码片段,但不幸的是,由于我正在使用的迷宫图像导致的跨源错误,它无法正常工作。

var canvas;
var ctx;
var dx = 2;
var dy = 2;
var WIDTH = 482;
var HEIGHT = 482;

//movement
var x = 200,
    y = 5,
    staticX = 200,//this should be the same as x (used for resetting the game)
    staticY = 5,//this should be the same as y (used for resetting the game)
    keys = [];

var img = new Image();
var collision = 0;
var showingWinScreen = false;
var playerSize = 15;

var startTime = null,
  lastTime = null,
  endTime,  // for scale
  isRunning = false,
  FPS = 1000/60; // ideal frame rate


function rect(x,y,w,h) {
  ctx.beginPath();
  ctx.rect(x,y,w,h);
  ctx.closePath();
  ctx.fill();
}

function clear() {
  ctx.clearRect(0, 0, WIDTH, HEIGHT);
}

function drawMaze() {
  ctx.drawImage(img, 0, 0);
}

function drawPlayer() {
  doKeyDown();

  ctx.fillStyle = "purple";
  rect(x, y, 15,15);
}

function draw() {
  clear();

  if(showingWinScreen) {
    isRunning = false;
    drawRect(0,0,canvas.width, canvas.height,"black");
    ctx.fillStyle = "white";
    ctx.font = "20px Arial";
    ctx.fillText("You Won! Click to play again", 70,canvas.height/2);
    ctx.fillText("Time Elapsed: " + endTime, 70, canvas.height*0.6);
    return;
  }
  isRunning = true;

  drawMaze();
  drawPlayer();
  requestAnimationFrame(loop);
}

function drawRect(leftX, topY, width, height, drawColor) {
  ctx.fillStyle = drawColor;
  ctx.fillRect(leftX,topY,width, height);
}

//timer
function loop(timeStamp) {

  if (!startTime) {
    startTime = timeStamp;
  }

  var timeDiff = lastTime ? timeStamp - lastTime : FPS,
      timeElapsed = timeStamp - startTime,
      timeScale = timeDiff / FPS; // adjust variations in frame rates

  lastTime = timeStamp;

  var totalTime = timeElapsed*0.001;
  var minutes = Math.floor(totalTime / 60);
  var seconds = totalTime % 60;

  drawRect(WIDTH,10,70, 30,"black");
  ctx.fillStyle = "white";
  ctx.font = "14px Arial";
  ctx.fillText(minutes + ":" + (seconds).toFixed(2), WIDTH*1.04, 30);

  endTime = minutes + ":" + (seconds).toFixed(0);

  if (isRunning) requestAnimationFrame(loop);
}

function init() {

  canvas = document.getElementById("canvas");
  ctx = canvas.getContext("2d");
  img.src = "https://html5.litten.com/images/maze.gif";
  var framesPerSecond = 60;
  return setInterval( function() {
    draw();
  }, 1000/framesPerSecond);
}

function checkcollision() {
  var imgd = ctx.getImageData(x, y, playerSize, playerSize);
  var pix = imgd.data;
  for (var i = 0; n = pix.length, i < n; i += 4) {
    if (pix[i] == 0) {
      collision = 1;
    }
  }
}

function checkWin() {
  var imageData = ctx.getImageData(x, y, playerSize, playerSize);
  var r, g, b, a;
  for (var i = 0; i+3 < imageData.data.length; i += 4) {
    r = imageData.data[i];
    g = imageData.data[i+1];
    b = imageData.data[i+2];
    a = imageData.data[i+3];

    //if red
    if ( r === 255 && b === 0 ) {
      console.log(' R: ' + r + '<br>G: ' + g + '<br>B: ' + b);
      isRunning = false;
      showingWinScreen = true;
    }
  }
}



function handleMouseClick(event) {
  if (showingWinScreen) {
    showingWinScreen = false;
    x = staticX;
    y = staticY;
    draw();
  }
}

//arrow keys
function doKeyDown(){
  //left
  if (keys[37]) {
    if (x - dx > 0){
      x -= dx;
      checkcollision();
      checkWin();
      if (collision == 1){
        x += dx;
        collision = 0;
      }
    }
  }
  //right
  if (keys[39]) {
    if (x + dx < WIDTH){
      x += dx;
      checkcollision();
      checkWin();
      if (collision == 1){
        x -= dx;
        collision = 0;
      }
    }
  }
  //down
  if (keys[40]) {
    if (y + dy < HEIGHT ){
      y += dy;
      checkcollision();
      checkWin();
      if (collision == 1){
        y -= dy;
        collision = 0;
      }
    }
  }
  //up
  if (keys[38]) {
    if (y - dy > 0){
      y -= dy;
      checkcollision();
      checkWin();
      if (collision == 1){
        y += dy;
        collision = 0;
      }
    }
  }
}

init();

window.addEventListener("keydown", function (e) {
  keys[e.keyCode] = true;
});
window.addEventListener("keyup", function (e) {
  keys[e.keyCode] = false;
});

canvas.addEventListener("mousedown", handleMouseClick);

(function () {
  var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  window.requestAnimationFrame = requestAnimationFrame;
})()
<canvas id="canvas" width="582" height="582">
      This text is displayed if your browser does not support HTML5 Canvas.
      </canvas>
答案

最大的问题在这里? 你的计时器。

让我们删除与画布相关的所有内容,然后尝试记录每帧绘制这个小时间计数器的次数:

// If everything was ok, frame_count should never be higher than 1
var frame_count = 0;
var total_count = 0;

function frame_loop() {
  frame_log.textContent = frame_count;
  total_log.textContent = total_count;
  // reset our frame counter
  frame_count = 0;
  // do it again next loop
  requestAnimationFrame(frame_loop);
}
frame_loop();

var startTime = null,
  lastTime = null,
  endTime,  // for scale
  isRunning = false,
  FPS = 1000/60; // ideal frame rate

function draw() {
  isRunning = true;
  requestAnimationFrame(loop);
}

//timer
function loop(timeStamp) {

  frame_count ++;
  total_count ++;
  
  if (!startTime) {
    startTime = timeStamp;
  }

  var timeDiff = lastTime ? timeStamp - lastTime : FPS,
      timeElapsed = timeStamp - startTime,
      timeScale = timeDiff / FPS; // adjust variations in frame rates

  lastTime = timeStamp;

  var totalTime = timeElapsed*0.001;
  var minutes = Math.floor(totalTime / 60);
  var seconds = totalTime % 60;
  endTime = minutes + ":" + (seconds).toFixed(0);
  if (isRunning) requestAnimationFrame(loop);
}

function init() {
  var framesPerSecond = 60;
  return setInterval( function() {
    draw();
  }, 1000/framesPerSecond);
}


init();
<p>number of times loop() has been called <b>during last frame</b>: <span id="frame_log"></span></p>

<p>number of times loop() has been called <b>in total</b>: <span id="total_log"></span></p>

以上是关于帆布迷宫游戏流畅的动画的主要内容,如果未能解决你的问题,请参考以下文章

个税小游戏要点之节流函数(提高动画流畅性)

[OpenGL] 骨骼动画混合效果

如何将自定义形状变形/动画成圆形?帆布 JS

《迷宫大侦探》登陆Steam冬季游戏节

动画演示深度优先算法搜寻逃出迷宫的路径

帆布火花线