我正在构建一个小型的JavaScript游戏,但在查看教程和诸如此类的东西后,它只是不适合我。为了省去一些麻烦,这里是我认为可能出错的部分(实际问题在下面有所解释)。
它现在在一个非常基本的循环上运行,我有一个阵列可以在射击时保持玩家的螺栓:
var playerBolts=new Array(); //Holds all the bolt objects that the player shoots
setInterval(function(){
updateGame();
drawGame();
},25);
这是玩家射击时创建的螺栓对象。
function bolt(facing,playerX,playerY){ //The bolt object is shot from the player's current position
this.facingLeft=facing; //The direction at which the bolt moves, if left, true
this.x=playerX; //The x position of the bolt
this.y=playerY; //The y position of the bolt
if(facingLeft==true){
this.xSpeed=-3; //The horizontal speed at which the bolt is moving
}
else if (facingLeft==false){
this.xSpeed=3;
}
this.ySpeed=0; //The vertical speed at which the bolt is moving
this.W=3; //The width of the bolt's model
this.H=3; //The height of the bolt's model
this.color="red"; //The color of the bolt's model
this.update=update;
function update(){ //Updates the bolt's properties
this.x=this.x+this.xSpeed;
this.y=this.y+this.ySpeed;
}
this.draw=draw;
function draw(){ //Draws the bolt's model to the canvas
context.fillStyle=this.color;
context.fillRect(this.x, this.y, this.W, this.H);
}
}
当“玩家”射击时,来自玩家对象的shootBolt方法被称为:
function player(){ //The player object
this.facingLeft=true; //If the player's character is facing left, true
this.x=100; //The x position of the player
this.y=100; //The y position of the player
this.shootBolt=shootBolt;
function shootBolt(){ //Shoots a bolt, creating a new bolt object and adding it to the playerBolts array
playerBolts.push(bolt(this.facingLeft,this.x,this.y));
}
}
问题在于,每次拍摄后下一个螺栓都会变快。你开火得越多,他们就越快。此外,如果快速射击,应该可以看到多个螺栓,但每次射击时,前一个都会消失。
现在游戏循环更新和绘制功能。我用过了
function updateGame(){ //The main update phase
player1.update(); //Updates the player's properties
playerBolts.forEach(function(bolt){ //Updates all active bolts's properties
this.update();
});
}
function drawGame(){ //The main drawing phase
context.fillStyle="white";
context.fillRect(0,0,canvasW,canvasH); //Clears the canvas for the next frame
player1.draw(); //Draws the player
playerBolts.forEach(function(bolt){ //Draws all bolt's model to the canvas
this.draw();
});
}
所以,是的......我认为这可能与我使用“push”向数组添加对象的方式有关,即“forEach”方法(尽管我也尝试了for循环)。我不知道我做错了什么,而且我已经找到了消息来源,这应该是不行的?如果没有足够的信息,我总是可以发布整个事情(只有119个记录良好的行)。
谢谢。
答案 0 :(得分:4)
我怀疑你遇到this
的问题。您正在通过调用:
bolt
个对象
bolt(this.facingLeft, this.x, this.y)
但是,在bolt
函数内部,您使用的是this
,就好像它引用了新创建的螺栓一样。不幸的是,事实并非如此。尝试构建这样的螺栓:
new bolt(this.facingLeft, this.x, this.y)
如果你这样做,那么this
内的bolt
就会引用新创建的对象。
此外,这个this
也可能是错误的:
playerBolts.forEach(function(bolt){ //Draws all bolt's model to the canvas
this.draw();
});
由于奇怪的原因,你的循环函数中的this
可能是也可能不是你的螺栓(见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)。为了安全起见,请尝试这样做:
playerBolts.forEach(function(bolt){ //Draws all bolt's model to the canvas
bolt.draw();
});
顺便说一下,new
问题很常见;我养成了构建函数的习惯,这样它们无论是否有new
都可以工作。要做到这一点,不要使用this
,只需让bolt
返回一个新对象,而不是操纵this
。因为JS的this
令人困惑,我发现这是一个更好的方法:
function bolt(facing,playerX,playerY){ //The bolt object is shot from the player's current position
var theBolt = {
facingLeft: facing, //The direction at which the bolt moves, if left, true,
x: playerX, //The x position of the bolt
y: playerY, //The y position of the bolt
xSpeed: facingLeft ? -3 : 3, //The horizontal speed at which the bolt is moving
ySpeed: 0, //The vertical speed at which the bolt is moving
W: 3, //The width of the bolt's model
H: 3, //The height of the bolt's model
color: 'red', //The color of the bolt's model
update: update,
draw: draw
};
function update(){ //Updates the bolt's properties
theBolt.x = theBolt.x + theBolt.xSpeed;
theBolt.y = theBolt.y + theBolt.ySpeed;
}
function draw(){ //Draws the bolt's model to the canvas
context.fillStyle = theBolt.color;
context.fillRect(theBolt.x, theBolt.y, theBolt.W, theBolt.H);
}
return theBolt;
}
答案 1 :(得分:1)
问题是function bolt(facing,playerX,playerY){
没有创建新的bolt
,它只是将变量设置在与以前相同的位置:
function bolt(facing,playerX,playerY){ //The bolt object is shot from the player's current position
this.facingLeft=facing; //The direction at which the bolt moves, if left, true
...
- 因为你没有在新对象上调用bolt
,所以每次都在同一个地方调用它,你在this
下设置的所有变量都会反复被覆盖。< / p>
答案 2 :(得分:0)
正如其他人所说,你的问题是你每次都没有创建一个新的螺栓,你只需要调用螺栓功能。因此函数中的“this”引用了全局对象,因此您实际上只有一个螺栓需要多次更新。
另外,以下内容:
> if(facingLeft==true){
> this.xSpeed=-3; //The horizontal speed at which the bolt is moving
> }
> else if (facingLeft==false){
> this.xSpeed=3;
> }
可以使用?: conditional operator(也称为三元运算符)替换:
this.xSpeed = facingLeft? -3 : 3;
你在哪里:
> this.update=update;
> function update(){ //Updates the bolt's properties
> this.x=this.x+this.xSpeed;
> this.y=this.y+this.ySpeed;
> }
您可以使用函数表达式直接指定函数:
// Update the bolt's properties
this.update = function () {
this.x = this.x + this.xSpeed;
this.y = this.y + this.ySpeed;
}
或者更好的是,将函数放在构造函数的原型上,以便所有实例都继承相同的函数:
bolt.prototype.update = function () {
...
}
draw 方法相同。代码中的更多空白区域会使其更具可读性。 : - )