5

我正在构建一个小型 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();
    });     
}

所以是的......我认为这可能与我向数组中添加对象的方式有关,即“forEach”方法(尽管我也尝试过 for 循环)。我不知道我做错了什么,我已经查找了资源,这应该可以正常工作吗?如果没有足够的信息,我总是可以发布整个内容(只有 119 行有据可查)。

谢谢你。

4

3 回答 3

4

我怀疑你遇到了问题this。您正在bolt通过调用构造对象:

bolt(this.facingLeft, this.x, this.y)

但是,在bolt函数内部,您使用this的好像它指的是新创建的螺栓。不幸的是,事实并非如此。尝试构建这样的螺栓:

new bolt(this.facingLeft, this.x, this.y)

如果你这样做,那么thisinside ofbolt指的是新创建的对象。

此外,这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。因为 JSthis非常令人困惑,我发现这是一个更好的方法:

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;
}
于 2013-06-13T00:43:30.903 回答
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一遍又一遍地被覆盖。

于 2013-06-13T00:42:35.730 回答
0

正如其他人所说,您的问题是您不会每次都创建一个新螺栓,您只是调用螺栓函数。所以函数中的“this”引用了全局对象,所以你实际上只有一个被多次更新的螺栓。

此外,以下内容:

> if(facingLeft==true){ 
>     this.xSpeed=-3; //The horizontal speed at which the bolt is moving
> }
> else if (facingLeft==false){
>     this.xSpeed=3;  
> }

可以使用?: 条件运算符(又名三元运算符)替换:

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 () {
    ...
}

绘制方法也是如此。在你的代码中多留一点空白会让它更具可读性。:-)

于 2013-06-13T00:53:36.173 回答