簡體   English   中英

如何在HTML5畫布上創建正在播放的動畫?

[英]How can I create a running animation on an HTML5 canvas?

我正在構建一個簡單的2D游戲,以嘗試學習畫布。 角色可以在虛擬環境中運行,並且一個名為yOffset的變量控制其與屏幕頂部的偏移量。 我還有一個名為running的全局變量,它根據字符是否正在運行而將自身設置為true或false(此處未顯示)。 我的目標是使角色在運行時上下擺動,以下所有代碼都產生了許多setInterval() 這是使角色運行的正確方法,還是應該以其他方式進行? 如果是這樣,怎么辦?

$(document).keydown(function(e) {
        if(e.which == 97) {
            running = true;
            run();
        } else if(e.which == 100) {
            running = true;
            run();
        } else if(e.which == 119) {
            running = true;
            run();
        } else if(e.which == 115) {
            running = true;
            run();
        }
      });

(是的,如果角色停止運行,則運行變量確實變為false [此處未顯示]-我已經確保了運行變量運行良好)

runTimer = 0;
function run() {
    if(runTimer == 0 && running) {
        runTimer = 1;
        yOffset = 80;
        setTimeout(function() {
            yOffset = 120;
        }, 150);
        setTimeout(function() { if (running) { runTimer = 0;run(); } }, 300);
    }
}

如果您需要更多信息,請在此處獲得我當前正在使用的版本。

我認為你可以簡化你的代碼,而事實上,你必須在很可能的情況下,你想添加一些其它字符。

為了重新使用動畫,最好將動畫(==角色將經歷的不同步驟)和動畫狀態(==角色現在位於哪一步)分開。

我在這里寫了動畫系統的一些元素。
因此,我定義了什么是動畫步驟,整個動畫(到目前為止,這只是動畫步驟的一個數組)和一個動畫器(保存狀態,有人可能會將其視為動畫的“讀取器”)。

一旦定義了動畫和動畫師,並啟動了動畫師,您只需要調用tick(time)以使動畫繼續前進,並調用offset()來讀取偏移量,這比與一堆setIntervals戰斗要簡單得多。

http://jsfiddle.net/xWwFf/

// --------------------
function AnimationStep(duration, offset) {
    this.duration = duration;
    this.offset = offset;
    // you might add : image index, rotation, ....
}

// --------------------
function Animation(animationSteps) {
    this.steps = animationSteps;  // Array of AnimationStep
}

// define a read-only length property
Object.defineProperty(Animation.prototype, 'length', {
    get: function () {
        return this.steps.length
    }
});

// --------------------
function Animator() {
    this.currentAnimation = null;
    this.step = -1;
    this.running = false;
    this.remainingTime = 0; // remaining time in current step;
}

Animator.prototype.startAnim = function (newAnim, firstStep) {
    this.currentAnimation = newAnim;
    this.step = firstStep || 0;
    this.remainingTime = newAnim.steps[this.step].duration;
    this.running = true;
}

Animator.prototype.tick = function (dt) {
    // do nothing if no animation ongoing.
    if (!this.running) return;
    this.remainingTime -= dt;
    // 'eat' as many frames as required to have a >0 remaining time
    while (this.remainingTime <= 0) {
        this.step++;
        if (this.step == this.currentAnimation.length) this.step = 0;
        this.remainingTime += this.currentAnimation.steps[this.step].duration;
    }
};

Animator.prototype.offset = function () {
    return this.currentAnimation.steps[this.step].offset;
}

// ______________________________
// example

var bounceAnim = [];
bounceAnim.push(new AnimationStep(200, 10));
bounceAnim.push(new AnimationStep(180, 20));
bounceAnim.push(new AnimationStep(150, 30));
bounceAnim.push(new AnimationStep(300, 40));
bounceAnim.push(new AnimationStep(320, 45));
bounceAnim.push(new AnimationStep(200, 40));
bounceAnim.push(new AnimationStep(120, 30));
bounceAnim.push(new AnimationStep(100, 20));

var anim1 = new Animation(bounceAnim);

var animator1 = new Animator();
var animator2 = new Animator();

animator1.startAnim(anim1);
animator2.startAnim(anim1, 3);

// in action :
var ctx = document.getElementById('cv').getContext('2d');

function drawScene() {
    ctx.fillStyle = 'hsl(200,60%, 65%)';
    ctx.fillRect(0, 0, 600, 200);
    ctx.fillStyle = 'hsl(90,60%,75%)';
    ctx.fillRect(0, 200, 600, 200);
    ctx.fillStyle = 'hsl(10,60%,75%)';
    ctx.fillRect(200, 200 + animator1.offset(), 22, 22);
    ctx.fillStyle = 'hsl(40,60%,75%)';
    ctx.fillRect(400, 200 + animator2.offset(), 22, 22);
    animator1.tick(20);
    animator2.tick(20);
}

setInterval(drawScene, 20);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM