Search code examples
pythonpygamereturnincrement

How to receive updated variables from other functions?


so in my game here, I'm trying to have a scoring system where every time an enemy is hit, your score goes up by 1. However, the score doesn't seem to be updating and I'm not sure why and how to fix it. If possible, I do not want to use global variables due to my lecturer encouraging us against it.

Here's all relevant code (I have marked where the score variable is mentioned):

main():

def main():
    font = pygame.font.SysFont("28 Days Later", 35, True, False) # (Font name, Font size, Bold?, Italic?)
    board = player(225, 225, 64, 64, 0)
    DiArrow = enemy(100, 410, 48, 48, 410)
    score = 0 # <------------- SCORE
    bullets = []
    E_bullets = []
    while True:
        moveFunctions(board, DiArrow, bullets, E_bullets, score, font) # <------------- SCORE

moveFunctions:

def moveFunctions(board, DiArrow, bullets, E_bullets, score, font): # <------------- SCORE
    clock = pygame.time.Clock()
    run = True
    while run:
        clock.tick(15) # Frame rate per second (FPS)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                stopGame()

        fireBullet(board, bullets, DiArrow, score) # <------------- SCORE
        E_fireBullet(board, E_bullets, DiArrow)

        arrowKeys = pygame.key.get_pressed()

        bulletDirection(arrowKeys, board, bullets)
        E_bulletDirection(DiArrow, E_bullets, board)
        playerControls(arrowKeys, board)
        enemyControls(DiArrow, board)
        redrawGameWindow(board, DiArrow, bullets, E_bullets, font, score) # <------------- SCORE

fireBullet():

def fireBullet(board, bullets, DiArrow, score): # <------------- SCORE
    if board.lastDirection == "left":
        for bullet in bullets:
            if bullet.y - bullet.radius < DiArrow.hitbox[1] + DiArrow.hitbox[3] and bullet.y + bullet.radius > \
                    DiArrow.hitbox[1]:
                if bullet.x + bullet.radius > DiArrow.hitbox[0] and bullet.x - bullet.radius < DiArrow.hitbox[0] + \
                        DiArrow.hitbox[2]:
                    DiArrow.getHit()
                    score += 1 # <------------- SCORE
                    bullets.pop(bullets.index(bullet))
            if bullet.x < 500 and bullet.x > 50:
                bullet.x += bullet.vel
            else:
                bullets.pop(bullets.index(bullet))
    elif board.lastDirection == "right":
        for bullet in bullets:
            if bullet.y - bullet.radius < DiArrow.hitbox[1] + DiArrow.hitbox[3] and bullet.y + bullet.radius > \
                    DiArrow.hitbox[1]:
                if bullet.x + bullet.radius > DiArrow.hitbox[0] and bullet.x - bullet.radius < DiArrow.hitbox[0] + \
                        DiArrow.hitbox[2]:
                    DiArrow.getHit()
                    score += 1 # <------------- SCORE
                    bullets.pop(bullets.index(bullet))
            if bullet.x < 450 and bullet.x > 0:
                bullet.x += bullet.vel
            else:
                bullets.pop(bullets.index(bullet))
    elif board.lastDirection == "up":
        for bullet in bullets:
            if bullet.y - bullet.radius < DiArrow.hitbox[1] + DiArrow.hitbox[3] and bullet.y + bullet.radius > \
                    DiArrow.hitbox[1]:
                if bullet.x + bullet.radius > DiArrow.hitbox[0] and bullet.x - bullet.radius < DiArrow.hitbox[0] + \
                        DiArrow.hitbox[2]:
                    DiArrow.getHit()
                    score += 1 # <------------- SCORE
                    bullets.pop(bullets.index(bullet))
            if 500 > bullet.y > 50:
                bullet.y += bullet.vel
            else:
                bullets.pop(bullets.index(bullet))
    else:
        for bullet in bullets:
            if bullet.y - bullet.radius < DiArrow.hitbox[1] + DiArrow.hitbox[3] and bullet.y + \
                bullet.radius > DiArrow.hitbox[1]:
                if bullet.x + bullet.radius > DiArrow.hitbox[0] and bullet.x - bullet.radius < \
                    DiArrow.hitbox[0] + DiArrow.hitbox[2]:
                    DiArrow.getHit()
                    score += 1 # <------------- SCORE
                    bullets.pop(bullets.index(bullet))
            if 450 > bullet.y > 0:
                bullet.y += bullet.vel
            else:
                bullets.pop(bullets.index(bullet))
    # return score <------------------ I tried using return here but to no avail

redrawGameWindow():

def redrawGameWindow(board, DiArrow, bullets, E_bullets, font, score): # <------------- SCORE
    window.blit(bg, (0,0))
    text = font.render("Score: " + str(score), 1, (255, 255, 255)) # <------------- SCORE
    window.blit(text, (380, 515))
    board.drawCharacter(window)
    DiArrow.drawEnemy(window)
    for bullet in bullets:
        bullet.draw(window)
    for bullet in E_bullets:
        bullet.draw(window)
    pygame.display.update()

I should mention that aside from score, everything is working mostly as they should and that I am using the Pygame module (Although, the issue here is not related to any Pygame functions). Also, board represents the player while DiArrow represents the enemy.

Thank you to anyone who could help shed light on this matter of mine and have a great day to you all


Solution

  • In fact, your attempt to return score from a function should work if you do it for every function that uses score, but you must also save that returned value from every call to each function that uses it in order to propagate the updated value between function calls. Modify your code to meet the following format and you should achieve the desired behavior.

    def functionThatUsesScore(score):
        score += 1
        return score
    
    
    def functionThatDoesNotUseScore():
        pass
    
    
    def anotherFunctionThatUsesScore(score):
        score += 2
        return score
    
    
    def main():
        score = 0
        while True:
            score = functionThatUsesScore(score)
            functionThatDoesNotUseScore()
            score = anotherFunctionThatUsesScore(score)