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.
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With