(14) Astroid generation with collisions

So if we combine the info in (12) and (13) we should be able to get astroid generation where the astroids can collide. We will approximate the astroids with circles and ignore that they actually have a slightly different shape. If an astroid collides, we will split it into two and make them smaller, until we reach a minimum size.

While I was doing this, many of my attempts just stopped (hung, crashed, etc). This was because when they collided the new generated astroids immediately also crashed into eachother. This was solved by giving each astroid an "ID" number (like a social-security/personnummer). When two astroids collide, all "offspring" will have the same "ID" and no collisions happen between the same "ID".

If you take the code below and run it, it will look like this (but random):

The code is:

```ArrayList<astroid> astroids = new ArrayList<astroid>();

// Settings - how many seconds between each new astroid (1 seconds = 1 * 60)
int astroid_rate = 1 * 60;
int astroid_count = 60;
// Size in pixel of nominal astroid
float ast_size = 10;
float ast_min_size = 0.25;
int ast_id = 1;

// Run once
void setup () {
frameRate(60);
size(500, 500);
}

// Called 60 times per second
void draw()
{
int i;

// 1 new astroid every 5 seconds (60 fps * 4 sec)
if (astroid_count--==0) {
astroids.add(new astroid(random(0, TWO_PI), random(0.1, 2.0), random(0.5, 4), random(-0.1, 0.1),
random(-150, 150), random(-150, 150), ast_id++));
// Increase rate just a little
astroid_count = astroid_rate--;
if (astroid_rate<30) astroid_rate=30;
}

// Clear screen, black
background(0);
// Go through all astroids (if any) and update their position
for (i = 0; i<astroids.size(); i++) {
astroid a = astroids.get(i);
if (a.update()) {
// Remove bullet, if outside screen
astroids.remove(i);
}
}
}

// Class definition for the shot
class astroid {
// An astroid angle, speed, size, rotation
float angle, speed, size, rotSpeed;
float position;
float rotation;
float xoff, yoff;
float x, y;
PShape s;  // The PShape object - Keeps the astroid shape
float i;
int id;

// Constructor
astroid(float _angle, float _speed, float _size, float _rotSpeed, float _xoff, float _yoff, int _id) {
angle = _angle;
speed = _speed;
size = _size;
rotSpeed = _rotSpeed;
xoff = _xoff;
yoff = _yoff;
id = _id;
if (xoff<1000) {
x = 250+500*cos(angle)+xoff;
y = 250+500*sin(angle)+yoff;
} else {
x = _xoff-2000;
y = _yoff-2000;
}
rotation = 0;
// Generate the shape of the astroid - Some variations for all
s = createShape();
s.beginShape();
s.fill(255, 255, 100);
s.noStroke();
for (i=0; i<TWO_PI; i=i+PI/(random(4, 11))) {
s.vertex(random(ast_size*0.8, ast_size*1.2)*cos(i), random(ast_size*0.8, ast_size*1.2)*sin(i));
}
s.endShape(CLOSE);
}

// Update position, return true when out of screen
boolean update() {
int i;
x = x - cos(angle)*speed;
y = y - sin(angle)*speed;
rotation = rotation + rotSpeed;

// Check for astroid vs astroid collision
for (i = 0; i<astroids.size(); i++) {
astroid a = astroids.get(i);
// If we are not our own astroid, check collision
if ((a != this) && (a.coll(x, y, ast_size*size, id))) {
// if size is too small, do not generate new astroid
if (size > ast_min_size) {
astroids.add(new astroid(angle-random(PI/5, PI/7), speed+random(0, speed/2), size/2, rotSpeed, 2000+x, 2000+y, id));
astroids.add(new astroid(angle+random(PI/5, PI/7), speed+random(0, speed/2), size/2, rotSpeed, 2000+x, 2000+y, id));
}
astroids.remove(i);
}
}

pushMatrix();
// Set position as the new 0,0
translate(x, y);
// Rotate screen "angle"
rotate(rotation);
// Draw astroid
scale(size);
shape(s, 0, 0);
// Bring back normal perspektive
popMatrix();

if (x<-300 || x>800 || y<-300 || y>800) {
return true;
} else {
return false;
}
}

// Detect collision between this astroid and the one passed in
boolean coll(float _x, float _y, float _size, int _id) {
float dist;

dist = sqrt ((x-_x)*(x-_x) + (y-_y)*(y-_y));

// Check if distance is shorter than astroid size and other objects size
// No collision if the ID is same for both astroids
if ((dist<(_size+ast_size*size)) && (id!=_id)) {
// Collision, set the ID to the same so we do not call over and over again
if (_id>0) id = _id;
if (size > 1) {
// If the astroid was "large" generate two new fragments
astroids.add(new astroid(angle-random(PI/5, PI/7), speed+random(0, speed/2), size/2, rotSpeed, 2000+x, 2000+y, id));
astroids.add(new astroid(angle+random(PI/5, PI/7), speed+random(0, speed/2), size/2, rotSpeed, 2000+x, 2000+y, id));
}
return true;
} else {
return false;
}
}
}

```
See what happens if you change these variables. Like setting this:

```// Size in pixel of nominal astroid
float ast_size = 20;
float ast_min_size = 0.1;
```

In the actual game, we probably will use "ast_min_size=1" or so to not make it impossible :)