身体动画不流畅 [英] Body animation isn't smooth

查看:26
本文介绍了身体动画不流畅的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码中的spaceShip"在开始按住任何箭头键时移动不顺畅.它移动一步,冻结一瞬间,然后平稳"移动.我怎样才能让它从一开始就顺畅地移动,而不是冻结"?

The "spaceShip" in the following code isn't moving smoothly at the beginning of holding any arrow key down. It moves one step, freezes for a split second, and then moves "smoothly". How can I make it move smoothly right from the beginning, with not "freezing"?

我的代码:

<!doctype html>
<html>
<head>
    <meta http-content="Content-type" charset="utf-8">
    <title>Make body move smoothly</title>
    <style type="text/css">
        body {
        }

        canvas {
            margin: auto;
            position: absolute;
            left: 0;
            top: 0;
            right: 0;
            bottom: 0;
            border: 1px solid black;
        }

    </style>
</head>
<body>
<canvas id="canvas" width="400" height="600"></canvas>
<script type="text/javascript">

// Set up requestAnimationFrame and cancelAnimationFrame
(function() {
    var lastTime =0;
    var vendors=['ms', 'moz', 'webkit', 'o'];
    for(var x=0; x<vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame=window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame =
        window[vendors[x]+ 'CancelAnimationFrame'] ||
        window[vendors[x] +'CancelRequestAnimationFrame'];
    }
    if (!window.requestAnimationFrame)
    window.requestAnimationFrame=function(callback, element) {
        var currTime =new Date().getTime();
        var timeToCall =Math.max(0, 16 - (currTime - lastTime));
        var id =window.setTimeout(function() { callback(currTime+timeToCall); },
        timeToCall);
        lastTime =currTime + timeToCall;
        return id;
    };
    if (!window.cancelAnimationFrame)
    window.cancelAnimationFrame=function(id) {
        clearTimeout(id);
    };
}());


    var canvas;
    var ctx;
    // ship data
    var shipPositionX = document.getElementById('canvas').width/2;
    var shipPositionY = document.getElementById('canvas').height - 30;
    var deltaShipPositionX = 10;
    var deltaShipPositionY = 10;

    function init() {
        canvas = document.getElementById('canvas');
        ctx = canvas.getContext('2d');

        draw();
    }

    function draw(){
        clear();
        createRectangleToCoverCanvas();
        createSpaceShip(shipPositionX, shipPositionY, 10);

        requestAnimationFrame(draw);
    }

    function clear(){
        ctx.clearRect(0, 0, document.getElementById('canvas').width, document.getElementById('canvas').height);
    }

    function createRectangleToCoverCanvas(){
        ctx.fillStyle = 'black';
        ctx.strokeStyle = 'black';
        ctx.beginPath();
        ctx.rect(0, 0, canvas.width, canvas.height);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
    }

    function createSpaceShip(x, y, radius) {
        ctx.fillStyle = 'white'
        ctx.strokeStyle = 'white'
        ctx.beginPath();
        ctx.rect(x, y, 20, 20);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
    }

    function moveSpaceShip(event){
        switch(event.keyCode){
            // left
            case 37:
                if(shipPositionX - deltaShipPositionX + 15 > 0){
                    shipPositionX -= deltaShipPositionX;
                }
            break;

            // up
            case 38:
                if(shipPositionY - deltaShipPositionY + 15 > 0){
                    shipPositionY -= deltaShipPositionY;
                }
            break;

            // right
            case 39:
                if(shipPositionX + deltaShipPositionX < document.getElementById('canvas').width){
                    shipPositionX += deltaShipPositionX;
                }
            break;

            //down
            case 40:
                if(shipPositionY + deltaShipPositionY < document.getElementById('canvas').height){
                    shipPositionY += deltaShipPositionY;
                }
            break;
        }

    }

    window.addEventListener('load', init);
    window.addEventListener('keydown', moveSpaceShip, true);
</script>
</body>
</html>

注意我的代码和这个例子的区别:http://atomicrobotdesign.com/blog_media/sprite_sheet/spritesheet.html

Notice the difference between my code and this example: http://atomicrobotdesign.com/blog_media/sprite_sheet/spritesheet.html

看看这个例子是如何流畅的,但我的太空船"不是?为什么会发生这种情况,我该如何解决?是不是因为示例使用了精灵(但这似乎没有多大意义)?

