2017-06-13 4 views
-1

ich ein pygame Programm mit einem main.py haben ein player.py Modul einge wie folgt:Pygame Attribut Fehler

import pygame 
import random 
from walls import Wall 

class Player(pygame.sprite.Sprite): 
    #-------------------Define Variables here 
    speed=0 
    #------------------Initialise Constructor 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 
     self.image=pygame.image.load("player.png") 
     self.rect = self.image.get_rect() 

     #--------------Fetch the rectangle object that has the dimensions of the image 
     self.rect =self.image.get_rect() 
     #---------------Define movement 
    def moveRight(self,pixels): 
     self.rect.x+=pixels 
    def moveLeft(self,pixels): 
     self.rect.x-=pixels 
    def moveUp(self,pixels): 
     self.rect.y-=pixels 
    def moveDown(self,pixels): 
     self.rect.y+=pixels 

    # Make our top-left corner the passed-in location. 
    def settopleft(): 
     self.rect = self.image.get_rect() 
     self.rect.y = y 
     self.rect.x = x 

     # Set speed vector 
     self.change_x = 0 
     self.change_y = 0 
     self.walls = None 

    def changespeed(self, x, y): 
     """ Change the speed of the player. """ 
     self.change_x += x 
     self.change_y += y 


    def update(self): 
     # Did this update cause us to hit a wall? 
     block_hit_list = pygame.sprite.spritecollide(self, self.walls, False) 
     for block in block_hit_list: 
      # If we are moving right, set our right side to the left side of 
      # the item we hit 
      if self.change_x > 0: 
       self.rect.right = block.rect.left 
      else: 
       # Otherwise if we are moving left, do the opposite. 
       self.rect.left = block.rect.right 

     # Move up/down 
       self.rect.y += self.change_y 

     # Check and see if we hit anything 
     block_hit_list = pygame.sprite.spritecollide(self, self.walls, False) 
     for block in block_hit_list: 

      # Reset our position based on the top/bottom of the object. 
      if self.change_y > 0: 
       self.rect.bottom = block.rect.top 
      else: 
       self.rect.top = block.rect.bottom 

Das main.py Programm ist wie folgt:

#Create walls that the player can run into 
import pygame 
import random 
from player import Player 
from collectable import Collectable 
from walls import Wall 

pygame.init() 
BLACK=(0,0,0) 
WHITE=(255,255,255) 
RED=(255,0,0) 
GREEN =(0,255,0) 

BLUE=(0,0,255) 
GOLD=(255,215,0) 
WIDTH=500 
HEIGHT=500 
size= (WIDTH,HEIGHT) 
screen=pygame.display.set_mode(size) 
pygame.display.set_caption("The Life Game") 


done = False 
clock=pygame.time.Clock() 
wall_list=pygame.sprite.Group() 
all_sprites = pygame.sprite.Group() 
enemy_list = pygame.sprite.Group() 
player=Player() 
player.walls=wall_list 

all_sprites.add(player) 


for i in range(random.randrange(100,200)): 
     whiteStar = Collectable(WHITE, 3, 3, "White Star", "Rect") 
     whiteStar.rect.x = random.randrange(size[0]) 
     whiteStar.rect.y = random.randrange(size[1]) 
     all_sprites.add(whiteStar) 

for i in range(50): 

    enemy = Collectable(RED,6, 6,"Enemy","Ellipse") 
    enemy.rect.x = random.randrange(300) 
    enemy.rect.y = random.randrange(300) 
    enemy_list.add(enemy) 
    all_sprites.add(enemy) 

coin1 = Collectable(GOLD,50,50,"Coin","Ellipse") 
coin1.rect.x=440 
coin1.rect.y=0 
all_sprites.add(coin1) 

coin2 = Collectable(GOLD,50,50,"Coin","Ellipse") 
coin2.rect.x=0 
coin2.rect.y=440 
all_sprites.add(coin2) 

enemy = Collectable(RED,100,100,"Enemy","Ellipse") 
enemy.rect.x=70 
enemy.rect.y=230 
all_sprites.add(enemy) 

#Make the walls (x_pos,y_pos, width, height,colour) 



wall=Wall(0,0,10,600,GREEN) 
wall_list.add(wall) 
all_sprites.add(wall_list) 

wall = Wall(50, 300, 400, 10,RED) 
wall_list.add(wall) 
all_sprites.add(wall_list) 

wall = Wall(10, 200, 100, 10,BLUE) 
wall_list.add(wall) 
all_sprites.add(wall_list) 


score=0 
health=100 

