# ***********************************************************************************
# SOURCE CREDITS
# ***********************************************************************************
# Author:  Alexandria Cornwall

# Modified source code with help from Michael "MaceMan" Casey, Student, University of Texas at Arlington

# Background art and several ammo shots made by Travis "Sivantis" Wright, Student, Granbury, TX

# Music: (Rocket, What You Want ver 2, Harmful or Fatal, Guiton Sketch, Killing Time, Kick Shock,
       # Phat Sketch, Der Kleber Sting, Danse Macabre - Big Hit 2) Kevin MacLeod (incompetech.com)

# Short music loop from Brian, Daniel Fryman's roommate, Baylor University

# boss1 graphics design: Daniel Fryman, Student, Baylor University

# ***********************************************************************************
# END OF SOURCE CREDITS
# ***********************************************************************************
# Title:              "Project Daemonia"
# Description:        A space-shooter type game with RPG elements.
# Date Created:       10/6/2009 at 9:29  PM
# Date Last Modified: 12/8/2009 at 10:38 PM


# ***UPDATES***
# Small blitting optimization.
# Changed win/loss sounds after levels to something more appropriate.
# Changed collision detection.  It should now be much more accurate. (Collision fix)

# ***KNOWN BUGS***
# player1 needs to be added to the group for all sprites.
# player1.ammo needs to be added to the group for all sprites.
# boss2RightClaw is "jittery" at the 0 ammoCooldown interval.

# -----------------------------------------------------------------------------------

# To-do List:

# Should shop costs be based on experience points instead?  (Don't decay on death)
    # If not, maybe health, shield, and damage modifier should be on an Exp system.

# &&& Optimize blitting with a dirtyRects list

# &&& Make menu borders and backgrounds look better.

# &&& Create game menu
    # Add levels

# &&& Simplify collision for speed increase

# &&& Remove array-like features of lists, and use full capabilities of list for
# &&& collision detection, etc.

# &&& Add FPS test.  If FPS < 55, ask user if they want to enable frame skipping
# &&& Probably a good idea to develop frame skipping first by:
# &&&     Creating a global called frameSkip
# &&&     Multiplying all movement and collision variables by frameSkip
# &&&     frameSkip = 0 is default, frameSkip = 1 skips one frame, frameSkip = 2 skips two, etc.
# &&& ** POSSIBLE ALTERNATIVE *** Make game based off of system time and not FPS

# &&& Add achievements

# &&& Allow player to save and resume game

# &&& Make game modular

# Game should play as follows:  [] indicate gameMode
# Main Menu[1]: *DONE*
    # Start New Game:
        # Enter Name[14]: *DONE*
            # Second Menu[2]:
# &&&                Classic[3]:
# &&&                    Continuous Levels with powerups(?)
                # Adventure[5]: (Should resume from where player left off)
                    # Next Level[4]
# &&&                    Level Select[6]
                    # Shop[7] (spend points here for upgrades, bonus levels, etc.)
# &&&                Endurance Mode[8]:
# &&&                    Only one level (enemies get harder, bosses may appear, no upgrades, start with best, see how far you get)
# &&&                    Only one life
# &&&                    Score indicated by time alive
# &&&                    Health and/or shield regeneration
# &&&                Achievements[9]:
# &&&                    (List achievements earned by player)
# &&&                    Return to Previous Menu (Second Menu)
# &&&                Show Hi-Scores[10]:
# &&&                    (List hi-scores for classic, adventure, and endurance mode)
# &&&                Options[11]:
# &&&                    Change appearance of player
# &&&                    Change resolution
# &&&                    Change frame skipping ***Possible alternative:  Make game run off system time and not fps
# &&&                Save Game[12]:
# &&&                    Select File Name
# &&&    Load Game[13]:
# &&&        Select File Name:
# &&&            If exist, go to second menu
# &&&            Else, loop.  Include key to go back to previous menu to prevent infinite loop
# -----------------------------------------------------------------------------------

# Extra Notes:
    # Esc key should be the global "go back a menu" key / in-game options menu

	
import sys, pygame, os, random, math, psyco
#from pygame.locals import *
from pygame import *
#from threading import Thread
psyco.full() #Runs psyco on everything for major speed-ups

#Define constants
MAX_ENEMIES = 2500 #The number of enemies + enemy ammo that can be on the screen at once
MAXIMUM_AMMO = 500 #If anything goes above this, the game will break.
GAME_NAME = "Project Daemonia"
MAX_FPS   = 60 #(Default 60)
FRAMESKIPPING = 0 #Increase frameskipping if you drop below 60 FPS. (0 FRAMESKIPPING = OFF)

#Define global variables
x = 800 #(Default 800)
y = 600 #(Default 600)
gameState = 1   #Start at the main menu
difficultyMultiplier = 1.0 #Increases/Decreases difficulty of game (Default = 1)
defaultMultiplier    = difficultyMultiplier #Keeps track of starting game difficulty
soundOn = True #Sound is turned on
pygame.init()
if not pygame.mixer:
    soundOn = False #Sound is disabled if mixer fails to initialize
font = pygame.font.Font('Images/freesansbold.ttf', 11)
fontBig = pygame.font.Font('Images/freesansbold.ttf', 18)

screen = pygame.display.set_mode((x,y))


#End of global variables