See how the example's is smooth, but my "spaceShip" isn't? Why is it happening and how can I fix it? Is it because the example uses a sprite (but this doesn't seem to make much sense)?

推荐答案

问题是您要等待每个 keydown 事件更新船舶位置.
keydown 事件在再次触发之前有一个延迟:您在开始时遇到的延迟以及您在每次重绘时面临的跳转.

The problem is that you wait for each keydown event to update the ship position.
The keydown event has a delay before it triggers again : the delay you are experiencing at beginning and the jump you face at each redraw.

这里的解决方案是在 keydown 上触发移动并在 keyup 上释放它.这样,您一按下按钮,您的船就会平稳移动.

The solution here is to trigger the movement on keydown and release it on keyup. This way, your ship will move smoothly as soon as you push the button.

// Im' assuming most of visitors here have recent browsers, so I removed the rAF polyfill for readibility

// If you wrap it after the canvas element decalaration, you can already populate this variable, it will avoid that you make a lot of calls to document.getElementById()
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// ship data
var shipPositionX = canvas.width / 2;
// Just for the snippet height
var shipPositionY = 0;
var deltaShipPositionX = 10;
var deltaShipPositionY = 10;

//Removed the init() function, since our elements are loaded.


function draw() {
  clear();
  createRectangleToCoverCanvas();
  createSpaceShip(shipPositionX, shipPositionY, 10);
}

function clear() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
}

function createRectangleToCoverCanvas() {
  ctx.fillStyle = 'black';
  ctx.strokeStyle = 'black';
  ctx.beginPath();
  ctx.rect(0, 0, canvas.width, canvas.height);
  ctx.fill();
  ctx.stroke();
}

function createSpaceShip(x, y, radius) {
  ctx.fillStyle = 'white'
  ctx.strokeStyle = 'white'
  ctx.beginPath();
  ctx.rect(x, y, 20, 20);
  ctx.fill();
  ctx.stroke();
}
// instantiate a variable that will store our animationFrame id, so we can cancel it further
var raf, 
// the direction object, with an x and y values
    direction = {
      x: 0,
      y: 0
    };
// we can set a speed variable
var speed = 2.5;
function triggerMoveSpaceShip(event) {
  switch (event.keyCode) {
    // left
    case 37:
      // update the direction object
      direction.x = -speed;
      // avoid the scroll in the snippet
      event.preventDefault();
      break;

      // up
    case 38:
      direction.y = -speed;
      event.preventDefault();
      break;

      // right
    case 39:
      direction.x = speed;
      event.preventDefault();
      break;

      //down
    case 40:
      direction.y = speed;
      event.preventDefault();
      break;
  }
  // if we haven't initiated the animation yet, and that our direction is not 0, then do it now
  if (!raf && (direction.x || direction.y)) moveSpaceShip();
}

function releaseMoveSpaceShip(event) {;
  switch (event.keyCode) {
    // left
    case 37:
      //reset this direction
      direction.x = 0;
      break;

      // up
    case 38:
      direction.y = 0;
      break;

      // right
    case 39:
      direction.x = 0;
      break;

      //down
    case 40:
      direction.y = 0;
      break;
  }
  if (!direction.x && !direction.y) {
    // if none of the directions is set, stop the animation
    cancelAnimationFrame(raf);
    raf = undefined;
  }
}

function moveSpaceShip() {
  // declare our animation function
  var move = function() {
    // update the positions without going out of the screen
    // Sorry, this is dirty...
    if(direction.x){
    	if(
	    	(shipPositionX > 0 && shipPositionX < canvas.width-20) ||
			(shipPositionX <= 0 && direction.x > 0) ||
			(shipPositionX >= canvas.width-20 && direction.x < 0))
				shipPositionX += direction.x;
		}
	if(direction.y){
    	if(
	    	(shipPositionY > 0 && shipPositionY < canvas.height-20) ||
			(shipPositionY <= 0 && direction.y > 0) ||
			(shipPositionY >= canvas.width-20 && direction.y < 0))
				shipPositionY += direction.y;
		}

    // finally draw ou ship
    draw();
    // update our raf id
    raf = requestAnimationFrame(move);
  };
  // let's go !
  raf = requestAnimationFrame(move);
}


draw();

window.addEventListener('keydown', triggerMoveSpaceShip, true);
window.addEventListener('keyup', releaseMoveSpaceShip, true);

canvas {
  margin: auto;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  border: 1px solid black;
}
body{
   overflow: none;
  }

<canvas id="canvas" width="400" height="200"></canvas>

未注释的小提琴

这篇关于身体动画不流畅的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