Pygame UnboundLocalError

时间:2016-06-03 14:01:56

标签: python python-2.7 pygame

我正在修改的游戏引擎中的以下代码给出了这个错误:

***"UnboundLocalError: local variable 'event' referenced before assignment":***

player.update(current_level.object_list, event) found in the main_loop() in line 342

main_loop() in line 364.

我在这里尝试做的唯一事情是按回车从红色介绍屏幕转换到主循环。

引擎本身运行良好,直到我创建game_intro()函数并将其定位在main_loop()函数之前,以便在最后几行运行。我试着玩这两个功能本身,看看有什么可以使它工作,但没有运气。同样在第340行中的player.update语句上方的第340行中放置event = None允许我从intro过渡到主循环但是移动控件停止工作。

我很确定错误必须对Player类中的update()函数执行某些操作,但不知道是什么导致它,特别是当引用函数不使用更新函数中使用的事件时(分开)来自pygame.event)它只在添加了介绍屏幕后才开始崩溃。

from pygame import *
import pygame
# from colours import *
# from textObjects import small, medium, large

black = pygame.Color(0, 0, 0)
white = pygame.Color(255, 255, 255)
red = pygame.Color(255, 0, 0)
green = pygame.Color(0, 255, 0)
blue = pygame.Color(0, 0, 255)

pygame.font.init()
small = pygame.font.SysFont(None, 25)
medium = pygame.font.SysFont(None, 50)
large = pygame.font.SysFont(None, 80)

class Player(pygame.sprite.Sprite):
# Initialise function
    def __init__(self, color=blue, width=32, height=48, health=100):
        # I assume super() inherits everything from the block class
        super(Player, self).__init__()
        # Set the image to a Surface of size width and height
        self.image = pygame.Surface((width, height))
        # Fill the image with the default color of blue
        self.image.fill(color)
        # Use the Surface of the image to get the rectangular co-ordinates
        self.set_properties()
        # Create speed for x and y
        self.speed_x = 0
        self.speed_y = 0
        # Create health
        self.health = 100
        self.level = None

    def set_properties(self):
        self.rect = self.image.get_rect()
        # Create an x and y origin position (Centered the mouse on the sprite)
        self.origin_x = self.rect.centerx
        self.origin_y = self.rect.centery
        self.speed = 5
        # Create total travel distance to check the player's position on the map
        self.travel_distance_x = 0
        self.travel_distance_y = 0

    # Function to easily set the position of any block object on the center
    def set_position(self, x, y):
        self.rect.x = x - self.origin_x
        self.rect.y = y - self.origin_y

    # Function made to print the position on the map
    def print_position(self):
        self.travel_distance_x += self.speed_x
        self.travel_distance_y += self.speed_y
        print self.travel_distance_x, self.travel_distance_y

    def set_level(self, level):
        self.level = level
        self.set_position(level.player_start_x, level.player_start_y)

    def set_image(self, filename=None):
        if filename != None:
            self.image = pygame.image.load(filename).convert()
            self.set_properties()

    def death(self):
        print "Kill"
        return display_message("Vaziuojam", black)


    def update(self, collidable=pygame.sprite.Group(), event=True):
        self.experience_gravity()
        self.event = True
        self.rect.x += self.speed_x

        collision_list = pygame.sprite.spritecollide(self, collidable, False)
        for collided_object in collision_list:
            # Right direction
            if self.speed_x > 0:
                self.rect.right = collided_object.rect.left
            # Left direction
            elif self.speed_x < 0:
                self.rect.left = collided_object.rect.right
        self.rect.y += self.speed_y
        collision_list = pygame.sprite.spritecollide(self, collidable, False)
        for collided_object in collision_list:
            # Down direction
            if self.speed_y > 0:
                self.rect.bottom = collided_object.rect.top
                self.speed_y = 0
            # Up direction
            elif self.speed_y < 0:
                self.rect.top = collided_object.rect.bottom
                self.speed_y = 0
        if not event == None:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    self.speed_x = -self.speed
                    # self.change_speed(-self.speed, 0)
                if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    self.speed_x = self.speed
                    # self.change_speed(self.speed, 0)
                if event.key == pygame.K_UP or event.key == pygame.K_w:
                    if len(collision_list) >= 1:
                        self.speed_y = -(self.speed) * 2
                        # self.change_speed(0, -self.speed * 2)
                if event.key == pygame.K_DOWN:
                    # self.change_speed(0, self.speed)
                    pass
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    if self.speed_x < 0:
                        self.speed_x = 0
                if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    if self.speed_x > 0:
                        self.speed_x = 0

    def experience_gravity(self, gravity=0.35):
        if self.speed_y == 0:
            self.speed_y = 1
        else:
            self.speed_y += gravity


