![](/img/trans.png)
[英]Setting document style width with Javascript makes the animation go from left to right. How do I counteract this?
[英]How do I run an animation when moving to the left or right in JavaScript?
在JavaScript中按向左或向右箭頭鍵時如何運行Sprite動畫? 這是我的代碼:
var avatarX = 0;
var avatarY = 240;
var avatarImage;
var counter = 1;
var XWIDTH = 0;
var WIDTH = 400;
var dx = 5;
var tt;
var gameCanvas;
var context;
var moving;
var animationCounter = 1;
window.addEventListener('keydown', KeyDown);
function setUpGame() { //This is the function that is called from the html document.
gameCanvas = document.getElementById("gameCanvas"); //Declare a new variable & assigns it the id of the CANVAS from the html document.
context=gameCanvas.getContext("2d");
context.font = "18px Iceland";
context.textBaseline = "top";
avatarImage = new Image(); //Declaring a new variable. This is so that we can store the image at a later date.
avatarImage.onload=function(){
// avatarImage is now fully loaded and ready to drawImage
context.drawImage(avatarImage, Math.random() * 100, avatarY);
// start the timer
tt = setInterval(function(){counTer()},1000);
setInterval(handleTick, 25);
}
avatarImage.addEventListener('load', startLoop, false);
avatarImage.src = "img/ships.png"; //Ditto from above.
}
function startLoop() {
console.log("Detecting whether moving to the right is: " + moving);
if(moving == 0) {
gameLoop();
}
}
function gameLoop() {
setTimeout(gameLoop, 100);
handleTick();
}
function KeyDown(evt) {
switch (evt.keyCode) {
case 39: /*Arrow to the right*/
if(avatarX + dx <WIDTH && avatarX + dx >XWIDTH) {
avatarX += dx;
moving = 0;
}
break;
case 37: /*Arrow to the left*/
if(avatarX - dx >XWIDTH) {
avatarX -= dx;
moving = 1;
}
break;
}
}
function counTer() {
if(counter == 60) {
clearInterval(tt);
} else {
counter++;
}
}
function handleTick() {
context.clearRect(0,0,gameCanvas.width,gameCanvas.height);
context.drawImage(avatarImage, 32*animationCounter, 0, 32,32, avatarX, avatarY, 64, 64);
context.fillText("Seconds: " + counter, 5, 5);
context.fillText("1 is Right, 2 is Left, 0 is idle: " + moving, 20, 20);
animationCounter++
if(animationCounter >1) {
animationCounter = 0;
}
}
有很多方法可以實現動畫。 我使用的一個非常簡單,看起來像這樣:
var player = {
x: 0,
y: 0,
width: 50,
height: 100,
sprite: {
column: 0,
row: 0,
height: 50,
width: 100
},
image: PlayerImage,
animation: {
active: true, //Determines if the animation is running or not.
counter: 0,
progress: 0,
sequence: []
}
}
//This functions fires when the left arrow is pressed.
var onLeft = function(){
player.animation.sequence = [{column: 0, row: 0, t: 12}, {column: 1, row: 0, t: 12}, {column: 2, row: 0, t: 12}];
player.animation.active = true;
}
//This functions fires when the right arrow is pressed.
var onRight = function(){
player.animation.sequence = [{column: 0, row: 1, t: 12}, {column: 1, row: 1, t: 12}, {column: 2, row: 1, t: 12}];
player.animation.active = true;
}
//This function fires when no arrow are pressed.
var standingStill = function(){
player.animation.active = false;
}
var handleTick = function(){
//Clear the canvas.
context.canvas.width = context.canvas.width;
//If the animation is active.
if(player.animation.active){
//If the counter >= tick in the sequence. If not, just keep on increasing the counter value.
if(player.animation.counter >= player.animation.sequence[player.animation.progress]){
player.animation.counter = 1;
if(player.animation.progress >= player.animation.sequence.length - 1){
player.animation.progress = 0;
}else{
player.animation.progress++;
}
var currentFrame = player.animation.sequence[player.animation.progress];
//Change player.sprite column and row.(new frame)
player.sprite.column = currentFrame.column;
player.sprite.row = currentFrame.row;
}else{
player.animation.counter++;
}
}
context.drawImage(player.image, player.sprite.column * player.sprite.width, player.sprite.row * player.sprite.height, player.sprite.width, player.sprite.height, player.x, player.y, player.width, player.height)
}
該序列是一個包含以下對象的數組: {column: 0, row: 0, t: 12}
每個對象都是一個框架。 column
值是子畫面的當前x
, row
是子畫面的y
。 該腳本會自動創建x
和y
值,因此您只需添加0、1、3、5等值(僅在x或y軸上是哪一幀即可)。例如,如果列為0,行為0,則這是左上角的框架(第一幀)。 t
值代表滴答聲,它確定動畫進入下一幀之前必須發生多少滴答聲。
Player.sprite
還具有屬性width
和height
,即框架的寬度和高度,它通常與播放器對象的寬度和高度相同。
您必須在onLeft
和onRight
函數中onLeft
自己的player.animation.sequence
,以便對其進行動畫處理。
我希望你明白我的意思。 這可能看起來很復雜,但實際上並非如此,如果您現在不了解它,請不用擔心,您最終會得到它。 如果您確實難以理解,請提出。
編輯:首先,我強烈建議使用對象存儲有關實體的信息。 它使游戲制作變得更加輕松和整潔。 只需查看player
對象,只需編寫player.x
即可獲得x, player.x
比PlayerX
player.x
得多。 它看起來也更專業。 :)而且,當您必須提供有關實體的大量信息時,不必傳遞許多參數,則可以傳遞整個對象。 例:
//Entity properties stored in separate variable.
function animate(EntityX, EntityY, EntitySpriteX, EntitySpriteY, ...){
var x = EntityX;
//And so on...
}
//Entity stored in an object.
function animate(Entity){
var x = Entity.x;
//And so on...
}
無論如何,回到您的問題。 首先,我們必須添加變量來存儲有關精靈的信息。
var avatarSpriteColumn = 0; //Sprite frame on the x axis.
var avatarSpriteRow = 0; //Sprite frame on the y axis.
var avatarSpriteWidth = 50; //The width of a frame.
var avatarSpriteHeight = 100; //The height of a frame.
我們還必須添加變量來存儲有關動畫的信息。
var animationActive = false; //A variable that controls if the animation is 'running'.
var animationCounter = 0; //How many frames(ticks) have passed since the last frame(animation frame) has changed. (I'm not good at describing variables. :P)
var animationProgress = 0; //Current animation frame.
var animationSequence = []; //Array that stores the sequence of animation, as i explained.
然后,在handleTick
函數中,您必須添加將使Sprite動畫的代碼。 在繪制實體之前,您必須添加此代碼。
//If the animation is active.
if(animationActive){
//If the counter >= tick in the sequence. If not, just keep on increasing the counter value.
if(animationCounter >= animationSequence[animationProgress]){
animationCounter = 1;
//Reset the progress, so that next time another animation frame shows up.
if(animationProgress >= animationSequence.length - 1){
animationProgress = 0;
}else{
animationProgress++;
}
//Select information about the current animation frame and store it in a variable so it is easier to access.
var currentFrame = animationSequence[animationProgress];
//Change player.sprite column and row.(new frame);
avatarSpriteColumn = currentFrame.column;
avatarSpriteRow = currentFrame.row;
}else{
animationCounter.counter++;
}
}
好的,現在您有了使子畫面動畫的代碼,但是我們如何運行它呢? 好吧,我看到您有一個名為moving
的變量。 它告訴我們玩家朝哪個方向移動,以及是否根本在移動。 看來您實現了它有點錯誤。 現在,您操作按鍵的功能如下所示:
function KeyDown(evt) {
switch (evt.keyCode) {
case 39: /*Arrow to the right*/
if(avatarX + dx <WIDTH && avatarX + dx >XWIDTH) {
avatarX += dx;
moving = 0;
}
break;
case 37: /*Arrow to the left*/
if(avatarX - dx >XWIDTH) {
avatarX -= dx;
moving = 1;
}
break;
}
}
如果實體向右移動,則該變量應返回1;如果實體向左移動,則該變量應返回2;如果實體靜止不動,則該變量返回0,對嗎? 現在,當實體向右移動時,它顯示0;當實體向左移動時,它顯示1。 它也不會顯示實體是否空閑。 我們必須修復它。 將其更改為如下所示:
function KeyDown(evt) {
switch (evt.keyCode) {
case 39: /*Arrow to the right*/
if(avatarX + dx <WIDTH && avatarX + dx >XWIDTH) {
avatarX += dx;
moving = 1;
}
break;
case 37: /*Arrow to the left*/
if(avatarX - dx >XWIDTH) {
avatarX -= dx;
moving = 2;
}
break;
default:
moving = 0;
}
}
好的,現在我們必須將此代碼添加到handleTick函數中。 此代碼啟動動畫並更改序列。:
if(moving == 1){ //Moving in the right direction.
animationSequence = []; //Animation of moving in the right direction. Change the sequence to your own.
animationActive = true; //Run the animation.
}else if(moving == 2){ //Moving to the left.
animationSequence = []; //Animation of moving to the left. Change the sequence to your own.
animationActive = true; //Run the animation.
}else{
animationActive = false; //Stops the animation, but the last frame stays.
/*
Alternatively, if you want a separate frame or animation that is animating when the entity is standing, you run this code.
animationSequence = []; // Your sequence. If you want a single frame, with no animation just add one frame to the sequence.
animationActive = true;
*/
}
現在,我們要做的最后一件事是繪制實體。 您的情況如下所示:
context.drawImage(avatarImage, avatarSpriteColumn * avatarSpriteWidth, avatarSpriteRow * avatarSpriteHeight, avatarWidth, avatarHeight, avatarX, avatarY, 64, 64);
最后,您的整個代碼將如下所示:
var avatarX = 0;
var avatarY = 240;
var avatarImage;
var counter = 1;
var XWIDTH = 0;
var WIDTH = 400;
var dx = 5;
var tt;
var gameCanvas;
var context;
var moving;
var animationCounter = 1;
var avatarSpriteColumn = 0; //Sprite frame on the x axis.
var avatarSpriteRow = 0; //Sprite frame on the y axis.
var avatarSpriteWidth = 50; //The width of a frame.
var avatarSpriteHeight = 100; //The height of a frame.
var animationActive = false; //A variable that controls if the animation is 'running'.
var animationCounter = 0; //How many frames(ticks) have passed since the last frame(animation frame) has changed. (I'm not good at describing variables. :P)
var animationProgress = 0; //Current animation frame.
var animationSequence = []; //Array that stores the sequence of animation, as i explained.
window.addEventListener('keydown', KeyDown);
function setUpGame() { //This is the function that is called from the html document.
gameCanvas = document.getElementById("gameCanvas"); //Declare a new variable & assigns it the id of the CANVAS from the html document.
context=gameCanvas.getContext("2d");
context.font = "18px Iceland";
context.textBaseline = "top";
avatarImage = new Image(); //Declaring a new variable. This is so that we can store the image at a later date.
avatarImage.onload=function(){
// avatarImage is now fully loaded and ready to drawImage
context.drawImage(avatarImage, Math.random() * 100, avatarY);
// start the timer
tt = setInterval(function(){counTer()},1000);
setInterval(handleTick, 25);
}
avatarImage.addEventListener('load', startLoop, false);
avatarImage.src = "img/ships.png"; //Ditto from above.
}
function startLoop() {
console.log("Detecting whether moving to the right is: " + moving);
if(moving == 0) {
gameLoop();
}
}
function gameLoop() {
setTimeout(gameLoop, 100);
handleTick();
}
function KeyDown(evt) {
switch (evt.keyCode) {
case 39: /*Arrow to the right*/
if(avatarX + dx <WIDTH && avatarX + dx >XWIDTH) {
avatarX += dx;
moving = 1;
}
break;
case 37: /*Arrow to the left*/
if(avatarX - dx >XWIDTH) {
avatarX -= dx;
moving = 2;
}
break;
default:
moving = 0;
}
}
function counTer() {
if(counter == 60) {
clearInterval(tt);
} else {
counter++;
}
}
function handleTick() {
context.clearRect(0,0,gameCanvas.width,gameCanvas.height);
if(moving == 1){ //Moving in the right direction.
animationSequence = []; //Animation of moving in the right direction. Change the sequence to your own.
animationActive = true; //Run the animation.
}else if(moving == 2){ //Moving to the left.
animationSequence = []; //Animation of moving to the left. Change the sequence to your own.
animationActive = true; //Run the animation.
}else{
animationActive = false; //Stops the animation, but the last frame stays.
/*
Alternatively, if you want a separate frame or animation that is animating when the entity is standing, you run this code.
animationSequence = []; // Your sequence. If you want a single frame, with no animation just add one frame to the sequence.
animationActive = true;
*/
}
//If the animation is active.
if(animationActive){
//If the counter >= tick in the sequence. If not, just keep on increasing the counter value.
if(animationCounter >= animationSequence[animationProgress]){
animationCounter = 1;
//Reset the progress, so that next time another animation frame shows up.
if(animationProgress >= animationSequence.length - 1){
animationProgress = 0;
}else{
animationProgress++;
}
//Select information about the current animation frame and store it in a variable so it is easier to access.
var currentFrame = animationSequence[animationProgress];
//Change player.sprite column and row.(new frame);
avatarSpriteColumn = currentFrame.column;
avatarSpriteRow = currentFrame.row;
}else{
animationCounter.counter++;
}
}
context.drawImage(avatarImage, avatarSpriteColumn * avatarSpriteWidth, avatarSpriteRow * avatarSpriteHeight, avatarWidth, avatarHeight, avatarX, avatarY, 64, 64);
context.fillText("Seconds: " + counter, 5, 5);
context.fillText("1 is Right, 2 is Left, 0 is idle: " + moving, 20, 20);
}
您現在唯一要做的就是制作自己的animationSequences
並檢查其是否有效,如果您有任何問題,請告訴我。
當然,我使用的代碼更加復雜,具有更多的“功能”,並且易於使用(后面的代碼更加復雜),但是希望這會對您有所幫助。
我還必須為使事情看起來如此復雜(如果不是這樣)感到不安。 我不好解釋。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.