#- - - - - - - - - - - - - -Main Program Loop - - - - - - - - - - - - - - - - 
def main(): 
     done=False 
     score=0 
     health=100 
     while not done: 


        #- - - - - - Main event loop (this is where code for handling keyboard and mouse clicks will go) 
     #Loop until the user clicks the 'x' button (to close program) 
        for event in pygame.event.get(): #User does something 
          if event.type == pygame.QUIT: #If the user clicked close 
             done = True #set the done flag to 'true' to exit the loop 

        keys = pygame.key.get_pressed() #checking pressed keys 
        if keys[pygame.K_LEFT]: 
        player.moveLeft(5) 
        if keys[pygame.K_RIGHT]: 
        player.moveRight(5) 
        if keys[pygame.K_UP]: 
        player.moveUp(5) 
        if keys[pygame.K_DOWN]: 
        player.moveDown(5)     


       #>>----------DRAW SECTION ----------------------------------- 
        #Clear the screen to BLACK. Any drawing commands should be put BELOW this or they will be reased with this command 
        screen.fill(BLACK) 



        #Select the font to be used (size, bold, italics, etc) 
        font_score = pygame.font.SysFont('Calibri',20,True,False) 
        font_health = pygame.font.SysFont('Calibri',20,True,False) 
       #Printing a variable (score or health) to the screen involves converting the score (if integer) to a string first.score_label = font_score.render("Score: " + str(score),True,BLACK) 
        health_label = font_health.render("Health: "+str(health),True,WHITE) 
        score_label = font_score.render("Score: " + str(score),True, WHITE) 
       #Now we can use this line of code to put the image of the text on the screen at a given position 
        screen.blit(score_label,[100,480]) 
        screen.blit(health_label,[190,480]) 


        #>>---------UPDATE SECTION/Put the logic of your game here (i.e. how objects move, when to fire them, etc) 


        all_sprites.update() 

        if coin1.collision_with(player): 
         score=score+1 
         coin1.kill() 
         coin1.rect.x=-20 
         coin1.rect.y=-330 

        if coin2.collision_with(player): 
         score=score+1 
         coin2.kill() 
         coin2.rect.x=-20 
         coin2.rect.y=-330 

        if enemy.collision_with(player): 
         health=health-25 
         enemy.kill() 
         enemy.rect.x=-20 
         enemy.rect.y=-330 

        enemy.update() 





     #-------------PRINTING VARIABLES LIKE SCORE TO SCREEN 
        #Any drawing/graphics code should go here 
        all_sprites.draw(screen) 

        #Update the screen to show whatever you have drawn 
        pygame.display.flip() 

        #Set the frames per second (e.g. 30, 60 etc) 
        clock.tick(120) 

main() 

Auf Lauf das Programm, kommt der folgende Fehler auf:

Traceback (most recent call last): 
    File "N:\pygame\working_on_30\main.py", line 164, in <module> 
    main() 
    File "N:\pygame\working_on_30\main.py", line 128, in main 
    all_sprites.update() 
    File "C:\Python 3.6\lib\site-packages\pygame\sprite.py", line 462, in update 
    s.update(*args) 
    File "N:\pygame\working_on_30\player.py", line 49, in update 
    if self.change_x > 0: 
AttributeError: 'Player' object has no attribute 'change_x' 

ich verschiedene Dinge ausprobiert habe zu ändern, kann es aber nicht an der Arbeit. Könnte jemand a) erklären geben Sie den Fehler b) eine Lösung zu beheben

Antwort

0

tl; dr - füge self.change_x = 0 und self.change_y = 0 zu Ihrem __init__ in der Spieler-Klasse.

Ihre Player-Klasse hat ein Attribut player.change_x, das Sie an verschiedenen Stellen zuweisen, aber nicht in Ihrem init. Wenn Sie player.update() anrufen, bevor Sie (zum Beispiel) player.settopleft() anrufen, dann wenn die update() Methode die Zeile if self.change_x > 0: es Fehler, weil self.change_x wurde nicht definiert. Wenn Sie self.change_x = 0 zu Ihrem init hinzufügen, stellen Sie sicher, dass die Variable immer für eine Instanz von Player festgelegt ist.


Klärende auf Anfrage:

Sie definieren die Klasse Spieler in player.py. Eine der Klassenmethoden ist __init__. Wenn Sie ein Objekt der Klasse erstellen Player (dh, wenn Ihr Code so etwas wie player=Player() tut, wie Sie in main.py haben, ruft dies die __init__ Methode, die Sie sicher, verwenden können, um, dass alle Ihre Objekte korrekt initialisiert werden.

. Ihr Fehler wird verursacht durch self.change_x nicht definiert sind, so sollten Sie es in den __init__ Ihre Klasse definieren, um sicherzustellen, dass dieser Fehler nie auftritt, würde ich vorschlagen:

class Player(pygame.sprite.Sprite): 
    #-------------------Define Variables here 
    speed=0 
    #------------------Initialise Constructor 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 
     self.image=pygame.image.load("player.png") 
     self.rect = self.image.get_rect() 

     # - CHANGE HERE! - sets initial speed to 0 
     self.change_x = 0 
     self.change_y = 0 
     # - END OF CHANGE 

     #--------------Fetch the rectangle object that has the dimensions of the image 
     self.rect =self.image.get_rect() 
     #---------------Define movement 
+0

Zwei Fragen 1. Was ist „tl; dr“. am Anfang deiner Antwort 2. Kannst du ein Beispiel für diese Codezeile mit der Einfügung von self.change_x = 0 an den __init__ des Players cla posten? ss. Ich bin mir der Struktur nicht ganz sicher. Ich kann dann die Frage stellen, Antwortstatus! Vielen Dank im Voraus – MissComputing

+0

haha, tl; dr ist Internet für 'zu lang; nicht gelesen '- es ist im Grunde das gleiche wie eine Zusammenfassung in einer Zeitung. Ich werde meinen Beitrag bearbeiten. – Stael

+0

@MissComputing - aktualisiert, haben Sie es versucht? – Stael