Search code examples
pythonimagepygamegame-developmentgamecontroller

Trying to make my first game with pygame and after making the title screen, I've been unable to change my players image


I've been making a game where a car drives around an open road eating other cars. Pressing spacebar allows the player car to transform and cannibalize other cars until any key event is finished. I had to turn my main game loop into a function to get the intro screen to work and ever since, the cannibalizing still works, but the image transformation stopped working. Does anybody know what's wrong with my code? The functions in question are the 3 at the bottom. Thank you anybody who answers

import pygame
import random
import math
from pygame import mixer


pygame.init()

# Window
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Cannibal Cars")
background = pygame.image.load("backgrpund.png")
clock = pygame.time.Clock()
green = 50, 168, 80
bright_green = 50, 250, 80
black = 0, 0, 0


# background sound
mixer.music.load('background music.wav')
mixer.music.play(-1)

# player animation
playerImg = pygame.image.load("player.png").convert_alpha()
playerX = 200
playerY = 200
playerX_change = 0
playerY_change = 0
player_state = "nice"

# enemy

enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
num_of_enemies = 30

for i in range(num_of_enemies):
    enemyImg.append(pygame.image.load("enemy.png"))
    enemyX.append(random.randint(400, 750))
    enemyY.append(random.randint(0, 550))
    enemyX_change.append(1)


# In game text
score_value = 0
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
textY = 10
game_over_font = pygame.font.Font('freesansbold.ttf', 64)


def show_score(x, y):  
    score = font.render("Score:" + str(score_value), True, (255, 255, 255))  
    screen.blit(score, (x, y))  


def text_object(text, font):
    textSurface = font.render(text, True, black)
    return textSurface, textSurface.get_rect()


def player(x, y):
    screen.blit(playerImg, (x, y))


def enemy(x, y):
    screen.blit(enemyImg[i], (x, y))


def isCollision(enemyX, enemyY, playerX, playerY):
    distance = math.sqrt((math.pow(enemyX - playerX, 2)) + 
(math.pow(enemyY - playerY, 2)))
    if distance < 27:
        return True
    else:
        return False


def game_over():
    game_over_text = game_over_font.render("GAME OVER: ", True, (255, 255, 255))
    screen.blit(game_over_text, (200, 250))
    game_intro()


def button(msg,x,y,w,h,ic,ac,action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    if x + w > mouse[0] > x and y + h > mouse[1] > y:
        pygame.draw.rect(screen, ac, (x, y, w, h))
        if click[0] == 1 and action != None:
            if action == "play":
                game_loop()
    else:
        pygame.draw.rect(screen, ic, (x, y, w, h))
    textSurf, textRect = text_object(msg, font)
    textRect.center = ((x + (w / 2)), (y + h / 2))
    screen.blit(textSurf, textRect)


def game_intro():  
    intro = True  
    while intro:  
        for event in pygame.event.get():  
            if event.type == pygame.QUIT:  
                pygame.quit()  
                quit()  
        screen.fill("white")  
        font = pygame.font.Font('freesansbold.ttf', 32)  

        intro_text = font.render("Cannibal Cars", True, (0, 0, 0))
    controls_text = font.render("Arrow keys to move", True, (0, 0, 0))
    controls_text2 = font.render("Space bar to transform", True, (0, 0, 0))
    controls_text3 = font.render("Stop pressing any key to return to normal", True, (0, 0, 0))
    screen.blit(intro_text, (300, 100))
    screen.blit(controls_text, (20, 150))
    screen.blit(controls_text2, (20, 200))
    screen.blit(controls_text3, (20, 250))
    button("Play", 300, 450, 100, 50, green, bright_green, "play")
    pygame.display.update()
    clock.tick(15)


def game_loop():

    playerImg = pygame.image.load("player.png").convert_alpha()
    playerX = 200
    playerY = 200
    playerX_change = 0
    playerY_change = 0
    player_state = "nice"
    score_value = 0
    playerImg2 = pygame.image.load("cannibal car.png").convert_alpha()

    running = True
    while running:

        screen.fill((0, 0, 0))
        screen.blit(background, (0, 0))

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

            # controls
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    playerX_change = -0.8
                    playerImg = pygame.transform.flip(playerImg, True, False)
                if event.key == pygame.K_RIGHT:
                    playerX_change = 0.8
                if event.key == pygame.K_UP:
                    playerY_change = -0.8
                if event.key == pygame.K_DOWN:
                    playerY_change = 0.8
                    if playerX_change < 0:
                        playerImg = pygame.transform.flip(playerImg, True, False)
                if event.key == pygame.K_SPACE:
                    playerImg = playerImg2
                    player_state = "cannibal"
            if event.type == pygame.KEYUP:
                playerX_change = 0
                playerY_change = 0
                playerImg = pygame.image.load("player.png")
                player_state = "nice"

        # player movement
        player(playerX, playerY)
        playerX += playerX_change
        playerY += playerY_change
        if playerX <= 0:
            playerX = 0
        elif playerX >= 770:
            playerX = 770
        if playerY <= 0:
            playerY = 0
        elif playerY >= 570:
            playerY = 570


        # enemy movement
        for i in range(num_of_enemies):

            enemyX[i] += enemyX_change[i]
            if enemyX[i] <= 0:
                enemyX_change[i] = 1
            elif enemyX[i] >= 736:
                enemyX_change[i] = -1

        # Collision with enemy
            enemy(enemyX[i], enemyY[i])
            collision = isCollision(enemyX[i], enemyY[i], playerX, playerY)
            show_score(textX, textY)
            if collision:
                if player_state == "cannibal":
                    cannibal_sound = mixer.Sound('Cannibal car.wav')
                    cannibal_sound.play()
                    enemyX[i] = (random.randint(0, 800))
                    enemyY[i] = (random.randint(0, 600))
                    score_value += 1
                else:
                    game_over()

        pygame.display.update()

game_intro()  

game_loop()
pygame.display.update()  
pygame.quit()  
quit()

Solution

  • First, you have to resolve the indentation issue with your game_intro function, otherwise it will only run an infinite loop with black screen.

    def game_intro():
        intro = True
        while intro:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()
            screen.fill("white")
            font = pygame.font.Font('freesansbold.ttf', 32)
    
            intro_text = font.render("Cannibal Cars", True, (0, 0, 0))
            controls_text = font.render("Arrow keys to move", True, (0, 0, 0))
            controls_text2 = font.render("Space bar to transform", True, (0, 0, 0))
            controls_text3 = font.render("Stop pressing any key to return to normal", True, (0, 0, 0))
            screen.blit(intro_text, (300, 100))
            screen.blit(controls_text, (20, 150))
            screen.blit(controls_text2, (20, 200))
            screen.blit(controls_text3, (20, 250))
            button("Play", 300, 450, 100, 50, green, bright_green, "play")
            pygame.display.update()
            clock.tick(15)
    

    Second, the playerImg inside your game_loop function is only a local variable to that function. Consequently, the function call player(playerX, playerY) will only change the playerImg as defined in your # player animation portion of the code and not the playerImg variable inside your game_loop. To address that issue, remove/comment the playerImg variable inside your game_loop and replace it with the global playerImg.

    def game_loop():
        global playerImg
        # playerImg = pygame.image.load("player.png").convert_alpha()