Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
SpaceInvadersWithPygame/SpaceInvadiFinal.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
478 lines (456 sloc)
20.6 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pygame, time, sys, random, math | |
from pygame.locals import * | |
pygame.font.init() | |
#This is a class that both aliens and the player will be derived from | |
class Entity: | |
def __init__(self, name, health, sprite, bulletsprite, width, height): | |
self.name = name | |
self.health = health | |
self.sprite = sprite | |
self.bulletsprite = bulletsprite | |
self.width = width | |
self.height = height | |
#The Class is now split into subclasses of Player and Alien. This allows for examples of both to be created and have different attributes. | |
class Player(Entity): | |
def HighScore(self, highscore): | |
self.highscore = highscore | |
def Earnings(self, earnings): | |
self.earnings = earnings | |
class Alien(Entity): | |
def Points(self,value): | |
self.value = value | |
def Movement(self, velocity): | |
self.velocity = velocity | |
def Location(self, x, y): | |
self.x = x | |
self.y = y | |
def Bullet(self, invadernotshot, invadershotstillgoing, invadershotchanceincrease, bullet_x, bullet_y): | |
self.invadernotshot = invadernotshot | |
self.invadershotstillgoing = invadershotstillgoing | |
self.invadershotchanceincrease = invadershotchanceincrease | |
self.invadershotchance = random.randint(0, 4000-self.invadershotchanceincrease*10) | |
self.bullet_x = bullet_x | |
self.bullet_y = bullet_y | |
#This function creates multiple invader objects | |
def InvaderFactory(): | |
SpaceInvadi = [] | |
InvaderHeight = 5 | |
InvaderWidth = 5 | |
for i in range(InvaderHeight): | |
Row = [] | |
for j in range(InvaderWidth): | |
BInvaderSprite = pygame.image.load("BInvader.png") | |
BInvaderBulletSprite = pygame.image.load("InvaderBullet.jpg") | |
BInvader = Alien("BInvader{0}".format(j), 1, BInvaderSprite, BInvaderBulletSprite, 22, 19) | |
BInvader.Points(100) | |
BInvader.Movement(2) | |
BInvader.Location(1, 1) | |
InvaderShotChanceIncrease = 1 | |
BInvader.Bullet(True, False, 1, BInvader.x + 10, BInvader.y) | |
Row.append(BInvader) | |
SpaceInvadi.append(Row) | |
for i in range(5): | |
for j in range(5): | |
SpaceInvadi[i][j].x = 50 + (BInvader.width*j) + (20*j) | |
SpaceInvadi[i][j].y = 50 + (BInvader.height*i) + (20*i) | |
return SpaceInvadi | |
def StartGame(InputtedName, WindowH, WindowW, Clock, Window, MyFont, NewPlayer, SpaceInvadi, CurrentLevel): | |
pygame.display.set_caption("Space Invaders") | |
#Defining coordinates before the main game loop | |
Ship_x = (WindowW/2) | |
Ship_y = (9/10*WindowH) | |
PlayerBullet_y = Ship_y + 5 | |
PlayerBullet_x = Ship_x + 28 | |
#Set to false as default to prevent called before assignement error (also should defaultly not be true). | |
PlayerBulletStart = False | |
CurrentInvaderBreakTime = 1 | |
InGameLoop = True | |
InvincibleFrames = 0 | |
#Calls the main game loop | |
GameLoop(WindowH, | |
WindowW, | |
Clock, | |
Window, | |
MyFont, | |
NewPlayer, | |
Ship_y, | |
Ship_x, | |
PlayerBullet_y, | |
PlayerBullet_x, | |
PlayerBulletStart, | |
CurrentInvaderBreakTime, | |
InputtedName, | |
InGameLoop, | |
SpaceInvadi, | |
CurrentLevel, | |
InvincibleFrames) | |
def GameLoop(WindowH, | |
WindowW, | |
Clock, | |
Window, | |
MyFont, | |
NewPlayer, | |
Ship_y, | |
Ship_x, | |
PlayerBullet_y, | |
PlayerBullet_x, | |
PlayerBulletStart, | |
CurrentInvaderBreakTime, | |
InputtedName, | |
InGameLoop, | |
SpaceInvadi, | |
CurrentLevel, | |
InvincibleFrames): | |
while InGameLoop: | |
#Checks which invaders are alive and moves those invaders across the screen accordingly | |
for i in range(len(SpaceInvadi)): | |
for j in range(len(SpaceInvadi[i])): | |
if SpaceInvadi[i][j].health == 1: | |
SpaceInvadi[i][j].x += SpaceInvadi[i][j].velocity | |
SpaceInvadi[i][j].invadershotchance = random.randint(0, 4000-SpaceInvadi[i][j].invadershotchanceincrease*100) | |
else: | |
SpaceInvadi[i][j].x = -2000 | |
SpaceInvadi[i][j].y = -2000 | |
#When invaders get to the left hand side of the screen | |
CurrentFirstAliveColumn = 0 | |
CheckForDeadColumnsLEFT = True | |
while CheckForDeadColumnsLEFT: | |
PreviousFirstAliveColumn = CurrentFirstAliveColumn | |
DeadColumnCounter = 0 | |
for i in range(len(SpaceInvadi)): | |
if SpaceInvadi[i][CurrentFirstAliveColumn].health == 0: | |
DeadColumnCounter += 1 | |
if DeadColumnCounter == 5: | |
CurrentFirstAliveColumn += 1 | |
if CurrentFirstAliveColumn == PreviousFirstAliveColumn: | |
CheckForDeadColumnsLEFT = False | |
for i in range(len(SpaceInvadi)): | |
if SpaceInvadi[i][CurrentFirstAliveColumn].x <= 0 and SpaceInvadi[i][CurrentFirstAliveColumn].x != -2000: | |
for i in range(len(SpaceInvadi)): | |
for j in range(len(SpaceInvadi[i])): | |
SpaceInvadi[i][j].y += 20 | |
if SpaceInvadi[i][j].velocity < 0: | |
SpaceInvadi[i][j].velocity -= 0.5 | |
SpaceInvadi[i][j].velocity *= -1 | |
else: | |
SpaceInvadi[i][j].velocity += 0.5 | |
SpaceInvadi[i][j].velocity *= -1 | |
SpaceInvadi[i][j].invadershotchanceincrease += 1 | |
break | |
#When invaders get to the right hand side of the screen | |
CurrentLastAliveColumn = -1 | |
CheckForDeadColumnsRIGHT = True | |
while CheckForDeadColumnsRIGHT: | |
PreviousLastAliveColumn = CurrentLastAliveColumn | |
DeadColumnCounter = 0 | |
for i in range(len(SpaceInvadi)): | |
if SpaceInvadi[i][CurrentLastAliveColumn].health == 0: | |
DeadColumnCounter += 1 | |
if DeadColumnCounter == 5: | |
CurrentLastAliveColumn -= 1 | |
if CurrentLastAliveColumn == PreviousLastAliveColumn: | |
CheckForDeadColumnsRIGHT = False | |
for i in range(len(SpaceInvadi)): | |
if SpaceInvadi[i][CurrentLastAliveColumn].x >= 1280 - SpaceInvadi[i][CurrentLastAliveColumn].width: | |
for i in range(len(SpaceInvadi)): | |
for j in range(len(SpaceInvadi[i])): | |
SpaceInvadi[i][j].y += 20 | |
SpaceInvadi[i][j].velocity *= -1 | |
SpaceInvadi[i][j].velocity -= 0.5 | |
SpaceInvadi[i][j].invadershotchanceincrease += 1 | |
break | |
#player hits space invader | |
for i in range(len(SpaceInvadi)): | |
for j in range(len(SpaceInvadi[i])): | |
if PlayerBullet_y >= SpaceInvadi[i][j].y and PlayerBullet_y <= SpaceInvadi[i][j].y + SpaceInvadi[i][j].height and PlayerBullet_x >= SpaceInvadi[i][j].x and PlayerBullet_x <= SpaceInvadi[i][j].x + SpaceInvadi[i][j].width or PlayerBullet_y >= SpaceInvadi[i][j].y and PlayerBullet_y <= SpaceInvadi[i][j].y + SpaceInvadi[i][j].height and PlayerBullet_x + 5 >= SpaceInvadi[i][j].x and PlayerBullet_x + 5 <= SpaceInvadi[i][j].x + SpaceInvadi[i][j].width: | |
PlayerBullet_y = Ship_y + 5 | |
PlayerBullet_x = Ship_x + 28 | |
SpaceInvadi[i][j].health = 0 | |
PlayerBulletStart = False | |
NewPlayer.earnings += SpaceInvadi[i][j].value | |
if NewPlayer.earnings > NewPlayer.highscore: | |
NewPlayer.highscore = NewPlayer.earnings | |
#invader hits player | |
for i in range(len(SpaceInvadi)): | |
for j in range(len(SpaceInvadi[i])): | |
if SpaceInvadi[i][j].invadershotchance == 0: | |
SpaceInvadi[i][j].invadernotshot = False | |
if SpaceInvadi[i][j].invadernotshot: | |
SpaceInvadi[i][j].bullet_x = -50 | |
SpaceInvadi[i][j].bullet_y = -50 | |
elif not SpaceInvadi[i][j].invadernotshot and SpaceInvadi[i][j].invadershotstillgoing: | |
SpaceInvadi[i][j].bullet_y += 10 | |
else: | |
SpaceInvadi[i][j].bullet_x = SpaceInvadi[i][j].x | |
SpaceInvadi[i][j].bullet_y = SpaceInvadi[i][j].y + 10 | |
SpaceInvadi[i][j].invadershotstillgoing = True | |
if SpaceInvadi[i][j].bullet_x >= Ship_x and SpaceInvadi[i][j].bullet_x <= Ship_x + NewPlayer.width and SpaceInvadi[i][j].bullet_y + 9 >= Ship_y and SpaceInvadi[i][j].bullet_y + 9 <= Ship_y + NewPlayer.height and InvincibleFrames <= 0 or SpaceInvadi[i][j].bullet_x + 5 >= Ship_x and SpaceInvadi[i][j].bullet_x + 5 <= Ship_x + NewPlayer.width and SpaceInvadi[i][j].bullet_y + 9 >= Ship_y and SpaceInvadi[i][j].bullet_y + 9 <= Ship_y + NewPlayer.height and InvincibleFrames <= 0: | |
NewPlayer.health -= 1 | |
InvincibleFrames = 60 | |
SpaceInvadi[i][j].invadernotshot = True | |
SpaceInvadi[i][j].invadershotstillgoing = False | |
time.sleep(1) | |
Ship_x = (WindowW/2) | |
Ship_y = (9/10*WindowH) | |
if SpaceInvadi[i][j].x >= Ship_x and SpaceInvadi[i][j].x <= Ship_x + NewPlayer.width and SpaceInvadi[i][j].y + SpaceInvadi[i][j].height >= Ship_y and SpaceInvadi[i][j].y + SpaceInvadi[i][j].height <= Ship_y + NewPlayer.height or SpaceInvadi[i][j].x + SpaceInvadi[i][j].width >= Ship_x and SpaceInvadi[i][j].x + SpaceInvadi[i][j].width <= Ship_x + NewPlayer.width and SpaceInvadi[i][j].y + SpaceInvadi[i][j].height >= Ship_y and SpaceInvadi[i][j].y + SpaceInvadi[i][j].height <= Ship_y + NewPlayer.height: | |
NewPlayer.health = 0 | |
SpaceInvadi[i][j].invadernotshot = True | |
SpaceInvadi[i][j].invadershotstillgoing = False | |
Ship_x = (WindowW/2) | |
Ship_y = (9/10*WindowH) | |
if SpaceInvadi[i][j].bullet_y >= 1280: | |
SpaceInvadi[i][j].bulletnotshot = True | |
SpaceInvadi[i][j].invadershotstillgoing = False | |
#For when event keys are pressed | |
for event in pygame.event.get(): | |
if event.type == pygame.QUIT: | |
pygame.quit() | |
sys.exit() | |
try: | |
if event.type == pygame.KEYDOWN or event.type == pygame.KEYUP: | |
#print(event) | |
keys = pygame.key.get_pressed() | |
if keys[K_LEFT]: | |
Ship_x -= 8 | |
if keys[K_RIGHT]: | |
Ship_x += 8 | |
if keys[K_RIGHT] and PlayerBullet_x != (Ship_x + 28) and PlayerBulletStart == False: | |
PlayerBullet_x = Ship_x + 28 | |
PlayerBullet_y = Ship_y + 5 | |
if keys[K_LEFT] and PlayerBullet_x != (Ship_x + 28) and PlayerBulletStart == False: | |
PlayerBullet_x = Ship_x + 28 | |
PlayerBullet_y = Ship_y + 5 | |
if keys[K_SPACE]: | |
#PlayerBulletStart becomes true when the space key is pressed (or is 'down') and now the non-keydown event will occur unless | |
PlayerBulletStart = True | |
#...it gets to the top of the screen | |
if PlayerBullet_y < 0: | |
PlayerBullet_x = Ship_x + 28 | |
PlayerBullet_y = Ship_y + 5 | |
#it gets sent back to behind the ship before being fired again | |
PlayerBulletStart = False | |
if event.key == pygame.K_q: | |
pygame.quit() | |
sys.exit() | |
except UnboundLocalError: | |
pass | |
#print("I assume no event happened here") | |
#PLAYER SHIP BOUNADARIES | |
if Ship_x < 0: | |
Ship_x = 0 | |
if Ship_x + NewPlayer.width> 1280: | |
Ship_x = 1280 - NewPlayer.width | |
if PlayerBulletStart == True: | |
PlayerBullet_y -= 20 | |
if InGameLoop == True: | |
MainGameLoopOutput(MyFont, Window, InputtedName, Clock, NewPlayer, PlayerBullet_x, PlayerBullet_y, Ship_x, Ship_y, SpaceInvadi) | |
#This checks if the game is over | |
LivingList = [] | |
for i in range(len(SpaceInvadi)): | |
for j in range(len(SpaceInvadi[i])): | |
if SpaceInvadi[i][j].health == 0: | |
LivingList.append(SpaceInvadi[i][j]) | |
if len(LivingList) == 25 or NewPlayer.health == 0: | |
GameFinish(WindowH, | |
WindowW, | |
Clock, | |
Window, | |
MyFont, | |
NewPlayer, | |
InputtedName, | |
InGameLoop, | |
SpaceInvadi, | |
CurrentLevel) | |
InvincibleFrames -= 1 | |
def MainGameLoopOutput(MyFont, | |
Window, | |
InputtedName, | |
Clock, | |
NewPlayer, | |
PlayerBullet_x, | |
PlayerBullet_y, | |
Ship_x, | |
Ship_y, | |
SpaceInvadi): | |
Clock.tick(60) | |
#This removes all the images from the previous events. | |
Black = (0, 0, 0) | |
Window.fill(Black) | |
#Renders and displays name. | |
NameDisplay = MyFont.render(InputtedName, False, (255, 255, 255)) | |
Window.blit(NameDisplay,(0,0)) | |
#Makes sure that the Highscore is diplayed and that it doesn't overlap with the name. | |
HighScoreDisplay = MyFont.render("HighScore: "+(str(NewPlayer.highscore)), False, (255, 255, 255)) | |
HealthDisplay = MyFont.render("Health: "+(str(NewPlayer.health)), False, (255, 255, 255)) | |
Window.blit(HighScoreDisplay,((len(NewPlayer.name)*10) + 10,0)) | |
Window.blit(HealthDisplay,((len(NewPlayer.name)*10) + 100 + len(str((NewPlayer.highscore)))*10,0)) | |
#Places sprite(s) with current cooridinates. | |
Window.blit(NewPlayer.bulletsprite, (PlayerBullet_x, PlayerBullet_y)) | |
for i in range(len(SpaceInvadi)): | |
for j in range(len(SpaceInvadi[i])): | |
Window.blit(SpaceInvadi[i][j].bulletsprite, (SpaceInvadi[i][j].bullet_x, SpaceInvadi[i][j].bullet_y)) | |
Window.blit(NewPlayer.sprite, (Ship_x, Ship_y)) | |
for i in range(len(SpaceInvadi)): | |
for j in range(len(SpaceInvadi[i])): | |
Window.blit(SpaceInvadi[i][j].sprite, (SpaceInvadi[i][j].x, SpaceInvadi[i][j].y)) | |
#Carries out all of the above. | |
pygame.display.flip() | |
pygame.display.update() | |
def GameFinish(WindowH, | |
WindowW, | |
Clock, | |
Window, | |
MyFont, | |
NewPlayer, | |
InputtedName, | |
InGameLoop, | |
SpaceInvadi, | |
CurrentLevel): | |
if NewPlayer.health < 1: | |
print("The game is over") | |
with open("HighScores.txt", 'a') as f: | |
PlayerData = (str(NewPlayer.name) + ": " + str(NewPlayer.highscore) + '\n') | |
f.write(PlayerData) | |
pygame.quit() | |
sys.exit() | |
else: | |
SpaceInvadi = InvaderFactory() | |
CurrentLevel += 1 | |
for i in range(len(SpaceInvadi)): | |
for j in range(len(SpaceInvadi[i])): | |
#CurrentLevel += 1 | |
SpaceInvadi[i][j].velocity += CurrentLevel | |
StartGame(InputtedName, WindowH, WindowW, Clock, Window, MyFont, NewPlayer, SpaceInvadi, CurrentLevel) | |
def DisplayMenu(InputtedName): | |
WindowH = 720 | |
WindowW = 1280 | |
Clock = pygame.time.Clock() | |
Window = pygame.display.set_mode((WindowW, WindowH)) | |
pygame.display.set_caption("Space Invaders") | |
MyFont = pygame.font.SysFont('Bernard MT Condensed MS', 18) | |
#InputtedName = "Jake" | |
MenuChoiceList = ["PlayGame", "HighScoreList", "Quit"] | |
MenuDisplay = True | |
MenuChoice = 0 | |
MENU1 = pygame.image.load("MENU1.png") | |
MENU2 = pygame.image.load("MENU2.png") | |
MENU3 = pygame.image.load("MENU3.png") | |
while MenuDisplay: | |
for event in pygame.event.get(): | |
if event.type == pygame.QUIT: | |
pygame.quit() | |
sys.exit() | |
if event.type == pygame.KEYDOWN: | |
if event.key == pygame.K_DOWN: | |
MenuChoice += 1 | |
if MenuChoice > 2: | |
MenuChoice = 0 | |
if event.key == pygame.K_UP: | |
MenuChoice -= 1 | |
if MenuChoice < -3: | |
MenuChoice = -1 | |
time.sleep(0.1) | |
if event.key == pygame.K_RETURN: | |
MenuDisplay = False | |
if MenuChoiceList[MenuChoice] == MenuChoiceList[0]: | |
Window.blit(MENU1, (0, 64)) | |
if MenuChoiceList[MenuChoice] == MenuChoiceList[1]: | |
Window.blit(MENU2, (0, 64)) | |
if MenuChoiceList[MenuChoice] == MenuChoiceList[2]: | |
Window.blit(MENU3, (0, 64)) | |
pygame.display.flip() | |
pygame.display.update() | |
if MenuChoiceList[MenuChoice] == MenuChoiceList[0]: | |
#Creates a fresh player with no highscore and three lives | |
PlayerShipSprite = pygame.image.load("ship.png") | |
PlayerBulletSprite = pygame.image.load("pbullet.png") | |
NewPlayer = Player(InputtedName, 3, PlayerShipSprite, PlayerBulletSprite, 58, 38) | |
NewPlayer.HighScore(0) | |
NewPlayer.Earnings(0) | |
SpaceInvadi = InvaderFactory() | |
CurrentLevel = 0 | |
StartGame(InputtedName, WindowH, WindowW, Clock, Window, MyFont, NewPlayer, SpaceInvadi, CurrentLevel) | |
elif MenuChoiceList[MenuChoice] == MenuChoiceList[1]: | |
DisplayHighscores(InputtedName) | |
pygame.quit() | |
else: | |
pygame.quit() | |
sys.exit() | |
def DisplayHighscores(InputtedName): | |
HighscoresDisplay = True | |
WindowH = 720 | |
WindowW = 1280 | |
Clock = pygame.time.Clock() | |
Window = pygame.display.set_mode((WindowW, WindowH)) | |
pygame.display.set_caption("Space Invaders") | |
MyFont1 = pygame.font.SysFont('sitkasmallsitkatextbolditalicsitkasubheadingbolditalicsitkaheadingbolditalicsitkadisplaybolditalicsitkabannerbolditalic', 25) | |
MyFont2 = pygame.font.SysFont('Bernard MT Condensed MS', 25) | |
HighscoreList = [] | |
with open("HighScores.txt", 'r') as f: | |
for line in f: | |
CurrentHighscoreList = line.split(": ") | |
HighscoreList.append(CurrentHighscoreList) | |
HighscoreList = MergeSortingHighscores(HighscoreList) | |
while HighscoresDisplay: | |
for event in pygame.event.get(): | |
if event.type == pygame.QUIT: | |
pygame.quit() | |
sys.exit() | |
if event.type == pygame.KEYDOWN: | |
if event.key == pygame.K_ESCAPE: | |
DisplayMenu(InputtedName) | |
Clock.tick(60) | |
Window.fill((0, 0, 0)) | |
for i in range(len(HighscoreList)): | |
HighScoresDisplay = MyFont2.render(HighscoreList[i][0] + ": " + HighscoreList[i][1], False, (255, 235, 255)) | |
Window.blit(HighScoresDisplay,(10,i*50 + 30)) | |
HighscoreText = MyFont1.render("Highscores - Press Escape to Return to Main Menu:", False, (255, 235, 255)) | |
Window.blit(HighscoreText,(10,0)) | |
pygame.display.flip() | |
pygame.display.update() | |
def MergeSortingHighscores(HighscoreList): | |
ArrayA = [] | |
for i in range(len(HighscoreList)): | |
ArrayA.append(int(HighscoreList[i][1])) | |
OrderedHighscoreNumbers = Split(ArrayA) | |
FinalArray = [] | |
for i in range(len(OrderedHighscoreNumbers)): | |
for j in range(len(HighscoreList)): | |
if int(OrderedHighscoreNumbers[i]) == int(HighscoreList[j][1]): | |
FinalArray.append(HighscoreList[j]) | |
FinalArray = FinalArray[::-1] | |
HighscoreList = FinalArray | |
return HighscoreList | |
def Merge(ArrayA, ArrayB): | |
ArrayC = [] | |
while len(ArrayA) > 0 and len(ArrayB) > 0: | |
if ArrayA[0] > ArrayB[0]: | |
ArrayC.append(ArrayB[0]) | |
del ArrayB[0] | |
else: | |
ArrayC.append(ArrayA[0]) | |
del ArrayA[0] | |
while len(ArrayA) > 0: | |
ArrayC.append(ArrayA[0]) | |
del ArrayA[0] | |
while len(ArrayB) > 0: | |
ArrayC.append(ArrayB[0]) | |
del ArrayB[0] | |
return ArrayC | |
def Split(ArrayA): | |
#base case | |
if len(ArrayA) == 1: | |
return ArrayA | |
ArrayOne = [] | |
for i in range(int(len(ArrayA)/2)): | |
ArrayOne.append(ArrayA[i]) | |
#print(ArrayOne) | |
ArrayTwo = [] | |
for i in range(math.ceil(len(ArrayA)/2)): | |
ArrayTwo.append(ArrayA[int(i+len(ArrayOne))]) | |
#print(ArrayTwo) | |
ArrayOne = Split(ArrayOne) | |
ArrayTwo = Split(ArrayTwo) | |
return Merge(ArrayOne, ArrayTwo) | |
InputtedName = str(input("Enter your name: ")) | |
DisplayMenu(InputtedName) |