def submitScoreState(window, control, score):
    '''The playing screen for submitting a new score'''

    sprites,            \
    errorMessage,       \
    inputBox,           \
    submitScoreButton   = makeSubmitMenuGUI(score, window)

    drawer.drawList(sprites[:-2] + [inputBox], window)
    isError = False

    while not window.closed:
        point = window.checkMouse()
        if button.isButtonPressed(point, submitScoreButton, window):
            name = inputBox.getText()
            if (len(name) < 3 or len(name) > 25) or "`" in name:
                if not isError:
                    errorMessage.draw(window)
                    isError = True
            else:
                name = inputBox.getText()
                highscores.submitScore(name, score)
                break
        gfx.update(common.UPDATE_SPEED)
    drawer.undrawList(sprites + [inputBox, errorMessage])
 def displayMenu(guiCreateFunction=None):
     drawer.undrawList([titleText] + sprites)
     showMenu(window, control, apples, guiCreateFunction)
     if window.closed:
         return True
     drawer.drawList([titleText] + sprites, window)
     return False
 def displayMenu(guiCreateFunction):
     drawer.undrawList(sprites + backButtonSprites)
     showMenu(window, control, apples, guiCreateFunction)
     if window.closed:
         return True
     drawer.drawList(sprites + backButtonSprites, window)
     return False
def runMenuState(window, control):
    '''Says it on the tin'''
    titleText = common.createTitle(common.GAME_NAME, window)

    sprites,         \
    playButton,      \
    howToPlayButton, \
    highscoreButton, \
    exitButton       = createFrontMenuButtons(window)

    bg = common.createCenteredImage("menu_bg")
    bg.draw(window)

    menu_top = common.createCenteredImage("menu_top")
    menu_top.draw(window)

    apples = []
    for i in range(50):
        addApple(apples, window)

    def displayMenu(guiCreateFunction=None):
        drawer.undrawList([titleText] + sprites)
        showMenu(window, control, apples, guiCreateFunction)
        if window.closed:
            return True
        drawer.drawList([titleText] + sprites, window)
        return False

    start = time.time()
    while control["state"] == states.STATE_MENU and not window.closed:
        key = common.getKeyPress(window)
        point = window.checkMouse()
        elapsed = common.calculateTime(start)

        if button.isButtonPressed(point, playButton, window):
            common.switchState(window, control, states.STATE_PLAYING)
        elif button.isButtonPressed(point, howToPlayButton, window):
            drawer.undrawList([titleText] + sprites)
            displayHowToPlayMenu(window, control, apples)
            if window.closed:
                break
            drawer.drawList([titleText] + sprites, window)
        elif button.isButtonPressed(point, highscoreButton, window):
            if displayMenu(highscores.createHighscoresDisplay):
                break
        elif button.isButtonPressed(point, exitButton, window):
            common.switchState(window, control, states.EXIT)

        updateApples(apples, window)
        #make it so the title is ALWAYS on front
        drawer.redrawSprite(menu_top, window)
        drawer.redrawList([titleText] + sprites, window)
        gfx.update(common.UPDATE_SPEED)

    drawer.undrawList([titleText, bg, menu_top] + sprites + apples)
def showMenu(window, control, apples, guiCreateFunction):
    '''Shows a basic menu which only has a back button (eg how to play, highscores)'''
    sprites = guiCreateFunction(window)
    backButtonSprites, \
    backButtonBounds   = button.create(BACK_BTN_Y, "Back", window)

    menu_top = common.createCenteredImage("menu_top")
    menu_top.draw(window)

    sprites += backButtonSprites
    while not window.closed:
        mouseClickPoint = window.checkMouse()
        updateApples(apples, window)
        if button.isButtonPressed(mouseClickPoint, backButtonBounds, window):
            break
        drawer.redrawSprite(menu_top, window)
        drawer.redrawList(sprites, window)
        gfx.update(common.UPDATE_SPEED)
    drawer.undrawList(sprites + [menu_top])
def runGameOverState(window, control, score, elapsed):
    '''Runs after the player has run out of lives'''
    bg = common.createCenteredImage("menu_bg")
    bg.draw(window)
    overallScore = score * round(elapsed)
    messages = [
        addMessage(window, "GAME OVER", 30, "red", reset=True, bold=True),
        addMessage(window, "Score: " + str(score)),
        addMessage(window, "Time:  " + str(round(elapsed)) + " seconds"),
        addMessage(window, "Final Score:  " + str(overallScore))
    ]

    sprites,            \
    playAgainButton,    \
    submitScoreButton,  \
    exitToMenuButton    = makeGameOverButtons(len(messages), window)
    sprites += messages

    scoreSubmitted = False
    while control["state"] is states.STATE_GAME_OVER and not common.shouldExit(
            window, control):
        mouseClick = window.checkMouse()
        if button.isButtonPressed(mouseClick, playAgainButton, window):
            common.switchState(window, control, states.STATE_PLAYING)
        elif button.isButtonPressed(mouseClick, submitScoreButton,
                                    window) and not scoreSubmitted:
            drawer.undrawList(sprites)
            submitScoreState(window, control, overallScore)
            if window.closed:
                break
            drawer.drawList(sprites, window)
            scoreSubmitted = True
            sprites[0].setFill("dim gray")
            sprites[1].setFill("gray")
        elif button.isButtonPressed(mouseClick, exitToMenuButton, window):
            common.switchState(window, control, states.STATE_MENU)

        gfx.update(common.UPDATE_SPEED)

    drawer.undrawList(sprites + [bg])
