2

我有一个我正在制作的游戏的动画,似乎不会重复。当按下空格键时,它会触发一个事件,将一个圆圈“射”到画布的顶部。问题是当再次按下该键时,它不会启动动画。这是我编写的示例代码:

var canvas, ctx,
    spaceKey = false,
    upKey = false,
    downKey = false,
    canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    shotX = 150, shotY = 280;

function loop() {
    if (spaceKey) shoot();
}

function keyDown(e) {
    if (e.keyCode == 32) spaceKey = true;
}
function keyUp(e) {
    if (e.keyCode == 32) spaceKey = false;
}

function shoot() {
    setTimeout(function() { if (shotY > 0) {
        ctx.clearRect(shotX-5,shotY-5,600,20);
        ctx.beginPath();
        ctx.arc(shotX, shotY,4,0,Math.PI * 2, false);
        ctx.fillStyle = "yellow";
        ctx.fill();
        ctx.closePath();

        shotY = shotY - 1;

        shoot();

    } else
        ctx.clearRect(shotX-5,shotY-5,600,20);
    }, 100);
}

(function init() {
    setInterval(loop, 10);
    document.addEventListener('keydown', keyDown, false);
    document.addEventListener('keyup', keyUp, false);
})();
//init();

我使用keyUpand的原因keyDown是因为我还有其他使用不同键的功能。此代码已修改为仅显示此功能。为了更容易理解我在说什么,我创建了一个JSFiddle。我拥有的其他功能具有类似的结构和工作原理,唯一的区别是它的持续时间不是由按键直接控制的。

4

2 回答 2

2

我发现您的代码没有太多可重用性。您应该考虑使用对象来表示画布上的实体。我已经创建了简单的代码来完成你的工作,但它也不能重复使用(尽管你可以重复使用它来创建一个简单的实体,比如你创建的球)。检查这个jsFiddle

您的代码的问题是,当那个黄色球到达屏幕的 to 时,shotY是 0,然后您从屏幕上擦除球,但不要重置shotY并且不要在其家重绘球(原始位置)。

我创建了一个简单的Ball对象来完成这项工作-

function Ball() {
    this.x = 150;
    this.y = 295;
}
Ball.prototype.draw = function(newx, newy) {
    ctx.clearRect(this.x-5,this.y-5,600,20);
    newx = newx || this.x;
    newy = newy || this.y;
    this.x = newx; this.y = newy;
    var ball = this;
    ctx.beginPath( );
    ctx.arc(ball.x, ball.y,4,0,Math.PI * 2, false);
    ctx.fillStyle = "yellow";
    ctx.fill();
    ctx.closePath();
}
Ball.prototype.shootUp = function() {
    var ball = this;
    inter = setInterval(function () {
        if(ball.x <= 0) clearInterval(inter);
        ball.draw(ball.x, ball.y-20);
    }, 100);
}

并修改了您的shoot功能-

function shoot() {
    var currentBall = new Ball();
    currentBall.draw();
    currentBall.shootUp();
}

再一次,这只是一个简单的例子。你可以对它进行很多改进。首先,您应该有一个输入引擎来管理所有输入。然后你应该有一个通用实体类来表示你在画布上拥有的所有对象。就像Ball. 最后你应该有一个游戏引擎来绑定所有这些东西。

于 2013-03-22T05:32:38.687 回答
2

你只有一个“子弹”。您的项目符号应该是实例化的单独对象shoot()

我通常处理“粒子”的方式是创建一个单例对象来存储每个实例并在主循环中更新所有实例。

这是一个简单的 Bullet 对象:

function Bullet(){
    this.x = 150;
    this.y = 280;
    this.velX = 0;
    this.velY = -1;

    this.update = function(){
        this.y += this.velY;
    };

    this.draw = function(){
        ctx.beginPath();
        ctx.arc(this.x, this.y,4,0,Math.PI * 2, false);
        ctx.fillStyle = "yellow";
        ctx.fill();
        ctx.closePath();
    };
};

这是一个处理子弹的 BulletRenderer 单例:

BulletRenderer = function(){
    var bullets = [];

    this.push = function(bullet){
        bullets.push(bullet);
    };

    this.render = function(){
        for (var i in bullets){
            if (bullets[i].active){
                bullets[i].update();
                bullets[i].draw();
            } else {
                delete bullets[i];
            }
        }
    };

    return this;
}();

在示例中,我只是在每帧清除画布。射击机制现在就像激光一样。我个人会改变这种行为。

http://jsfiddle.net/NAJus/18/

于 2013-03-22T05:36:20.670 回答