因此,我正在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个项目符号的一部分,但是一旦解决了这一中心问题,该问题便可以解决。
答案 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";
}
请勿在类方法内使用全局变量(shot
,ammo
,...)。而是使用参数或其他实例属性。
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();