Jump to content

Asteroids?


frokenstein
 Share

Recommended Posts

Ok, here is a fun question. I created a space game that involves shooting asteroids. Right now all the asteroids have the same velocity and they don't rotate. When I try to altering their properties using random number ranges, for example, it makes the game choppy. My question is - what is the best way to create a pool of, say, 20 asteroids, and give them unique velocities, starting locations, as well as rotational velocities? I must be doing something wrong as it tends to slow the game down.

var Asteroid = function(game, x, y, key, frame){key = 'asteroid';Phaser.Sprite.call(this, game, x, y, key, frame);this.scale.setTo(0.3);this.anchor.setTo(0.5);this.game.physics.arcade.enableBody(this);this.events.onRevived.add(this.onRevived, this);};Asteroid.prototype = Object.create(Phaser.Sprite.prototype);Asteroid.prototype.constructor = Asteroid;Asteroid.prototype.onRevived = function() {this.body.velocity.x = this.game.rnd.integerInRange(-30, 30);this.body.velocity.y = this.game.rnd.integerInRange(-30, 30);};
var asteroid = this.asteroids.getFirstExists(false);if (!asteroid){asteroid = new Asteroid(this.game, x, y);this.asteroids.add(asteroid);}asteroid.reset(x, y);asteroid.revive();

I haven't gotten the rotation part down yet. I am not sure how to alter body.angle for a group and make it work efficiently during an update(). Is there an efficient way to give them random start locations (which I've done), random velocities (which I've done but inefficiently, apparently), and most importantly give them unique rotations (which I've not been able to accomplish using body.angle so I wont post code for that) while still keeping them in one group?

 

Link to comment
Share on other sites

just an attempt
for setting different velocities etc.

for ( var i = 0; i > asteroidGroup.length; i++ ){    var rnd = game.rnd.integerInRange(0,4);    if( rnd == 0 ){         velocity.y = 100    }else if ( rnd == 1 ){        velocity.y = 140    }else ... etc}

regards

Link to comment
Share on other sites

Lewster,

 

I think the problem is how I create them. I had them creating at an interval so the number of asteroids would keep growing. I have it set to kill them once they move out of the game boundaries. But kill() doesn't remove them from memory, so perhaps that is the issue. I was unable to find a destroy() function for the out of bounds event. Since that is the case, I am trying to limit them to a certain number but I am having issues coding it. They will show up but they will not reset()/revive() because whenever I run getFirstExists(false) or getFirstDead() it never returns a dead sprite. I am not sure why yet. Investigation continues...

Link to comment
Share on other sites

Ok, so here is where I am.

 

I have my asteroid group and it is set to check for out of bounds:

this.asteroids = this.game.add.group();this.asteroids.setAll('anchor.x', 0.5);this.asteroids.setAll('anchor.y', 0.5);this.asteroids.setAll('checkWorldBounds', true);

I have this function that I call on an interval until I reach the max number of asteroids:

createAsteroid: function () {if (this.asteroidCount < this.TOTALASTEROIDS) {var start = this.game.rnd.integerInRange(1, 4);switch (start) {case 1:var x = this.game.world.bounds.width;var y = this.game.rnd.integerInRange(0, this.game.world.bounds.height);var direction = 1;break;case 2:var x = this.game.world.bounds.x;var y = this.game.rnd.integerInRange(0, this.game.world.bounds.height);var direction = 2;break;case 3:var x = this.game.rnd.integerInRange(0, this.game.world.bounds.width);var y = this.game.world.bounds.height;var direction = 3;break;case 4:var x = this.game.rnd.integerInRange(0, this.game.world.bounds.width);var y = this.game.world.bounds.y;var direction = 4;break;}var asteroid = this.asteroids.getFirstExists(false);if (!asteroid) {asteroid = new Asteroid(this.game, x, y, direction);asteroid.events.onOutOfBounds.add(this.killAsteroid, asteroid);this.asteroids.add(asteroid);}asteroid.reset(x, y);asteroid.revive();this.asteroidCount++;}}

As you can see, I have bound a function to each asteroid for the out of bounds event:

