I'm trying to remove an image when a collision occurs without success, I have the primary image which is the chopper and a secondary image called powerup. Basically when the two collide it stops the game from running, instead I would like it to delete or remove the powerup image (gemList). I'm getting a Object [object Array] has no method 'delete' in console.
My code:
function animateGems() {
gemCount++;
for(var i=0; i<gemList.length; i++) {
if(gemList[i].x < 0-gemWidth) {
gemList.splice(i, 1); //remove gem once its outside of the canvas
} else {
gemList[i].x = gemList[i].x - gemV
ctx.drawImage(gemList[i].image, gemList[i].x, gemList[i].y, gemWidth, gemHeight)
if(gemCount >= gemInterval) {
addGem();
gemCount = 0;
}
}
}
}
function gemCollision () {
var collideCount = 0;
for(var i=0; i<gemList.length;) {
var thisGem = gemList[i];
//collision detection if the xposition of the chopper offset by its width
// and comparing it against the xposition of the gem then the collision detection
// check Y values also
if( (chopperX + chopperWidth ) >= thisGem.x && chopperX <= (thisGem.x + gemWidth ) &&
(chopperY + chopperHeight) >= thisGem.y && chopperY <= (thisGem.y + gemHeight)) {
collideCount++;
gemList.splice(i,1);//removes the current collided gem
score += 5;
} else i++; //close if
}//close for on gemList
if (collidedCount !=0) collidedCount == gemList[i]-1;
}//close function
you are modifying the list at the same time you are iterating it. You can do it, but you have to do it in a sligthly different way, increasing the index only if the array did not just shrunk. :
function gemCollision () {
var collidedCount = 0;
for(var i=0; i<gemList.length;) {
var thisGem = gemList[i];
//collision detection if the xposition of the chopper offset by its width
// and comparing it against the xposition of the gem then the collision detection
// check Y values also
if( (chopperX + chopperWidth ) >= thisGem.x && chopperX <= (thisGem.x + gemWidth ) &&
(chopperY + chopperHeight) >= thisGem.y && chopperY <= (thisGem.y + gemHeight)) {
collidedCount++;
gemList.splice(i,1);
score += 5;
} else i++; //close if
}//close for on gemList
if (collidedCount > 0) powerUpSound.play();
}//close function*/
(i assumed remove(i) was just removing the i-th element, but correct this if need be)
(i corrected also for just one sound to play if several occurs at once. You might want to increase sound level in that case instead of playing several times a sound at the very same time... or not ! )
Edit : it seems you are doing the same mistake in your animateGems code that you did in your collision code : you are iterating over a list (array) and changing it at the same time.
For all those kind of pattern : either take care of indexes, either build a separate defferedRemove list that you will use afterwise.
I changed your code a bit, so a gem is created in a random time (500 to 3500 ms) after one disapeared to avoid the -quite frustating- apparition of a gem as soon as one disapears.
var wantedGemCount = 20;
function animateGems() {
// gemCount++; // i commented. gemCount is gemList.length, that's all.
for(var i=0; i<gemList.length; /* i++ nope !! */) {
var thisGem = gemList[i] ;
if (thisGem.x < 0-gemWidth) {
gemList.splice(i, 1); //remove gem once its outside of the canvas
} else {
thisGem.x = thisGem.x - gemV
ctx.drawImage(thisGem.image, thisGem.x, thisGem.y, gemWidth, gemHeight)
i++; // here !!
}
}
// add gems only after the for loop if need be
// i did not understood the logic, and changed it a bit
if(gemList.length < wantedGemCount) {
addGemLater();
}
handleGemCreation();
}
var gemAddTime = [];
function addGemLater() {
gemAddTime.push(Date.now() + 500 + Math.random()*3000);
}
function handleGemCreation() {
var now = Date.now();
for (var i=0; i<gemAddTime?length; ) {
var thisTime = gemAddTime[i];
if (thisTime > now) {
// push a new gem
gemList.push( ???? );
// remove add request
gemAddTime.splice(i,1);
} else i++;
}
}