#Define classes
class Ammo(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #Magic word
        self.image = pygame.image.load("Images/Ammunition/missileDefault.png").convert_alpha()
        self.rect  = self.image.get_rect()
        self.rect.centerx = (x + 200)
        self.rect.centery = (y + 200)
        self.mask = pygame.mask.from_surface(self.image)

class CollisionBox(pygame.sprite.Sprite):
    def __init__(self, object):
        pygame.sprite.Sprite.__init__(self) #Magic word
        self.image = pygame.image.load("Images/Ship/shipCenterPixel.png").convert()
        self.rect  = self.image.get_rect()
        self.rect.centerx = object.rect.left + 15
        self.rect.centery = object.rect.top  + 24
        self.mask = pygame.mask.from_surface(self.image)
        self.mask.fill

    def update(self, object):
        self.rect.centerx = object.rect.left + 15 #14
        self.rect.centery = object.rect.top  + 24 #23
        
class Sounds: #Stores all sounds and music in the game.
    currentMusicType = "None" #Keeps track of the current type of music.
    musicCooldownRemaining = 0 #Keeps count of the cooldown between song-skipping/fading.
    musicCooldown = 20 #Sets the duration of song-skipping/fading.  Set to 0 to disable.
    songSkip = 0 #Keeps me from going insane.  Doesn't allow song repeating in random selection.
    
    def loadSounds(self): #If load times become too long, break this up into levels
                          #by using gameState and player1.currentAdventureLevel
        self.collision = pygame.mixer.Sound("Sounds/doomp.wav")
        self.levelLose = pygame.mixer.Sound("Sounds/failure.wav")
        self.levelWin  = pygame.mixer.Sound("Sounds/success.wav")
        self.ammoFireType1 = pygame.mixer.Sound("Sounds/drng.wav")
        return

    def playMusic(self): #Plays music files.
        musicType = "spaceLevels" #Default ("spaceLevels").  Helps prevent game from breaking.
        if soundOn == True: #Checks to make sure sound is enabled.
            #Part 1: Specify type of music to play based on gamestate and level (if applicable)
            if gameState == 1 or gameState == 14 or gameState == 15: #If in start menu or name select
                musicType = "gameIntro"
            elif gameState == 7: #If player is in the adventure shop
                musicType = "shop"
            elif gameState == 4 or gameState == 5 or gameState == 6: #If player is in any adventure mode menu
                if player1.currentAdventureLevel >= 1 and player1.currentAdventureLevel <= 4: #Levels 1-4
                    musicType = "spaceLevels"
                elif player1.currentAdventureLevel == 5: #boss1
                    musicType = "boss1"
                elif player1.currentAdventureLevel >= 6 and player1.currentAdventureLevel <= 9: #Levels 6-9
                    musicType = "spaceLevels"
                elif player1.currentAdventureLevel == 10: #boss2
                    musicType = "boss1"
            
            if not pygame.mixer.music.get_busy() or self.currentMusicType != musicType: #If wrong/no music file is playing.
                if self.musicCooldownRemaining <= 0: #These next few lines look really weird, but it has to be this way to fade correctly.
                    pygame.mixer.music.fadeout(100) #Time is in milliseconds
                    self.musicCooldownRemaining = self.musicCooldown
                if self.musicCooldownRemaining > 0:
                    self.musicCooldownRemaining -= 1
                if self.musicCooldownRemaining <= 0:
                    self.currentMusicType = musicType #Necessary for music type transitions.
                    if musicType == "spaceLevels":
                        selectRandom = random.randint(1, 4)
                        if selectRandom == 1:
                            pygame.mixer.music.load("Music/harmfulOrFatal.ogg")
                        elif selectRandom == 2:
                            pygame.mixer.music.load("Music/rocket.ogg")
                        elif selectRandom == 3:
                            pygame.mixer.music.load("Music/killingTime.ogg")
                        elif selectRandom == 4:
                            pygame.mixer.music.load("Music/kickShock.ogg")
                    elif musicType == "shop":
                        selectRandom = random.randint(1, 2)
                        if selectRandom == 1:
                            pygame.mixer.music.load("Music/guitonSketch.ogg")
                        elif selectRandom == 2:
                            pygame.mixer.music.load("Music/phatSketch.ogg")
                    elif musicType == "boss1":
                        pygame.mixer.music.load("Music/whatYouWantVer2.ogg")
                    elif musicType == "gameIntro":
                        pygame.mixer.music.load("Music/gameIntro.ogg")
                    pygame.mixer.music.play() #Plays music


class Enemy(pygame.sprite.Sprite):
    ammoCooldownRemaining = 0

    def __init__(self, idParent, idNumber = 0, health = 0, value = 0, model = "Images/defaultModel.png",
                 ammoCooldown = 0, damage = 0, modelRotation = 0, damageCooldown = 0, selfDamage = 500,
                 changeDifficulty = True):
        pygame.sprite.Sprite.__init__(self) #Magic word
        self.idParent     = idParent
        self.idNumber     = idNumber
        if changeDifficulty: self.health = health + int( 1.0 * health * (difficultyMultiplier - 1) * 0.65)
        else: self.health = health
        self.healthMax    = self.health
        self.value        = value  + int( 1.0 * value  * (difficultyMultiplier - defaultMultiplier) * 0.923)
        self.image        = pygame.transform.rotate(pygame.image.load(model).convert_alpha(), 180 + modelRotation)
        self.rect         = self.image.get_rect()
        self.mask = pygame.mask.from_surface(self.image)
        if self.idNumber < 10000: self.add(enemyGroup) #Adds sprite of self to enemyGroup if enemy
        elif self.idNumber >= 10000: self.add(enemyAmmoGroup) #Adds sprite to enemyAmmoGroup if enemy ammo
        self.add(all)        #Adds sprite of self to all
        self.ammoCooldown   = ammoCooldown
        self.damage         = damage + int( 1.0 * damage * (difficultyMultiplier - 1) * 0.65) #Damage that the enemy deals to the player on impact
        self.damageCooldown = damageCooldown #Cooldown between dealing damage to player
        self.damageCooldownRemaining = 0     #Keeps track of cooldown on damaging player
        self.selfDamage   = selfDamage + selfDamage * (difficultyMultiplier - 1) * 0.65 #Damage enemy does to itself on impact with player
        self.offset       = random.randint(-50, 50) #Offset must be included here for it to work properly
        return

    def delete(self):
        self.idNumber    = 0 #Deleted
        self.health      = 0
        self.value       = 0
        self.damage      = 0
        self.image = pygame.image.load("Images/defaultModel.png").convert_alpha()
        self.rect.centerx = (x + 100) #Off screen
        self.rect.centery = (y + 100) #Off screen
        self.kill() #Remove object from all sprite groups
        if enemy.count(self) > 0:
            enemy.remove(self)
        return

    def deleteAmmo(self, ammoTypeNumber):
        self.ammoType[ammoTypeNumber] = 0
        self.ammo.rect[ammoTypeNumber].centerx = x + 200
        self.ammo.rect[ammoTypeNumber].centery = x + 200
        return

class Player(pygame.sprite.Sprite):
    """A class to store all information about players"""
    global gameState
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #Magic word
        self.name = "Player"   #Default player name
        self.image = pygame.image.load("Images/Ship/shipCenterNew.png").convert_alpha()
        self.maxAmmo       = 13 #Higher numbers = more ammo          (Default 13)
        self.ammoCooldown  = 0  #Don't change this (Default = 0)
        self.ammoSpeed     = 6  #Lower numbers = faster rate of fire        (Default 6)
        self.ammoVelocity  = 4  #Higher numbers = faster projectile velocity       (Default 4)
        self.damageModifier = 10 #Higher numbers = ammo does more damage to enemy (Default 10)
        self.movementSpeed = 3  #Higher numbers = faster player movement (Default 3)
        self.healthMax     = 25 #Higher numbers = more survivability (Default 25)
        self.healthCurrent = self.healthMax #Same as healthMax (Default 25)
        self.shieldMax     = 4  #Higher numbers = longer lasting shield. 0 is off. (Default 4)
        self.shieldCurrent = self.shieldMax  #Same as shieldMax (Default 25)
        self.shieldRechargeCooldown = 120 #Lower recharge rates = less time needed for a recharge (Default 120)
        self.shieldRechargeRemaining = self.shieldRechargeCooldown
        self.totalDeaths   = 0  #Keeps track of the number of times the player has died.
        self.totalUpgrades = 0  #Keeps track of the number of upgrades purchased.
    
        self.rect = self.image.get_rect()
        self.rect.centerx = (x / 2) #Default x starting point of player.
        self.rect.centery = (y - y * .075) #Default y starting point of player.

        self.mask = pygame.mask.from_surface(self.image)

        self.collisionBox = CollisionBox(self)
        self.collisionBox.mask = pygame.mask.from_surface(pygame.image.load("Images/Ship/shipCenterPixel.png"))

        self.points = 0
        self.pointsString = "Score: " + str(self.points)
        self.pointsDisplay = font.render(self.pointsString, True, (80, 80, 80))
        self.pointsDisplayPos = self.pointsDisplay.get_rect()
        self.pointsDisplayPos.left = x - 139
        self.pointsDisplayPos.centery = 20

        self.currentClassicLevel = 1 #(Default 1)
        self.currentAdventureLevel = 1 #(Default 1)
        self.levelTime = 0 #Time since beginning of level.  Should be reset for each level.
        self.levelEndTime = 0 #Level ends at this time.
        self.defaultLevelVictory = 0
        self.bossIsDead = 0
        self.levelBackground = pygame.image.load("Images/Backgrounds/starLevel1to4.png").convert_alpha()
        
        self.levelCurrentDisplayString = "Level: " + str(self.currentAdventureLevel)
        self.levelCurrentDisplay = font.render(self.levelCurrentDisplayString, True, (80, 80, 80))
        self.levelCurrentDisplayPos = self.levelCurrentDisplay.get_rect()
        self.levelCurrentDisplayPos.left = x - 139
        self.levelCurrentDisplayPos.centery = 80

        self.levelTimeDisplayString = "Time Remaining: " + str(int((self.levelEndTime - self.levelTime)/60))
        self.levelTimeDisplay = font.render(self.levelTimeDisplayString, True, (80, 80, 80))
        self.levelTimeDisplayPos = self.levelTimeDisplay.get_rect()
        self.levelTimeDisplayPos.left = x - 139
        self.levelTimeDisplayPos.centery = 92
    
    ammoType = [0] * MAXIMUM_AMMO
    for i in range(0, MAXIMUM_AMMO, 1):
        ammoType[i] = 0
    
    ammo = [0] * MAXIMUM_AMMO
    for i in range(0, MAXIMUM_AMMO, 1):
        ammo[i] = Ammo()

    def movement(self, keyinput):
        shotFired = 0

        tempSpeed = self.movementSpeed

        if ((keyinput[K_LSHIFT] or keyinput[K_RSHIFT]) and not (keyinput[K_LCTRL] or keyinput[K_RCTRL])):
            tempSpeed *= 2

        if ((keyinput[K_LCTRL]  or keyinput[K_RCTRL])  and not (keyinput[K_LSHIFT] or keyinput[K_RSHIFT])):
            tempSpeed = 2
        
        if ((keyinput[K_a] and self.rect.centerx > 0) and not keyinput[K_d]):
            self.rect.centerx -= tempSpeed
            
        elif ((keyinput[K_d] and self.rect.centerx < x) and not keyinput[K_a]):
            self.rect.centerx += tempSpeed

        if ((keyinput[K_w] and self.rect.centery > 0) and not keyinput[K_s]):
            self.rect.centery -= tempSpeed

        elif ((keyinput[K_s] and self.rect.centery < y) and not keyinput[K_w]):
            self.rect.centery += tempSpeed

        self.collisionBox.update(self)
        
        if keyinput[K_i] and self.ammoCooldown <= 0:
            for i in range(0, self.maxAmmo, 1):
                if not self.ammoType[i] and not shotFired == 1:
                    fireAmmo(i, 1)
                    shotFired = 1
                    i = self.maxAmmo
        if keyinput[K_k] and self.ammoCooldown <= 0:
            for i in range(0, self.maxAmmo, 1):
                if not self.ammoType[i] and not shotFired == 2:
                    fireAmmo(i, 2)
                    shotFired = 2
                    i = self.maxAmmo
        if keyinput[K_j] and self.ammoCooldown <= 0:
            for i in range(0, self.maxAmmo, 1):
                if not self.ammoType[i] and not shotFired == 3:
                    fireAmmo(i, 3)
                    shotFired = 3
                    i = self.maxAmmo
        if keyinput[K_l] and self.ammoCooldown <= 0:
            for i in range(0, self.maxAmmo, 1):
                if not self.ammoType[i] and not shotFired == 4:
                    fireAmmo(i, 4)
                    shotFired = 4
                    i = self.maxAmmo
        if not shotFired == 0:
            self.ammoCooldown = self.ammoSpeed
            shotFired = 0
        if self.ammoCooldown > 0:
            self.ammoCooldown -= 1
        return

    def levelSetup(self): #Runs at start of level to prepare it
        global difficultyMultiplier
        self.levelTime = 0 #Sets beginning of level time
        self.healthCurrent = self.healthMax    #Heals player
        self.shieldCurrent = self.shieldMax    #Restores player's shield
        self.rect.centerx = (x / 2)        #Restores player's rect to default
        self.rect.centery = (y - y * .075) #Restores player's rect to default
        self.bossIsDead = 0
        self.shieldRechargeRemaining = self.shieldRechargeCooldown
        self.levelCurrentDisplayString = "Level: " + str(self.currentAdventureLevel)
        self.levelCurrentDisplay = font.render(self.levelCurrentDisplayString, True, (80, 80, 80))
        for i in enemy:     #Clears all enemies from game
            i.idNumber = 0
        for i in range(0, MAXIMUM_AMMO, 1):    #Clears all player ammo from game
            player1.ammoType[i] = 0
        if gameState == 4: #If in adventure mode
            if self.currentAdventureLevel == 1:
                createEnemies("scorpion", 2)
                if difficultyMultiplier >= 2:
                    createEnemies("wallStationaryRight", 5)
                    createEnemies("wallStationaryLeft", 5)
                self.levelEndTime = 1450
            elif self.currentAdventureLevel == 2:
                createEnemies("scorpion", 3)
                createEnemies("fighter",  2)
                if difficultyMultiplier >= 2:
                    createEnemies("fighter", 10)
                self.levelEndTime = 1550
            elif self.currentAdventureLevel == 3:
                createEnemies("scorpion", 5)
                createEnemies("fighter",  3)
                self.levelEndTime = 4200
            elif self.currentAdventureLevel == 4:
                createEnemies("scorpion", 10)
                createEnemies("fighter",  5)
                self.levelEndTime = 3000
            elif self.currentAdventureLevel == 5:
                createEnemies("boss1",   1)
                self.levelEndTime = 8000
            elif self.currentAdventureLevel == 6:
                createEnemies("fighter", 5)
                createEnemies("razor", 1)
                createEnemies("scorpion", 3)
                self.levelEndTime = 3730
            elif self.currentAdventureLevel == 7:
                createEnemies("fighter", 6)
                self.levelEndTime = 6000
            elif self.currentAdventureLevel == 8:
                createEnemies("wallHuggerRight", 10)
                createEnemies("wallHuggerLeft",  10)
                self.levelEndTime = 5000
            elif self.currentAdventureLevel == 9:
                createEnemies("fighter", 8)
                createEnemies("wallHuggerRight", 1)
                createEnemies("wallHuggerLeft",  1)
                createEnemies("scorpion", 3)
                createEnemies("razor", 2)
                self.levelEndTime = 6000
            elif self.currentAdventureLevel == 10:
                self.levelEndTime = 24000
            if self.currentAdventureLevel >= 1 and self.currentAdventureLevel <= 4:
                self.levelBackground = pygame.image.load("Images/Backgrounds/starLevel1to4.png").convert()
            elif self.currentAdventureLevel == 5:
                self.levelBackground = pygame.image.load("Images/Backgrounds/bossStarLevel.png").convert()
            elif self.currentAdventureLevel >= 6 and self.currentAdventureLevel <= 9:
                self.levelBackground = pygame.image.load("Images/Backgrounds/starLevel6to9.png").convert()
            elif self.currentAdventureLevel == 10:
                self.levelBackground = pygame.image.load("Images/Backgrounds/bossStarLevel2.png").convert()
            else: #If no more levels, reset to level 1
                self.currentAdventureLevel = 1
                difficultyMultiplier += 1
                self.levelSetup()
        return

    def levelUpdate(self): #Runs every frame to update level with new enemies, etc. (self.levelTime - timeFromStart)
                           #allows you to delay the start of spawning enemies until later into the level
        #createEnemiesQueue(time-timeFromStart, name, number, timeBetweenSpawns, numberOfSpawns(default=1)
        global difficultyMultiplier
        if gameState == 4: #Adventure Mode
            #if self.levelTime <= 2: #Just incase levelSetup doesn't catch it (this does happen on occassion)
            #    self.levelCurrentDisplayString = "Level: " + str(self.currentAdventureLevel)
            #    self.levelCurrentDisplay = font.render(self.levelCurrentDisplayString, True, (80, 80, 80))
            if self.currentAdventureLevel == 1:
                createEnemiesQueue(self.levelTime, "scorpion", 1, 42, 30)
            elif self.currentAdventureLevel == 2:
                createEnemiesQueue(self.levelTime, "scorpion", 1, 84, 15)
                createEnemiesQueue(self.levelTime, "fighter",  1, 110, 11)
                if difficultyMultiplier >= 2:
                    createEnemiesQueue(self.levelTime, "fighter", 1, 180, -1)
            elif self.currentAdventureLevel == 3:
                createEnemiesQueue(self.levelTime, "scorpion",   1, 60, 30)
                createEnemiesQueue(self.levelTime, "fighter",    2, 80, 45)
                createEnemiesQueue(self.levelTime-1800, "razor", 1, 42, 43)
            elif self.currentAdventureLevel == 4:
                createEnemiesQueue(self.levelTime, "scorpion",     1, 50, 39)
                createEnemiesQueue(self.levelTime, "razor",        1, 124, -1)
                createEnemiesQueue(self.levelTime-360, "fighter",  2, 75, -1)
                createEnemiesQueue(self.levelTime-1200, "fighter", 1, 80, -1)
                createEnemiesQueue(self.levelTime-1800, "fighter", 1, 120, -1)
                createEnemiesQueue(self.levelTime-2400, "fighter", 1, 160, -1)
                createEnemiesQueue(self.levelTime-2700, "razor",   1, 20,  -1)
            elif self.currentAdventureLevel == 5:
                if difficultyMultiplier >= 2:
                    createEnemiesQueue(self.levelTime-1200, "wallStationaryRight", 1, 360, -1)
                    createEnemiesQueue(self.levelTime-1380, "wallStationaryLeft", 1, 360, -1)
                if self.bossIsDead >= 120: #If boss has been dead for 120 frames
                    self.defaultLevelVictory = 1
                    self.bossIsDead = 0
                else:
                    self.bossIsDead += 1
            elif self.currentAdventureLevel == 6:
                createEnemiesQueue(self.levelTime, "fighter", 5, 300, -1)
                createEnemiesQueue(self.levelTime, "scorpion", 1, 100, -1)
                createEnemiesQueue(self.levelTime, "fighter", 3, 240, -1)
                createEnemiesQueue(self.levelTime-180, "razor", 1, 200, -1)
                createEnemiesQueue(self.levelTime-1000, "wallHuggerRight", 1, 300, -1)
                if difficultyMultiplier >= 2:
                    createEnemiesQueue(self.levelTime-1500, "wallStationaryRight", 1, 720, -1)
                    createEnemiesQueue(self.levelTime-1860, "wallStationaryLeft",  1, 720, -1)
                createEnemiesQueue(self.levelTime-2000, "scorpion", 180, 1, 1)
                createEnemiesQueue(self.levelTime-3500, "fighter", 1, 150, -1)
                createEnemiesQueue(self.levelTime-3500, "fighter", 1, 5, -1)
                createEnemiesQueue(self.levelTime-3500, "wallHuggerRight", 1, 7, -1)
                createEnemiesQueue(self.levelTime-3500, "wallHuggerLeft",  1, 7, -1)
            elif self.currentAdventureLevel == 7:
                createEnemiesQueue(self.levelTime, "fighter",   1, 150, -1)
                createEnemiesQueue(self.levelTime, "scorpion",  1, 10 + int(self.levelTime/30), -1) #Fades enemies out over time
                createEnemiesQueue(self.levelTime, "razor", 1, 120, -1)
                createEnemiesQueue(self.levelTime, "wallHuggerRight", 1, 260, -1)
                createEnemiesQueue(self.levelTime, "fighter", 1, 240, -1)
                createEnemiesQueue(self.levelTime, "wallHuggerLeft", 1, 260, -1)
            elif self.currentAdventureLevel == 8:
                createEnemiesQueue(self.levelTime, "wallHuggerRight", 1, 360, -1)
                createEnemiesQueue(self.levelTime, "wallHuggerLeft",  1, 360, -1)
                createEnemiesQueue(self.levelTime, "scorpion", 1, 60, -1)
                createEnemiesQueue(self.levelTime, "fighter", 1, 120, -1)
                createEnemiesQueue(self.levelTime-3600, "wallHuggerRight", 1, 360, -1)
                createEnemiesQueue(self.levelTime-3600, "wallHuggerLeft",  1, 360, -1)
            elif self.currentAdventureLevel == 9:
                createEnemiesQueue(self.levelTime, "fighter", 1, 330, -1)
                createEnemiesQueue(self.levelTime, "scorpion", 1, 180, 10)
                createEnemiesQueue(self.levelTime, "wallHuggerRight", 1, 520, -1)
                createEnemiesQueue(self.levelTime, "wallHuggerLeft", 1, 520, -1)
                createEnemiesQueue(self.levelTime, "wallHuggerRight", 1000 - int((self.levelTime-1500)/10), -1)
                createEnemiesQueue(self.levelTime, "wallHuggerLeft", 1000 - int((self.levelTime-1500)/10), -1)
                createEnemiesQueue(self.levelTime, "fighter", 1, 240, -1)
                createEnemiesQueue(self.levelTime, "fighter", 1, 240, -1)
                createEnemiesQueue(self.levelTime, "fighter", 1, 80,  -1)
            elif self.currentAdventureLevel == 10:
                #createEnemiesQueue(self.levelTime, "fighter", 3, 100, 10)
                #createEnemiesQueue(self.levelTime, "scorpion", 1, 50, 20)
                createEnemiesQueue(self.levelTime, "boss2Head", 1, 1, 1)
                createEnemiesQueue(self.levelTime, "boss2RightClaw", 1, 1, 1)
                createEnemiesQueue(self.levelTime, "boss2LeftClaw",  1, 1, 1)
                createEnemiesQueue(self.levelTime, "wallStationaryRight", 1, 360, -1)
                createEnemiesQueue(self.levelTime-180, "wallStationaryLeft", 1, 360, -1)
                if self.bossIsDead >= 120: #If boss has been dead for 120 frames
                    self.defaultLevelVictory = 1
                    self.bossIsDead = 0
                else:
                    self.bossIsDead += 1
            #levelUpdate does not require an else statement.  Don't add one.
        return

    def levelVictory(self): #Checks to see if level has ended
        global gameState
        victory = 0
        if gameState == 4: #Adventure Mode
            if self.currentAdventureLevel == 1: #Level
                if self.levelTime > self.levelEndTime: #Victory Conditions
                    playSound(sounds.levelWin)
                    victory = 1
                    self.currentAdventureLevel += 1 #Allow player to go to next level
                    gameState = 5 #Return to adventure main menu
            elif self.currentAdventureLevel == 2: #Level
                if self.levelTime > self.levelEndTime:
                    playSound(sounds.levelWin)
                    victory = 1
                    self.currentAdventureLevel += 1 #Allow player to go to next level
                    gameState = 5 #Return to adventure main menu
            elif self.currentAdventureLevel == 3: #Level
                if self.levelTime > self.levelEndTime:
                    playSound(sounds.levelWin)
                    victory = 1
                    self.currentAdventureLevel += 1 #Allow player to go to next level
                    gameState = 5 #Return to adventure main menu
            elif self.currentAdventureLevel == 4: #Level
                if self.levelTime > self.levelEndTime:
                    playSound(sounds.levelWin)
                    victory = 1
                    self.currentAdventureLevel += 1 #Allow player to go to next level
                    gameState = 5 #Return to adventure main menu
            elif self.currentAdventureLevel == 5:
                if  self.levelTime > self.levelEndTime:
                    playSound(sounds.levelWin)
                    victory = 1
                    self.currentAdventureLevel += 1 #Allow player to go to next level
                    gameState = 5 #Return to adventure main menu
            elif self.currentAdventureLevel == 6:
                if self.levelTime > self.levelEndTime:
                    playSound(sounds.levelWin)
                    victory = 1
                    self.currentAdventureLevel += 1 #Allow player to go to next level
                    gameState = 5 #Return to adventure main menu
            elif self.currentAdventureLevel == 7:
                if self.levelTime > self.levelEndTime:
                    playSound(sounds.levelWin)
                    victory = 1
                    self.currentAdventureLevel += 1 #Allow player to go to next level
                    gameState = 5 #Return to adventure main menu
            elif self.currentAdventureLevel == 8:
                if self.levelTime > self.levelEndTime:
                    playSound(sounds.levelWin)
                    victory = 1
                    self.currentAdventureLevel += 1 #Allow player to go to next level
                    gameState = 5 #Return to adventure main menu
            elif self.currentAdventureLevel == 9:
                if self.levelTime > self.levelEndTime:
                    playSound(sounds.levelWin)
                    victory = 1
                    self.currentAdventureLevel += 1 #Allow player to go to next level
                    gameState = 5 #Return to adventure main menu
            if self.defaultLevelVictory == 1:
                playSound(sounds.levelWin)
                self.defaultLevelVictory = 0
                victory = 1
                self.currentAdventureLevel += 1
                gameState = 5
            #levelVictory does not require an else statement.  Don't add one.
            if player1.healthCurrent <= 0: #If player dies, return to adventure menu and do not go to next level.
                playSound(sounds.levelLose)
                victory = 1
                player1.points = int(player1.points/1.05) #If player dies, score is lowered a bit.
                self.totalDeaths += 1
                gameState = 5
        return victory
#End define classes

#---------------------------------------------------------------------------------------------------------------
def keyPressed(keyinput): #Differences between event.key and keyinput:  If you want keys to repeat an event when
                          #held down, use keyinput.  If you want a key to only activate an event once per key press,
                          #then use event.key and clear with pygame.event.clear() when you're finished with checking
                          #that key press.


    global gameState, difficultyMultiplier, defaultMultiplier
    
    if pygame.event.get(pygame.QUIT) or (keyinput[K_LALT] or keyinput[K_RALT]) and keyinput[K_F4]: #Checks for closing game
        gameState = 0
        closeGame() 
    
    if gameState == 1:
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                if event.key == K_s or event.key == K_RETURN: gameState = 15 #Start new game
                #elif event.key == K_l: gameState = 13 #Load game
        pygame.event.clear()
        return 0
    
    elif gameState == 2:
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                #if event.key == K_c:   gameState = 3 #Classic Mode
                if event.key == K_a or event.key == K_RETURN: gameState = 5 #Adventure Mode
                #elif event.key == K_e: gameState = 8 #Endurance Mode
                #elif event.key == K_l: gameState = 9 #Load Game
                #elif event.key == K_h: gameState = 10 #Highscores
                #elif event.key == K_o: gameState = 11 #Options
                #elif event.key == K_s: gameState = 12 #Save Game
        pygame.event.clear()
        return 0
    
    elif gameState == 4:
        player1.movement(keyinput)
        return

    elif gameState == 5:
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                if   event.key == K_ESCAPE: gameState = 2 #Return to previous menu
                elif event.key == K_n or event.key == K_RETURN: gameState = 4 #Next Level
                #elif event.key == K_l: gameState = 6 #Level Select
                elif event.key == K_b: gameState = 7 #Shop
        pygame.event.clear()
        return 0

    elif gameState == 7:
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                if   event.key == K_ESCAPE: gameState = 5 #Return to previous menu
                elif player1.points >= (player1.totalUpgrades + 1) * 500:
                    if event.key == K_a:
                        player1.maxAmmo += 3 #maxAmmo increase
                        player1.points -= (player1.totalUpgrades + 1) * 500
                        player1.totalUpgrades += 1
                    elif event.key == K_r and player1.ammoSpeed > 0:
                        player1.ammoSpeed -= 1 #ammoSpeed increase
                        player1.points -= (player1.totalUpgrades + 1) * 500
                        player1.totalUpgrades += 1
                    elif event.key == K_v and player1.ammoVelocity < 8:
                        player1.ammoVelocity   += 1 #ammoVelocity increase
                        player1.points -= (player1.totalUpgrades + 1) * 500
                        player1.totalUpgrades += 1
                    elif event.key == K_d:
                        player1.damageModifier += 2 #damageModifier increase
                        player1.points -= (player1.totalUpgrades + 1) * 500
                        player1.totalUpgrades += 1
                    elif event.key == K_h: #HP max increase
                        player1.healthMax += 5
                        player1.healthCurrent = player1.healthMax
                        player1.points -= (player1.totalUpgrades + 1) * 500
                        player1.totalUpgrades += 1
                    elif event.key == K_s: #Shield max increase
                        player1.shieldMax += 2
                        player1.shieldCurrent = player1.shieldMax
                        player1.points -= (player1.totalUpgrades + 1) * 500
                        player1.totalUpgrades += 1
        pygame.event.clear()
        return 0
    
    elif gameState == 14:
        if keyinput[K_BACKSPACE]:
            player1.name = player1.name[:-1]
            pygame.time.delay(160) #Think of a better way to implement this.  It works fine, but it's not 100% like I want it.
        for event in pygame.event.get():
            if event.type == KEYDOWN: #Enter player name
                if event.key == K_1: player1.name += '1'
                elif event.key == K_2: player1.name += '2'
                elif event.key == K_3: player1.name += '3'
                elif event.key == K_4: player1.name += '4'
                elif event.key == K_5: player1.name += '5'
                elif event.key == K_6: player1.name += '6'
                elif event.key == K_7: player1.name += '7'
                elif event.key == K_8: player1.name += '8'
                elif event.key == K_9: player1.name += '9'
                elif event.key == K_0: player1.name += '0'
                elif event.key == K_SPACE: player1.name += ' '
                if not keyinput[K_LSHIFT] and not keyinput[K_RSHIFT]:
                    if   event.key == K_a: player1.name += 'a'
                    elif event.key == K_b: player1.name += 'b'
                    elif event.key == K_c: player1.name += 'c'
                    elif event.key == K_d: player1.name += 'd'
                    elif event.key == K_e: player1.name += 'e'
                    elif event.key == K_f: player1.name += 'f'
                    elif event.key == K_g: player1.name += 'g'
                    elif event.key == K_h: player1.name += 'h'
                    elif event.key == K_i: player1.name += 'i'
                    elif event.key == K_j: player1.name += 'j'
                    elif event.key == K_k: player1.name += 'k'
                    elif event.key == K_l: player1.name += 'l'
                    elif event.key == K_m: player1.name += 'm'
                    elif event.key == K_n: player1.name += 'n'
                    elif event.key == K_o: player1.name += 'o'
                    elif event.key == K_p: player1.name += 'p'
                    elif event.key == K_q: player1.name += 'q'
                    elif event.key == K_r: player1.name += 'r'
                    elif event.key == K_s: player1.name += 's'
                    elif event.key == K_t: player1.name += 't'
                    elif event.key == K_u: player1.name += 'u'
                    elif event.key == K_v: player1.name += 'v'
                    elif event.key == K_w: player1.name += 'w'
                    elif event.key == K_x: player1.name += 'x'
                    elif event.key == K_y: player1.name += 'y'
                    elif event.key == K_z: player1.name += 'z'
                elif keyinput[K_LSHIFT] or keyinput[K_RSHIFT]:
                    if   event.key == K_a: player1.name += 'A'
                    elif event.key == K_b: player1.name += 'B'
                    elif event.key == K_c: player1.name += 'C'
                    elif event.key == K_d: player1.name += 'D'
                    elif event.key == K_e: player1.name += 'E'
                    elif event.key == K_f: player1.name += 'F'
                    elif event.key == K_g: player1.name += 'H'
                    elif event.key == K_h: player1.name += 'H'
                    elif event.key == K_i: player1.name += 'I'
                    elif event.key == K_j: player1.name += 'J'
                    elif event.key == K_k: player1.name += 'K'
                    elif event.key == K_l: player1.name += 'L'
                    elif event.key == K_m: player1.name += 'M'
                    elif event.key == K_n: player1.name += 'N'
                    elif event.key == K_o: player1.name += 'O'
                    elif event.key == K_p: player1.name += 'P'
                    elif event.key == K_q: player1.name += 'Q'
                    elif event.key == K_r: player1.name += 'R'
                    elif event.key == K_s: player1.name += 'S'
                    elif event.key == K_t: player1.name += 'T'
                    elif event.key == K_u: player1.name += 'U'
                    elif event.key == K_v: player1.name += 'V'
                    elif event.key == K_w: player1.name += 'W'
                    elif event.key == K_x: player1.name += 'X'
                    elif event.key == K_y: player1.name += 'Y'
                    elif event.key == K_z: player1.name += 'Z'
                if event.key == K_RETURN: gameState = 2
        
            pygame.event.clear()
        return player1.name

    elif gameState == 15:
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                if event.key == K_1:                          #Easy Mode
                    difficultyMultiplier = 0.5
                    gameState = 14                            #Start new game
                if event.key == K_2 or event.key == K_RETURN: #Normal Mode
                    difficultyMultiplier = 1.0
                    gameState = 14 #Start new game
                if event.key == K_3:                          #Hard Mode
                    difficultyMultiplier = 2.0
                    gameState = 14 #Start new game
                if event.key == K_4:                          #insane Mode
                    difficultyMultiplier = 3.0
                    gameState = 14 #Start new game
                    
            defaultMultiplier = difficultyMultiplier #Set difficulty to default difficulty
        pygame.event.clear()
        return 0
    
#---------------------------------------------------------------------------------------------------------------
def fireAmmo(ammoNumber, ammoType): #Modify player ammo direction and set rect of ammo
    player1.ammoType[ammoNumber] = ammoType
    if player1.ammoType[ammoNumber] > 0 and player1.ammoType[ammoNumber] <= 4:
        if player1.ammoType[ammoNumber] == 1:
             player1.ammo[ammoNumber].image = pygame.image.load("Images/Ammunition/missileDefault.png").convert_alpha() #Up
        elif player1.ammoType[ammoNumber] == 2:
             player1.ammo[ammoNumber].image = pygame.transform.rotate(pygame.image.load("Images/Ammunition/missileDefault.png").convert_alpha(), 180) #Down
        elif player1.ammoType[ammoNumber] == 3:
             player1.ammo[ammoNumber].image = pygame.transform.rotate(pygame.image.load("Images/Ammunition/missileDefault.png").convert_alpha(), 90) #Right
        elif player1.ammoType[ammoNumber] == 4:
             player1.ammo[ammoNumber].image = pygame.transform.rotate(pygame.image.load("Images/Ammunition/missileDefault.png").convert_alpha(), -90) #Left
        player1.ammo[ammoNumber].rect = player1.ammo[ammoNumber].image.get_rect()
        player1.ammo[ammoNumber].rect.centerx = player1.rect.centerx
        player1.ammo[ammoNumber].rect.centery = player1.rect.centery
        #sounds.ammoFireType1.play()

#---------------------------------------------------------------------------------------------------------------
def playerBoundary(object): #Checks if out of bounds and sets to boundary point
    outOfBounds = False
    if object.centerx < 0:
        object.centerx = 0
        outOfBounds = True
    elif object.centerx > x:
        object.centerx = x
        outOfBounds = True
    if object == player1:
        if object.centery < 4:
            object.centery = 4
            outOfBounds = True
        elif object.centery > y:
            object.centery = y
            outOfBounds = True
    else:
        if object.centery < 0:
            object.centery = 0
            outOfBounds = True
        elif object.centery > y:
            object.centery = y
            outOfBounds = True
    return outOfBounds

#---------------------------------------------------------------------------------------------------------------
def playSound(object, numberOfTimes=0): #Checks if sound is enabled.  If yes, then plays sound
    if soundOn:
        object.play(numberOfTimes)
    return

#---------------------------------------------------------------------------------------------------------------
def playerAmmoMove():
    #Fire the ammo
    global x, y
    for i in range(0, player1.maxAmmo, 1):
        if player1.ammoType[i]:
            if player1.ammoType[i] == 1:
                player1.ammo[i].rect.centery -= 2 * player1.ammoVelocity
            elif player1.ammoType[i] == 2:
                player1.ammo[i].rect.centery += 2 * player1.ammoVelocity
            elif player1.ammoType[i] == 3:
                player1.ammo[i].rect.centerx -= 2 * player1.ammoVelocity
            elif player1.ammoType[i] == 4:
                player1.ammo[i].rect.centerx += 2 * player1.ammoVelocity
                
    #Reset the ammo if out of boundaries
    for i in range(0, player1.maxAmmo, 1):
        if player1.ammoType[i]:
            if player1.ammo[i].rect.centery < 0 or player1.ammo[i].rect.centery > y:
                player1.ammoType[i] = 0
            if player1.ammo[i].rect.centerx < 0 or player1.ammo[i].rect.centerx > x:
                player1.ammoType[i] = 0

#---------------------------------------------------------------------------------------------------------------
def enemyMove(): #This is where enemies get their "AI"
    global x, y
    enemiesRemaining = 0
    listCount = -1 #Counts the current index of the list
    for i in enemy:
        listCount += 1 #Increments listCount by 1 for each iteration of the loop
        if i.idNumber: #i is the index of enemy. So this loop will go through all of the stored values in enemy
            if i.idNumber < 10000: #If enemy and not ammo
                enemiesRemaining += 1
            differenceX = i.rect.centerx - player1.rect.centerx #Pos = to the right / Neg = to the left
            differenceY = i.rect.centery - player1.rect.centery #Pos = below player / Neg = above player
            
            #ID 1 (Scorpion)
            if i.idNumber == 1: #Attempts to crash into the player.
                #Move
                i.rect.centery += 3
                if i.rect.centerx > (player1.rect.centerx + 1):
                    i.rect.centerx -= 2
                elif i.rect.centerx < (player1.rect.centerx - 1):
                    i.rect.centerx += 2
                if  i.rect.centery >= y: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
                else:
                    i.rect.centery += 1
                    
            #ID 2 (Fighter)
            elif i.idNumber == 2: #Attempts to avoid direct contact with player.  Attacks diagonally.
                #Move
                differenceX += i.offset
                differenceY += i.offset
                if differenceX > 0:
                    if abs(differenceX) < abs(differenceY):
                        i.rect.centerx += 1
                    elif abs(differenceX) > abs(differenceY):
                        i.rect.centerx -= 1
                elif differenceX <= 0:
                    if abs(differenceX) < abs(differenceY):
                        i.rect.centerx -= 1
                    elif abs(differenceX) > abs(differenceY):
                        i.rect.centerx += 1
                if differenceX != differenceY and i.rect.centerx < x/4 or i.rect.centerx > x - x/4: #Moves towards player if needed
                    if differenceY + 50 < 0:
                        i.rect.centery += 1
                    elif differenceY - 50 > 0:
                        i.rect.centery -= 1
                #Fire ammo
                if differenceX < 0 and differenceY > 0 and  i.ammoCooldownRemaining <= 0:
                    createEnemiesAmmo("fighterAmmo1", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                if differenceX < 0 and differenceY < 0 and  i.ammoCooldownRemaining <= 0:
                    createEnemiesAmmo("fighterAmmo2", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                if differenceX > 0 and differenceY < 0 and  i.ammoCooldownRemaining <= 0:
                    createEnemiesAmmo("fighterAmmo3", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                if differenceX > 0 and differenceY > 0 and  i.ammoCooldownRemaining <= 0:
                    createEnemiesAmmo("fighterAmmo4", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif i.ammoCooldownRemaining > 0:
                    i.ammoCooldownRemaining -= 1
            #ID 3 (Razor)
            elif i.idNumber == 3: #Charges player from sides until close, then goes for head-on collision.
                #Move
                if differenceY < -110 and (differenceX > 20 or (differenceX > -20 and differenceX < 0)):
                    i.rect.centerx -= 1
                    i.rect.centery += 8
                elif differenceY < -110 and (differenceX < -20 or (differenceX < 20 and differenceX >=0)):
                    i.rect.centerx += 1
                    i.rect.centery += 8
                elif differenceY >= -110 and differenceY < 90 and differenceX >= 5:
                    i.rect.centerx -= 5
                    i.rect.centery += 5
                elif differenceY >= -110 and differenceY < 90 and differenceX <= -5:
                    i.rect.centerx += 5
                    i.rect.centery += 5
                elif differenceY >= -110 and differenceY < 90 and differenceX > 0 and differenceX < 5:
                    i.rect.centerx = player1.rect.centerx
                    i.rect.centery += 5
                elif differenceY >= -110 and differenceY < 90 and differenceX < 0 and differenceX > -5:
                    i.rect.centerx = player1.rect.centerx
                    i.rect.centery += 5
                else:
                    i.rect.centery += 11
                if  i.rect.centery >= y: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 4 (wallHuggerRight)
            elif i.idNumber == 4: #"Hugs" right wall and shoots up and left, left, and down and left towards the player.
                #Move
                differenceY += i.offset
                if abs(differenceY) < (abs(differenceX) * math.tan(22.5)): #If player is closest to middle of enemy
                    if differenceY > 1:
                        i.rect.centery -= 2 #Move towards player
                    elif differenceY < -1:
                        i.rect.centery += 2 #Move towards player
                    elif abs(differenceY) <= 1:
                        i.rect.centery = player1.rect.centery - i.offset
                elif differenceX > differenceY and differenceY > 0:
                    if differenceX > differenceY + 2:
                        i.rect.centery += 2
                    else:
                        i.rect.centery = player1.rect.centery + differenceY - i.offset
                elif differenceY > differenceX and differenceY > 0:
                    if differenceY > differenceX + 2:
                        i.rect.centery -= 2
                    else:
                        i.rect.centery = player1.rect.centery + differenceY - i.offset
                elif differenceX > abs(differenceY) and differenceY < 0:
                    if differenceX > abs(differenceY) + 2:
                        i.rect.centery -= 2
                    else:
                        i.rect.centery = player1.rect.centery + differenceY - i.offset
                elif abs(differenceY) > differenceX and differenceY < 0:
                    if abs(differenceY) > differenceX + 2:
                        i.rect.centery += 2
                    else:
                        i.rect.centery = player1.rect.centery + differenceY - i.offset
                #Fire Ammo
                if abs(differenceY) < (abs(differenceX) * math.tan(22.5)) and i.ammoCooldownRemaining <= 0: #If closest to middle
                    createEnemiesAmmo("wallHuggerRight2", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif differenceY > 0 and i.ammoCooldownRemaining <= 0 or i.rect.centery > y - 5 and i.ammoCooldownRemaining <= 0:
                    #If closest to "up and left" shot
                    createEnemiesAmmo("wallHuggerRight1", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif differenceY < 0 and i.ammoCooldownRemaining <= 0 or i.rect.centery < 5 and i.ammoCooldownRemaining <= 0:
                    #If closest to "down and left" shot
                    createEnemiesAmmo("wallHuggerRight3", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif i.ammoCooldownRemaining > 0:
                    i.ammoCooldownRemaining -= 1
            #ID 5 (wallHuggerLeft)
            elif i.idNumber == 5: #"Hugs" left wall and shoots up and right, right, and down and right towards the player.
                #Move
                differenceY += i.offset
                differenceX *= -1
                if abs(differenceY) < (abs(differenceX) * math.tan(22.5)): #If player is closest to middle of enemy
                    if differenceY > 1:
                        i.rect.centery -= 2 #Move towards player
                    elif differenceY < -1:
                        i.rect.centery += 2 #Move towards player
                    elif abs(differenceY) <= 1:
                        i.rect.centery = player1.rect.centery - i.offset
                elif differenceX > differenceY and differenceY > 0:
                    if differenceX > differenceY + 2:
                        i.rect.centery += 2
                    else:
                        i.rect.centery = player1.rect.centery + differenceY - i.offset
                elif differenceY > differenceX and differenceY > 0:
                    if differenceY > differenceX + 2:
                        i.rect.centery -= 2
                    else:
                        i.rect.centery = player1.rect.centery + differenceY - i.offset
                elif differenceX > abs(differenceY) and differenceY < 0:
                    if differenceX > abs(differenceY) + 2:
                        i.rect.centery -= 2
                    else:
                        i.rect.centery = player1.rect.centery + differenceY - i.offset
                elif abs(differenceY) > differenceX and differenceY < 0:
                    if abs(differenceY) > differenceX + 2:
                        i.rect.centery += 2
                    else:
                        i.rect.centery = player1.rect.centery + differenceY - i.offset
                #Fire Ammo
                if abs(differenceY) < (abs(differenceX) * math.tan(22.5)) and i.ammoCooldownRemaining <= 0: #If closest to middle
                    createEnemiesAmmo("wallHuggerLeft2", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif differenceY > 0 and i.ammoCooldownRemaining <= 0 or i.rect.centery > y - 5 and i.ammoCooldownRemaining <= 0:
                    #If closest to "up and left" shot
                    createEnemiesAmmo("wallHuggerLeft1", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif differenceY < 0 and i.ammoCooldownRemaining <= 0 or i.rect.centery < 5 and i.ammoCooldownRemaining <= 0:
                    #If closest to "down and left" shot
                    createEnemiesAmmo("wallHuggerLeft3", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif i.ammoCooldownRemaining > 0:
                    i.ammoCooldownRemaining -= 1
            #ID 6 (boss1)
            elif i.idNumber == 6: #boss1 does not move
                #Fire Ammo
                if (i.ammoCooldownRemaining) == 0:
                    createEnemiesAmmo("boss1Down", 1, i)
                if (player1.levelTime % 200) == 0 and player1.levelTime > 400:
                    createEnemiesAmmo("boss1StartCharge", 1, i)
                if i.ammoCooldownRemaining <= 0:
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif i.ammoCooldownRemaining > 0:
                    i.ammoCooldownRemaining -= 1
                if gameState == 4 and player1.currentAdventureLevel == 5:
                    player1.bossIsDead = 0
                if i.health < i.healthMax * 0.50 and i.health > i.healthMax * 0.25 and i.ammoCooldown >= 25:
                    i.ammoCooldown = 20
                    i.image = pygame.image.load("Images/Enemies/boss1Yellow.png").convert_alpha()
                elif i.health <= i.healthMax * 0.25 and i.ammoCooldown >= 20:
                    i.ammoCooldown = 15
                    i.image = pygame.image.load("Images/Enemies/boss1Red.png").convert_alpha()
            #ID 7 (boss2Head)
            elif i.idNumber == 7:
                if player1.levelTime % 600 == 0:
                    createEnemiesAmmo("boss2StartCharge", 1, i)
                if gameState == 4 and player1.currentAdventureLevel == 10:
                    player1.bossIsDead = 0
            #ID 8 (boss2RightClaw)
            elif i.idNumber == 8:
                #Move
                if (i.ammoCooldownRemaining % 180 < 70) and i.ammoCooldownRemaining >= 180 and not i.ammoCooldownRemaining == 540: #boss2RightClaw attacks every 3 seconds
                    if i.ammoCooldownRemaining < 180 or i.ammoCooldownRemaining >= 360:
                        if differenceX >= 0 + 3:
                            i.rect.centerx -= 3
                        elif differenceX <= 0 - 3:
                            i.rect.centerx += 3
                        elif abs(differenceX) < 3:
                            i.rect.centerx = player1.rect.centerx
                        if differenceY >= 0 + 3:
                            i.rect.centery -= 3
                        elif differenceY <= 0 - 3:
                            i.rect.centery += 3
                        elif abs(differenceY) < 3:
                            i.rect.centery = player1.rect.centery
                    elif i.ammoCooldownRemaining >= 180 and i.ammoCooldownRemaining < 360:
                        if differenceX >= 0 + 2:
                            i.rect.centerx -= 2
                        elif differenceX <= 0 - 2:
                            i.rect.centerx += 2
                        elif abs(differenceX) < 2:
                            i.rect.centerx = player1.rect.centerx
                        if differenceY >= 0 + 2:
                            i.rect.centery -= 2
                        elif differenceY <= 0 - 2:
                            i.rect.centery += 2
                        elif abs(differenceY) < 2:
                            i.rect.centery = player1.rect.centery
                elif (i.ammoCooldownRemaining % 180 >= 70): #boss2RightClaw resets to default position here
                    if i.rect.centerx >= x / 2 + 200 + 4:
                        i.rect.centerx -= 4
                    elif i.rect.centerx <= x / 2 + 200 - 4:
                        i.rect.centerx += 4
                    elif i.rect.centerx < x / 2 + 200 + 4 and i.rect.centerx > x / 2 + 200 - 4:
                        i.rect.centerx = x / 2 + 200
                    if i.rect.centery >= 300 + 4:
                        i.rect.centery -= 4
                    elif i.rect.centery <= 300 - 4:
                        i.rect.centery += 4
                    elif i.rect.centery < 300 + 4 and i.rect.centery > 300 - 4:
                        i.rect.centery = 300
                if i.ammoCooldownRemaining <= 0:
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif i.ammoCooldownRemaining > 0:
                    i.ammoCooldownRemaining -= 1
                        
            #ID 9 (boss2LeftClaw)
            elif i.idNumber == 9:
                #Move
                if (i.ammoCooldownRemaining % 180 < 70) and i.ammoCooldownRemaining < 360: #boss2LeftClaw attacks every 3 seconds
                    if i.ammoCooldownRemaining < 180:
                        if differenceX >= 0 + 3:
                            i.rect.centerx -= 3
                        elif differenceX <= 0 - 3:
                            i.rect.centerx += 3
                        elif abs(differenceX) < 3:
                            i.rect.centerx = player1.rect.centerx
                        if differenceY >= 0 + 3:
                            i.rect.centery -= 3
                        elif differenceY <= 0 - 3:
                            i.rect.centery += 3
                        elif abs(differenceY) < 3:
                            i.rect.centery = player1.rect.centery
                    elif i.ammoCooldownRemaining >= 180:
                        if differenceX >= 0 + 2:
                            i.rect.centerx -= 2
                        elif differenceX <= 0 - 2:
                            i.rect.centerx += 2
                        elif abs(differenceX) < 2:
                            i.rect.centerx = player1.rect.centerx
                        if differenceY >= 0 + 2:
                            i.rect.centery -= 2
                        elif differenceY <= 0 - 2:
                            i.rect.centery += 2
                        elif abs(differenceY) < 2:
                            i.rect.centery = player1.rect.centery
                elif (i.ammoCooldownRemaining % 180 >= 70): #boss2LeftClaw resets to default position here
                    if i.rect.centerx >= x / 2 - 200 + 4:
                        i.rect.centerx -= 4
                    elif i.rect.centerx <= x / 2 - 200 - 4:
                        i.rect.centerx += 4
                    elif i.rect.centerx < x / 2 - 200 + 4 and i.rect.centerx > x / 2 - 200 - 4:
                        i.rect.centerx = x / 2 - 200
                    if i.rect.centery >= 300 + 4:
                        i.rect.centery -= 4
                    elif i.rect.centery <= 300 - 4:
                        i.rect.centery += 4
                    elif i.rect.centery < 300 + 4 and i.rect.centery > 300 - 4:
                        i.rect.centery = 300
                if i.ammoCooldownRemaining <= 0:
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif i.ammoCooldownRemaining > 0:
                    i.ammoCooldownRemaining -= 1
            #ID 10 (wallStationaryRight)
            elif i.idNumber == 10: #Doesn't move
                #Fire Ammo
                if abs(differenceY) < (abs(differenceX) * math.tan(22.5)) and i.ammoCooldownRemaining <= 0: #If closest to middle
                    createEnemiesAmmo("wallHuggerRight2", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif differenceY > 0 and i.ammoCooldownRemaining <= 0 or i.rect.centery > y - 5 and i.ammoCooldownRemaining <= 0:
                    #If closest to "up and left" shot
                    createEnemiesAmmo("wallHuggerRight1", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif differenceY < 0 and i.ammoCooldownRemaining <= 0 or i.rect.centery < 5 and i.ammoCooldownRemaining <= 0:
                    #If closest to "down and left" shot
                    createEnemiesAmmo("wallHuggerRight3", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif i.ammoCooldownRemaining > 0:
                    i.ammoCooldownRemaining -= 1
                
            #ID 11 (wallStationaryLeft)
            elif i.idNumber == 11: #Doesn't move
                if abs(differenceY) < (abs(differenceX) * math.tan(22.5)) and i.ammoCooldownRemaining <= 0: #If closest to middle
                    createEnemiesAmmo("wallHuggerLeft2", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif differenceY > 0 and i.ammoCooldownRemaining <= 0 or i.rect.centery > y - 5 and i.ammoCooldownRemaining <= 0:
                    #If closest to "up and left" shot
                    createEnemiesAmmo("wallHuggerLeft1", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif differenceY < 0 and i.ammoCooldownRemaining <= 0 or i.rect.centery < 5 and i.ammoCooldownRemaining <= 0:
                    #If closest to "down and left" shot
                    createEnemiesAmmo("wallHuggerLeft3", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif i.ammoCooldownRemaining > 0:
                    i.ammoCooldownRemaining -= 1

                    
            #Enemy Ammo AI
                    
            #ID 10001 (Fighter ammo 1)
            elif i.idNumber == 10001: #Moves up and to the right
                i.rect.centerx += 2
                i.rect.centery -= 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10002 (Fighter ammo 2)
            elif i.idNumber == 10002: #Moves down and to the right
                i.rect.centerx += 2
                i.rect.centery += 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10003 (Fighter ammo 3)
            elif i.idNumber == 10003: #Moves down and to the left
                i.rect.centerx -= 2
                i.rect.centery += 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10004 (Fighter ammo 4)
            elif i.idNumber == 10004: #Moves up and to the left
                i.rect.centerx -= 2
                i.rect.centery -= 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10005 (wallHuggerRight1)
            elif i.idNumber == 10005: #Moves up and to the left
                i.rect.centerx -= 2
                i.rect.centery -= 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10006 (wallHuggerRight2)
            elif i.idNumber == 10006: #Moves to the left
                i.rect.centerx -= 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10007 (wallHuggerRight3)
            elif i.idNumber == 10007: #Moves down and to the left
                i.rect.centerx -= 2
                i.rect.centery += 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10008 (wallHuggerLeft1)
            elif i.idNumber == 10008: #Moves up and to the right
                i.rect.centerx += 2
                i.rect.centery -= 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10009 (wallHuggerLeft2)
            elif i.idNumber == 10009: #Moves to the right
                i.rect.centerx += 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10010 (wallHuggerLeft3)
            elif i.idNumber == 10010: #Moves down and to the right
                i.rect.centerx += 2
                i.rect.centery += 2
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10011 (boss1Down)
            elif i.idNumber == 10011: #Moves down
                i.rect.centery += 3 + (i.offset % 2)
                i.rect.centerx += -1 + (i.offset % 3)
                if  i.rect.centery > y or i.rect.centery < 0 or i.rect.centerx > x or i.rect.centerx < 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10012 (boss1StartCharge)
            elif i.idNumber == 10012: #Creates boss1Charge for charging effect.  At 0 HP, creates boss1Blast
                i.health -= 1
                if i.health > 410:
                    if i.ammoCooldownRemaining <= 0:
                        createEnemiesAmmo("boss1Charge", 1, i)
                        i.ammoCooldownRemaining = i.ammoCooldown
                    elif i.ammoCooldownRemaining > 0:
                        i.ammoCooldownRemaining -= 1
                elif i.health <= 400 and i.health % 4 == 0:
                    if differenceY <= 0:
                        createEnemiesAmmo("boss1Blast", 1, i)
                    elif differenceY > 0:
                        createEnemiesAmmo("boss1BlastUp", 1, i)
            #ID 10013 (boss1Charge)
            elif i.idNumber == 10013:
                if i.rect.centerx < i.idParent.rect.centerx: #If boss1Charge's rect < boss1StartCharge
                    i.rect.centerx += 1
                elif i.rect.centerx > i.idParent.rect.centerx: #If boss1Charge's rect < boss1StartCharge
                    i.rect.centerx -= 1
                if i.rect.centery < i.idParent.rect.centery: #If boss1Charge's rect < boss1StartCharge
                    i.rect.centery += 1
                elif i.rect.centery > i.idParent.rect.centery: #If boss1Charge's rect < boss1StartCharge
                    i.rect.centery -= 1
                if i.rect.centerx == i.idParent.rect.centerx and i.rect.centery == i.idParent.rect.centery: #If same rect as boss1StartCharge
                    i.delete()
                if  i.rect.centery >= y or i.rect.centery <= 0 or i.rect.centerx >= x or i.rect.centerx <= 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
                if not (i.idParent.idNumber == 10012 or i.idParent.idNumber == 10017):
                   i.delete()
            #ID 10014 (boss1Blast)
            elif i.idNumber == 10014:
                i.rect.centery += 2 + (i.offset % 4)
                i.rect.centerx += -2 + (i.offset % 5)
                if  i.rect.centery >= y or i.rect.centery <= 0 or i.rect.centerx >= x or i.rect.centerx <= 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10015 (boss1BlastUp)
            elif i.idNumber == 10015:
                i.rect.centery -= 2 + (i.offset % 4)
                i.rect.centerx += -2 + (i.offset % 5)
                if  i.rect.centery >= y or i.rect.centery <= 0 or i.rect.centerx >= x or i.rect.centerx <= 0: #Not all enemies should be deleted if off-screen, so don't change this.
                    i.delete()
            #ID 10016 (boss2HeadBeam)
            elif i.idNumber == 10016:
                i.health -= 1
            #ID 10017 (boss2StartCharge)
            elif i.idNumber == 10017:
                i.health -= 1
                if i.ammoCooldownRemaining <= 0:
                    createEnemiesAmmo("boss1Charge", 1, i)
                    i.ammoCooldownRemaining = i.ammoCooldown
                elif i.ammoCooldownRemaining > 0:
                    i.ammoCooldownRemaining -= 1
                if i.health == 0:
                    createEnemiesAmmo("boss2HeadBeam", 1, i)
            playerBoundary(i.rect)
    return enemiesRemaining
#---------------------------------------------------------------------------------------------------------------
def screenDraw():
    global enemiesRemainingDisplay, currentFPSDisplay
    if gameState == 1:
        screen.blit( player1.levelBackground, (0, 0))
        screen.blit( menuBorder, menuBorderPos)
        screen.blit( startNewGame, startNewGamePos)
        #screen.blit( loadGame, loadGamePos)
        return 0
    
    elif gameState == 2:
        screen.blit( player1.levelBackground, (0, 0))
        screen.blit( menuBorder, menuBorderPos)
        #screen.blit( classicMode, classicModePos)
        screen.blit( adventureMode, adventureModePos)
        """screen.blit( enduranceMode, enduranceModePos)
        screen.blit( achievements, achievementsPos)
        screen.blit( options, optionsPos)
        screen.blit( hiScores, hiScoresPos)
        screen.blit( saveGame, saveGamePos)"""
        return 0
    
    elif gameState == 4:
        screen.blit( player1.levelBackground, (0, 0))
        #enemyGroup.update()
        #enemyAmmoGroup.update()
        #enemyGroup.clear(screen, player1.levelBackground)
        #enemyAmmoGroup.clear(screen, player1.levelBackground)
        screen.blit( player1.image, player1.rect)
        #screen.blit( player1.collisionBox.image, player1.collisionBox.rect)
        for i in enemyGroup:
            screen.blit( i.image, i.rect)
        for i in enemyAmmoGroup:
            screen.blit( i.image, i.rect)
        #enemyGroup.draw(screen)
        #enemyAmmoGroup.draw(screen)
        #dirty = all.draw(screen)
        for i in range(0, player1.maxAmmo, 1):
            if player1.ammoType[i]:
                screen.blit( player1.ammo[i].image, player1.ammo[i].rect)
        screen.blit( p1UserInterface, p1UserInterfacePos)
        screen.blit( player1.pointsDisplay, player1.pointsDisplayPos)
        screen.blit( enemiesRemainingDisplay, enemiesRemainingDisplayPos)
        screen.blit( currentFPSDisplay, currentFPSDisplayPos)
        screen.blit( healthCurrentDisplay, healthCurrentDisplayPos)
        screen.blit( shieldCurrentDisplay, shieldCurrentDisplayPos)
        screen.blit( player1.levelCurrentDisplay, player1.levelCurrentDisplayPos)
        screen.blit( player1.levelTimeDisplay, player1.levelTimeDisplayPos)
        return 0#dirty

    elif gameState == 5:
        screen.blit( player1.levelBackground, (0, 0))
        screen.blit( menuBorder, menuBorderPos)
        screen.blit( nextLevel, nextLevelPos)
        #screen.blit( levelSelect, levelSelectPos)
        screen.blit( shop, shopPos)
        return 0

    elif gameState == 7:
        screen.blit( player1.levelBackground, (0, 0))
        screen.blit( menuBorder, menuBorderPos)
        screen.blit( statBorder, statBorderPos)
        screen.blit( upgradeMaxAmmo, upgradeMaxAmmoPos)
        screen.blit( upgradeMaxAmmoCost, upgradeMaxAmmoCostPos)
        screen.blit( upgradeAmmoFireRate, upgradeAmmoFireRatePos)
        screen.blit( upgradeAmmoFireRateCost, upgradeAmmoFireRateCostPos)
        screen.blit( upgradeAmmoVelocity, upgradeAmmoVelocityPos)
        screen.blit( upgradeAmmoVelocityCost, upgradeAmmoVelocityCostPos)
        screen.blit( upgradeDamageModifier, upgradeDamageModifierPos)
        screen.blit( upgradeDamageModifierCost, upgradeDamageModifierCostPos)
        screen.blit( upgradeHealthMax, upgradeHealthMaxPos)
        screen.blit( upgradeHealthMaxCost, upgradeHealthMaxCostPos)
        screen.blit( upgradeShieldMax, upgradeShieldMaxPos)
        screen.blit( upgradeShieldMaxCost, upgradeShieldMaxCostPos)
        screen.blit( displayPlayerName, displayPlayerNamePos)
        screen.blit( displayMaxAmmo, displayMaxAmmoPos)
        screen.blit( displayAmmoFireRate, displayAmmoFireRatePos)
        screen.blit( displayAmmoVelocity, displayAmmoVelocityPos)
        screen.blit( displayDamageModifier, displayDamageModifierPos)
        screen.blit( displayHealthMax, displayHealthMaxPos)
        screen.blit( displayShieldMax, displayShieldMaxPos)
        screen.blit( player1.pointsDisplay, player1.pointsDisplayPos)
        return 0
    
    elif gameState == 14:
        screen.blit( player1.levelBackground, (0, 0))
        screen.blit( menuBorder, menuBorderPos)
        screen.blit( enterName, enterNamePos)
        return 0

    elif gameState == 15:
        screen.blit( player1.levelBackground, (0, 0))
        screen.blit( menuBorder, menuBorderPos)
        screen.blit( easyDifficulty, easyDifficultyPos)
        screen.blit( normalDifficulty, normalDifficultyPos)
        screen.blit( hardDifficulty,   hardDifficultyPos)
        screen.blit( insaneDifficulty,  insaneDifficultyPos)
        return 0

#---------------------------------------------------------------------------------------------------------------
def updateHP():
    healthCurrentString  = "HP: " + str(player1.healthCurrent) + "/" + str(player1.healthMax)
    if (1.0 * player1.healthCurrent / player1.healthMax) > 0.50: #If health is greater than 50%
        healthCurrentDisplay = font.render(healthCurrentString, True, (19, 157, 8))
    elif (1.0 * player1.healthCurrent / player1.healthMax) > 0.25 and (1.0 * player1.healthCurrent / player1.healthMax) <= 0.50: #Else if health is between 25-50%
        healthCurrentDisplay = font.render(healthCurrentString, True, (243, 155, 40))
    elif (1.0 * player1.healthCurrent / player1.healthMax) <= 0.25: #Else if health is at or below 25%
        healthCurrentDisplay = font.render(healthCurrentString, True, (243, 40, 40))
    return healthCurrentDisplay

#---------------------------------------------------------------------------------------------------------------
def updatePoints():
    player1.pointsString  = "Score: " + str(player1.points)
    player1.pointsDisplay = font.render(player1.pointsString, True, (80, 80, 80))
    
    if gameState == 4:
        player1.pointsDisplayPos.left = x - 139
        player1.pointsDisplayPos.centery = 20
    elif gameState == 7:
        player1.pointsDisplayPos.left = 12
        player1.pointsDisplayPos.centery = 28
    return player1.pointsDisplay

#---------------------------------------------------------------------------------------------------------------
def updateEnemiesRemaining():
    enemiesRemainingString = "Enemies Remaining: " + str(enemiesRemaining)
    enemiesRemainingDisplay = font.render(enemiesRemainingString, True, (80, 80, 80))
    return enemiesRemainingDisplay

#---------------------------------------------------------------------------------------------------------------
def updateFPS():
    currentFPS = clock.get_fps()
    integerFPS = int(currentFPS)
    currentFPSString = "FPS: " + str(integerFPS)
    currentFPSDisplay = font.render(currentFPSString, True, (80, 80, 80))
    return currentFPSDisplay

#---------------------------------------------------------------------------------------------------------------
def makeEnemy(enemyName, enemyNumber, enemyId = 0):
    global x, y

    if enemyId == 0: #Used to bypass enemy list not defined
        enemyId = enemy[0]
    #Note on modelRotation:  All enemies are rotated 180 degrees by default
    #Default: Enemy(idParent, idNumber = 0, health = 0, value = 0, model = "Images/defaultModel.png",
    #               ammoCooldown = 0, damage = 0, modelRotation+180 = 0, damageCooldown = 0, selfDamage = 500,
    #               changeDifficulty = True)

    #ENEMY
    if enemyName == "scorpion":
        enemy[enemyNumber] = Enemy(enemyId, 1, 10, 7, "Images/Enemies/scorpionLowestQuality.png", 0, 3)
        enemy[enemyNumber].rect.centerx = random.randint(0, x)
        enemy[enemyNumber].rect.centery = 0
    elif enemyName == "fighter":
        enemy[enemyNumber] = Enemy(enemyId, 2, 15, 11, "Images/Enemies/fighterLowestQuality.png", 60, 2)
        enemy[enemyNumber].rect.centerx = random.randint(0, x)
        enemy[enemyNumber].rect.centery = 30 + random.randint(0, 40)
    elif enemyName == "razor":
        enemy[enemyNumber] = Enemy(enemyId, 3, 21, 12, "Images/Enemies/razorLowestQuality.png", 0, 5)
        enemy[enemyNumber].rect.centerx = player1.rect.centerx + random.randint(-20, 20)
        enemy[enemyNumber].rect.centery = 0 + random.randint(0, 3)
    elif enemyName == "wallHuggerRight":
        enemy[enemyNumber] = Enemy(enemyId, 4, 38, 19, "Images/Enemies/wallHuggerLowestQuality.png", 95, 10, 270)
        enemy[enemyNumber].rect.right = x
        enemy[enemyNumber].rect.centery = random.randint(0, y)
    elif enemyName == "wallHuggerLeft":
        enemy[enemyNumber] = Enemy(enemyId, 5, 38, 19, "Images/Enemies/wallHuggerLowestQuality.png", 95, 10, 90)
        enemy[enemyNumber].rect.left = 0
        enemy[enemyNumber].rect.centery = random.randint(0, y)
    elif enemyName == "boss1":
        enemy[enemyNumber] = Enemy(enemyId, 6, 5000, 2500, "Images/Enemies/boss1.png", 25, 8, 0, 25, 0)
        enemy[enemyNumber].rect.centerx = x / 2
        enemy[enemyNumber].rect.centery = 0 + 100
    elif enemyName == "boss2Head":
        enemy[enemyNumber] = Enemy(enemyId, 7, 7000, 5000, "Images/Enemies/boss2Head.png", 1000, 20, 180, 30, 0)
        enemy[enemyNumber].rect.centerx = x / 2
        enemy[enemyNumber].rect.centery = 0 + 100
    elif enemyName == "boss2RightClaw":
        enemy[enemyNumber] = Enemy(enemyId, 8, 8000, 750, "Images/Enemies/boss2RightClaw.png", 540, 5, 180, 30, 0)
        enemy[enemyNumber].rect.centerx = x / 2 + 200
        enemy[enemyNumber].rect.centery = 0 + 100 + 200
    elif enemyName == "boss2LeftClaw":
        enemy[enemyNumber] = Enemy(enemyId, 9, 8000, 750, "Images/Enemies/boss2LeftClaw.png", 540, 5, 180, 30, 0)
        enemy[enemyNumber].rect.centerx = x / 2 - 200
        enemy[enemyNumber].rect.centery = 0 + 100 + 200
    elif enemyName == "wallStationaryRight":
        enemy[enemyNumber] = Enemy(enemyId, 10, 58, 19, "Images/Enemies/wallHuggerLowestQuality.png", 95, 10, 270)
        enemy[enemyNumber].rect.right = x
        enemy[enemyNumber].rect.centery = random.randint(0, y)
    elif enemyName == "wallStationaryLeft":
        enemy[enemyNumber] = Enemy(enemyId, 11, 58, 19, "Images/Enemies/wallHuggerLowestQuality.png", 95, 10, 90)
        enemy[enemyNumber].rect.left = 0
        enemy[enemyNumber].rect.centery = random.randint(0, y)
    elif enemyName == "testMobSingle": #Good for when you only want one test mob.
        enemy[enemyNumber] = Enemy(enemyId, 9998, 1, 0, "Images/Enemies/boss2RightClaw.png", 100, 0, 180)
        enemy[enemyNumber].rect.centerx = x / 2
        enemy[enemyNumber].rect.centery = y / 2
    elif enemyName == "testMob": #Fill the entire screen.  Good for collision detection / speed tests
        enemy[enemyNumber] = Enemy(enemyId, 9999, 1, 0, "Images/Enemies/testMob.png", 100, 0, 0)
        enemy[enemyNumber].rect.centerx = (0 + enemyNumber * 2) % x
        enemy[enemyNumber].rect.centery = int((0 + enemyNumber * 2) / x) * 2
    #AMMO
    if enemyName == "fighterAmmo1": #Fires up and right
        enemy[enemyNumber] = Enemy(enemyId, 10001, 100, 0, "Images/Ammunition/fighterAmmo1LowestQuality.png", 0, 3, 180)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "fighterAmmo2": #Fires down and right
        enemy[enemyNumber] = Enemy(enemyId, 10002, 100, 0, "Images/Ammunition/fighterAmmo1LowestQuality.png", 0, 3, 90)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "fighterAmmo3": #Fires down and left
        enemy[enemyNumber] = Enemy(enemyId, 10003, 100, 0, "Images/Ammunition/fighterAmmo1LowestQuality.png", 0, 3, 0)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "fighterAmmo4": #Fires up and left
        enemy[enemyNumber] = Enemy(enemyId, 10004, 100, 0, "Images/Ammunition/fighterAmmo1LowestQuality.png", 0, 3, 270)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "wallHuggerRight1": #Shoots up and left
        enemy[enemyNumber] = Enemy(enemyId, 10005, 100, 0, "Images/Ammunition/novaSmallLowestQuality.png", 0, 4, 0)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "wallHuggerRight2": #Shoots left
        enemy[enemyNumber] = Enemy(enemyId, 10006, 100, 0, "Images/Ammunition/novaSmallLowestQuality.png", 0, 4, 0)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "wallHuggerRight3": #Shoots down and left
        enemy[enemyNumber] = Enemy(enemyId, 10007, 100, 0, "Images/Ammunition/novaSmallLowestQuality.png", 0, 4, 0)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "wallHuggerLeft1": #Shoots up and right
        enemy[enemyNumber] = Enemy(enemyId, 10008, 100, 0, "Images/Ammunition/novaSmallLowestQuality.png", 0, 4, 0)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "wallHuggerLeft2": #Shoots right
        enemy[enemyNumber] = Enemy(enemyId, 10009, 100, 0, "Images/Ammunition/novaSmallLowestQuality.png", 0, 4, 0)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "wallHuggerLeft3": #Shoots down and right
        enemy[enemyNumber] = Enemy(enemyId, 10010, 100, 0, "Images/Ammunition/novaSmallLowestQuality.png", 0, 4, 0)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery
    elif enemyName == "boss1Down": #Shoots down directly at player
        enemy[enemyNumber] = Enemy(enemyId, 10011, 100, 0, "Images/Ammunition/novaSmallLowestQuality.png", 0, 6, 180)
        enemy[enemyNumber].rect.centerx = player1.rect.centerx + random.randint(-5, 5)
        enemy[enemyNumber].rect.centery = enemyId.rect.centery + random.randint(-10, 10)
    elif enemyName == "boss1StartCharge": #Center of "charging" effect
        enemy[enemyNumber] = Enemy(enemyId, 10012, 900, 0, "Images/Ammunition/novaSmallRedLowestQuality.png", 7, 10, 0, 30, 0, False)
        enemy[enemyNumber].rect.centerx = player1.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.bottom #Starts at lowest part of boss
    elif enemyName == "boss1Charge": #"Charging" effect
        enemy[enemyNumber] = Enemy(enemyId, 10013, 100, 0, "Images/Ammunition/novaSmallRedLowestQuality.png", 0, 3, 0, 15, 0, False)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx + random.randint(-80, 80)
        enemy[enemyNumber].rect.centery = enemyId.rect.centery + random.randint(-80, 80)
    elif enemyName == "boss1Blast": #Blast after charging effect
        enemy[enemyNumber] = Enemy(enemyId, 10014, 100, 0, "Images/Ammunition/novaSmallRedLowestQuality.png", 0, 1, 0)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx + random.randint(-5, 5)
        enemy[enemyNumber].rect.centery = enemyId.rect.centery + random.randint(-5, 5)
    elif enemyName == "boss1BlastUp": #Blast after charging effect
        enemy[enemyNumber] = Enemy(enemyId, 10015, 100, 0, "Images/Ammunition/novaSmallRedLowestQuality.png", 0, 1, 0)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx + random.randint(-5, 5)
        enemy[enemyNumber].rect.centery = enemyId.rect.centery + random.randint(-5, 5)
    elif enemyName == "boss2HeadBeam": #Blast after charging effect
        enemy[enemyNumber] = Enemy(enemyId, 10016, 60, 0, "Images/Ammunition/bigRedBeam.png", 0, 8, 180, 15, 0, False)
        enemy[enemyNumber].rect.top = enemyId.rect.top
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
    elif enemyName == "boss2StartCharge": #Center of "charging" effect
        enemy[enemyNumber] = Enemy(enemyId, 10017, 110, 0, "Images/Ammunition/novaSmallRedLowestQuality.png", 2, 10, 0, 30, 0, False)
        enemy[enemyNumber].rect.centerx = enemyId.rect.centerx
        enemy[enemyNumber].rect.centery = enemyId.rect.centery - 29 #Center of purple "jewel" in boss2Head
    return

#---------------------------------------------------------------------------------------------------------------
def createEnemies(enemyName, countAmount):
    listNumber = len(enemy) #Counts number of enemies that exist
    enemiesAvailableToMake = MAX_ENEMIES - listNumber
    if enemiesAvailableToMake < countAmount and enemiesAvailableToMake > 0: #If not enough room to make all of countAmount
        countAmount -= enemiesAvailableToMake
    elif enemiesAvailableToMake <= 0:
        countAmount = 0
    for i in range(0, countAmount, 1): #Keeps number of enemies below MAX_ENEMIES
        enemy.append(Enemy)
        makeEnemy(enemyName, listNumber) #Doesn't need -1, because listNumber is set before enemy.append()
        listNumber += 1 #If an enemy was made, then listNumber should increase to reflect that.
    return

#---------------------------------------------------------------------------------------------------------------
def createEnemiesQueue(currentTime, enemyName, countAmount, cooldownTime, number=1):
    #number of -1 is used for continuous streams of enemies until the level ends
    if (currentTime % cooldownTime) == 0 and currentTime > 0 and number == -1:
        createEnemies(enemyName, countAmount)
    elif (currentTime % cooldownTime) == 0 and currentTime > 0 and currentTime <= (cooldownTime * number):
        createEnemies(enemyName, countAmount)
    return

#---------------------------------------------------------------------------------------------------------------
def createEnemiesAmmo(enemyName, countAmount, enemyId):
    listNumber = len(enemy) #Counts number of enemies that exist
    enemiesAvailableToMake = MAX_ENEMIES - listNumber
    if enemiesAvailableToMake < countAmount and enemiesAvailableToMake > 0: #If not enough room to make all of countAmount
        countAmount -= enemiesAvailableToMake
    elif enemiesAvailableToMake <= 0:
        countAmount = 0
    for i in range(0, countAmount and listNumber < MAX_ENEMIES, 1): #Keeps number of enemies below MAX_ENEMIES
        enemy.append(Enemy)
        makeEnemy(enemyName, listNumber, enemyId) #Doesn't need -1, because listNumber is set before enemy.append()
        listNumber += 1 #If an enemy was made, then listNumber should increase to reflect that.
    return

#---------------------------------------------------------------------------------------------------------------
def listCleanup(list):
    for object in list:
        if object.idNumber == 0:
            object.kill() #Remove object from all sprite groups
            list.remove(object)
    return
    
#---------------------------------------------------------------------------------------------------------------
def collisionOccur():
    basicShot = 1
    playerIsHit = 0
    p1RectSmall = pygame.Rect(player1.rect.centerx - 1, player1.rect.centery - 6, 30, 30) #1-pixel hit box for player
    for i in range(0, player1.maxAmmo, 1):
        if player1.ammoType[i] > 0 and player1.ammoType[i] < 5:
            for j in enemy:
                if j.idNumber > 0 and j.idNumber < 10000:
                    if j.rect.colliderect(player1.ammo[i].rect):
                        if pygame.sprite.collide_mask(player1.ammo[i], j) and j.health > 0:
                            player1.points += int((1.0 * basicShot * player1.damageModifier) * (1.0 * j.value / j.health))
                            j.value  -= int((1.0 * basicShot * player1.damageModifier) * (1.0 * j.value / j.health))
                            j.health -= int(1.0 * basicShot * player1.damageModifier)
                            if j.idNumber < 10000:
                                player1.ammo[i].rect.centerx   = (x + 200) #Removes player ammo from screen
                                player1.ammo[i].rect.centery   = (y + 200) #Removes player ammo from screen
    for i in enemy:
        if i.idNumber:
            if i.damageCooldownRemaining > 0:
                i.damageCooldownRemaining -= 1
            if i.rect.colliderect(p1RectSmall):
                if pygame.sprite.collide_mask(i, player1.collisionBox):
                    if i.damageCooldownRemaining <= 0: #Checks for collision cooldown
                        i.damageCooldownRemaining = i.damageCooldown
                        enemyDamageTotal = i.damage
                        i.health -= i.selfDamage
                        playerIsHit = 1
                        if player1.shieldCurrent > 0:
                            if player1.shieldCurrent >= enemyDamageTotal:
                                player1.shieldCurrent -= enemyDamageTotal
                                enemyDamageTotal = 0
                            elif player1.shieldCurrent < enemyDamageTotal:
                                enemyDamageTotal -= player1.shieldCurrent
                                player1.shieldCurrent = 0
                        player1.healthCurrent  -= enemyDamageTotal
            if i.idNumber and i.health <= 0:
                player1.points += i.value
                i.delete()
    if not playerIsHit: #If the player doesn't get hit
        if player1.shieldRechargeRemaining > 0:
            player1.shieldRechargeRemaining -= 1
        elif player1.shieldRechargeRemaining <= 0 and player1.levelTime % (1 + int(19.0 / (1.0 + player1.shieldMax / 100.0))) == 0 and player1.shieldCurrent < player1.shieldMax:
            player1.shieldCurrent += 1 + int(player1.shieldMax / 600)
            if player1.shieldCurrent > player1.shieldMax: player1.shieldCurrent = player1.shieldMax
    elif playerIsHit: #If the player is hit
        player1.shieldRechargeRemaining = player1.shieldRechargeCooldown + 120 #Resets the timer on the shield recharge
    return

#---------------------------------------------------------------------------------------------------------------
def closeGame():
    pygame.quit()       #Makes pyGame windows close when the program stops (Very nice to have)
    sys.exit()
    #raise SystemExit("Exit Success")

#---------------------------------------------------------------------------------------------------------------
pygame.display.set_caption(GAME_NAME)          #Sets window to game name
#background = pygame.image.load("Images/Ground Textures/leavesBig800.png").convert()
background = pygame.Surface(screen.get_size()).convert() #Sets background to size of screen
background.fill((255,255,255))                 #Sets background to white
clock = pygame.time.Clock()
player1 = Player()
sounds = Sounds()
sounds.loadSounds()
enemy = [] #Creates an empty list for storage of all enemies and enemy ammo.
enemyGroup = pygame.sprite.Group()
enemyAmmoGroup = pygame.sprite.Group()
all        = pygame.sprite.RenderUpdates() #A group for all sprites

gameState = 1

while not gameState == 0:   #All non-loop declarations should be made between the if and while loops.
    pygame.event.pump()     #Keeps pygame from locking up -- only needed until other event calls are made

    if gameState == 1:      #Main Menu
        pygame.event.clear()        #Prevents user from skipping this gameState
        player1.levelBackground = pygame.image.load("Images/Backgrounds/startMenu.png")
        
        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        startNewGame = fontBig.render("Start New Game [Enter][S]", True, (50, 187, 53))
        startNewGamePos = startNewGame.get_rect()
        startNewGamePos.centerx = x / 2
        startNewGamePos.centery = y / 2
        
        #loadGame = fontBig.render("Load Game [L]", True, (62, 114, 198), (255, 255, 255))
        #loadGamePos = loadGame.get_rect()
        #loadGamePos.centerx = x / 2
        #loadGamePos.centery = (y / 2) + 22
        while gameState == 1:
            pygame.event.pump()
            screenDraw()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            keyPressed(pygame.key.get_pressed())
            pygame.display.flip()
            clock.tick(MAX_FPS)
            
    elif gameState == 2:    #Second Menu
        pygame.event.clear()        #Prevents user from skipping this gameState
        
        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        
        """classicMode = fontBig.render("Classic Mode [C]", True, (50, 187, 53), (255, 255, 255))
        classicModePos = classicMode.get_rect()
        classicModePos.centerx = x / 2
        classicModePos.centery = y / 2"""
        
        adventureMode = fontBig.render("Adventure Mode [A]", True, (62, 114, 198))
        adventureModePos = adventureMode.get_rect()
        adventureModePos.centerx = x / 2
        adventureModePos.centery = (y / 2) + 22
        
        """enduranceMode = fontBig.render("Endurance Mode [E]", True, (62, 114, 198), (255, 255, 255))
        enduranceModePos = enduranceMode.get_rect()
        enduranceModePos.centerx = x / 2
        enduranceModePos.centery = (y / 2) + 44
        
        achievements = fontBig.render("Achievements [L]", True, (62, 114, 198), (255, 255, 255))
        achievementsPos = achievements.get_rect()
        achievementsPos.centerx = x / 2
        achievementsPos.centery = (y / 2) + 66
        
        hiScores = fontBig.render("Hi-Scores [H]", True, (62, 114, 198), (255, 255, 255))
        hiScoresPos = hiScores.get_rect()
        hiScoresPos.centerx = x / 2
        hiScoresPos.centery = (y / 2) + 88
        
        options = fontBig.render("Options [O]", True, (62, 114, 198), (255, 255, 255))
        optionsPos = options.get_rect()
        optionsPos.centerx = x / 2
        optionsPos.centery = (y / 2) + 110

        saveGame = fontBig.render("Save Game [S]", True, (62, 114, 198), (255, 255, 255))
        saveGamePos = saveGame.get_rect()
        saveGamePos.centerx = x / 2
        saveGamePos.centery = (y / 2) + 132"""
        while gameState == 2:
            pygame.event.pump()
            screenDraw()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            keyPressed(pygame.key.get_pressed())
            pygame.display.flip()
            clock.tick(MAX_FPS)
            
    elif gameState == 3:    #Classic Mode
        pygame.event.clear()        #Prevents user from skipping this gameState
        
        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        while gameState == 3:
            pygame.event.pump()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            gameState = 4
            
    elif gameState == 4:    #Next Level
        pygame.event.clear()        #Prevents user from skipping this gameState
        player1.levelSetup()
        enemiesRemaining = 0
        #player1.image = pygame.image.load("Images/Ship/shipCenterLowestQuality.png").convert_alpha()

        p1UserInterface = pygame.image.load("Images/User Interface/inGameBorderTopRight.png").convert()
        p1UserInterfacePos = p1UserInterface.get_rect()
        p1UserInterfacePos.left = x - 150
        p1UserInterfacePos.top  = 4
        
        enemiesRemaining = 0
        enemiesRemainingString = "Enemies Remaining: " + str(enemiesRemaining)
        enemiesRemainingDisplay = font.render(enemiesRemainingString, True, (80, 80, 80))
        enemiesRemainingDisplayPos = enemiesRemainingDisplay.get_rect()
        enemiesRemainingDisplayPos.left = x - 139
        enemiesRemainingDisplayPos.centery = 32
        
        currentFPS = 0
        currentFPSString = "FPS: " + str(currentFPS)
        currentFPSDisplay = font.render(currentFPSString, True, (80, 80, 80))
        currentFPSDisplayPos = currentFPSDisplay.get_rect()
        currentFPSDisplayPos.left = x - 139
        currentFPSDisplayPos.centery = 44
        
        healthCurrentString = "HP: " + str(player1.healthCurrent) + "/" + str(player1.healthMax)
        healthCurrentDisplay = font.render(healthCurrentString, True, (20, 215, 40))
        healthCurrentDisplayPos = healthCurrentDisplay.get_rect()
        healthCurrentDisplayPos.left = x - 139
        healthCurrentDisplayPos.centery = 56

        shieldCurrentString = "Shield: " + str(player1.shieldCurrent) + "/" + str(player1.shieldMax)
        shieldCurrentDisplay = font.render(shieldCurrentString, True, (0, 108, 255))
        shieldCurrentDisplayPos = shieldCurrentDisplay.get_rect()
        shieldCurrentDisplayPos.left = x - 139
        shieldCurrentDisplayPos.centery = 68
        
        while gameState == 4 and not player1.levelVictory():
            pygame.event.pump()
            keyPressed(pygame.key.get_pressed())
            playerBoundary(player1.rect) #Keeps player from leaving game boundaries
            playerAmmoMove()        #Fires and resets ammo
            enemiesRemaining = enemyMove()
            collisionOccur()         #Tests collisions between ammo and enemies
            player1.pointsDisplay = updatePoints()
            enemiesRemainingDisplay = updateEnemiesRemaining()
            currentFPSDisplay = updateFPS()
            healthCurrentDisplay = updateHP()
            shieldCurrentDisplayString = "Shield: " + str(player1.shieldCurrent) + "/" + str(player1.shieldMax) #Update shield display
            shieldCurrentDisplay = font.render(shieldCurrentDisplayString, True, (0, 108, 255))
            player1.levelCurrentDisplayString = "Level: " + str(player1.currentAdventureLevel)
            player1.levelUpdate() #Don't put this before collision detection
            player1.levelTime += 1  #Adds 1 to the level's time
            player1.levelTimeDisplayString = "Time Remaining: " + str(int((player1.levelEndTime - player1.levelTime)/60))
            player1.levelTimeDisplay = font.render(player1.levelTimeDisplayString, True, (80, 80, 80))
            listCleanup(enemy) #Cleans all "dead" enemies from list
            if FRAMESKIPPING > 0:
                if player1.levelTime % (FRAMESKIPPING + 1) == 0:
                    screenDraw()
                    pygame.display.update()   #Refresh screen
            else:
                screenDraw()
                pygame.display.update()   #Refresh screen
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            clock.tick(MAX_FPS)          #Sets max FPS
            
    elif gameState == 5:            #Adventure Mode
        pygame.event.clear()        #Prevents user from skipping this gameState

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        player1.healthCurrent = player1.healthMax
        player1.shieldCurrent = player1.shieldMax
        
        nextLevel = fontBig.render("Next Level [N]", True, (50, 187, 53))
        nextLevelPos = nextLevel.get_rect()
        nextLevelPos.centerx = x / 2
        nextLevelPos.centery = y / 2
        
        """levelSelect = fontBig.render("Level Select [L]", True, (62, 114, 198), (255, 255, 255))
        levelSelectPos = levelSelect.get_rect()
        levelSelectPos.centerx = x / 2
        levelSelectPos.centery = (y / 2) + 22"""
        
        shop = fontBig.render("Shop [B]", True, (62, 114, 198))
        shopPos = shop.get_rect()
        shopPos.centerx = x / 2
        shopPos.centery = (y / 2) + 44
        while gameState == 5:
            pygame.event.pump()
            screenDraw()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            keyPressed(pygame.key.get_pressed())
            pygame.display.flip()
            clock.tick(MAX_FPS)
            
    elif gameState == 6:            #Level Select
        pygame.event.clear()        #Prevents user from skipping this gameState

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        while gameState == 6:
            pygame.event.pump()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            gameState = 4
            
    elif gameState == 7:            #Shop
        pygame.event.clear()        #Prevents user from skipping this gameState
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        #Show List of Upgrades (center of screen)

        menuBorder = pygame.image.load("Images/User Interface/shopMenuBorder.png").convert_alpha()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2 - 10
        menuBorderPos.centery = y / 2 - 10

        statBorder = pygame.image.load("Images/User Interface/inGameBorderTopLeft.png").convert()
        statBorderPos = statBorder.get_rect()
        statBorderPos.left = 0
        statBorderPos.top  = 0
        
        upgradeMaxAmmo = fontBig.render("Upgrade Max Ammo [A]", True, (62, 114, 198))
        upgradeMaxAmmoPos = upgradeMaxAmmo.get_rect()
        upgradeMaxAmmoPos.left = x / 4
        upgradeMaxAmmoPos.centery = y / 2 - 66

        upgradeMaxAmmoCost = fontBig.render("Cost: " + str((player1.totalUpgrades + 1) * 500), True, (50, 187, 53))
        upgradeMaxAmmoCostPos = upgradeMaxAmmoCost.get_rect()
        upgradeMaxAmmoCostPos.left = x / 2 + 90
        upgradeMaxAmmoCostPos.centery = y / 2 - 66
        
        upgradeAmmoFireRate = fontBig.render("Upgrade Ammo Fire Rate [R]", True, (62, 114, 198))
        upgradeAmmoFireRatePos = upgradeAmmoFireRate.get_rect()
        upgradeAmmoFireRatePos.left = x / 4
        upgradeAmmoFireRatePos.centery = (y / 2) - 44

        upgradeAmmoFireRateCost = fontBig.render("Cost: " + str((player1.totalUpgrades + 1) * 500), True, (50, 187, 53))
        upgradeAmmoFireRateCostPos = upgradeAmmoFireRateCost.get_rect()
        upgradeAmmoFireRateCostPos.left = x / 2 + 90
        upgradeAmmoFireRateCostPos.centery = (y / 2) - 44
        
        upgradeAmmoVelocity = fontBig.render("Upgrade Ammo Velocity [V]", True, (62, 114, 198))
        upgradeAmmoVelocityPos = upgradeAmmoVelocity.get_rect()
        upgradeAmmoVelocityPos.left = x / 4
        upgradeAmmoVelocityPos.centery = (y / 2) - 22

        upgradeAmmoVelocityCost = fontBig.render("Cost: " + str((player1.totalUpgrades + 1) * 500), True, (50, 187, 53))
        upgradeAmmoVelocityCostPos = upgradeAmmoVelocityCost.get_rect()
        upgradeAmmoVelocityCostPos.left = x / 2 + 90
        upgradeAmmoVelocityCostPos.centery = (y / 2) - 22

        upgradeDamageModifier = fontBig.render("Increase Damage Modifier [D]", True, (62, 114, 198))
        upgradeDamageModifierPos = upgradeDamageModifier.get_rect()
        upgradeDamageModifierPos.left = x / 4
        upgradeDamageModifierPos.centery = (y / 2)

        upgradeDamageModifierCost = fontBig.render("Cost: " + str((player1.totalUpgrades + 1) * 500), True, (50, 187, 53))
        upgradeDamageModifierCostPos = upgradeDamageModifierCost.get_rect()
        upgradeDamageModifierCostPos.left = x / 2 + 90
        upgradeDamageModifierCostPos.centery = (y / 2)

        upgradeHealthMax = fontBig.render("Increase Maximum Health [H]", True, (62, 114, 198))
        upgradeHealthMaxPos = upgradeHealthMax.get_rect()
        upgradeHealthMaxPos.left = x / 4
        upgradeHealthMaxPos.centery = (y / 2) + 22

        upgradeHealthMaxCost = fontBig.render("Cost: " + str((player1.totalUpgrades + 1) * 500), True, (50, 187, 53))
        upgradeHealthMaxCostPos = upgradeHealthMaxCost.get_rect()
        upgradeHealthMaxCostPos.left = x / 2 + 90
        upgradeHealthMaxCostPos.centery = (y / 2) + 22
        
        upgradeShieldMax = fontBig.render("Increase Maximum Shield [S]", True, (62, 114, 198))
        upgradeShieldMaxPos = upgradeShieldMax.get_rect()
        upgradeShieldMaxPos.left = x / 4
        upgradeShieldMaxPos.centery = (y / 2) + 44

        upgradeShieldMaxCost = fontBig.render("Cost: " + str((player1.totalUpgrades + 1) * 500), True, (50, 187, 53))
        upgradeShieldMaxCostPos = upgradeShieldMaxCost.get_rect()
        upgradeShieldMaxCostPos.left = x / 2 + 90
        upgradeShieldMaxCostPos.centery = (y / 2) + 44
        
        #Show Player Stats (top-left corner)
        displayPlayerName = font.render(player1.name, True, (55, 108, 180))
        displayPlayerNamePos = displayPlayerName.get_rect()
        displayPlayerNamePos.left = 12 #Sets left-most rect of text to the x co-ordinate of 0
        displayPlayerNamePos.centery = 0 + 16

        displayMaxAmmoString = "Max Ammo: " + str(player1.maxAmmo)
        displayMaxAmmo = font.render(displayMaxAmmoString, True, (130, 0, 0))
        displayMaxAmmoPos = displayMaxAmmo.get_rect()
        displayMaxAmmoPos.left = 12
        displayMaxAmmoPos.centery = 0 + 40 #Increase by 12 of last display line so text doesn't overlap

        displayAmmoFireRateString = "Ammo Fire Rate: " + str(player1.ammoSpeed)
        displayAmmoFireRate = font.render(displayAmmoFireRateString, True, (130, 0, 0))
        displayAmmoFireRatePos = displayAmmoFireRate.get_rect()
        displayAmmoFireRatePos.left = 12
        displayAmmoFireRatePos.centery = 0 + 52

        displayAmmoVelocityString = "Ammo Velocity: " + str(player1.ammoVelocity)
        displayAmmoVelocity = font.render(displayAmmoVelocityString, True, (130, 0, 0))
        displayAmmoVelocityPos = displayAmmoVelocity.get_rect()
        displayAmmoVelocityPos.left = 12
        displayAmmoVelocityPos.centery = 0 + 64
        
        displayDamageModifierString = "Damage Modifier: " + str(player1.damageModifier)
        displayDamageModifier = font.render(displayDamageModifierString, True, (130, 0, 0))
        displayDamageModifierPos = displayDamageModifier.get_rect()
        displayDamageModifierPos.left = 12
        displayDamageModifierPos.centery = 0 + 76

        displayHealthMaxString = "HP: " + str(player1.healthCurrent) + "/" + str(player1.healthMax)
        displayHealthMax = font.render(displayHealthMaxString, True, (20, 215, 40))
        displayHealthMaxPos = displayHealthMax.get_rect()
        displayHealthMaxPos.left = 12
        displayHealthMaxPos.centery = 0 + 88

        displayShieldMaxString = "Shield: " + str(player1.shieldCurrent) + "/" + str(player1.shieldMax)
        displayShieldMax = font.render(displayShieldMaxString, True, (0, 108, 255))
        displayShieldMaxPos = displayShieldMax.get_rect()
        displayShieldMaxPos.left = 12
        displayShieldMaxPos.centery = 0 + 100
        
        while gameState == 7:
            pygame.event.pump()
            player1.pointsDisplay = updatePoints()
            displayMaxAmmoString = "Max Ammo: " + str(player1.maxAmmo)
            displayMaxAmmo = font.render(displayMaxAmmoString, True, (130, 0, 0))
            displayAmmoFireRateString = "Ammo Fire Rate: " + str(player1.ammoSpeed)
            displayAmmoFireRate = font.render(displayAmmoFireRateString, True, (130, 0, 0))
            displayAmmoVelocityString = "Ammo Velocity: " + str(player1.ammoVelocity)
            displayAmmoVelocity = font.render(displayAmmoVelocityString, True, (130, 0, 0))
            displayDamageModifierString = "Damage Modifier: " + str(player1.damageModifier)
            displayDamageModifier = font.render(displayDamageModifierString, True, (130, 0, 0))
            displayHealthMaxString = "HP: " + str(player1.healthCurrent) + "/" + str(player1.healthMax)
            displayHealthMax = font.render(displayHealthMaxString, True, (20, 215, 40))
            displayShieldMaxString = "Shield: " + str(player1.shieldCurrent) + "/" + str(player1.shieldMax)
            displayShieldMax = font.render(displayShieldMaxString, True, (0, 108, 255))
            if player1.points >= (player1.totalUpgrades + 1) * 500:
                upgradeMaxAmmoCost = upgradeAmmoFireRateCost = upgradeAmmoVelocityCost = upgradeDamageModifierCost = upgradeHealthMaxCost = upgradeShieldMaxCost = fontBig.render("Cost: " + str((player1.totalUpgrades + 1) * 500), True, (50, 187, 53))
            elif player1.points < (player1.totalUpgrades + 1) * 500:
                upgradeMaxAmmoCost = upgradeAmmoFireRateCost = upgradeAmmoVelocityCost = upgradeDamageModifierCost = upgradeHealthMaxCost = upgradeShieldMaxCost = fontBig.render("Cost: " + str((player1.totalUpgrades + 1) * 500), True, (243, 40, 40))
            screenDraw()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            keyPressed(pygame.key.get_pressed())
            pygame.display.flip()
            clock.tick(MAX_FPS)
            
    elif gameState == 8:            #Endurance Mode
        pygame.event.clear()        #Prevents user from skipping this gameState

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        while gameState == 8:
            pygame.event.pump()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            gameState = 4
            
    elif gameState == 9:            #Achievements
        pygame.event.clear()        #Prevents user from skipping this gameState

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        while gameState == 9:
            pygame.event.pump()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            gameState = 4
            
    elif gameState == 10:           #Hi-Scores
        pygame.event.clear()        #Prevents user from skipping this gameState

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        while gameState == 10:
            pygame.event.pump()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            gameState = 4
            
    elif gameState == 11:           #Options
        pygame.event.clear()        #Prevents user from skipping this gameState

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        while gameState == 11:
            pygame.event.pump()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            gameState = 4
            
    elif gameState == 12:           #Save Game
        pygame.event.clear()        #Prevents user from skipping this gameState

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        while gameState == 12:
            pygame.event.pump()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            gameState = 4
            
    elif gameState == 13:           #Load Game
        pygame.event.clear()        #Prevents user from skipping this gameState

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85
        
        player1.levelBackground = pygame.image.load("Images/Backgrounds/otherMenu.png")
        while gameState == 13:
            pygame.event.pump()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            gameState = 4
            
    elif gameState == 14:           #Enter Name
        pygame.event.clear()        #Prevents user from skipping this gameState

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85

        player1.levelBackground = pygame.image.load("Images/Backgrounds/startMenu.png")
        enterName = fontBig.render("Enter Name: " + player1.name, True, (50, 187, 53))
        enterNamePos = enterName.get_rect()
        enterNamePos.centerx = x / 2
        enterNamePos.centery = y / 2

        while gameState == 14:
            pygame.event.pump()
            enterName = fontBig.render("Enter Name: " + player1.name, True, (50, 187, 53))
            screenDraw()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            player1.name = keyPressed(pygame.key.get_pressed())
            pygame.display.flip()
            clock.tick(MAX_FPS)

    elif gameState == 15:           #Select Difficulty
        pygame.event.clear()

        menuBorder = pygame.image.load("Images/User Interface/mainMenuBorder.png").convert()
        menuBorderPos = menuBorder.get_rect()
        menuBorderPos.centerx = x / 2
        menuBorderPos.centery = y / 1.85

        player1.levelBackground = pygame.image.load("Images/Backgrounds/startMenu.png")
        easyDifficulty = fontBig.render("Easy [1]", True, (0, 108, 255))
        easyDifficultyPos = easyDifficulty.get_rect()
        easyDifficultyPos.centerx = x / 2
        easyDifficultyPos.centery = y / 2 - 11

        normalDifficulty = fontBig.render("Normal [2]", True, (50, 187, 53))
        normalDifficultyPos = normalDifficulty.get_rect()
        normalDifficultyPos.centerx = x / 2
        normalDifficultyPos.centery = y / 2 + 11

        hardDifficulty = fontBig.render("Hard [3]", True, (220, 116, 24))
        hardDifficultyPos = hardDifficulty.get_rect()
        hardDifficultyPos.centerx = x / 2
        hardDifficultyPos.centery = y / 2 + 33

        insaneDifficulty = fontBig.render("Insane [4]", True, (220, 11, 24))
        insaneDifficultyPos = insaneDifficulty.get_rect()
        insaneDifficultyPos.centerx = x / 2
        insaneDifficultyPos.centery = y / 2 + 55
        while gameState == 15:
            pygame.event.pump()
            screenDraw()
            sounds.playMusic() #Plays/updates music.  MUST be in a loop.
            keyPressed(pygame.key.get_pressed())
            pygame.display.flip()
            clock.tick(MAX_FPS)
        
#End program processes
if gameState == 0:
    closeGame()
