Game Over
Python Asteroids+Invaders on GitHub
Today, just a simple Game Over screen, so that we can at least see our final score.
I’ve been thinking and /chatting with friends about the possibility of a leaning “AI”1 that plays the game as a kind of attract mode. This is not that.
There is a lot of rigmarole that goes on, detecting that the player is gone, creating a new one, and so on. When you are out of reserve players, we toss a slug coin into the fleets, which clears the game and starts the Asteroids GameOver screen.
class PlayerMaker(InvadersFlyer):
def reserve_absent_game_over(self, fleets):
coin.slug(fleets)
That was a sort of stopgap solution so that we could do more interesting things. It’s time to have our own GameOver screen, so that you can see your final score.
The object in question will really have no behavior at all other than to display “GameOver”. Let’s see how the Asteroids game does that:
class GameOver(AsteroidFlyer):
def __init__(self):
self.init_game_over()
# noinspection PyAttributeOutsideInit
def init_game_over(self):
if not pygame.get_init():
return
big_font = pygame.font.SysFont("arial", 64)
small_font = pygame.font.SysFont("arial", 48)
self.game_over_surface = big_font.render("GAME OVER", True, "white")
self.game_over_pos = self.game_over_surface.get_rect(centerx=u.CENTER.x, centery=u.CENTER.y / 2)
pos_left = u.CENTER.x - 150
pos_top = self.game_over_pos.centery
self.help_lines = []
messages = ["d - turn left", "f - turn right", "j - accelerate", "k - fire missile", "q - insert quarter", "2 - two players"]
for message in messages:
pos_top += 60
text = small_font.render(message, True, "white")
text_rect = text.get_rect(topleft=(pos_left, pos_top))
pair = (text, text_rect)
self.help_lines.append(pair)
def draw(self, screen):
screen.blit(self.game_over_surface, self.game_over_pos)
for text, pos in self.help_lines:
screen.blit(text, pos)
def interact_with(self, other, fleets):
other.interact_with_gameover(self, fleets)
We cannot just use that one. If we did, it would require all our objects to implement interact_with_gameover
and that’s in a different hierarchy and just no. Let’s just copy and paste the whole thing and make an InvadersGameOver class. This can be considered an experiment, but if it works, as I think it might, we’ll consider blessing it.
With just a bit of manual testing:
class PlayerMaker(InvadersFlyer):
def reserve_absent_game_over(self, fleets):
fleets.remove(self)
fleets.append(InvadersGameOver())
class InvadersGameOver(InvadersFlyer):
def __init__(self):
self.init_game_over()
# noinspection PyAttributeOutsideInit
def init_game_over(self):
if not pygame.get_init():
return
big_font = pygame.font.SysFont("arial", 64)
self.game_over_surface = big_font.render("GAME OVER", True, "white")
self.game_over_pos = self.game_over_surface.get_rect(centerx=u.CENTER.x, centery=u.CENTER.y / 2)
@property
def mask(self):
return None
@property
def rect(self):
return None
def interact_with(self, other, fleets):
other.interact_withinvadersgameover(self, fleets)
def draw(self, screen):
screen.blit(self.game_over_surface, self.game_over_pos)
That works, with this result:
Mistakes/discoveries along the way included:
- I needed to put in the proper imports, no surprise there;
- I needed to implement
rect
,mask
, andinteract_with
before the InvadersGameOver could be instantiated; - I needed to remove the PlayerMaker in
reserve_absent_game_over
, lest an infinite number of GameOver instances be created, leading to chaos, disorder, and very slow missile fall; - I needed to implement
interact_withinvadersgameover
in the InvadersFleet superclass; - The original copy-pasta version included the help information, which overwrote the invaders and looked bad:
My tests informed me about the need for the superclass implementation and the corresponding interact_with
in the new class, so that was good. Commit: simple game over screen.
The only serious flaw remaining is that when GameOver happens, the invaders keep approaching—which is good—but will just march on down, if you wait long enough, until they consume the whole screen and fall off the bottom. We will deal with that later, perhaps by just creating a new fleet of invaders every now and again, from GameOver.
For now, we have a GameOver screen that lets us see our final score. QED.
See you next time!
-
Peace, all of you who want to argue about what is and isn’t AI. I’m using the term as a term of art in game development, no more than that. Whatever I do will not be any deep kind of Artificial Intelligence. It will be some kind of simple hackery that tries to automate the player actions enough to make an interesting attract screen. It will not be the antepenultimate step on the road to Artificial General Intelligence. Stand down. ↩