Collision check loop stops looping after enemy is spawned - javascript

So I have been making this little shooter game with javascript and I have ran to a problem I cant figure out.
I have a collision check which checks if any alive enemy collides with the player or a bullet using a for loop. The loop runs fine until I spawn an enemy.
In the beginning of the for loop you can see console.log, it logs numbers only ti­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ll the first alive enemy's index. For example if enemies[4] is alive and no other enemies with index before that are alive, it keeps logging 0, 1, 2, 3 and 4. If I then kill all the enemies the loop runs full 50 times again (which is the length of the array) until an enemy spawns.­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
checkCollision: function(){
function calculate(enemy, other){
var r = enemy.r + other.r;
var dx = enemy.posX - other.posX;
var dy = enemy.posY - other.posY;
var d = Math.sqrt((dx * dx) + (dy * dy));
if(r > d){
enemy.alive = false;
other.alive = false;
return true;
}
return false;­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
}
for (var i = 0, max = this.enemies.length; i < max; i++) {
console.log(i);
if(this.e­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­nemies[i].alive){
if(calculate(this.enemies[i], this.player)){
continue;
}
for (var i = 0, max = this.player.weapon.bullets.length; i < max; i++){
if(this.player.weapon.bullets[i].alive){
if(calculate(this.enemies[i], this.player.weapon.bullets[i])){
break;­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
}
}­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
}
}
} ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
}
Here is a little visualization:
[0] = !alive
[1] = alive
[2] = !alive
[3] = alive
[4] = alive
Now the for loop would run only 2 times, therefore not checking the collision for 3 and 4, which is what i want it to do.