def displayHowToPlayMenu(window, control, apples):
    '''Displays the how to play menu, eg it's buttons'''
    sprites, ctrlButton, objButton, typeButton = createHowToPlayMenu(window)
    backButtonSprites, \
    backButtonBounds   = button.create(BACK_BTN_Y, "Back", window)

    menu_top = common.createCenteredImage("menu_top")
    menu_top.draw(window)

    def displayMenu(guiCreateFunction):
        drawer.undrawList(sprites + backButtonSprites)
        showMenu(window, control, apples, guiCreateFunction)
        if window.closed:
            return True
        drawer.drawList(sprites + backButtonSprites, window)
        return False

    while not window.closed:
        mouseClickPoint = window.checkMouse()
        updateApples(apples, window)
        if button.isButtonPressed(mouseClickPoint, backButtonBounds, window):
            break
        if button.isButtonPressed(mouseClickPoint, ctrlButton, window):
            if displayMenu(createHowToControls):
                break
        if button.isButtonPressed(mouseClickPoint, objButton, window):
            if displayMenu(createHowToObjectives):
                break
        if button.isButtonPressed(mouseClickPoint, typeButton, window):
            if displayMenu(createHowToAppleTypes):
                break

        drawer.redrawSprite(menu_top, window)
        drawer.redrawList(sprites, window)
        gfx.update(common.UPDATE_SPEED)
    drawer.undrawList(sprites + backButtonSprites + [menu_top])
def runMainGame(window, control):
    '''The main function handling the actual gameplay of the game'''
    '''Also a shamefully long function :( '''
    #Draw background image
    background = common.createCenteredImage("game_background")
    background.draw(window)

    treeTop = common.createCenteredImage("tree_top")
    treeTop.draw(window)

    #Set up score
    score = 0
    lives = 10
    scoreDisplay, livesDisplay, statSprites = createStatsDisplay(window)

    #Set up player
    playerXVel = 0.0
    playerAABB = aabb.create(500.0, 500.0, 60.0, 45.0)
    playerSprite = player.createAndroid(window)

    #Create tiles
    tileSprites,  \
    isTilesActive = tiles.createTiles(window)
    NUM_TILES = len(tileSprites)

    #Create apple list
    x = appleFuncs.getRandomAppleXPosition()
    apples = [appleFuncs.makeDefaultApple(x, 0, window)]

    projectiles = []
    projectilesDirections = []

    def updateScore(delta):
        nonlocal score
        score += delta
        scoreDisplay.setText("Score: " + str(score))

    def updateLives(delta):
        nonlocal lives
        lives += delta
        livesDisplay.setText("Lives: " + str(lives))

    #Begin timer
    startTime = time.time()
    elapsed = 0

    isGamePaused = False
    gamePausedDisplay = common.createTitle("Paused - Press E to exit",
                                           colour="red",
                                           y=tiles.BASE_HEIGHT / 2)

    #Main loop section for the playing state
    while lives > 0 and not common.shouldExit(window, control):
        #Create data for this frame
        elapsed = common.calculateTime(startTime)
        playerMinX = playerAABB["x"]
        playerMaxX = playerAABB["x"] + playerAABB["w"]
        key = common.getKeyPress(window)

        #Handle game pausing
        if key == "p":
            isGamePaused = not isGamePaused
            if isGamePaused:
                gamePausedDisplay.draw(window)
            else:
                gamePausedDisplay.undraw()

        #Game logic itself
        if not isGamePaused:
            #Player input
            playerXVel = player.handleInput(key, playerXVel)
            playerXVel = player.clampVelocity(playerXVel)

            if (playerFire(window, playerSprite, projectiles,
                           projectilesDirections, score)):
                updateScore(-1)

            #Fix for a glitch causing player to get stuck
            tileIndex = math.floor(playerSprite[1].getCenter().x /
                                   tiles.TILE_SIZE)
            if not isTilesActive[tileIndex]:
                isTilesActive[tileIndex] = True
                tileSprites[tileIndex].draw(window)

            #Update players, apples, and then projectiles
            playerXVel = player.tryCollideEdges(playerXVel, playerMinX,
                                                playerMaxX, isTilesActive)
            player.movePlayer(playerSprite, playerXVel)
            playerAABB["x"] += playerXVel

            tryAddMoreApples(apples, elapsed, window)
            deltaLives, deltaScore = updateApples(apples, playerMinX,
                                                  isTilesActive, tileSprites,
                                                  window)
            updateScore(deltaScore)
            updateLives(deltaLives)

            projectile.update(projectiles, projectilesDirections, apples)

            #Redraw fore-ground
            drawer.redrawSprite(treeTop, window)
            drawer.redrawList(statSprites, window)
        else:  #is paused
            if key == "e":
                break
        gfx.update(common.UPDATE_SPEED * 2)

    #End of the game/ Game over
    drawer.undrawList(apples + projectiles + playerSprite + statSprites +
                      [background])
    tiles.undraw(tileSprites, isTilesActive)

    return score, elapsed