简单的Javascript游戏:可能的对象数组错误

时间:2013-06-13 00:36:22

标签: javascript arrays object

我正在构建一个小型的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个记录良好的行)。

谢谢。

3 个答案:

答案 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 方法相同。代码中的更多空白区域会使其更具可读性。 : - )