Making the game interesting!

In this session the spaceship becomes vulnerable to the asteroids.

Blowing Up the Spaceship

In the last lesson, we added the code that blew up asteroids. In this lesson we add code to blow up the spaceship when an asteroid hits it. The code for blowing up the spaceship is similar to the code for blowing up asteroids. First, we'll write some code to keep track of how many lives our game will let us have.

The lives appear on the right side of the window because of this code.

Place this code after the score.pack() line in your code.

    score.pack() # This line should already be in your program.

livesTitle = tkinter.Label(frame, \ text="Extra Lives Remaining")
livesTitle.pack()

livesFrame = tkinter.Frame(frame, \ height=30,width=60,relief=tkinter.SUNKEN)
livesFrame.pack()
livesCanvas = ScrolledCanvas(livesFrame,150,40,150,40)
livesCanvas.pack()
livesTurtle = RawTurtle(livesCanvas)
livesTurtle.ht()
livesScreen = livesTurtle.getscreen()
livesScreen.register_shape("ship", \ ((-10,-10),(0,-5),(10,-10),(0,10)))
life1 = SpaceShip(livesCanvas,0,0,-35,0)
life2 = SpaceShip(livesCanvas,0,0,0,0)
life3 = SpaceShip(livesCanvas,0,0,35,0)
lives = [life1, life2, life3]

This code records the lives in a list called lives. Each time the ship dies, a life will be popped from the list.

Then, we need to go back to the play function and add code there to see if an asteroid intersects with the spaceship. If it does, we'll keep track of the asteroid or asteroids that hit the ship and to make things interesting we'll delete those asteroids. If your ship gets hit by an asteroid, you lose the possibility of those points you would have attained had you blown up that asteroid.

This code is added to the play function.

        shipHitAsteroids = []
        shipHit = False

for asteroid in asteroids:
if intersect(asteroid,ship):
if len(lives) > 0:
if not shipHit:
tkinter.messagebox.showwarning( \ "Uh-Oh","You Lost a Ship!")
deadship = lives.pop()
deadship.ht()
shipHit = True
shipHitAsteroids.append(asteroid)
else:
tkinter.messagebox.showwarning("Game Over", \ "Your game is finished!\nPlease try again.")
return

This is a relatively complicated piece of code. It keeps track of whether the ship was hit on this call to the play function. The shipHit variable is a Boolean variable (it refers to either True or False). We first assume that the ship was not hit, but the first asteroid that is detected colliding with the ship causes a message to be displayed that you lost a ship. Then one of the lives is used up. However, the code continues looking for other asteroids that might also have collided with the ship on this call to play. This would only happen if multiple asteroids collided with the ship at the same exact moment.

All the asteroids that collided with the ship are added to the shipHitAsteroids list so they can be deleted. That's the purpose of the next bit of code. It deletes all asteroids that have collided with the ship.

This code can be added after the code above.

        for asteroid in shipHitAsteroids:
try:
asteroids.remove(asteroid)
except:
print("asteroid that hit ship not found") asteroid.ht()
asteroid.goto(screenMaxX*2, screenMaxY*2)

The try-except code above tries to delete the asteroids that collided with the ship. However, if they have already been deleted from the list, then the error is ignored and a message is printed to the console. A try-except tries to execute some code but if an error (called an exception) occurs, then the except block is executed and the program continues executing.

Finally, the game should detect whether you won the game or not. To do that we can check to see if the asteroids list is empty.

This code can be added as one of the first things inside the play function.

        if len(asteroids) == 0:
tkinter.messagebox.showinfo("You Win!!", \ "You won the game!")
return

Have More Time?

The spaceship and asteroid can be made more interesting if you like. The shapes can be made compound shapes. This just means the shape is made of more than one polygon with possibly different coloring for each polygon. Here is some code that makes the big asteroids have a couple of shadows on them to give them some texture.

    s = Shape("compound")
poly1 = ((-20, -16),(-21, 0),(-20,18),(0,27),(17,15), \ (25,0),(16,-15),(0,-21))
s.addcomponent(poly1,"gray","gray")
poly2 = (( -17, -14),(-12, -12),(-8, -13), \ (-8, -7),(-12, -8))
s.addcomponent(poly2, "dark gray", "dark gray")
poly3 = ((3,2),(6,3),(9,6),(10,9),(6,12),(0,8),(-1,6))
s.addcomponent(poly3,"dark gray","dark gray")
screen.register_shape("rock3",s)

This code creates a Shape object called s. The shape object has the polygons added to it. Then, the shape object is registered as the "rock3" shape with the screen object.

You can use the same code to create a spaceship with windows and multiple colors.

In addition, if you want your background of your screen to be black (like space looks in the absence of other light), then you can use the bgcolor method on the screen object to set it to black.

    screen.bgcolor("black")

If you want something a little more interesting for your background, you can use a .GIF file. For instance this space.gif file can can used as your background if you write this line of code

    screen.bgpic("space.gif")
     

What's Next?

Next time we'll finish up the game by fixing the timing of the game so it plays at the same speed whether bullets are being fired or not.