2016-06-03 14 views
0

Die folgenden Code aus einer Game-Engine gibt mir ich bin bastelt in diesen Fehler:Pygame UnboundLocalError

***"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. 

Das einzige, was ich versuche, hier zu tun ist, aus dem roten Startbildschirm zur Hauptschleife, um den Übergang von Drücken auf Zurück.

Die Maschine selbst lief gut, bis ich die game_intro() Funktion machte und sie vor der main_loop() Funktion positionierte, um in den letzten paar Zeilen zu laufen. Ich habe versucht, mit den 2 Funktionen herumzuspielen, um zu sehen, was es zum Laufen bringen könnte, aber kein Glück. Wenn in Zeile 340 auch event = None gesetzt wird, über der player.update-Anweisung in Zeile 339, kann ich von der Intro- zur Hauptschleife wechseln, aber die Bewegungssteuerung hört auf zu arbeiten.

Ich bin mir ziemlich sicher, dass der Fehler etwas mit der Funktion update() in der Player-Klasse zu tun hat, aber keine Ahnung, was das verursacht, besonders wenn die Intro-Funktion kein Ereignis verwendet, das in der Update-Funktion verwendet wird (abgesehen von pygame.event) und es begann erst nach dem Hinzufügen des Intro-Bildschirms abzustürzen.

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() 

ich nur noch ich versuche, Startklassen und Bereiche zu verstehen, so würden alle Tipps eine große Hilfe sein, vielen Dank im Voraus!

+0

Willkommen bei Stackoverflow. Sie sollten uns ein [minimales, vollständiges und überprüfbares Beispiel] (http://stackoverflow.com/help/mcve) zur Verfügung stellen, mit dem wir Ihnen helfen können. – DomTomCat

+0

Sie haben die Einrückung durcheinander gebracht. Nur die Bedingung 'if event.type == ...' befindet sich innerhalb der Ereignisschleife, und Sie müssen auch das 'player.update' dort haben, wenn Sie die Ereignisse an den Player weitergeben möchten. – molbdnilo

+0

Okay ich sehe, was du meinst, ich habe es zum Laufen bekommen, obwohl in Super-Zeitlupe, aber es macht viel mehr Sinn, danke, werde sehen, was ich mit der abgehackten Bewegung auch machen kann. –

Antwort

1

Wie in molbdnilo erwähnt, war der Einzug in der Hauptschleife falsch. Sobald Sie das Ereignis jedoch übergeben, ist es in Ordnung, aber wenn es kein Ereignis gibt, wird der Player nicht aktualisiert.

Der bessere Weg wäre, um eine globale Variable für Ereignisse zu machen, dann führen Sie die Update-Funktion einmal pro Frame und in diesem nach Ereignissen suchen, aber als eine schnelle Lösung, hier gehen Sie.

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() 
+0

Das ist fantastisch, hätte nicht erwartet, dass die Spielschleife ihre Struktur so verändert, dass sie eine Intro-Funktion implementiert. Danke, dass du mir heute etwas Neues beigebracht hast! –