Well, you have a loop, which loops over all enemies, but checks only one enemy at a time and only against the player, not against each other.
So try something like:
for (var i = 0, max = this.enemies.length; i < max; i++) {
for (var j = 0, max = this.enemies.length; j < max; j++) {
if(calculate(this.enemies[i], this.enemies[j]){
doSomething();
}
}
}
// Don't forget the player.
In case you are interested, there is a quite good HTML5 Game Development course which teaches you how to use an open source physics engine, which takes care of those things.
While looking for a job, I made a small version of Mario, using that open source project, and the info from that course. You can see the game on my website under "projects".
Edit
So after your example I understood your question. You are reusing the i and max variables in the inner loop about bullets. So if the inner loop finishes, the outer loop will also terminate as they both check i < max.

Related

JavaScript game starts fast and slows down over time

My simple JavaScript game is a Space Invaders clone.
I am using the p5.js client-side library.
I have tried many things to attempt at speeding up the game.
It start off fast, and then over time it get slower, and slower, it isn't as enjoyable.
I do not mean to show every bit of code I have. I am not showing every class, but I will show the main class where everything is happening.
Could someone eyeball this and tell me if you see anything major?
I am new to JS and new to making games, I know there is something called update()
that people use in scripting but I am not familiar with it.
Thank you.
var ship;
var flowers = []; // flowers === aliens
var drops = [];
var drops2 = [];
function setup() {
createCanvas(600, 600);
ship = new Ship();
for (var i = 0; i < 6; i ++) {
flowers[i] = new Flower(i * 80 + 80, 60);
}
flower = new Flower();
}
function draw() {
background(51);
ship.show();
ship.move();
shipDrops();
alienDrops();
dropsAndAliens();
dropDelete();
drop2Delete();
}
// if 0 drops, show and move none, if 5, etc..
function shipDrops() {
for (var i = 0; i < drops.length; i ++) {
drops[i].show();
drops[i].move();
for (var j = 0; j < flowers.length; j++) {
if(drops[i].hits(flowers[j]) ) {
flowers[j].shrink();
if (flowers[j].r === 0) {
flowers[j].destroy();
}
// get rid of drops after it encounters ship
drops[i].evaporate();
}
if(flowers[j].toDelete) {
// if this drop remove, use splice function to splice out of array
flowers.splice(j, 1); // splice out i, at 1
}
}
}
}
function alienDrops() {
// below is for alien/flower fire drops 2
for (var i = 0; i < drops2.length; i ++) {
drops2[i].show();
drops2[i].move();
if(drops2[i].hits(ship) ) {
ship.shrink();
drops2[i].evaporate(); // must evap after shrink
ship.destroy();
if (ship.toDelete) {
delete ship.x;
delete ship.y;
} // above is in progress, deletes after ten hits?
}
}
}
function dropsAndAliens() {
var randomNumber; // for aliens to shoot
var edge = false;
// loop to show multiple flowers
for (var i = 0; i < flowers.length; i ++) {
flowers[i].show();
flowers[i].move();
// ******************************************
randomNumber = Math.floor(Math.random() * (100) );
if(randomNumber === 5) {
var drop2 = new Drop2(flowers[i].x, flowers[i].y, flowers[i].r);
drops2.push(drop2);
}
//**************** above aliens shooting
// below could be method, this will ensure the flowers dont
//go offscreen and they move
//makes whtever flower hits this space become the farther most
//right flower,
if (flowers[i].x > width || flowers[i]. x < 0 ) {
edge = true;
}
}
// so if right is true, loop thru them all again and reset x
if (edge) {
for (var i = 0; i < flowers.length; i ++) {
// if any flower hits edge, all will shift down
// and start moving to the left
flowers[i].shiftDown();
}
}
}
function dropDelete() {
for (var i = drops.length - 1; i >= 0; i--) {
if(drops[i].toDelete) {
// if this drop remove, use splice function to splice out of array
drops.splice(i, 1); // splice out i, at 1
}
}
}
function drop2Delete() {
for (var i = drops2.length - 1; i >= 0; i--) {
if(drops2[i].toDelete) {
// if this drop remove, use splice function to splice out of array
drops2.splice(i, 1); // splice out i, at 1
}
}
}
function keyReleased() {
if (key != ' ') {
ship.setDir(0); // when i lift the key, stop moving
}
}
function keyPressed() {
// event triggered when user presses key, check keycode
if(key === ' ') {
var drop = new Drop(ship.x, height); // start ship x and bottom of screen
drops.push(drop); // when user hits space, add this event to array
}
if (keyCode === RIGHT_ARROW) {
// +1 move right
ship.setDir(1);
} else if (keyCode === LEFT_ARROW) {
// -1 move left
ship.setDir(-1);
} // setir only when pressing key, want continuous movement
}
Please post a MCVE instead of a disconnected snippet that we can't run. Note that this should not be your entire project. It should be a small example sketch that just shows the problem without any extra code.
But to figure out what's going on, you need to debug your program. You need to find out stuff like this:
What is the length of every array? Are they continuously growing over time?
What is the actual framerate? Is the framerate dropping, or does it just appear to be slower?
At what point does it become slower? Try hard-coding different values to see what's going on.
Please note that I'm not asking you to tell me the answers to these questions. These are the questions you need to be asking yourself. (In fact, you should have all of these answers before you post a question on Stack Overflow!)
If you still can't figure it out, then please post a MCVE in a new question post and we'll go from there. Good luck.

Shoot 3 bullets on set times from each enemy

I'm trying to create a simple game with kineticJS on my canvas(Just some practice) and managed to get my player to shoot bullets. The same goes for the enemies that are spawned. They shoot a bullet each time the last bullet leaves the stage.
However: I'd like all the enemies(Variable number) to shoot 3 bullets at a 2 seconds interval. But i'm stuck completely and can't figure a way how to get it done.
Could anyone please look at my fiddle and see what's up?
http://jsfiddle.net/eRQ3P/6/
Note: line 573 is the function that loops(And draws the bullets and such every 30FPS)
Here's the code where i create a new bullet object:(Line 406 in fiddle)
function Enemybullet(destinationX, destinationY, enemySprite) {
this.id = 'bullet';
this.x = enemySprite.getX()+(enemySprite.getWidth()/2);
this.y = enemySprite.getY()+(enemySprite.getHeight()/2);
var targetX = destinationX - this.x,
targetY = destinationY - this.y,
distance = Math.sqrt(targetX * targetX + targetY * targetY);
this.velX = (targetX / distance) * 5;
this.velY = (targetY / distance) * 5;
this.finished = false;
this.sprite = new Kinetic.Circle({
x: this.x,
y: this.y,
radius: 3,
fill: 'black',
name: 'enemyProjectile'
});
this.draw = function(index) {
var mayDelete = false;
this.x += this.velX;
this.y += this.velY;
this.sprite.setAbsolutePosition(this.x, this.y);
//console.log(this.sprite.getX());
/*
if(enemyCollision(this) == true) {
mayDelete = true;
}*/
if (bulletLeftField(this.sprite) == true) {
mayDelete = true;
}
if (mayDelete == true) {
this.sprite.remove();
enemies[index].bullets.splice(0, 1);
createEnemyBullet(enemies[index]);
}
ammoLayer.draw();
}
}
And the function providing a new bullet: (line 247 in fiddle)
function createEnemyBullet(enemy) {
var blt = new Enemybullet(player.sprite.getX(), player.sprite.getY(), enemy.sprite);
ammoLayer.add(blt.sprite);
enemy.bullets.push(blt);
}
Probably the hardest part of this problem is figuring out when to draw each bullet to make three be fired in every 2-second interval. To make the bullets fire evenly, you want to divide the number of frames in the interval by the number of bullets to fire in that interval.
Because you're running the game at 30 frames per second, 2 seconds equals 60 frames.
60 frames / 3 bullets = 20 frames/bullet
So, we're going to create a new bullet for each enemy every 20 frames, or every 20th time refreshLoop() is called, and inside refreshLoop(), you now have to loop through all of the bullets each enemy has in its bullets array, because there can now be more than just one.
The fact that there can be more than one bullet in the bullets array introduces a new problem to the way bullets are removed from the array. Previously, you relied on the fact that one bullet at a time means it will always be the first one in the array, thus your code called bullets.splice(0, 1);. However, when the player is moving around and the enemies fire at the different locations, it is completely possible to have a bullet leave the screen and be removed sooner than one that was fired before it. This would cause the correct bullet sprite to be removed, but the first bullet in the array would be removed from bullets, so it wouldn't be updated anymore in refreshLoop(), and it would just sit on the screen doing nothing.
In order to avoid this, it is necessary to pass to the enemy bullets' draw() function the index in bullets at which the bullet being drawn is located. Since you need to loop through the array anyway, the index is already at hand in refreshLoop(), so just pass this to draw(). Now, every time a bullet needs to be removed, you can just call bullets.splice(bulletIndex, 1);
I hope you don't mind; I forked your fiddle to update it with the changes listed below.
EDIT: A new fiddle for burst-fire instead of sustained fire.
// Inside your Enemybullet definition
// One simple change to draw(), pass in the index of the bullet in the array
this.draw = function(indexEnemy, indexBullet) {
var mayDelete = false;
...
if (bulletLeftField(this.sprite) == true) {
mayDelete = true;
}
if (mayDelete == true) {
this.sprite.remove();
// Since you now have multiple bullets, you'll have to make
// sure you're removing the correct one from the array
enemies[indexEnemy].bullets.splice(indexBullet, 1);
}
ammoLayer.draw();
}
...
// Inside your refreshLoop function
// If there are enemies they should be checked
if (enemies.length > 0) {
for (var i = 0; i < enemies.length; i++) {
enemies[i].draw();
// At 30 frames per second, 3 bullets in 2 seconds would be
// one bullet for every 20 frames. So, every 20 frames,
// create a new bullet for each enemy
if ((enemyShootTimer % 20) == 0) {
createEnemyBullet(enemies[i]);
}
// The same way you draw all of the player's bullets,
// loop through the array of bullets for this enemy,
// and draw each one, passing in the new parameters
if (enemies[i].bullets.length > 0) {
for (var j = 0; j < enemies[i].bullets.length; j++) {
enemies[i].bullets[j].draw(i, j);
}
}
}
}
// Update loop for burst-fire instead of sustained fire
var burstTime = 10; // 10 frames between bullets, 3 per second
var needToShoot = ((enemyShootTimer % burstTime) == 0);
if (enemies.length > 0) {
for (var i = 0; i < enemies.length; i++) {
enemies[i].draw();
// if the enemies still have bullets to shoot this burst
// and if 10 frames have passed since the last shot
// ( enemyBurstCounter is declared outside refreshLoop() )
if (enemyBurstCounter < 3 && needToShoot) {
createEnemyBullet(enemies[i]);
}
if (enemies[i].bullets.length > 0) {
for (var j = 0; j < enemies[i].bullets.length; j++) {
enemies[i].bullets[j].draw(i, j);
}
}
}
if ((enemyShootTimer % 60) == 0) {
enemyBurstCounter = 0; // if 2 seconds have passed, reset burst counter
} else if (needToShoot) {
enemyBurstCounter++; // if the enemies shot, update burst counter
}
}

Same code takes longer if executed more often?

I've got the following code inside a <script> tag on a webpage with nothing else on it. I'm afraid I do not presently have it online. As you can see, it adds up all primes under two million, in two different ways, and calculates how long it took on average. The variable howOften is used to do this a number of times so you can average it out. What puzzles me is, for howOften == 1, method 2 is faster, but for howOften == 10, method 1 is. The difference is significant and holds even if you hit F5 a couple of times.
My question is simply: how come?
(This post has been edited to incorporate alf's suggestion. But that made no difference! I'm very much puzzled now.)
(Edited again: with howOften at or over 1000, the times seem stable. Alf's answer seems correct.)
function methodOne(maxN) {
var sum, primes_inv, i, j;
sum = 0;
primes_inv = [];
for ( var i = 2; i < maxN; ++i ) {
if ( primes_inv[i] == undefined ) {
sum += i;
for ( var j = i; j < maxN; j += i ) {
primes_inv[j] = true;
}
}
}
return sum;
}
function methodTwo(maxN) {
var i, j, p, sum, ps, n;
n = ((maxN - 2) / 2);
sum = n * (n + 2);
ps = [];
for(i = 1; i <= n; i++) {
for(j = i; j <= n; j++) {
p = i + j + 2 * i * j;
if(p <= n) {
if(ps[p] == undefined) {
sum -= p * 2 + 1;
ps[p] = true;
}
}
else {
break;
}
}
}
return sum + 2;
}
// ---------- parameters
var howOften = 10;
var maxN = 10000;
console.log('iterations: ', howOften);
console.log('maxN: ', maxN);
// ---------- dry runs for warm-up
for( i = 0; i < 1000; i++ ) {
sum = methodOne(maxN);
sum = methodTwo(maxN);
}
// ---------- method one
var start = (new Date).getTime();
for( i = 0; i < howOften; i++ )
sum = methodOne(maxN);
var stop = (new Date).getTime();
console.log('methodOne: ', (stop - start) / howOften);
// ---------- method two
for( i = 0; i < howOften; i++ )
sum = methodTwo(maxN);
var stop2 = (new Date).getTime();
console.log('methodTwo: ', (stop2 - stop) / howOften);
Well, JS runtime is an optimized JIT compiler. Which means that for a while, your code is interpreted (tint), after that, it gets compiled (tjit), and finally you run a compiled code (trun).
Now what you calculate is most probably (tint+tjit+trun)/N. Given that the only part depending almost-linearly on N is trun, this comparison soes not make much sense, unfortunately.
So the answer is, I don't know. To have a proper answer,
Extract the code you are trying to profile into functions
Run warm-up cycles on these functions, and do not use timing from the warm-up cycles
Run much more than 1..10 times, both for warm-up and measurement
Try swapping the order in which you measure time for algorithms
Get into JS interpretator internals if you can and make sure you understand what happens: do you really measure what you think you do? Is JIT run during the warm-up cycles and not while you measure? Etc., etc.
Update: note also that for 1 cycle, you get run time less than the resolution of the system timer, which means the mistake is probably bigger than the actual values you compare.
methodTwo simply requires that the processor execute fewer calculations. In methodOne your initial for loop is executing maxN times. In methodTwo your initial for loop is executing (maxN -2)/2 times. So in the second method the processor is doing less than half the number of calculations that the first method is doing. This is compounded by the fact that each method contains a nested for loop. So big-O of methodOne is maxN^2. Whereas big-O of methodTwo is ((maxN -2)/2)^2.

Cellular automata implemented in JavaScript and HTML5 Canvas

I implemented a Conway's Game of Life in JavaScript but I'm not seeing the same patterns such as Gosper's Glider Gun. I seed the grid the ways it's depicted in the Wikipedia article but, the gun never happens.
Will someone look at my code and see if there's anything wrong with it, any suggestions to the implementation?
https://github.com/DiegoSalazar/ConwaysGameOfLife
You are not updating all of the cells simultaneously, rather sequentially. A cell that is born in the first generation will not appear alive to the calculation of other cells of the first generation (it still counts as dead).
Create a new property called willBeAlive and use that to hold the cell's new calculated alive state. Once all the calculations for that generation are done, set each cell's alive property to its willBeAlive property and redraw.
Here are the changes:
Automaton.prototype.update = function() {
for (var x = 0; x < this.w; x++) {
for (var y = 0; y < this.h; y++) {
this.grid[x][y].killYourselfMaybe();
}
}
// set the alive property to willBeAlive
for (var x = 0; x < this.w; x++) {
for (var y = 0; y < this.h; y++) {
this.grid[x][y].alive = this.grid[x][y].willBeAlive;
}
}
}
Cell.prototype.killYourselfMaybe = function(grid) {
var num = this.numLiveNeighbors();
this.willBeAlive = false;
if (this.alive) {
// 1. Any live cell with fewer than two live neighbours dies, as if caused by under-population.
if (num < 2) this.willBeAlive = false;
// 2. Any live cell with two or three live neighbours lives on to the next generation.
if (num == 2 || num == 3) { this.willBeAlive = true}
// 3. Any live cell with more than three live neighbours dies, as if by overcrowding.
if (num > 3) this.willBeAlive = false;
} else {
// 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
if (num == 3) this.willBeAlive = true;
}
}
and here is a seed array for "Gosper's Glider Gun":
[[2,6],[2,7],[3,6],[3,7],[12,6],[12,7],[12,8],[13,5],[13,9],[14,4],[14,10],[15,4],[15,10],[16,7],[17,5],[17,9],[18,6],[18,7],[18,8],[19,7],[22,4],[22,5],[22,6],[23,4],[23,5],[23,6],[24,3],[24,7],[26,2],[26,3],[26,7],[26,8],[36,4],[36,5],[37,4],[37,5]]

CPU use keeps growing; is there a way to delete my unused objects in JavaScript?

I'm making a game in HTML5's Canvas + JavaScript. My CPU use for the tab keeps growing by a couple percent every second until it hits 50% (all of one core). I am successfully removing my objects from the array of objects, but the objects themselves seem to persist. I have tried "delete obj" and "obj = null" in a few places, but no luck.
Any ideas?
var falling_blocks = setInterval(add_falling_block, 1000);
...
function add_falling_block(){
b = new Object();
b.x = (randFromTo(0,sq) * scale) - boff;
b.y = -scale + boff;
b.color = "#f00";
b.moving = true;
b.number = f.length;
f.push(b);
}
function draw_falling_blocks(){
var db = new Array()
for(i = 0; i < f.length; i++){
var ba = f[i];
if(ba.y < (bottom + scale)){
ba.y += scale;
draw_block(ba.x,ba.y,"#f00");
}
else if(ba.y = (bottom + scale)){
db.push(i);
console.log(f.length);
}
}
for(i = 0; i < db.length; i++){
f.splice(db[i],1);
}
}
As I mentioned in my comment, CPU usage != memory usage. With Chrome's developer tools, it's easy to profile your application in order to locate the code which is consuming all of the CPU cycles.
Open your app, open the dev tools, and go to the Profiles tab. Click the Record button (the black circle). It will turn red; Chrome is now recording CPU usage. Let it record for a few seconds and click the Record button again. You will now see CPU usage by function.
In this case, we can see that draw_grid() has consumed 92% of CPU time – we've found our culprit!
I made some changes to the draw_grid function:
function draw_grid(){
c.strokeStyle = '#333';
for (var i = poff; i < w; i += scale) {
c.beginPath();
c.moveTo(0, i);
c.lineTo(w, i);
c.closePath();
c.stroke();
}
for (var j = poff; j < h; j += scale) {
c.beginPath();
c.moveTo(j, 0);
c.lineTo(j, h);
c.closePath();
c.stroke();
}
}
CPU usage never tops 5% now.
A few notes:
I've added beginPath() and closePath() and moved stroke() into each loop iteration.
I changed the size of each line from a constant 500px to use the appropriate variable.
You only need to set strokeStyle once. It remains the same unless you change it again.
You should write var in your loops' initializer to restrict the variable's (i and j in this case) scope to the local function. Otherwise, you're creating a global variable, which is a bad idea for a variety of reasons.
You may need to delete all properties/methods of that object in addition to deleting the pointer (variable), but memory leakage has always been a problem that's plagued JavaScript.
Have you thrown in setTimeout('',0) anywhere to allow the processor to do some other things.

Categories

Resources