Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Javascript game: Possible object array error

I'm building a small JavaScript game, but after looking at tutorials and whatnot online, it's just not working for me. To save you some trouble, here's the parts where I think stuff might've gone wrong (actual problem explained a bit more below).

It runs on a very basic loop for now and I have an array to hold the player's bolts as he shoots them:

var playerBolts=new Array(); //Holds all the bolt objects that the player shoots  

setInterval(function(){
    updateGame(); 
    drawGame();
},25);

This is the bolt object that is created when the player shoots.

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);
    }
}

When the "player" shoots, the shootBolt method from the player object is called:

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));
    }
}

The problem is that the next bolt gets faster every following shot. The more you fire, the faster they get. Also, there are supposed to be multiple bolts visible if fired rapidly, but every time you shoot, the previous one vanishes.

Now the game loops through the update and draw functions. I've used a for

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();
    });     
}

So yea...I think it might have to do with the way I add objects with "push" to the array, the "forEach" method (although I've tried a for loop too). I don't know what I'm doing wrong and I've looked up sources and this should be working no? If there isn't enough information, I could always post the whole thing (only 119 well documented lines).

Thank you.

like image 896
Alexander Weihmayer Avatar asked Jun 13 '13 00:06

Alexander Weihmayer


2 Answers

I suspect you're having issues with this. You are constructing bolt objects by calling:

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

However, inside of the bolt function, you're using this as though it refers to a newly-created bolt. Unfortunately, it doesn't. Try constructing bolts like this instead:

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

If you do it that way, then this inside of bolt refers to the newly created object.

Additionally, this this is also possibly wrong:

playerBolts.forEach(function(bolt){ //Draws all bolt's model to the canvas
    this.draw();
});

For strange reasons, this within your loop function may or may not be your bolts (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach). Just to be safe, try this instead:

playerBolts.forEach(function(bolt){ //Draws all bolt's model to the canvas
    bolt.draw();
});

By the way, the new issue is very common; I make it a habit to make my constructor functions so they work either with or without new. To do that, instead of using this, simply have bolt return a new object instead of manipulating this. Because JS's this is horribly confusing, I find this a much better approach:

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;
}
like image 163
Jacob Avatar answered Sep 25 '22 06:09

Jacob


The problem is that function bolt(facing,playerX,playerY){ does not create a new bolt, it just sets variables in the same spot as before:

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
    ...

-Because you do not call bolt on a new object, you call it from the same place every time, all of the variables you set under this keep getting overriden over and over again.

like image 29
Patashu Avatar answered Sep 23 '22 06:09

Patashu