class Block(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, color=blue):
        # I assume super() inherits everything from the block class
        super(Block, self).__init__()
        # Set the image to a Surface of size width and height
        self.image = pygame.Surface((width, height))
        # Fill the image with the default color of blue
        self.image.fill(color)
        # Get rectangle object of the block
        self.rect = self.image.get_rect()
        # Assign x and y co-ordinates of the block
        self.rect.x = x
        self.rect.y = y

    def experience_gravity(self, gravity=0.35):
        if self.speed_y == 0:
            self.speed_y = 1
        else:
            self.speed_y += gravity


class Level(object):
    def __init__(self, player_object):
        self.object_list = pygame.sprite.Group()
        self.player_object = player_object
        self.player_start = self.player_start_x, self.player_start_y = 80, 150

        self.world_shift_x = 0
        self.world_shift_y = 0

        self.left_viewbox = screen_width / 2 - screen_width / 8
        self.right_viewbox = screen_width / 2 + screen_width / 8
        self.up_viewbox = screen_height / 3
        self.down_viewbox = screen_height / 2 # + screen_height / 12

    def update(self):
        self.object_list.update()

    def draw(self, screen):
        screen.fill(white)
        self.object_list.draw(screen)

    def shift_world(self, shift_x, shift_y):
        self.world_shift_x += shift_x
        self.world_shift_y += shift_y

        for each_object in self.object_list:
            each_object.rect.x += shift_x
            each_object.rect.y += shift_y

    def scroll(self):
        if self.player_object.rect.x <= self.left_viewbox:
            view_difference = self.left_viewbox - self.player_object.rect.x
            self.player_object.rect.x = self.left_viewbox
            self.shift_world(view_difference, 0)

        if self.player_object.rect.x >= self.right_viewbox:
            view_difference = self.right_viewbox - self.player_object.rect.x
            self.player_object.rect.x = self.right_viewbox
            self.shift_world(view_difference, 0)

        if self.player_object.rect.y <= self.up_viewbox:
            view_difference = self.up_viewbox - self.player_object.rect.y
            self.player_object.rect.y = self.up_viewbox
            self.shift_world(0, view_difference)

        if self.player_object.rect.y >= self.down_viewbox:
            view_difference = self.down_viewbox - self.player_object.rect.y
            self.player_object.rect.y = self.down_viewbox
            self.shift_world(0, view_difference)


class Level_01(Level):
    def __init__(self, player_object):
        super(Level_01, self).__init__(player_object)
        level = [
            #[x, y, width, height, color]
            [0, 3, 10, 844, black],
            [108, 0, 21, 730, black],
            [5, 838, 325, 9, black],
            [240, 815, 130, 32, black],
            [316, 782, 204, 64, black],
            [364, 749, 179, 96, black],
            [469, 680, 84, 156, black],
            [365, 805, 189, 42, black],
            [410, 715, 68, 56, black],
            [645, 679, 244, 18, black],
            [977, 678, 265, 13, black],
            [1439, 676, 93, 14, black],
            [1668, 670, 222, 16, black],
            [2068, 664, 359, 18, black],
            [2544, 617, 11, 64, black],
            [2653, 556, 11, 80, black],
            [2771, 484, 15, 113, black],
            [2922, 434, 277, 12, black],
            [2777, 327, 138, 15, black],
            [2659, 242, 20, 126, black],
            [2505, 178, 17, 145, black],
            [2226, 257, 176, 14, black],
            [2120, 266, 10, 92, black],
            [1808, 252, 213, 10, black],
            [1631, 265, 8, 86, black],
            [1231, 255, 293, 14, black],
            [1009, 261, 169, 12, black],
            [670, 259, 189, 18, black],
            [116, 127, 420, 20, black],
            [590, 183, 19, 95, black]
        ]
        for block in level:
            block = Block(block[0], block[1], block[2], block[3], block[4])
            self.object_list.add(block)

