L’animazione del corpo non è liscia

Lo “spaceShip” nel codice seguente non si muove agevolmente all’inizio di tenere premuto alcun tasto freccia. Si muove di un passo, si blocca per una frazione di secondo e poi si sposta “senza problemi”. Come posso farlo muovere senza problemi fin dall’inizio, senza “congelare”?

Il mio codice:

    Make body move smoothly  body { } canvas { margin: auto; position: absolute; left: 0; top: 0; right: 0; bottom: 0; border: 1px solid black; }      // Set up requestAnimationFrame and cancelAnimationFrame (function() { var lastTime =0; var vendors=['ms', 'moz', 'webkit', 'o']; for(var x=0; x 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);    

Notare la differenza tra il mio codice e questo esempio: http://atomicrobotdesign.com/blog_media/sprite_sheet/spritesheet.html

Guarda come l’esempio è liscio, ma la mia “spaceShip” non lo è? Perché sta accadendo e come posso risolverlo? È perché l’esempio usa uno sprite (ma questo non sembra avere molto senso)?

Il problema è che attendi ogni evento keydown per aggiornare la posizione della nave.
L’evento keydown ha un ritardo prima che si inneschi di nuovo: il ritardo che stai vivendo all’inizio e il salto che affronti ad ogni nuovo aggiornamento.

La soluzione qui è di triggersre il movimento su keydown e rilasciarlo su keyup . In questo modo, la tua navetta si muoverà senza intoppi non appena premi il pulsante.

 // 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; }