【问题标题】:Shoot 3 bullets on set times from each enemy在设定的时间从每个敌人身上射出 3 发子弹
【发布时间】:2013-03-12 05:39:01
【问题描述】:

我正在尝试在我的画布上使用 kineticJS 创建一个简单的游戏(只是一些练习)并设法让我的玩家射击子弹。产生的敌人也是如此。每次最后一颗子弹离开舞台时,他们都会发射一颗子弹。

但是:我希望所有敌人(可变数量)以 2 秒的间隔发射 3 发子弹。但我完全被卡住了,想不出办法来完成它。

谁能看看我的小提琴,看看发生了什么? http://jsfiddle.net/eRQ3P/6/

注意:第 573 行是循环的函数(并且每 30FPS 绘制一次子弹等)

这是我创建新项目符号对象的代码:(小提琴中的第 406 行)

function Enemybullet(destinationX, destinationY, enemySprite) {

    this.id = 'bullet';
    this.x = enemySprite.getX()+(enemySprite.getWidth()/2);
    this.y = enemySprite.getY()+(enemySprite.getHeight()/2);

    var targetX = destinationX - this.x,
        targetY = destinationY - this.y,
        distance = Math.sqrt(targetX * targetX + targetY * targetY);

    this.velX = (targetX / distance) * 5;
    this.velY = (targetY / distance) * 5;

    this.finished = false;

    this.sprite = new Kinetic.Circle({
        x: this.x,
        y: this.y, 
        radius: 3,
        fill: 'black',
        name: 'enemyProjectile'
    });

    this.draw = function(index) {

        var mayDelete = false;

        this.x += this.velX;
        this.y += this.velY;

        this.sprite.setAbsolutePosition(this.x, this.y);
        //console.log(this.sprite.getX());

/*
        if(enemyCollision(this) == true) {
            mayDelete = true;
        }*/

        if (bulletLeftField(this.sprite) == true) {
            mayDelete = true;
        }

        if (mayDelete == true) {
            this.sprite.remove();
            enemies[index].bullets.splice(0, 1);
            createEnemyBullet(enemies[index]);
        }



        ammoLayer.draw();
    }
}

以及提供新项目符号的函数:(小提琴中的第 247 行)

function createEnemyBullet(enemy) {
    var blt = new Enemybullet(player.sprite.getX(), player.sprite.getY(), enemy.sprite);
    ammoLayer.add(blt.sprite);
    enemy.bullets.push(blt);
}

