如何在不定义类的情况下创建一个类的多个实例?

时间:2019-04-28 21:49:25

标签: javascript

因此,我正在HTML5画布上制作游戏。这是一个自上而下的射击游戏,每次单击以进行角色射击时,我都需要创建一个子弹。

一开始,我只是阻止玩家发射另一枚子弹,直到它越界或撞到敌人为止,如此处所示。这确实很有效,但当然会导致无趣的游戏玩法。

然后,我开始研究JS类,我认为这将是解决问题的关键。我创建了项目符号类,并将项目符号的所有逻辑移至该类。然后,我创建了它的一个实例,并在代码的其他部分调用了它以执行其逻辑。这完全可以像以前一样工作,这很好,因为这意味着我可以将以前拥有的东西翻译成一堂课,但是它有一个类似的问题。

这是定义类的方式:

class bullet{

    constructor(_img, _piercing){

        this.bulletPic = document.createElement("img");
        this.img = this.bulletPic.src = _img;
        this.piercing = _piercing;
    }

    shoot(){
        this.bulletAngle = playerAngle;
        this.bulletX = playerX;
        this.bulletY = playerY;
        bulletShot = true;
        shots = 0;
    }

    draw(){
        canvasContext.save();
        canvasContext.translate(this.bulletX, this.bulletY);
        canvasContext.rotate(this.bulletAngle);
        canvasContext.drawImage(this.bulletPic, -this.bulletPic.width / 2, -this.bulletPic.height / 2);
        canvasContext.restore();

        if(bulletShot){
            this.bulletX += Math.sin(this.bulletAngle) * BULLET_SPEED;
            this.bulletY -= Math.cos(this.bulletAngle) * BULLET_SPEED;
        }

    }
}

这是对象定义:

let bullet1 = new bullet("Textures/player.png", true);

如果我想同时拍摄另一枚子弹,我需要已经定义了子弹类的新实例,我每次单击时有什么方法可以定义一个新实例?

编辑:射击和绘制方法在另一个文件中调用,该文件遵循此处未显示的逻辑。主要是其他代码的作用是检测何时击中敌人或何时超出范围以将“ bulletShot”设置为false,使其变为“ despawn”,然后我可以发射另一枚子弹。这是我尝试在此处删除的时间限制中的1个项目符号的一部分,但是一旦解决了这一中心问题,该问题便可以解决。

3 个答案:

答案 0 :(得分:0)

如果我了解您的情况,则可以使用一个返回新类的函数:

function bulletFactory( className ) {
    return new className();
}

答案 1 :(得分:0)

如果要实现“空中”中可能有多个项目符号,请在一系列快速连续单击之后,创建一系列项目符号。您可以像这样初始化该数组:

const bullets = Array({length: ammo}, () => new Bullet());

ammo是用户总共可以射击的子弹数。

NB:我简化了构造函数的调用。添加您要传递的参数。其次,通常的做法是使用大写字母开头课程名称。

然后在Bullet实例中添加一个state属性,该属性指示Bullet是否为:

  • 隐藏的:尚不可见,但总弹药的一部分仍可以在将来使用
  • 就绪:这是在开始位置可见的一颗子弹,随时可供用户发射
  • 射击:一颗子弹已被射击,目前正飞过游戏区域

首先,此状态为“隐藏”:

constructor(_img, _piercing){
    this.state = "hidden";
    // ...
}
draw() {
    if (this.state === "hidden") return; // Don't draw bullets that are not available
    // ...
}

然后,在游戏开始时,使一颗子弹可见(应在其中单击):

bullets[0].state = "ready"; // From now on it will be drawn when `draw()` is called

在点击处理程序中,执行以下操作:

// Fire the bullet the user clicked on:
bullets.find(bullet => bullet.state === "ready").shoot(playerAngle, playerX, playerY);
// See if there is a next bullet remaining in the user's ammo:
const nextBullet = bullets.find(bullet => bullet.state === "hidden");
if (nextBullet) nextBullet.state = "ready"; // Otherwise ammo is depleted.

shoot方法不应依赖全局变量,而应获取必要的外部信息作为参数:

shoot(playerAngle, playerX, playerY) {
    this.bulletAngle = playerAngle;
    this.bulletX = playerX;
    this.bulletY = playerY;
    this.state = "shot";
}

请勿在类方法内使用全局变量(shotammo,...)。而是使用参数或其他实例属性。

draw方法也应与该state一起使用:

draw() {
    if (this.state === "hidden") return; // Don't draw bullets that are not available
    // ...
    if(this.state === "shot") {
        this.bulletX += Math.sin(this.bulletAngle) * BULLET_SPEED;
        this.bulletY -= Math.cos(this.bulletAngle) * BULLET_SPEED;
    }
}

在动画循环中,应在所有项目符号上调用draw。像这样:

bullets.forEach(bullet => bullet.draw());

我没有看到任何子弹离开游戏区的代码,无论是通过击中东西还是只是飞出了范围。在这种情况下,应从bullets数组中删除项目符号,以避免draw方法使绘制的东西没有视觉上的意义。

以下是删除特定项目符号的方法:

function deleteBullet(bullet) {
     const i = bullets.indexOf(bullet);
     if (i > -1) bullets.splice(i, 1);
}

我希望这能使您继续进行项目。

答案 2 :(得分:0)

我最终制作了一个包含该类的多个实例的数组。我定义了一个变量作为限制,然后设置了一个for语句来创建所有对象,然后,我可以使用数组名称和位置来调用它们。

for(var i = 0; i < arraySize; i++){
    arrayName[i] = new className(parameters);
}

用法示例:

arrayName[5].method();
相关问题