/**
* Moves a group of VisibleObjects rigidly from left to right*/
public class Formation extends VisibleObject {
protected List _obj;
protected int _dx = 1;
protected int _minX = 0;
protected int _maxX = 0;
/** create a formation that will go from left to right in the given range */
public Formation(int minX, int maxX) {
_minX = minX;
_maxX = maxX;
_obj = new ArrayList();
}
/** Add a VisibleObject from the formation */
public void add(VisibleObject noob) {
_obj.add(noob);
}
/** Set the initial horizontal velocity */
public void setSpeed(int dx) {
_dx = dx;
}
/** Move all objects in the formation */
public void move() {
// change direction if needed
if (_dx<0 && minX()+_dx<_minX) _dx=Math.abs(_dx);
else if (_dx>0 && maxX()+_dx>_maxX) _dx=-Math.abs(_dx);
// move all objects
for (Iterator ir = _obj.iterator(); ir.hasNext(); ) {
VisibleObject o = ir.next();
o.x += _dx;
if (!o._alive) ir.remove();
}
}
/** does nothing: you should draw the objects yourself */
public void draw(Graphics g) { }
/** the leftmost point in a group of rectangles */
protected int minX() {
int mx = Integer.MAX_VALUE;
for (Rectangle r : _obj) {
if (r.x < mx) mx = r.x;
}
return mx;
}
/** the rightmost point in a group of rectangles */
protected int maxX() {
int mx = Integer.MIN_VALUE;
for (Rectangle r : _obj) {
if (r.x+r.width > mx) mx = r.x+r.width;
}
return mx;
}
}
We also modify Enemy so that the move() method does not change the enemy's position (since that's now the responsibility of Formation). We still want move() to be called, though, because that's where the enemy decides whether to fire or not.
public class Enemy extends VisibleObject {
public void move() {
if (_fire.shouldFire()) fire();
}
(...)
}
So now when we initialize the level, we create a 4x3 grid of enemies and add them to the formation. The code (shown below) should be pretty clear.
public void buildLevel() throws Exception {
_enemies.clear();
_animations.clear();
Formation f = new Formation(0,getWidth());
f.setSpeed(2);
for (int x=0; x<4; x++) {
for (int y=0; y<3; y++) {
Enemy baddie = new Enemy(this, 10+x*50, 10+y*40);
f.add(baddie);
_enemies.add(baddie);
}
}
_animations.add(f);
}
We call this new method at beginning of playLevel(), and we're set! As you can see in the screenshot below, the enemies are arranged in a nice grid. What you cannot see is that they move together from left to right in a very nice motion.