1

我正在尝试在我的画布上使用 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);
}
4

1 回答 1

1

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

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

60 frames / 3 bullets = 20 frames/bullet

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

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

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

我希望你不介意;我分叉了你的小提琴,用下面列出的更改来更新它。

编辑:一种用于连发而不是持续开火的新小提琴。

// 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
    }
}
于 2013-03-22T13:02:58.847 回答