asteroid.events.onOutOfBounds.add(this.killAsteroid, asteroid);

This is the kill function, which kills the asteroid, console logs it, and reduces the total asteroid count so another can be created:

// Asteroid out of boundskillAsteroid: function(asteroid) {asteroid.kill();console.log("asteroid destroyed");this.asteroidCount--;},

The problem is that this event is never triggered. I have properly set the asteroids group to check if they're out of bounds, yet the killAsteroid() function is never called. What this means is I have one wave of asteroids that fly through the canvas, then nothing. What am I doing wrong?

Link to comment
Share on other sites

this.asteroids.setAll('anchor.x', 0.5);this.asteroids.setAll('anchor.y', 0.5);this.asteroids.setAll('checkWorldBounds', true);

This will only affect asteroids already in the group. When you instantiate a new asteroid you will need to set checkWorldBounds on it for it to work.

 

Just FYI the method of reviving dead asteroids you're using is called 'object pooling' in case you weren't sure - there's a good example of pooling in Phaser here: http://gamemechanicexplorer.com/#bullets-2

Link to comment
Share on other sites

This is the solution.

 

Asteroid obj:

var Asteroid = function(game, x, y, direction, key, frame){key = 'asteroid';Phaser.Sprite.call(this, game, x, y, key, frame);this.scale.setTo(this.game.rnd.realInRange(0.1,0.5));this.anchor.setTo(0.5);this.game.physics.arcade.enableBody(this);this.direction = direction;this.events.onRevived.add(this.onRevived, this);this.maxUpperVel = 600;this.maxLowerVel = 200;this.maxAngularVel = 400;};Asteroid.prototype = Object.create(Phaser.Sprite.prototype);Asteroid.prototype.constructor = Asteroid;Asteroid.prototype.onRevived = function() {switch (this.direction) {case 1:this.body.velocity.x = this.game.rnd.integerInRange(-this.maxUpperVel,-this.maxLowerVel);this.body.velocity.y = this.game.rnd.integerInRange(-this.maxLowerVel,this.maxLowerVel);break;case 2:this.body.velocity.x = this.game.rnd.integerInRange(this.maxLowerVel, this.maxUpperVel);this.body.velocity.y = this.game.rnd.integerInRange(-this.maxLowerVel,this.maxLowerVel);break;case 3:this.body.velocity.y = this.game.rnd.integerInRange(-this.maxUpperVel,-this.maxLowerVel);this.body.velocity.x = this.game.rnd.integerInRange(-this.maxLowerVel,this.maxLowerVel);break;case 4:this.body.velocity.y = this.game.rnd.integerInRange(this.maxLowerVel, this.maxUpperVel);this.body.velocity.x = this.game.rnd.integerInRange(-this.maxLowerVel, this.maxLowerVel);break;}this.body.angularVelocity = this.game.rnd.integerInRange(0, this.maxAngularVel);};

Create asteroid function:

createAsteroid: function () {var start = this.game.rnd.integerInRange(1, 4);switch (start) {case 1:var x = this.game.world.bounds.width;var y = this.game.rnd.integerInRange(0, this.game.world.bounds.height);var direction = 1;break;case 2:var x = 0;var y = this.game.rnd.integerInRange(0, this.game.world.bounds.height);var direction = 2;break;case 3:var x = this.game.rnd.integerInRange(0, this.game.world.bounds.width);var y = this.game.world.bounds.height;var direction = 3;break;case 4:var x = this.game.rnd.integerInRange(0, this.game.world.bounds.width);var y = 0;var direction = 4;break;}var asteroid = this.asteroids.getFirstDead();if (!asteroid) {asteroid = new Asteroid(this.game, x, y, direction);asteroid.checkWorldBounds = true;asteroid.outOfBoundsKill = true;this.asteroids.add(asteroid);}asteroid.reset(x, y);asteroid.revive();},

Loop to run createAsteroid() function to create pool of asteroids at beginning of game:

while (this.asteroids.countLiving() < this.TOTALASTEROIDS) {this.createAsteroid();}

using countLiving() seems to be what helped. I no longer need an extra var/function to track how many are alive.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...