How can I make multiple asteroids, after making the code for one?


I'm using JavaScript to make a game, and I have created one asteroid that moves vertically and picks a random x position.

How can I create multiple asteroids that pick random starting points?

Below is what I currently have for the asteroid:

//create asteroid
asteroid={
    x:width/2,
    y:-6,
    min:1.6,
    max:2.2,
    speed:1.6
}

// move asteroid
if(asteroid.y<height){
    asteroid.y+=asteroid.speed;
}else{
    asteroid.y=-6;
    asteroid.x=Math.random()*(width-0)-0;
}

//draw asteroid
ctx.beginPath();
ctx.fillStyle = "#D9BA5F";
ctx.arc(asteroid.x, asteroid.y,3,0,2*Math.PI,false);
ctx.closePath();
ctx.fill();

Make your move and draw routines into methods of the asteroid objects:

// Define an Asteroid constructor
function Asteroid(width, height) {
    this.width = width;
    this.height = height;
    this.x = width/2;
    this.y = -6;
    this.min = 1.6;
    this.max = 2.2;
    this.speed = 1.6;
}

// Move asteroid
Asteroid.prototype.move = function() {
    if(this.y < this.height) {
        this.y += this.speed;
    } else {
        this.y = -6;
        this.x = Math.random()*(this.width-0)-0;
    }
}

// Draw asteroid
Asteroid.prototype.draw = function() {
    ctx.beginPath();
    ctx.fillStyle = "#D9BA5F";
    ctx.arc(this.x, this.y, 3, 0, 2*Math.PI, false);
    ctx.closePath();
    ctx.fill();
}

Then you can create multiple asteroids:

var asteroids = [];
// create 10 asteroids
for(var i = 0; i < 10; i++) {
    asteroids.push(new Asteroid(Math.random()*10, Math.random()*10));
}

In your main loop, move and draw them all:

for(var i = 0; i < asteroids.length; i++) {
    asteroids[i].move();
    asteroids[i].draw();
}

As pointed out by @blunderboy in the comments, this still doesn't randomize anything you weren't already randomizing. You could use Powerslave's parametrized constructor, where all randomization should take place at instantiation time, or generate at least part of the random values from within the constructor.

Also, passing in the canvas context object instead of relying on a closure would be preferred.


Create a constructor instead of a static JSON object.

function Asteroid(x, y, min, max, speed) {
    this.x = x;
    this.y = y;
    this.min = min;
    this.max = max;
    this.speed = speed;
}

Then you can create an asteroid as follows:

var asteroid = new Asteroid(width / 2, -6, 1.6, 2.2, 1.6);

Note: this is not the optimal way of doing it, but a pretty simple one to work with. For optimal solution you would apply encapsulation, design patterns, etc.

EDIT: See bfavaretto's answer for more detail on encapsulating asteroid-related functionality and the whole approach.


Put it in a for loop and set n to the number of asteroids you want when calling the function.

Something like this:

function createAsteroid(n) {

   for (var i = 1; i < n; i++) {

     //create asteroid
     asteroid[i] = {
         x : width/2,
         y : -6,
         min : 1.6,
         max : 2.2,
         speed : 1.6
     }

     // move asteroid
     if (asteroid[i].y < height) {
         asteroid[i].y+ = asteroid.speed;
     }
     else {
         asteroid[i].y = -6;
         asteroid[i].x = Math.random() * (width-0) -0;
     }
     return asteroid;
}

I haven't tested this code, but the logic-idea behind it is sound.