【问题讨论】:

    标签: javascript html canvas html5-canvas kineticjs


    【解决方案1】:

    这个问题中最难的部分可能是弄清楚何时绘制每颗子弹以使每 2 秒间隔发射三颗子弹。为了使子弹均匀发射,您需要将间隔内的帧数除以该间隔内发射的子弹数。

    因为您以每秒 30 帧的速度运行游戏,所以 2 秒等于 60 帧。

    60 frames / 3 bullets = 20 frames/bullet

    因此,我们将每 20 帧或每 20 次调用 refreshLoop() 为每个敌人创建一个新子弹,在 refreshLoop() 内部,您现在必须循环遍历每个敌人拥有的所有子弹在其bullets 数组中,因为现在可以不止一个。

    bullets 数组中可能有多个项目符号这一事实为从数组中删除项目符号的方式引入了一个新问题。以前,您依赖于这样一个事实,即一次一颗子弹意味着它将始终是数组中的第一个,因此您的代码称为bullets.splice(0, 1);。然而,当玩家四处移动并且敌人在不同位置开火时,完全有可能让一颗子弹离开屏幕并比之前发射的子弹更快地被移除。这将导致正确的子弹精灵被删除,但数组中的第一个子弹将从bullets 中删除,因此它不会再在refreshLoop() 中更新,它只会坐在屏幕上什么都不做。

    为了避免这种情况,有必要将bullets中被绘制子弹所在的索引传递给敌人子弹的draw()函数。由于无论如何您都需要遍历数组,因此索引已经在refreshLoop() 中,因此只需将其传递给draw()。现在,每次需要移除子弹时,您只需拨打bullets.splice(bulletIndex, 1);

    希望你不要介意;我将您的fiddle 分叉了,以使用下面列出的更改对其进行更新。

    编辑:一个新的fiddle 用于连发而不是持续开火。

    // Inside your Enemybullet definition
    // One simple change to draw(), pass in the index of the bullet in the array
    this.draw = function(indexEnemy, indexBullet) {
    
        var mayDelete = false;
    
        ...
    
        if (bulletLeftField(this.sprite) == true) {
            mayDelete = true;
        }
    
        if (mayDelete == true) {
            this.sprite.remove();
    
            // Since you now have multiple bullets, you'll have to make
            // sure you're removing the correct one from the array
            enemies[indexEnemy].bullets.splice(indexBullet, 1);
        }
    
        ammoLayer.draw();
    }
    
    ...
    
    // Inside your refreshLoop function
    // If there are enemies they should be checked
    if (enemies.length > 0) {
        for (var i = 0; i < enemies.length; i++) {
            enemies[i].draw();
    
            // At 30 frames per second, 3 bullets in 2 seconds would be
            // one bullet for every 20 frames. So, every 20 frames,
            // create a new bullet for each enemy
            if ((enemyShootTimer % 20) == 0) {
                createEnemyBullet(enemies[i]);
            }
    
            // The same way you draw all of the player's bullets,
            // loop through the array of bullets for this enemy,
            // and draw each one, passing in the new parameters
            if (enemies[i].bullets.length > 0) {
                for (var j = 0; j < enemies[i].bullets.length; j++) {
                    enemies[i].bullets[j].draw(i, j);
                }
            }
        }
    }
    
    // Update loop for burst-fire instead of sustained fire
    var burstTime = 10; // 10 frames between bullets, 3 per second
    var needToShoot = ((enemyShootTimer % burstTime) == 0);
    if (enemies.length > 0) {
        for (var i = 0; i < enemies.length; i++) {
            enemies[i].draw();
    
            // if the enemies still have bullets to shoot this burst
            // and if 10 frames have passed since the last shot
            // ( enemyBurstCounter is declared outside refreshLoop() )
            if (enemyBurstCounter < 3 && needToShoot) {
                createEnemyBullet(enemies[i]);
            }
            if (enemies[i].bullets.length > 0) {
                for (var j = 0; j < enemies[i].bullets.length; j++) {
                    enemies[i].bullets[j].draw(i, j);
                }
            }
        }
        if ((enemyShootTimer % 60) == 0) {
            enemyBurstCounter = 0; // if 2 seconds have passed, reset burst counter
        } else if (needToShoot) {
            enemyBurstCounter++; // if the enemies shot, update burst counter
        }
    }
    

    【讨论】:

    • 在这种情况下,时序逻辑让我非常失望。然而,子弹似乎是定期发射的,但不是成对的 3 个(pop、pop、pop....wait...pop、pop、pop...等)
    • 我实际上是在质疑这是否是你想要的......我会用它来更新。
    • 用新的小提琴编辑了答案,并在底部添加了更改后的代码
    • 不客气。游戏看起来很棒,我很高兴能帮助改进它
    • 当我在它的时候;当我停止游戏并清空敌人数组(enemies = [])时,我遇到了一个错误。当我调用停止所有侦听器的函数时,我得到一个Uncaught TypeError: Cannot read property 'bullets' of undefined 错误。但是如果我在上面 console.log enemies[i],它不是未定义的。并且在它周围使用 if (if (enemies[i].bullets){}),它仍然以某种方式在 FOR 的行上给出错误...我没有更新小提琴,因为我猜这一定是一些愚蠢的 JS 事情:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    • 2014-02-27
    相关资源
    最近更新 更多