I have the facts. Let’s draw four shields. Then shoot them a bit.

Well, I have some facts. The old code comments say that the shields are 22 pixels across, and that they are placed 23 pixels apart. We are at scale 4, so we have, if they are centered:

``````spacing + 4*22 + 4*23 + 4*22 + 4*23 + 4*22 + 4*23 + 4*22 + spacing ==
spacing + 88 + 92 + 88 + 92 + 88 + 92 + 88 + spacing ==
spacing + 628 + spacing == 1024
2*spacing == 1024 - 628 == 396
spacing == 198
``````

The step between the origins is 88 + 92 or 180. And we measure from the center not the upper left, so we need to add half the width of the shield or 44. I don’t know the y coordinate yet: that will take more exploration. I’ll estimate it and eyeball it and wind up with this:

``````coin.python

fleets.clear()
left_bumper = 64
fleets.append(Bumper(left_bumper, -1))
fleets.append(Bumper(960, +1))
fleets.append(TopBumper())
fleets.append(ShotController())
half_width = 88 / 2
spacing = 198
step = 180
for i in range(4):
place = Vector2(half_width + spacing + i*step, 800-16)
fleets.append(Shield(place))
``````

That looks good for now.

No tests involved, but many magic numbers. We’ll settle, for now. Commit: game displays four shields.

What’s our next story?

1. Get one shield on the screen;
2. Get all four on the screen;
3. Shots ignore shields;
4. Shots die upon hitting shields;
5. Shots do simple damage;
6. Shots do fancy damage;

We got #3 for free. My cunning plan is working out. Surely we are ahead of schedule now. Let’s add the interaction with shield and invader shot. Lets test-drive it if we can.

I notice a bug! Invader shots do not die when they hit the player. They continue on down to the edge. We’ll test-drive that one too. I start with this:

``````    def test_dies_on_shield(self):
fleets = Fleets()
fi = FI(fleets)
shield = Shield(Vector2(100, 100))
maker = BitmapMaker.instance()
assert shot.colliding(shield)
``````

That much passes. And then:

``````    def test_dies_on_shield(self):
fleets = Fleets()
fi = FI(fleets)
shield = Shield(Vector2(100, 100))
maker = BitmapMaker.instance()
assert shot.colliding(shield)
fleets.append(shot)
shot.interact_with_shield(shield, fleets)
``````

Failing as expected on the `not`. We need a better `interact_with_shield`:

``````    def interact_with_shield(self, shield, fleets):
if self.colliding(shield):
self.die(fleets)
``````

And we’re green. Make the same kind of test for InvaderPlayer:

``````    def test_dies_on_player(self):
fleets = Fleets()
fi = FI(fleets)
player.position = Vector2(100, 100)
maker = BitmapMaker.instance()
assert shot.colliding(player)
fleets.append(shot)
``````

Fails as did the other. Fix as we did the other:

``````    def interact_with_invaderplayer(self, player, fleets):
if self.colliding(player):
self.die(fleets)
``````

We now have three methods with those two lines in them. Let’s extract before we commit.

``````    def interact_with_invaderplayer(self, player, fleets):
self.die_on_collision(player, fleets)

def die_on_collision(self, flyer, fleets):
if self.colliding(flyer):
self.die(fleets)

def interact_with_playershot(self, shot, fleets):
self.die_on_collision(shot, fleets)

def interact_with_shield(self, shield, fleets):
self.die_on_collision(shield, fleets)
``````

That’s nice. Commit: Invader shot dies on hitting player or shield. (I confess that I did run the game to see it happen.)

Another story—well, half story—bites the dust. I split the shots stories into Invader ones and Player ones:

1. Get one shield on the screen;
2. Get all four on the screen;
3. Shots ignore shields;
4. InvaderShots die upon hitting shields;
5. PlayerShots die upon hitting shields