space_invaders.py

#! /usr/bin/python3
# ==================================================================
# Space Invaders  (from YouTube)
# ==================================================================
# Part 1: www.youtube.com/watch?v=crV6T3piwHQ
#         Set up the screen
# Part 2: www.youtube.com/watch?v=FdmjXnyoS0A
#         Move player left and right
# Part 3: www.youtube.com/watch?v=zYeEHIX7sfo
#         Create the enemy and move up, down, left, right
# Part 4: www.youtube.com/watch?v=74msqu5phts
#         Create playser bullet and fire with the space bar
# Part 5: www.youtube.com/watch?v=OnR9acEWMC0
#         Register collisions between the bullet and enemies and
#         the enemies and the player
#
# ---- THE FOLLOWING NOT CURRENTLY IMPLEMENTED ---------------------
# Part 6: www.youtube.com/watch?v=Ve-BvoCVN40
#         Add multiple enemies
# Part 7: www.youtube.com/watch?v=-Bi0W_EKeYg
#         Move all enemies down at the same time
# Part 8: www.youtube.com/watch?v=ZNVxp8cT_JI
#         Scoring
# Part 9: www.youtube.com/watch?v=--MZ7I9Eepw
#         Image for invaders
#         Image for player
#         Image for background
# Part 10: www.youtube.com/watch?v=wOZw9EytJEE
#         Sound (MacOSX and Linux)
# ==================================================================

import turtle
import math
import os

# ---- global data
# ---- collected here for ease of modification

# ---- Note: bullet state
# ----       ready - ready to fire
# ----       fire  - bullet is firing

bulletspeed = 20
bulletstate = 'ready'
enemyspeed  = 2
playerspeed = 15

# ---- setup the screen

wn = turtle.Screen()
wn.bgcolor('black')
wn.title('Space Invaders')

# ---- draw a border

border_pen = turtle.Turtle()
border_pen.speed(0)
border_pen.color('white')
border_pen.penup()
border_pen.setposition(-300,-300)
border_pen.pendown()
border_pen.pensize(3)
for side in range(4):
    border_pen.fd(600)
    border_pen.lt(90)
border_pen.hideturtle()

# ---- create the player turtle

player = turtle.Turtle()
player.color('blue')
player.shape('triangle')
player.penup()
player.speed(0)
player.setposition(0,-250)
player.setheading(90)

# ---- move player left and right

def move_left():
    x = player.xcor()
    x -= playerspeed
    if x < -280:               # boundary checking
        x = -280
    player.setx(x)

def move_right():
    x = player.xcor()
    x += playerspeed
    if x > 280:                # boundary checking
        x = 280
    player.setx(x)

# ---- fire the bullet

def fire_bullet():

    # declare bulletstate as global
    global bulletstate

    # if ready fire the bullet else do nothing (already firing)
    if bulletstate == 'ready':
        bulletstate = 'fire'
        # move the bullet to just above the player
        x = player.xcor()
        y = player.ycor() + 10
        bullet.setposition(x,y)
        bullet.showturtle()

# ---- test for a collision?
# ---- Note: a collision is when two turtles are within
# ----       20 pixels of each other

def isCollision(t1,t2):
    distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(),2) +
                         math.pow(t1.ycor()-t2.ycor(),2))
    if distance > 20:
        return False
    else:
        return True

# ---- create the enemy

enemy = turtle.Turtle()
enemy.color('red')
enemy.shape('circle')
enemy.penup()
enemy.speed(0)
enemy.setposition(-200,250)
enemy.setheading(270)

# ---- create the player's bullet

bullet = turtle.Turtle()
bullet.color('yellow')
bullet.shape('triangle')
bullet.penup()
bullet.speed(0)
bullet.setheading(90)
bullet.shapesize(0.5,0.5)
bullet.hideturtle()

# ---- create keyboard bindings

turtle.listen()
turtle.onkey(move_left,'Left')
turtle.onkey(move_right,'Right')
turtle.onkey(fire_bullet,'space')

# -------------------------------------------------------------------
# ---- main game loop -----------------------------------------------
# -------------------------------------------------------------------

while True:

    # move the enemy left, right, and down

    if enemy.xcor() < -280:
        enemyspeed *= -1           # reverse enemy movement direction
        y = enemy.ycor()
        y -= 40
        enemy.sety(y)

    if enemy.xcor() > 280:
        enemyspeed *= -1           # reverse enemy movement direction
        y = enemy.ycor()
        y -= 40
        enemy.sety(y)

    if bulletstate == 'fire':

        # move the bullet
        y = bullet.ycor()
        y += bulletspeed
        bullet.sety(y)

        # check if the bullet has reached the top
        if bullet.ycor() > 275:
            bullet.hideturtle()
            bulletstate = 'ready'

        # check for a collision between the bullet and the enemy
        if isCollision(bullet,enemy):
            # Reset the bullet
            bullet.hideturtle()
            bulletstate = 'ready'
            # hide the bullet so no collisions are possible
            bullet.setposition(0,-400)
            # reset the enemy
            enemy.setposition(-200,250)

    # check for collision between the enemy and the player
    if isCollision(enemy,player):
        print('Game Over - You Loose')
        break

    # automatically move the enemy

    x = enemy.xcor()
    x += enemyspeed
    enemy.setx(x)

# ---- end of game

delay = input('Press enter to exit ')