Advertisement
xgeovanni

Invasion!

Feb 16th, 2013
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 34.75 KB | None | 0 0
  1. # Invasion!
  2. # Originally created for Ludum Dare 25
  3. # Theme: "You are the villian"
  4.  
  5. # Code: GNU Genral Public License 3.0
  6. # Images: All Rights Reserved (At artist's request)
  7.  
  8. # LethalWare.co.uk
  9.  
  10. # Post Compo re-release
  11.  
  12. #Changelog:
  13.  
  14. # Vastly improved graphics and sound
  15. # New menu screen
  16. # Code refactored
  17. # Upgrades now have a base cost of 80 rather than 100
  18. # Bullet "physics" overhauled.
  19. # Pausing
  20. # 'Splosions!
  21.  
  22. #To do:
  23. # More / unique upgrades
  24. # Animate tank
  25.  
  26. # coding = UTF-8
  27.  
  28. #Imports
  29. import pygame
  30. import sys
  31. import os
  32. import random
  33. import math
  34. import pickle
  35. import sprite
  36. from time import sleep
  37. from pygame.locals import *
  38. pygame.init()
  39.  
  40. clock = pygame.time.Clock()
  41. WIDTH = 800
  42. HEIGHT = 600
  43. screen = pygame.display.set_mode((WIDTH, HEIGHT))
  44. gamename = "Invasion!"
  45. pygame.display.set_caption(gamename)
  46. pygame.mouse.set_visible(False)
  47. SCREENRECT = pygame.Rect((0, 0), screen.get_size())
  48.  
  49. red = (255, 0, 0)
  50. green = (0, 255, 0)
  51. black = (0, 0, 0)
  52.  
  53. explosionFrames = [pygame.image.load("Images\explosion frames\explosion {0}.png".format(str(i))) for i in range(1, 8)]
  54.  
  55. def isNegative(num):
  56.     try:
  57.         math.sqrt(num)
  58.         return False
  59.     except:
  60.         return True
  61.  
  62. def deNegate(num):
  63.     if isNegative(num):
  64.         return -num
  65.     else:
  66.         return num
  67.  
  68. def end():
  69.     pygame.quit()
  70.     sys.exit(0)
  71.  
  72. def pause(pauseimg = "Images/pause.png", unpause = K_ESCAPE, framerate = 30):
  73.     sleeptime = 1 / framerate #Unpause on-frame with maximum efficiency
  74.     paused = True
  75.     img = pygame.image.load(pauseimg).convert_alpha()
  76.     screen.blit(img, (0, 0))
  77.     pygame.display.update()
  78.     pygame.event.clear()
  79.  
  80.     while paused:
  81.         sleep(sleeptime)
  82.  
  83.         for event in pygame.event.get():
  84.             if event.type == pygame.QUIT:
  85.                 end()
  86.                 sys.exit(0)
  87.             elif event.type == KEYDOWN:
  88.                 if event.key == unpause:
  89.                     paused = False
  90.    
  91.  
  92. class Cursor():
  93.     def __init__(self, img = "Images/cursor.png"):
  94.         self.img = pygame.image.load(img).convert_alpha()
  95.     def draw(self):
  96.         pos = [pygame.mouse.get_pos()[i] - self.img.get_size()[i] / 2
  97.                for i in range(2)]
  98.        
  99.         screen.blit(self.img, pos)
  100.  
  101. class menuOption():
  102.     def __init__(self, img, pos, clickedImg = None, startState = False):
  103.         if isinstance(img, pygame.Surface):
  104.             self.img = img
  105.         else:
  106.             self.img = pygame.image.load(img).convert_alpha()
  107.  
  108.         self.pos = pos
  109.         self.rect = pygame.Rect(self.pos, self.img.get_size())
  110.         self.clickedImg = clickedImg
  111.  
  112.         if startState:
  113.             self.img, self.clickedImg = self.clickedImg, self.img
  114.  
  115.     def draw(self):
  116.         screen.blit(self.img, self.pos)
  117.     def checkClick(self):
  118.         if self.rect.collidepoint(pygame.mouse.get_pos()):
  119.             if self.clickedImg:
  120.                 self.img, self.clickedImg = self.clickedImg, self.img # Swap
  121.  
  122.             return True
  123.         else:
  124.             return False
  125.  
  126. class playerInputBox():
  127.     def __init__(self, font, colour, pos = None, maxlen = None):
  128.         self.text = ""
  129.         self.font = font
  130.         if pos is None:
  131.             self.pos = (WIDTH / 2, HEIGHT / 2)
  132.             self.central = True
  133.         else:
  134.             self.pos = pos
  135.             self.central = False
  136.         self.colour = colour
  137.         self.maxlen = maxlen
  138.         self.textImg = self.font.render(self.text, True, self.colour).convert_alpha()
  139.        
  140.         alphabet = "abcdefghigklmnopqrstuvwxyz1234567890"
  141.         self.key2char = {eval("K_" + char) : char for char in alphabet}
  142.         self.key2upperchar = {eval("K_" + char) : char.upper() for char in alphabet}
  143.         self.upperCase = False
  144.         self.shift = False
  145.  
  146.     def draw(self):
  147.         screen.blit(self.textImg, self.pos)
  148.  
  149.     def recentralise(self):
  150.         self.pos = (WIDTH / 2 - self.textImg.get_width() / 2,
  151.                     HEIGHT / 2 - self.textImg.get_height() / 2)
  152.    
  153.     def key_input(self, key, boolean):
  154.         if boolean:
  155.             if key in self.key2char and (self.maxlen is None or len(self.text) < self.maxlen):
  156.                 if (self.upperCase and not self.shift) or (self.shift and not self.upperCase):
  157.                     self.text += self.key2upperchar[key]
  158.                 else:
  159.                     self.text += self.key2char[key]
  160.  
  161.                 self.textImg = self.font.render(self.text, True, self.colour).convert_alpha()
  162.                 if self.central:
  163.                     self.recentralise()
  164.  
  165.             elif key == K_BACKSPACE:
  166.                 self.text = self.text[:len(self.text) - 1]
  167.                 self.textImg = self.font.render(self.text, True, self.colour).convert_alpha()
  168.                 if self.central:
  169.                     self.recentralise()
  170.             elif key == K_CAPSLOCK:
  171.                 if self.upperCase:
  172.                     self.upperCase = False
  173.                 else:
  174.                     self.upperCase = True
  175.  
  176.             elif key == K_SPACE:
  177.                 self.text += " "
  178.                 self.textImg = self.font.render(self.text, True, self.colour).convert_alpha()
  179.                 if self.central:
  180.                     self.recentralise()
  181.  
  182.         if key == K_LSHIFT or key == K_RSHIFT:
  183.             self.shift = boolean
  184.  
  185. class GUIManager():
  186.     def __init__(self, font = "Lucida Console, Trebuchet MS, Verdana", size = 24,
  187.                  medSize = 48, largeSize = 72, menuColour = (0, 50, 255)):
  188.         self.font = pygame.font.SysFont(font, size)
  189.         self.medFont = pygame.font.SysFont(font, medSize)
  190.         self.largeFont = pygame.font.SysFont(font, largeSize)
  191.         self.menuColour = menuColour
  192.  
  193.         self.menuimg = pygame.image.load("Images/menu.png")
  194.  
  195.     def drawHUD(self, ship):
  196.         texts = (self.font.render("Score: " + str(ship.score),
  197.                                 True, black).convert_alpha(),
  198.                  self.font.render("", True, black).convert(),
  199.                  self.font.render("Scrap:" + str(ship.scrap),
  200.                                 True, black).convert_alpha(),
  201.                  self.font.render("1: Laser Power ({0}): ".format(str(ship.laserPower * ship.upgradeCost)) + str(ship.laserPower),
  202.                                   True, black).convert_alpha(),
  203.                  self.font.render("2: Armour ({0}): ".format(str(ship.armour * ship.upgradeCost)) + str(ship.armour),
  204.                                   True, black).convert_alpha(),
  205.                  self.font.render("3: Speed ({0}): ".format(str(ship.speed * ship.upgradeCost)) + str(ship.speed),
  206.                                   True, black).convert_alpha())
  207.  
  208.        
  209.  
  210.         cumulativeHeight = 0
  211.         for text in texts:
  212.             screen.blit(text, (0, cumulativeHeight))
  213.             cumulativeHeight += text.get_height()
  214.  
  215.     def instructions(self):
  216.         title = self.largeFont.render("Instructions", True, self.menuColour).convert_alpha()
  217.         text = self.font.render("Press any key to return to the main menu", True, self.menuColour).convert_alpha()
  218.        
  219.         instructions = ("WASD: Movement",
  220.                         "ESC to pause",
  221.                         "Click: Fire the laser",
  222.                         "1: Upgrade laser power with scrap",
  223.                         "2: Upgrade ship armour with scrap",
  224.                         "3: Upgrade ship speed with scrap",
  225.                         "4: hold to use scrap to repair the ship",
  226.                         "",
  227.                         "While the laser is firing",
  228.                         "the ship cannot be repaired as the crew is busy",
  229.                         "",
  230.                         "Scrap is accumulated by killing enemies",
  231.                         "Upgrade cost is listed beside the upgrade in the HUD")
  232.  
  233.         txtInstructions = []
  234.         for line in instructions:
  235.             txtInstructions.append(self.font.render(line, True, self.menuColour).convert_alpha())
  236.  
  237.         screen.fill(black)
  238.  
  239.         screen.blit(title, (WIDTH / 2 - title.get_width() / 2 , 0))
  240.         screen.blit(text, (WIDTH / 2 - text.get_width() / 2, HEIGHT - text.get_height()))
  241.  
  242.         y = sum(line.get_height() for line in txtInstructions) / 2
  243.         for line in txtInstructions:
  244.             screen.blit(line, (WIDTH / 2 - line.get_width() / 2, HEIGHT / 2 + line.get_height() / 2 - y))
  245.             y -= line.get_height()
  246.  
  247.         pygame.display.update()
  248.  
  249.         while True:
  250.             for event in pygame.event.get():
  251.                 if event.type == pygame.QUIT:
  252.                     end()
  253.                 elif event.type == KEYDOWN:
  254.                     return True
  255.  
  256.     def menu(self, cursor, sm, hsm):
  257.         playRect = pygame.Rect((277, 173), (245, 73))
  258.         instructionsRect = pygame.Rect((277, 260), (245, 73))
  259.         highScoresRect = pygame.Rect((277, 347), (245, 73))
  260.         creditsRect = pygame.Rect((277, 434), (245, 73))
  261.         endRect = pygame.Rect((713, 15), (72, 21))
  262.  
  263.         audioButtonText = pygame.image.load("Images/note_green.png").convert_alpha()
  264.         audioButtonClickedText = pygame.image.load("Images/note_red.png").convert_alpha()
  265.         audioButton = menuOption(audioButtonText,
  266.                                  (0, 0),
  267.                                   audioButtonClickedText)
  268.  
  269.         while True:
  270.             screen.fill(black)
  271.             screen.blit(self.menuimg, (0, 0))
  272.             audioButton.draw()
  273.             cursor.draw()
  274.             pygame.display.update()
  275.            
  276.             for event in pygame.event.get():
  277.                 if event.type == pygame.QUIT:
  278.                     end()
  279.                 elif event.type == MOUSEBUTTONDOWN:
  280.                     if audioButton.checkClick():
  281.                         sm.mute()
  282.                     elif playRect.collidepoint(pygame.mouse.get_pos()):
  283.                         return True
  284.                     elif instructionsRect.collidepoint(pygame.mouse.get_pos()):
  285.                         self.instructions()
  286.                     elif highScoresRect.collidepoint(pygame.mouse.get_pos()):
  287.                         self.highScoreBoard(hsm)
  288.                     elif creditsRect.collidepoint(pygame.mouse.get_pos()):
  289.                         self.credits()
  290.                     elif endRect.collidepoint(pygame.mouse.get_pos()):
  291.                         end()
  292.  
  293.     def credits(self):
  294.         strCredits = ("Code and menu music",
  295.                       "xGeovanni",
  296.                       "",
  297.                       "Art",
  298.                       "BloodStalker",
  299.                       "",
  300.                       '"Battle In The Winter"',
  301.                       "Johan Brodd",
  302.                       "",
  303.                       "LethalWare.co.uk")
  304.        
  305.         txtCredits = [self.medFont.render(credit , True, self.menuColour).convert_alpha() for credit in strCredits]
  306.         text = self.font.render("Press any key to return to the main menu", True, self.menuColour).convert_alpha()
  307.  
  308.         screen.fill(black)
  309.  
  310.         y = sum(line.get_height() for line in txtCredits) / 2
  311.         for line in txtCredits:
  312.             screen.blit(line, (WIDTH / 2 - line.get_width() / 2, HEIGHT / 2 + line.get_height() / 2 - y))
  313.             y -= line.get_height()
  314.  
  315.         screen.blit(text, (WIDTH / 2 - text.get_width() / 2,
  316.                            HEIGHT - text.get_height()))
  317.  
  318.         pygame.display.update()
  319.  
  320.         while True:
  321.             for event in pygame.event.get():
  322.                 if event.type == pygame.QUIT:
  323.                     end()
  324.                     sys.exit(0)
  325.                 elif event.type == KEYDOWN:
  326.                     return True
  327.  
  328.  
  329.     def lose(self):
  330.         youLose = self.largeFont.render("You Lose!", True, self.menuColour).convert_alpha()
  331.         text = self.font.render("Press any key to return to the main menu", True, self.menuColour).convert_alpha()
  332.  
  333.         screen.fill(black)
  334.  
  335.         screen.blit(youLose, (WIDTH / 2 - youLose.get_width() / 2,
  336.                               HEIGHT / 2 - youLose.get_height() / 2))
  337.         screen.blit(text, (WIDTH / 2 - text.get_width() / 2,
  338.                            HEIGHT - text.get_height()))
  339.  
  340.         pygame.display.update()
  341.  
  342.         while True:
  343.             for event in pygame.event.get():
  344.                 if event.type == pygame.QUIT:
  345.                     end()
  346.                     sys.exit(0)
  347.                 elif event.type == KEYDOWN:
  348.                     return True
  349.  
  350.     def highScoreBoard(self, hsm):
  351.         title = self.largeFont.render("High Scores", True, self.menuColour).convert_alpha()
  352.         text = self.font.render("Press any key to return to the main menu", True, self.menuColour).convert_alpha()
  353.        
  354.         highScores = []
  355.         for highscore in hsm.highscores:
  356.             highScores.append(self.largeFont.render(highscore[0] + ": " + str(highscore[1]), True, self.menuColour).convert_alpha())
  357.  
  358.         screen.fill(black)
  359.  
  360.         screen.blit(title, (WIDTH / 2 - title.get_width() / 2, 0))
  361.         screen.blit(text, (WIDTH / 2 - text.get_width() / 2, HEIGHT - text.get_height()))
  362.  
  363.         y = sum(line.get_height() for line in highScores) / 2
  364.         for line in highScores:
  365.             screen.blit(line, (WIDTH / 2 - line.get_width() / 2, HEIGHT / 2 + line.get_height() / 2 - y))
  366.             y -= line.get_height()
  367.  
  368.         pygame.display.update()
  369.  
  370.         while True:
  371.             for event in pygame.event.get():
  372.                 if event.type == pygame.QUIT:
  373.                     end()
  374.                    
  375.                 elif event.type == KEYDOWN:
  376.                     return True
  377.  
  378.     def newHighScore(self):
  379.         title = self.largeFont.render("New High Score!", True, self.menuColour).convert_alpha()
  380.         text = self.font.render("Enter your name", True, self.menuColour).convert_alpha()
  381.  
  382.         inputBox = playerInputBox(self.largeFont, self.menuColour, maxlen = 10)
  383.  
  384.         while True:
  385.             clock.tick(10)
  386.             screen.fill(black)
  387.  
  388.             screen.blit(title, (WIDTH / 2 - title.get_width() / 2, 0))
  389.             screen.blit(text, (WIDTH / 2 - text.get_width() / 2, HEIGHT - text.get_height()))
  390.             inputBox.draw()
  391.  
  392.             pygame.display.update()
  393.  
  394.             for event in pygame.event.get():
  395.                 if event.type == pygame.QUIT:
  396.                     end()
  397.                 elif event.type == KEYDOWN:
  398.                     if event.key == K_RETURN:
  399.                         return inputBox.text
  400.                     else:
  401.                         inputBox.key_input(event.key, True)
  402.                 elif event.type == KEYUP:
  403.                     inputBox.key_input(event.key, False)
  404.            
  405. class SoundManager():
  406.     def __init__(self):
  407.         self.sounds = {"bullet" : pygame.mixer.Sound("Sounds/bullet.wav"),
  408.                        "laserstart" : pygame.mixer.Sound("Sounds/laserstart.wav"),
  409.                        "laserstop" : pygame.mixer.Sound("Sounds/laserstop.wav"),
  410.                        "explosion" : pygame.mixer.Sound("Sounds/explosion.wav")}
  411.  
  412.         self.music = {"menu" : "Sounds/Music/menu.ogg",
  413.                       "battle" : "Sounds/Music/Battle in the winter.ogg"}
  414.         self.isMuted = False
  415.  
  416.     def play(self, sound, loops = 0, fadems = 0):
  417.         self.sounds[sound].play(loops, 0, fadems)
  418.  
  419.     def loadSong(self, song):
  420.         pygame.mixer.music.load(self.music[song])
  421.         if not self.isMuted:
  422.             pygame.mixer.music.play(-1)
  423.  
  424.     def stop(self, sound):
  425.         self.sounds[sound].stop()
  426.     def stopSong(self, fadeout = 0):
  427.         if not self.isMuted:
  428.             if fadeout == 0:
  429.                 pygame.mixer.music.stop()
  430.             else:
  431.                 pygame.mixer.music.fadeout(fadeout)
  432.  
  433.     def mute(self):
  434.         if self.isMuted:
  435.             for sound in self.sounds:
  436.                 self.sounds[sound].set_volume(1)
  437.             self.isMuted = False
  438.  
  439.             pygame.mixer.music.unpause()
  440.         else:
  441.             for sound in self.sounds:
  442.                  self.sounds[sound].set_volume(0)
  443.             self.isMuted = True
  444.  
  445.             pygame.mixer.music.pause()
  446.  
  447. class HighScoreManager():
  448.     def __init__(self):
  449.         self.filename = "highscores.dat"
  450.         self.numScores = 5
  451.        
  452.         if not os.path.isfile(self.filename):
  453.             self.setup()
  454.         else:
  455.             file = open(self.filename, "rb")
  456.            
  457.             try:
  458.                 self.highscores = pickle.load(file)
  459.             except EOFError:
  460.                 self.setup()
  461.                
  462.             file.close()
  463.             self.file = open(self.filename, "wb")
  464.  
  465.             self.names = [highscore[0] for highscore in self.highscores]
  466.             self.scores = [highscore[1] for highscore in self.highscores]
  467.             self.updateFile()
  468.  
  469.     def __del__(self):
  470.         self.file.close()
  471.  
  472.     def setup(self):
  473.         self.file = open(self.filename, "wb")
  474.         baseScore = 100
  475.         self.scores = [baseScore for i in range(self.numScores)]
  476.         self.names = ["A", "B", "C", "D", "E"]
  477.         self.highscores = [(self.names[i], self.scores[i]) for i in range(self.numScores)]
  478.         self.updateFile()
  479.  
  480.     def checkScore(self, score):
  481.         tempScores = self.scores[:] # Copy
  482.         tempScores.append(score)
  483.         tempScores.sort(reverse = True)
  484.         tempScores = tempScores[:self.numScores]
  485.  
  486.         return (score in tempScores) # True if score is in tempScores
  487.  
  488.     def addScore(self, name, score):
  489.         self.scores.append(score) #Add new score
  490.         self.scores.sort(reverse = True) #Sort
  491.         self.names.insert(self.scores.index(score), name)
  492.         self.names = self.names[:self.numScores] # Top 5
  493.         self.scores = self.scores[:self.numScores]
  494.         self.highscores = [(self.names[i], self.scores[i]) for i in range(self.numScores)]
  495.         self.updateFile()
  496.  
  497.     def updateFile(self):
  498.         self.file.close()
  499.         self.file = open(self.filename, "wb")
  500.         pickle.dump(self.highscores, self.file)
  501.  
  502.  
  503. class UnitManager():
  504.     def __init__(self, sm):
  505.         self.units = []
  506.         self.explosions = []
  507.         self.sm = sm
  508.         self.baseSpawnRate = 80
  509.         self.explosionDelay = 2
  510.         self.explosionFrames = [pygame.image.load("Images\explosion frames\explosion {0}.png".format(str(i))).convert_alpha() for i in range(1, 8)]
  511.  
  512.     def spawn(self, unitclass):
  513.         self.units.append(unitclass())
  514.  
  515.     def kill(self, unit):
  516.         self.units.remove(unit)
  517.  
  518.     def explode(self, unit):
  519.         self.explosions.append(sprite.Sprite(screen, self.explosionFrames, unit.x, unit.y, self.explosionDelay))
  520.         self.sm.play("explosion")
  521.        
  522.     def updateExplosions(self):
  523.         for explosion in self.explosions:
  524.             explosion.animatedDraw()
  525.  
  526.             if explosion.cycles >= 1:
  527.                 self.explosions.remove(explosion)
  528.  
  529.     def update(self, beam, bm, ship, sm):
  530.         self.updateExplosions()
  531.         for unit in self.units:
  532.             unit.draw()
  533.             unit.move()
  534.             unit.HPBar.draw()
  535.  
  536.             if beam:
  537.                 for point in beam:
  538.                     if unit.rect.collidepoint(point):
  539.                         unit.remHP(ship.laserDamage)
  540.                         break
  541.  
  542.             if unit.shoots and random.randint(1, unit.fireRate) == 1:
  543.                 sm.play("bullet")
  544.                 bm.add(unit.fire(ship))
  545.  
  546.             if unit.HP <= 0:
  547.                 self.kill(unit)
  548.                 if unit.explodes:
  549.                     self.explode(unit)
  550.                 ship.addScrap(unit.scrapValue)
  551.  
  552.             if unit.delete:
  553.                 self.kill(unit)
  554.  
  555.         if random.randint(1, int((self.baseSpawnRate / ship.upgradeLevel) * len(self.units) + 1)) == 1:
  556.             choice = random.randrange(1, 20)
  557.             if choice in range(1, 6):
  558.                 self.spawn(Person)
  559.             elif choice in range(6, 12):
  560.                 self.spawn(Soldier)
  561.             elif choice == 13:
  562.                 self.spawn(StealthPlane)
  563.             elif choice in range(13, 18):
  564.                 self.spawn(Helicopter)
  565.             elif choice in range(19, 20):
  566.                 self.spawn(Tank)
  567.  
  568.  
  569.  
  570. class HPBar():
  571.     def __init__(self, maxHP, anchor, sizeIncreaseTrigger = 100):
  572.         self.maxHP = maxHP
  573.         self.currentHP = maxHP
  574.         self.anchor = anchor
  575.  
  576.         self.greenbar = pygame.image.load("Images/HPbars/greenbar.png").convert()
  577.         self.redbar = pygame.image.load("Images/HPbars/redbar.png").convert()
  578.  
  579.         if sizeIncreaseTrigger and maxHP >= sizeIncreaseTrigger:
  580.             self.greenbar = pygame.transform.scale(self.greenbar, (self.greenbar.get_width() * math.floor(maxHP / sizeIncreaseTrigger), self.redbar.get_height()))
  581.             self.redbar = pygame.transform.scale(self.redbar, (self.redbar.get_width() * math.floor(maxHP / sizeIncreaseTrigger), self.redbar.get_height()))
  582.        
  583.         self.maxwidth = self.greenbar.get_width()
  584.         self.x = self.anchor.x + self.anchor.img.get_width() / 2 - self.redbar.get_width() / 2
  585.         self.y = self.anchor.y - self.redbar.get_height()
  586.     def updateHP(self, currentHP):
  587.         self.currentHP = currentHP
  588.         if currentHP > 0:
  589.             newwidth = math.floor(self.maxwidth * (self.currentHP / self.maxHP))
  590.             self.greenbar = pygame.transform.scale(self.greenbar, (newwidth, self.greenbar.get_height()))
  591.         else:
  592.             self.greenbar.set_alpha(255)
  593.  
  594.     def draw(self):
  595.         screen.blit(self.redbar, (self.x, self.y))
  596.         screen.blit(self.greenbar, (self.x, self.y))
  597.  
  598.     def move(self):
  599.         self.x = self.anchor.x + self.anchor.img.get_width() / 2 - self.redbar.get_width() / 2
  600.         self.y = self.anchor.y - self.redbar.get_height()
  601.  
  602. class Ship():
  603.     def __init__(self, img = "Images/ship.png", HP = 400):
  604.         self.leftimg = pygame.image.load(img).convert_alpha()
  605.         self.rightimg = pygame.transform.flip(self.leftimg, True, False)
  606.         self.img = self.rightimg
  607.         self.x = WIDTH / 2 - self.img.get_width() / 2
  608.         self.y = self.img.get_height()
  609.         self.midpoint = (self.x + self.img.get_width() / 2,
  610.                          self.y + self.img.get_height() / 2)
  611.         self.maxHP = HP
  612.         self.HP = HP
  613.         self.HPBar = HPBar(HP, self)
  614.         self.rect = pygame.Rect((self.x, self.y), self.img.get_size())
  615.         self.score = 0
  616.         self.scrap = 0
  617.         self.speed = 5
  618.         self.armour = 1
  619.         self.laserPower = 1
  620.         self.upgradeLevel = self.laserPower + self.armour + self.speed
  621.         self.upgradeCost = 80
  622.         self.laserOffset = 0.8
  623.         self.laserDamage = self.laserPower * self.laserOffset
  624.         self.maxLevel = 5
  625.  
  626.         #Movement boolean variables
  627.  
  628.         self.up = False
  629.         self.down = False
  630.         self.left = False
  631.         self.right = False
  632.  
  633.         self.firing = False
  634.         self.healing = False
  635.  
  636.         #   #   #   #   #
  637.  
  638.     def draw(self):
  639.         screen.blit(self.img, (self.x, self.y))
  640.         self.HPBar.draw()
  641.  
  642.     def regen(self):
  643.         if self.healing and self.scrap > 0:
  644.             self.HP += 1
  645.             self.scrap -= 1
  646.  
  647.     def addScrap(self, amount):
  648.         self.scrap += amount
  649.         self.score += amount * 10
  650.  
  651.     def respondToKey(self, key, boolean):
  652.         if key == K_w:
  653.             self.up = boolean
  654.         elif key == K_a:
  655.             self.left = boolean
  656.  
  657.             if boolean:
  658.                 self.img = self.leftimg
  659.         elif key == K_s:
  660.             self.down = boolean
  661.         elif key == K_d:
  662.             self.right = boolean
  663.  
  664.             if boolean:
  665.                 self.img = self.rightimg
  666.  
  667.         self.spendScrap(key, boolean)
  668.  
  669.     def respondToMouse(self, boolean):
  670.         self.firing = boolean
  671.  
  672.     def spendScrap(self, key, boolean):
  673.         if boolean and key in (K_1, K_2, K_3):
  674.             if key == K_1 and self.scrap >= self.upgradeCost * self.laserPower and self.laserPower < self.maxLevel:
  675.                 self.scrap -= self.upgradeCost * self.laserPower
  676.                 self.laserPower += 1
  677.                 self.laserDamage = self.laserPower * self.laserOffset
  678.             elif key == K_2 and self.scrap >= self.upgradeCost * self.armour and self.armour < self.maxLevel:
  679.                 self.scrap -= self.upgradeCost * self.armour
  680.                 self.armour += 1
  681.             elif key == K_3 and self.scrap >= self.upgradeCost * self.speed and self.speed < self.maxLevel:
  682.                 self.scrap -= self.upgradeCost * self.speed
  683.                 self.speed += 1
  684.  
  685.             self.upgradeLevel = self.laserPower + self.armour + self.speed
  686.            
  687.         if key == K_4:
  688.             self.healing = boolean
  689.  
  690.     def remHP(self, loss):
  691.         self.HP -= loss * (1 - self.armour / 10)
  692.         self.HPBar.updateHP(self.HP)
  693.  
  694.     def update(self):
  695.         if self.up or self.down or self.left or self.right:
  696.             if self.up and not self.y < 0:
  697.                 self.y -= self.speed * 4
  698.             elif self.down and not self.y > HEIGHT - self.img.get_height():
  699.                 self.y += self.speed * 4
  700.             if self.left and not self.x < 0:
  701.                 self.x -= self.speed * 4
  702.             elif self.right and not self.x > WIDTH - self.img.get_width():
  703.                 self.x += self.speed * 4
  704.  
  705.             self.midpoint = (self.x + self.img.get_width() / 2,
  706.                              self.y + self.img.get_height() / 2)
  707.             self.rect = pygame.Rect((self.x, self.y), self.img.get_size())
  708.  
  709.             self.HPBar.move()
  710.  
  711.  
  712.         if self.firing:
  713.             return self.fire()
  714.            
  715.         else:
  716.             if self.HP < self.maxHP:
  717.                 self.regen()
  718.  
  719.     def fire(self):
  720.         mousepos = pygame.mouse.get_pos()
  721.        
  722.         pygame.draw.line(screen, red, self.midpoint,
  723.                          mousepos, 3 * self.laserPower)
  724.  
  725.         points = []
  726.         numpoints = 100
  727.  
  728.         for i in range(1, numpoints):
  729.             points.append((self.midpoint[0] + (mousepos[0] -
  730.                            self.midpoint[0]) * (i/numpoints),
  731.                            self.midpoint[1] + (mousepos[1] -
  732.                            self.midpoint[1]) * (i/numpoints)))
  733.  
  734.         return points
  735.  
  736. class BulletManager():
  737.     def __init__(self):
  738.         self.bullets = []
  739.  
  740.     def update(self, ship):
  741.         for bullet in self.bullets:
  742.             bullet.move()
  743.             bullet.draw()
  744.  
  745.             if ship.rect.colliderect(bullet.rect):
  746.                 self.remove(bullet)
  747.                 ship.remHP(bullet.damage)
  748.  
  749.             elif (bullet.x, bullet.y) == bullet.target:
  750.                 self.remove(bullet)
  751.  
  752.             if not SCREENRECT.colliderect(bullet.rect):
  753.                 self.remove(bullet)
  754.  
  755.     def add(self, bullet):
  756.         self.bullets.append(bullet)
  757.  
  758.     def remove(self, bullet):
  759.         self.bullets.remove(bullet)
  760.  
  761. class Bullet():
  762.     def __init__(self, startpoint, target,
  763.                  damage = 3, img = "Images/bullet.png", speed = 7):
  764.  
  765.         self.img = pygame.image.load(img).convert_alpha()
  766.         self.x = startpoint[0]
  767.         self.y = startpoint[1]
  768.         self.target = target
  769.         self.rect = ((self.x, self.y), self.img.get_size())
  770.         self.damage = damage
  771.         self.speed = speed
  772.  
  773.         self.xdist = (target[0] - self.x)
  774.         self.ydist = (target[1] - self.y)
  775.        
  776.         self.movesToTarget = math.ceil(math.sqrt(self.xdist ** 2 + self.ydist ** 2) / speed)
  777.  
  778.     def draw(self):
  779.         screen.blit(self.img, (self.x, self.y))
  780.  
  781.     def move(self):    
  782.         self.x += self.xdist / self.movesToTarget
  783.         self.y += self.ydist / self.movesToTarget
  784.         self.rect = ((self.x, self.y), self.img.get_size())
  785.  
  786.         if self.movesToTarget > 1:
  787.             self.movesToTarget -= 1
  788.        
  789. class Unit():
  790.     def __init__(self, HP):
  791.         self.HP = HP
  792.         self.HPBar = HPBar(HP, self)
  793.         self.rect = pygame.Rect((self.x, self.y), self.img.get_size())
  794.         self.fireRate = 100
  795.         self.explodes  = True
  796.         self.delete = False
  797.  
  798.     def remHP(self, loss):
  799.         self.HP -= loss
  800.         self.HPBar.updateHP(self.HP)
  801.  
  802.     def draw(self):
  803.         screen.blit(self.img, (self.x, self.y))
  804.  
  805.    
  806.     def move(self):
  807.         if self.x < 0 or self.x > WIDTH - self.img.get_width():
  808.             self.speed = -(self.speed)
  809.  
  810.             if self.img == self.rightimg:
  811.                 self.img = self.leftimg
  812.             else:
  813.                 self.img = self.rightimg
  814.        
  815.         self.x += self.speed
  816.         self.rect = pygame.Rect((self.x, self.y), self.img.get_size())
  817.         self.HPBar.move()
  818.         self.midpoint = (self.x + self.img.get_width() / 2,
  819.                          self.y + self.img.get_height() / 2)
  820.  
  821.     def fire(self, ship):
  822.         return Bullet(self.midpoint, ship.midpoint, self.damage)
  823.  
  824.  
  825. class Person(Unit):
  826.     def __init__(self, img = "Images/person.png", HP = 5):
  827.         self.img = pygame.image.load(img).convert_alpha()
  828.         self.x = random.randint(10, WIDTH)
  829.         self.y = HEIGHT - self.img.get_height()
  830.         self.speed = random.randint(-5, 5)
  831.        
  832.         if self.speed == 0:
  833.             self.moves = 0
  834.         elif not isNegative(self.speed):
  835.             self.moves = random.randint(1, math.floor(WIDTH / self.speed))
  836.         else:
  837.             self.moves = random.randint(1, math.floor(self.x / -self.speed))
  838.            
  839.         self.midpoint = (self.x + self.img.get_width() / 2,
  840.                          self.y + self.img.get_height() / 2)
  841.         self.shoots = False # Whether this mob can shoot
  842.         self.scrapValue = 1
  843.  
  844.         Unit.__init__(self, HP)
  845.         self.explodes = False
  846.  
  847.     def move(self):
  848.         if self.moves > 0:
  849.             self.x += self.speed
  850.             self.moves -= 1
  851.         else:
  852.             self.speed = -(self.speed)
  853.  
  854.             if self.speed == 0:
  855.                 self.moves = 0
  856.             elif not isNegative(self.speed):
  857.                 self.moves = random.randint(1, math.floor(WIDTH / self.speed))
  858.             else:
  859.                 self.moves = random.randint(1, math.floor(self.x / -self.speed))
  860.  
  861.         if self.x > WIDTH or self.x < -self.img.get_width():
  862.             self.delete = True
  863.  
  864.         self.rect = pygame.Rect((self.x, self.y), self.img.get_size())
  865.         self.HPBar.move()
  866.         self.midpoint = (self.x + self.img.get_width() / 2,
  867.                          self.y + self.img.get_height() / 2)
  868.  
  869. class Tank(Unit):
  870.     def __init__(self, img = "Images/tank.png", HP = 200, speed = 10):
  871.         self.rightimg = pygame.image.load(img).convert_alpha()
  872.         self.leftimg = pygame.transform.flip(self.rightimg, True, False)
  873.         self.img = self.leftimg
  874.         self.x = random.randint(self.img.get_width(),
  875.                                 WIDTH - self.img.get_width())
  876.         self.y = HEIGHT - self.img.get_height()
  877.         self.speed = speed
  878.         self.shoots = True # Whether this mob can shoot
  879.         self.scrapValue = 10
  880.         self.damage = 5
  881.         Unit.__init__(self, HP)
  882.  
  883. class Helicopter(Unit):
  884.     def __init__(self, img = "Images/helicopter.png", HP = 50, speed = 15):
  885.         self.rightimg = pygame.image.load(img).convert_alpha()
  886.         self.leftimg = pygame.transform.flip(self.rightimg, True, False)
  887.         self.img = self.leftimg
  888.         self.x = random.randint(self.img.get_width(),
  889.                                 WIDTH - self.img.get_width())
  890.         self.y = random.randint(0, int(HEIGHT - HEIGHT / 4))
  891.         self.speed = speed
  892.         self.shoots = True # Whether this mob can shoot
  893.         self.scrapValue = 7
  894.         self.damage = 4
  895.  
  896.         Unit.__init__(self, HP)
  897.  
  898. class StealthPlane(Unit):
  899.     def __init__(self, img = "Images/stealth plane.png", HP = 20):
  900.         leftimg = pygame.image.load(img).convert_alpha()
  901.         rightimg = pygame.transform.flip(leftimg, True, False)
  902.  
  903.         self.dir = random.choice(("left", "right"))
  904.         self.speed = random.randint(20, 30)
  905.  
  906.         if self.dir == "left":
  907.             self.img = leftimg
  908.             self.speed = -(self.speed)
  909.         else:
  910.             self.img = rightimg
  911.  
  912.         self.y = random.randint(0, HEIGHT / 4)
  913.  
  914.         if self.dir == "left":
  915.  
  916.             self.x = WIDTH
  917.         else:
  918.             self.x = -self.img.get_width()
  919.  
  920.         self.scrapValue = deNegate(self.speed) * 5
  921.         self.shoots = False
  922.         Unit.__init__(self, HP)
  923.  
  924.     def move(self):
  925.         self.x += self.speed
  926.         self.rect = pygame.Rect((self.x, self.y), self.img.get_size())
  927.         self.HPBar.move()
  928.  
  929.         if self.x > WIDTH and self.dir == "right":
  930.             self.delete = True
  931.         elif self.x < -self.img.get_width() and self.dir == "left":
  932.             self.delete = True
  933.  
  934. class Soldier(Person):
  935.     def __init__(self, img = "Images/soldier.png", HP = 8):
  936.         Person.__init__(self, img, HP)
  937.         self.shoots = True
  938.         self.scrapValue = 2
  939.         self.damage = 3
  940.         self.explodes = False
  941.  
  942. class Background():
  943.     def __init__(self, img):
  944.         self.img = pygame.image.load(img).convert()
  945.  
  946.         if self.img.get_size() != screen.get_size():
  947.             self.img = pygame.transform.scale(self.img, screen.get_size())
  948.  
  949.     def draw(self):
  950.         screen.blit(self.img, (0, 0))
  951.    
  952. def play(gm, sm, cursor):
  953.     bg = Background("Images/bg.png")
  954.     ship = Ship()
  955.  
  956.     um = UnitManager(sm)
  957.     bm = BulletManager()
  958.    
  959.     while True:
  960.         clock.tick(30)
  961.         bg.draw()
  962.         beam = ship.update()
  963.         ship.draw()
  964.  
  965.         um.update(beam, bm, ship, sm)
  966.         bm.update(ship)
  967.  
  968.         if ship.HP <= 0:
  969.             return ship.score
  970.  
  971.  
  972.         gm.drawHUD(ship)
  973.         cursor.draw()
  974.         pygame.display.update()
  975.  
  976.         if not pygame.key.get_focused():
  977.             pause()
  978.  
  979.         for event in pygame.event.get():
  980.             if event.type == pygame.QUIT:
  981.                 end()
  982.  
  983.             elif event.type == KEYDOWN:
  984.                 ship.respondToKey(event.key, True)
  985.  
  986.                 if event.key == K_ESCAPE:
  987.                     pause()
  988.             elif event.type == KEYUP:
  989.                 ship.respondToKey(event.key, False)
  990.             elif event.type == MOUSEBUTTONDOWN:
  991.                 ship.respondToMouse(True)
  992.                 sm.play("laserstart")
  993.             elif event.type == MOUSEBUTTONUP:
  994.                 ship.respondToMouse(False)
  995.                 sm.play("laserstop")
  996.  
  997. def main():
  998.     cursor = Cursor()
  999.     gm = GUIManager()
  1000.     sm = SoundManager()
  1001.     hsm = HighScoreManager()
  1002.     sm.loadSong("menu")
  1003.  
  1004.     while True:
  1005.         gm.menu(cursor, sm, hsm)
  1006.         sm.stopSong(1000)
  1007.         sm.loadSong("battle")
  1008.         score = play(gm, sm, cursor)
  1009.         sm.stopSong(2000)
  1010.        
  1011.         sm.loadSong("menu")
  1012.         if hsm.checkScore(score):
  1013.             hsm.addScore(gm.newHighScore(), score)
  1014.         else:
  1015.             gm.lose()
  1016.  
  1017. if __name__ == "__main__":
  1018.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement