2015-06-12 2 views
0

Я ученик средней школы, проводящий курс по разработке и разработке программного обеспечения для моего HSC, я пытался изучить pygame, и я занимался некоторой работой со спрайтами и комнатами, поскольку я закончил код, в котором я столкнулся с рядом ошибок.Ошибка при использовании sprite-модуля в python 3.1

Во-первых здесь исходный код:

import pygame 

BLACK = ( 0, 0, 0) 
WHITE = (255, 255, 255) 
BLUE = ( 0, 0, 255) 
GREEN = ( 0, 255, 0) 
RED = (255, 0, 0) 
PURPLE = (255, 0, 255) 


class Wall(pygame.sprite.Sprite): 
"""This class represents the bar at the bottom that the player controls """ 

def __init__(self, x, y, width, height, color): 
    """ Constructor function """ 

    # Call the parent's constructor 
    super().__init__() 

    # Make a BLUE wall, of the size specified in the parameters 
    self.image = pygame.Surface([width, height]) 
    self.image.fill(color) 

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

class Player(pygame.sprite.Sprite): 
""" This class represents the bar at the bottom that the player controls """ 

# Set speed vector 
change_x = 0 
change_y = 0 

def __init__(self, x, y): 
    """ Constructor function """ 

    # Call the parent's constructor 
    super().__init__() 

    # Set height, width 
    self.image = pygame.Surface([15, 15]) 
    self.image.fill(WHITE) 

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

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

def move(self, walls): 
    """ Find a new position for the player """ 

    # Move left/right 
    self.rect.x += self.change_x 

    # Did this update cause us to hit a wall? 
    block_hit_list = pygame.sprite.spritecollide(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, 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 

class Room(object): 
""" Base class for all rooms. """ 

""" Each room has a list of walls, and of enemy sprites. """ 
wall_list = None 
enemy_sprites = None 

def __init__(self): 
    """ Constructor, create our lists. """ 
    self.wall_list = pygame.sprite.Group() 
    self.enemy_sprites = pygame.sprite.Group() 

class Room1(Room): 
"""This creates all the walls in room 1""" 
def __init__(self): 
    Room.__init__(self) 
    # Make the walls. (x_pos, y_pos, width, height) 

    # This is a list of walls. Each is in the form [x, y, width, height] 
    walls = [[0, 0, 20, 250, WHITE], 
      [0, 350, 20, 250, WHITE], 
      [780, 0, 20, 250, WHITE], 
      [780, 350, 20, 250, WHITE], 
      [20, 0, 760, 20, WHITE], 
      [20, 580, 760, 20, WHITE], 
      [390, 50, 20, 500, BLUE] 
      ] 

    # Loop through the list. Create the wall, add it to the list 
    for item in walls: 
     wall = Wall(item[0], item[1], item[2], item[3], item[4]) 
     self.wall_list.add(wall) 

class Room2(Room): 
"""This creates all the walls in room 2""" 
def __init__(self): 
    Room.__init__(self) 

    walls = [[0, 0, 20, 250, RED], 
      [0, 350, 20, 250, RED], 
      [780, 0, 20, 250, RED], 
      [780, 350, 20, 250, RED], 
      [20, 0, 760, 20, RED], 
      [20, 580, 760, 20, RED], 
      [190, 50, 20, 500, GREEN], 
      [590, 50, 20, 500, GREEN] 
      ] 

    for item in walls: 
     wall = Wall(item[0], item[1], item[2], item[3], item[4]) 
     self.wall_list.add(wall) 


class Room3(Room): 
"""This creates all the walls in room 3""" 
def __init__(self): 
    Room.__init__(self) 

    walls = [[0, 0, 20, 250, PURPLE], 
      [0, 350, 20, 250, PURPLE], 
      [780, 0, 20, 250, PURPLE], 
      [780, 350, 20, 250, PURPLE], 
      [20, 0, 760, 20, PURPLE], 
      [20, 580, 760, 20, PURPLE] 
      ] 

    for item in walls: 
     wall = Wall(item[0], item[1], item[2], item[3], item[4]) 
     self.wall_list.add(wall) 

    for x in range(100, 800, 100): 
     for y in range(50, 451, 300): 
      wall = Wall(x, y, 20, 200, RED) 
      self.wall_list.add(wall) 

    for x in range(150, 700, 100): 
     wall = Wall(x, 200, 20, 200, WHITE) 
     self.wall_list.add(wall) 

def main(): 
""" Main Program """ 

# Call this function so the Pygame library can initialize itself 
pygame.init() 

# Create an 800x600 sized screen 
screen = pygame.display.set_mode([800, 600]) 

# Set the title of the window 
pygame.display.set_caption('Maze Runner') 

# Create the player paddle object 
player = Player(50, 50) 
movingsprites = pygame.sprite.Group() 
movingsprites.add(player) 

rooms = [] 

room = Room1() 
rooms.append(room) 

room = Room2() 
rooms.append(room) 

room = Room3() 
rooms.append(room) 

current_room_no = 0 
current_room = rooms[current_room_no] 

clock = pygame.time.Clock() 

done = False 

while not done: 

    # --- Event Processing --- 

    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      done = True 

     if event.type == pygame.KEYDOWN: 
      if event.key == pygame.K_LEFT: 
       player.changespeed(-5, 0) 
      if event.key == pygame.K_RIGHT: 
       player.changespeed(5, 0) 
      if event.key == pygame.K_UP: 
       player.changespeed(0, -5) 
      if event.key == pygame.K_DOWN: 
       player.changespeed(0, 5) 

     if event.type == pygame.KEYUP: 
      if event.key == pygame.K_LEFT: 
       player.changespeed(5, 0) 
      if event.key == pygame.K_RIGHT: 
       player.changespeed(-5, 0) 
      if event.key == pygame.K_UP: 
       player.changespeed(0, 5) 
      if event.key == pygame.K_DOWN: 
       player.changespeed(0, -5) 

    # --- Game Logic --- 

    player.move(current_room.wall_list) 

    if player.rect.x < -15: 
     if current_room_no == 0: 
      current_room_no = 2 
      current_room = rooms[current_room_no] 
      player.rect.x = 790 
     elif current_room_no == 2: 
      current_room_no = 1 
      current_room = rooms[current_room_no] 
      player.rect.x = 790 
     else: 
      current_room_no = 0 
      current_room = rooms[current_room_no] 
      player.rect.x = 790 

    if player.rect.x > 801: 
     if current_room_no == 0: 
      current_room_no = 1 
      current_room = rooms[current_room_no] 
      player.rect.x = 0 
     elif current_room_no == 1: 
      current_room_no = 2 
      current_room = rooms[current_room_no] 
      player.rect.x = 0 
     else: 
      current_room_no = 0 
      current_room = rooms[current_room_no] 
      player.rect.x = 0 

    # --- Drawing --- 
    screen.fill(BLACK) 

    movingsprites.draw(screen) 
    current_room.wall_list.draw(screen) 

    pygame.display.flip() 

    clock.tick(60) 

pygame.quit() 

if __name__ == "__main__": 
main() 

Когда я побежал код в оболочке Python следующие ошибки показали:

Traceback (most recent call last): 
    File "C:\Users\jack.portegies.KELSO-H.000\Desktop\maze_runner.py", line  273, in <module> 
main() 
File "C:\Users\jack.portegies.KELSO-H.000\Desktop\maze_runner.py", line 180, in main 
movingsprites.add(player) 
    File "C:\Python31\lib\site-packages\pygame\sprite.py", line 221, in add 
    if not self.has_internal(sprite): 
     File "C:\Python31\lib\site-packages\pygame\sprite.py", line 195, in has_internal 
    return self.spritedict.has_key(sprite) 
AttributeError: 'dict' object has no attribute 'has_key' 

Я пошел, чтобы посмотреть в модуле спрайтов в том, что кто-то, возможно, изменил его (как я должен использовать общий компьютер), и вот этот модуль:

class Sprite(object): 
"""The base class for your visible game objects. 
    The sprite class is meant to be used as a base class 
    for the objects in your game. It just provides functions 
    to maintain itself in different groups. 

    You can initialize a sprite by passing it a group or sequence 
    of groups to be contained in. 

    When you subclass Sprite, you must call this 
    pygame.sprite.Sprite.__init__(self) before you add the sprite 
    to any groups, or you will get an error.""" 

def __init__(self, *groups): 
    self.__g = {} # The groups the sprite is in 
    if groups: self.add(groups) 

def add(self, *groups): 
    """add(group or list of of groups, ...) 
     add a sprite to container 

     Add the sprite to a group or sequence of groups.""" 
    has = self.__g.has_key 
    for group in groups: 
     if hasattr(group, '_spritegroup'): 
      if not has(group): 
       group.add_internal(self) 
       self.add_internal(group) 
     else: self.add(*group) 

def remove(self, *groups): 
    """remove(group or list of groups, ...) 
     remove a sprite from container 

     Remove the sprite from a group or sequence of groups.""" 
    has = self.__g.has_key 
    for group in groups: 
     if hasattr(group, '_spritegroup'): 
      if has(group): 
       group.remove_internal(self) 
       self.remove_internal(group) 
     else: self.remove(*group) 

def add_internal(self, group): 
    self.__g[group] = 0 

def remove_internal(self, group): 
    del self.__g[group] 

def update(self, *args): 
    pass 

def kill(self): 
    """kill() 
     remove this sprite from all groups 

     Removes the sprite from all the groups that contain 
     it. The sprite still exists after calling this, 
     so you could use it to remove a sprite from all groups, 
     and then add it to some other groups.""" 
    for c in self.__g.keys(): 
     c.remove_internal(self) 
    self.__g.clear() 

def groups(self): 
    """groups() -> list of groups 
     list used sprite containers 

     Returns a list of all the groups that contain this 
     sprite. These are not returned in any meaningful order.""" 
    return self.__g.keys() 

def alive(self): 
    """alive() -> bool 
     check to see if the sprite is in any groups 

     Returns true if this sprite is a member of any groups.""" 
    return (len(self.__g) != 0) 

def __repr__(self): 
    return "<%s sprite(in %d groups)>" % (self.__class__.__name__, len(self.__g)) 

class AbstractGroup(object): 
"""A base for containers for sprites. It does everything 
    needed to behave as a normal group. You can easily inherit 
    a new group class from this, or the other groups below, 
    if you want to add more features. 

    Any AbstractGroup-derived sprite groups act like sequences, 
    and support iteration, len, and so on.""" 

# dummy val to identify sprite groups, and avoid infinite recursion. 
_spritegroup = True 

def __init__(self): 
    self.spritedict = {} 
    self.lostsprites = [] 

def sprites(self): 
    """sprites() 
     get a list of sprites in the group 

     Returns an object that can be looped over with a 'for' loop. 
     (For now it is always a list, but newer version of Python 
     could return different iterators.) You can also iterate directly 
     over the sprite group.""" 
    return self.spritedict.keys() 

def add_internal(self, sprite): 
    self.spritedict[sprite] = 0 

def remove_internal(self, sprite): 
    r = self.spritedict[sprite] 
    if r is not 0: 
     self.lostsprites.append(r) 
    del(self.spritedict[sprite]) 

def has_internal(self, sprite): 
    return self.spritedict.has_key(sprite) 

def copy(self): 
    """copy() 
     copy a group with all the same sprites 

     Returns a copy of the group that is the same class 
     type, and has the same sprites in it.""" 
    return self.__class__(self.sprites()) 

def __iter__(self): 
    return iter(self.sprites()) 

def __contains__(self, sprite): 
    return self.has(sprite) 

def add(self, *sprites): 
    """add(sprite, list, or group, ...) 
     add sprite to group 

     Add a sprite or sequence of sprites to a group.""" 
    for sprite in sprites: 
     # It's possible that some sprite is also an iterator. 
     # If this is the case, we should add the sprite itself, 
     # and not the objects it iterates over. 
     if isinstance(sprite, Sprite): 
      if not self.has_internal(sprite): 
       self.add_internal(sprite) 
       sprite.add_internal(self) 
     else: 
      try: 
       # See if sprite is an iterator, like a list or sprite 
       # group. 
       for spr in sprite: 
        self.add(spr) 
      except (TypeError, AttributeError): 
       # Not iterable, this is probably a sprite that happens 
       # to not subclass Sprite. Alternately, it could be an 
       # old-style sprite group. 
       if hasattr(sprite, '_spritegroup'): 
        for spr in sprite.sprites(): 
         if not self.has_internal(spr): 
          self.add_internal(spr) 
          spr.add_internal(self) 
       elif not self.has_internal(sprite): 
        self.add_internal(sprite) 
        sprite.add_internal(self) 

def remove(self, *sprites): 
    """remove(sprite, list, or group, ...) 
     remove sprite from group 

     Remove a sprite or sequence of sprites from a group.""" 
    # This function behaves essentially the same as Group.add. 
    # Check for Spritehood, check for iterability, check for 
    # old-style sprite group, and fall back to assuming 
    # spritehood. 
    for sprite in sprites: 
     if isinstance(sprite, Sprite): 
      if self.has_internal(sprite): 
       self.remove_internal(sprite) 
       sprite.remove_internal(self) 
     else: 
      try: 
       for spr in sprite: self.remove(spr) 
      except (TypeError, AttributeError): 
       if hasattr(sprite, '_spritegroup'): 
        for spr in sprite.sprites(): 
         if self.has_internal(spr): 
          self.remove_internal(spr) 
          spr.remove_internal(self) 
       elif self.has_internal(sprite): 
        self.remove_internal(sprite) 
        sprite.remove_internal(self) 

def has(self, *sprites): 
    """has(sprite or group, ...) 
     ask if group has a sprite or sprites 

     Returns true if the given sprite or sprites are 
     contained in the group. You can also use 'sprite in group' 
     or 'subgroup in group'.""" 
    # Again, this follows the basic pattern of Group.add and 
    # Group.remove. 
    for sprite in sprites: 
     if isinstance(sprite, Sprite): 
      return self.has_internal(sprite) 

     try: 
      for spr in sprite: 
       if not self.has(sprite): 
        return False 
      return True 
     except (TypeError, AttributeError): 
      if hasattr(sprite, '_spritegroup'): 
       for spr in sprite.sprites(): 
        if not self.has_internal(spr): 
         return False 
       return True 
      else: 
       return self.has_internal(sprite) 

def update(self, *args): 
    """update(*args) 
     call update for all member sprites 

     calls the update method for all sprites in the group. 
     Passes all arguments on to the Sprite update function.""" 
    for s in self.sprites(): s.update(*args) 

def draw(self, surface): 
    """draw(surface) 
     draw all sprites onto the surface 

     Draws all the sprites onto the given surface.""" 
    sprites = self.sprites() 
    surface_blit = surface.blit 
    for spr in sprites: 
     self.spritedict[spr] = surface_blit(spr.image, spr.rect) 
    self.lostsprites = [] 

def clear(self, surface, bgd): 
    """clear(surface, bgd) 
     erase the previous position of all sprites 

     Clears the area of all drawn sprites. the bgd 
     argument should be Surface which is the same 
     dimensions as the surface. The bgd can also be 
     a function which gets called with the passed 
     surface and the area to be cleared.""" 
    if callable(bgd): 
     for r in self.lostsprites: 
      bgd(surface, r) 
     for r in self.spritedict.values(): 
      if r is not 0: bgd(surface, r) 
    else: 
     surface_blit = surface.blit 
     for r in self.lostsprites: 
      surface_blit(bgd, r, r) 
     for r in self.spritedict.values(): 
      if r is not 0: surface_blit(bgd, r, r) 

def empty(self): 
    """empty() 
     remove all sprites 

     Removes all the sprites from the group.""" 
    for s in self.sprites(): 
     self.remove_internal(s) 
     s.remove_internal(self) 

def __nonzero__(self): 
    return (len(self.sprites()) != 0) 

def __len__(self): 
    """len(group) 
     number of sprites in group 

     Returns the number of sprites contained in the group.""" 
    return len(self.sprites()) 

def __repr__(self): 
    return "<%s(%d sprites)>" % (self.__class__.__name__, len(self)) 

class Group(AbstractGroup): 
"""The basic Group class you will want to use. 
    It supports all of the above operations and methods. 

    The RenderPlain and RenderClear groups are aliases to Group 
    for compatibility.""" 

def __init__(self, *sprites): 
    AbstractGroup.__init__(self) 
    self.add(*sprites) 

RenderPlain = Group 
RenderClear = Group 

class RenderUpdates(Group): 
"""A sprite group that's more efficient at updating. 
    This group supports drawing to the screen, but its draw method 
    also returns a list of the Rects updated by the draw (and any 
    clears in between the last draw and the current one). You 
    can use pygame.display.update(renderupdates_group.draw(screen)) 
    to minimize the updated part of the screen. This can usually 
    make things much faster.""" 

def draw(self, surface): 
    spritedict = self.spritedict 
    surface_blit = surface.blit 
    dirty = self.lostsprites 
    self.lostsprites = [] 
    dirty_append = dirty.append 
    for s in self.sprites(): 
     r = spritedict[s] 
     newrect = surface_blit(s.image, s.rect) 
     if r is 0: 
      dirty_append(newrect) 
     else: 
      if newrect.colliderect(r): 
       dirty_append(newrect.union(r)) 
      else: 
       dirty_append(newrect) 
       dirty_append(r) 
     spritedict[s] = newrect 
    return dirty 

class OrderedUpdates(RenderUpdates): 
"""RenderUpdates, but the sprites are drawn in the order they were added. 
    More recently added sprites are drawn last (and so, above other 
    sprites).""" 

def __init__(self, *sprites): 
    self._spritelist = [] 
    RenderUpdates.__init__(self, *sprites) 

def sprites(self): return list(self._spritelist) 

def add_internal(self, sprite): 
    RenderUpdates.add_internal(self, sprite) 
    self._spritelist.append(sprite) 

def remove_internal(self, sprite): 
    RenderUpdates.remove_internal(self, sprite) 
    self._spritelist.remove(sprite) 

class GroupSingle(AbstractGroup): 
"""A group container that holds a single most recent item. 
    This class works just like a regular group, but it only 
    keeps a single sprite in the group. Whatever sprite has 
    been added to the group last, will be the only sprite in 
    the group. 

    You can access its one sprite as the .sprite attribute. 
    Assigning to this attribute will properly remove the old 
    sprite and then add the new one.""" 

def __init__(self, sprite = None): 
    self.__sprite = None 
    if sprite is not None: self.add(sprite) 

def copy(self): 
    return GroupSingle(self.__sprite) 

def sprites(self): 
    if self.__sprite is not None: return [self.__sprite] 
    else: return [] 

def add_internal(self, sprite): 
    if self.__sprite is not None: 
     self.__sprite.remove_internal(self) 
    self.__sprite = sprite 

def __nonzero__(self): return (self.__sprite is not None) 

def _get_sprite(self): 
    return self.__sprite 

def _set_sprite(self, sprite): 
    self.add_internal(sprite) 
    sprite.add_internal(self) 
    return sprite 

sprite = property(_get_sprite, _set_sprite, None, 
        "The sprite contained in this group") 

def remove_internal(self, sprite): 
    if sprite is self.__sprite: self.__sprite = None 

def has_internal(self, sprite): 
    return (self.__sprite is sprite) 

# Optimizations... 
def __contains__(self, sprite): return (self.__sprite is sprite) 

def spritecollide(sprite, group, dokill): 
"""pygame.sprite.spritecollide(sprite, group, dokill) -> list 
    collision detection between sprite and group 

    given a sprite and a group of sprites, this will 
    return a list of all the sprites that intersect 
    the given sprite. 
    all sprites must have a "rect" value, which is a 
    rectangle of the sprite area. if the dokill argument 
    is true, the sprites that do collide will be 
    automatically removed from all groups.""" 
crashed = [] 
spritecollide = sprite.rect.colliderect 
if dokill: 
    for s in group.sprites(): 
     if spritecollide(s.rect): 
      s.kill() 
      crashed.append(s) 
else: 
    for s in group: 
     if spritecollide(s.rect): 
      crashed.append(s) 
return crashed 

def groupcollide(groupa, groupb, dokilla, dokillb): 
"""pygame.sprite.groupcollide(groupa, groupb, dokilla, dokillb) -> dict 
    collision detection between group and group 

    given two groups, this will find the intersections 
    between all sprites in each group. it returns a 
    dictionary of all sprites in the first group that 
    collide. the value for each item in the dictionary 
    is a list of the sprites in the second group it 
    collides with. the two dokill arguments control if 
    the sprites from either group will be automatically 
    removed from all groups.""" 
crashed = {} 
SC = spritecollide 
if dokilla: 
    for s in groupa.sprites(): 
     c = SC(s, groupb, dokillb) 
     if c: 
      crashed[s] = c 
      s.kill() 
else: 
    for s in groupa: 
     c = SC(s, groupb, dokillb) 
     if c: 
      crashed[s] = c 
return crashed 

def spritecollideany(sprite, group): 
"""pygame.sprite.spritecollideany(sprite, group) -> sprite 
    finds any sprites that collide 

    given a sprite and a group of sprites, this will 
    return return any single sprite that collides with 
    with the given sprite. If there are no collisions 
    this returns None. 

    if you don't need all the features of the 
    spritecollide function, this function will be a 
    bit quicker. 

    all sprites must have a "rect" value, which is a 
    rectangle of the sprite area.""" 
spritecollide = sprite.rect.colliderect 
for s in group: 
    if spritecollide(s.rect): 
     return s 
return None 

Было бы здорово, если бы кто-то помог мне справиться с этим, поскольку я спросил своего учителя, и он направил меня на этот сайт, так что пальцы, скрещенные, кто-то может помочь! не

ответ

-1

Я тоже изучаю один и тот же курс (я также использую тот же компьютер, что и вы). Копирование сопоставленного каталога Python в вашу собственную, по-видимому, устранило проблему для меня. Попробуй это?

+0

Привет, ты тоже занимаешь эту неподвижную шахту – Tacticus

1

has_key больше не используется в python3 просто использовать in:

return sprite in self.spritedict 

Если код изначально был написан для python2, то могут быть и другие вопросы, как python3 не имеет обратной совместимости с python2.

+0

Я использую Python3.1, есть ли вероятность того, что версия Pygame не совместима с этой версией Python? – Tacticus

+0

@Tacticus, как вы установили pygame? Вы действительно установили версию для python3? Если у вас все будет хорошо, вы будете использовать синтаксис и код, совместимый с python3 –

+0

, поскольку я сказал, что использую общий компьютер, Pygame был установлен учителем. самая странная вещь - все это отлично работает на других компьютерах, и у меня никогда не было этой проблемы до нескольких недель назад !? – Tacticus

Смежные вопросы