def set_message(text):
    global message, previous_message
    message = font.render(text, True, black, white)
    previous_message = message

def text_objects(text, color, size):
    if size == 'small':
        textSurface = small.render(text, True, color)
    if size == 'medium':
        textSurface = medium.render(text, True, color)
    if size == 'large':
        textSurface = large.render(text, True, color)
    return textSurface, textSurface.get_rect()

def display_message(text, color, y_displacement=0, size='small'):
    textSurface, textRectangle = text_objects(text, color, size)
    textRectangle.center = (screen_width / 2), (screen_height / 2) + y_displacement
    screen.blit(textSurface, textRectangle)

def character_message(text, color, y_displacement=0, size='small'):
    textSurface, textRectangle = text_objects(text, color, size)
    textRectangle = player.travel_distance_x , player.travel_distance_y + y_displacement
    screen.blit(textSurface, textRectangle)

# Initialise pygame module
pygame.init()

# Initialise pygame font
pygame.font.init()

# Defining the screen size
screen_size = screen_width, screen_height = 800, 600

# Setting the display and getting the Surface object
screen = pygame.display.set_mode(screen_size)

# Getting the Clock object
clock = pygame.time.Clock()

# Setting a title to the window
pygame.display.set_caption("TODO make title")

# Defining variable for FPS
fps_limit = 60

# Clear the screen
screen.fill(white)

# Setting the FPS at which the game will run
clock.tick(fps_limit)

# Group all the currently active objects
active_object_list = pygame.sprite.Group()

# Set variable player to the Player() class
player = Player()

# Add player to the active object list
active_object_list.add(player)

# Make a list for the levels and append Level_01 to that list with player as the handler
level_list = []
level_list.append(Level_01(player))

current_level_number = 0
current_level = level_list[current_level_number]

player.set_level(current_level)

# Define our font
font = pygame.font.SysFont(None, 25)
# Define a message, we're doing this because it will be used as a surface
message = previous_message = None
set_message("")


def game_intro():
    intro = True
    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    run=True
                    intro=False
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    quit()
        screen.fill(red)
        pygame.display.update()

def main_loop():
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                run = False

        # Update functions
        player.update(current_level.object_list, event)
        event = None
        current_level.update()

        # Logic testing
        current_level.scroll()

        # Draw everything
        current_level.draw(screen)
        active_object_list.draw(screen)
        if player.travel_distance_y > 900:
            player.health = 0
            display_message("Death test message", black)

        # Delay fps
        clock.tick(fps_limit)

        # Update screen
        pygame.display.update()
        player.print_position()

game_intro()
main_loop()

我仍然只是想开始理解课程和范围,所以任何提示都会有很大的帮助,谢谢你提前!

1 个答案:

答案 0 :(得分:1)

正如molbdnilo所提到的,主循环中的缩进是错误的。但是,一旦你传递了这个事件,没关系,但是如果没有事件,那么玩家就不会更新。

更好的方法是为事件创建一个全局变量,然后每帧运行一次更新函数,并在内部检查事件,但是对于快速修复,这里就去了。

def main_loop():
    run = True
    while run:
        current_events = pygame.event.get()
        if current_events:
            for event in current_events:
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()
                    run = False

                # Update functions
                player.update(current_level.object_list, event)
                current_level.update()

        else:
            player.update(current_level.object_list, None)
            current_level.update()

        # Logic testing
        current_level.scroll()

        # Draw everything
        current_level.draw(screen)
        active_object_list.draw(screen)
        if player.travel_distance_y > 900:
            player.health = 0
            display_message("Death test message", black)

        # Delay fps
        clock.tick(fps_limit)

        # Update screen
        pygame.display.update()
        player.print_position()