“Nonetype 对象在 Pygame 中没有属性 'take turn'。挂在单行上
"Nonetype object has no attribute 'take turn' in Pygame. Hung up on a single line
我正在用 python 2.7 创建一个类流氓游戏,使用 pygame 和 libtcodpy 库。这是一个基于图块的游戏,当我尝试实现一个名为 'take turn' 的函数时,每次玩家移动时都会将敌人 space 移动到左侧 - 它对玩家应用了相同的函数并且结果非常有问题,"PLAYER" 也向左移动了一个 space。错误发生在第 101 行。我正在查看是否有人可以指出该缺陷。我尝试使用此建议解决它,但无法弄清楚他要我把代码行放在哪里:
“即使我将 self.ai = ai
放在 if 语句之外,我仍然收到 NoneType
没有名为 take_turn
的函数的错误。
我怀疑与 'ai' 和 'take_turn' 函数相关的任何错误。
我通过创建一个名为 ai_Player 的新 ai 解决了这个问题,在 take_turn 函数中我只是输入了 return,所以它什么都不做。奇迹般有效。 (不要忘记将 AI 添加到播放器)"
我的代码如下(星号表示我删除代码并重新制作游戏的地方运行):
class obj_Actor:
def __init__(self, x, y, name_object, sprite, creature = None, ai = None):
self.x = x #map address
self.y = y #map address
self.sprite = sprite
self.creature = creature
if creature:
creature.owner = self
**self.ai = ai
if ai:
ai.owner = self**
def draw(self):
SURFACE_MAIN.blit(self.sprite, (self.x*constants.CELL_WIDTH, self.y*constants.CELL_HEIGHT))
def move(self, dx, dy):
if GAME_MAP[self.x + dx][self.y + dy].block_path == False:
self.x += dx
self.y += dy
**class ai_Test:
def take_turn(self):
self.owner.move(-1, 0)**
def game_main_loop():
game_quit = False
#player action definition
player_action = 'no-action'
while not game_quit:
#handle player input
player_action = game_handle_keys()
if player_action == 'QUIT':
game_quit == True
**if player_action != 'no-action':
for obj in GAME_OBJECTS:
obj.ai.take_turn()**
#TODO draw the game
draw_game()
#quit the game
pygame.quit()
exit()
def game_initialize():
#This function, initializes main window, and pygame
global SURFACE_MAIN, GAME_MAP, PLAYER, ENEMY, GAME_OBJECTS
#initialize pygame
pygame.init()
SURFACE_MAIN = pygame.display.set_mode( (constants.GAME_WIDTH,constants.GAME_HEIGHT) )
GAME_MAP = map_create()
creature_com1 = com_Creature('Greg')
PLAYER = obj_Actor(0, 0, "Human", constants.S_PLAYER, creature = creature_com1)
creature_com2 = com_Creature('Skeletor')
**ai_com = ai_Test()**
ENEMY = obj_Actor(15, 15, 'Skeleton', constants.S_ENEMY, **ai = ai_com)**
GAME_OBJECTS = [PLAYER, ENEMY]
#execute game
def game_handle_keys():
#gets player input
events_list = pygame.event.get()
#process player input
for event in events_list:
if event.type == pygame.QUIT:
return 'QUIT'
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
PLAYER.move(0, -1)
return 'player-moved'
if event.key == pygame.K_DOWN:
PLAYER.move(0, 1)
return 'player-moved'
if event.key == pygame.K_LEFT:
PLAYER.move(-1, 0)
return 'player-moved'
if event.key == pygame.K_RIGHT:
PLAYER.move (1, 0)
return 'player-moved'
return "no-action"
if __name__ == '__main__':
game_initialize()
game_main_loop()
Traceback (most recent call last):
File "/Users/wills/Desktop/my-pygame/my_pygame.py", line 152, in <module>
game_main_loop()
File "/Users/wills/Desktop/my-pygame/my_pygame.py", line 93, in game_main_loop
obj.ai.take_turn()
AttributeError: obj_Actor instance has no attribute 'ai'
我认为你的问题出在这里:
I thought by not assigning it a specific ai, PLAYER which is initialized in the initialize function would ignore the "take turn" function.
如果您将某些内容设置为 None
,它不会忽略您对其调用的所有内容,它会在您尝试调用任何内容时引发 AttributeError
。
一个选项是在调用之前检查值:
for obj in GAME_OBJECTS:
if obj.ai:
obj.ai.take_turn()
如果这绝对是您唯一会使用 ai
属性的地方,那么这可能是最佳答案。
但是如果你打算在多个地方使用它,那么很容易在 7 个地方进行检查而忘记第 8 个地方并且得到只在奇怪的情况下才会发生的神秘错误。在那种情况下,您确实希望它按照您期望的方式运行,而这样做的方法是分配一些自动忽略 "take turn" 函数的 "dummy" 对象。
最简单的版本是:
class DummyPlayer:
def take_turn(self):
pass
然后,当您将播放器分配给 None
时,将其分配给 DummyPlayer
实例。我想就在这里:
class obj_Actor:
def __init__(self, x, y, name_object, sprite, creature = None, ai = None):
# etc.
if ai:
ai.owner = self
else:
ai = DummyPlayer()
self.ai = ai
# etc.
现在,self.ai
总是带有 take_turn
方法的东西——要么是真正的 AI,要么是 DummyPlayer
——所以不检查就调用该方法总是安全的。
我正在用 python 2.7 创建一个类流氓游戏,使用 pygame 和 libtcodpy 库。这是一个基于图块的游戏,当我尝试实现一个名为 'take turn' 的函数时,每次玩家移动时都会将敌人 space 移动到左侧 - 它对玩家应用了相同的函数并且结果非常有问题,"PLAYER" 也向左移动了一个 space。错误发生在第 101 行。我正在查看是否有人可以指出该缺陷。我尝试使用此建议解决它,但无法弄清楚他要我把代码行放在哪里:
“即使我将 self.ai = ai
放在 if 语句之外,我仍然收到 NoneType
没有名为 take_turn
的函数的错误。
我怀疑与 'ai' 和 'take_turn' 函数相关的任何错误。
我通过创建一个名为 ai_Player 的新 ai 解决了这个问题,在 take_turn 函数中我只是输入了 return,所以它什么都不做。奇迹般有效。 (不要忘记将 AI 添加到播放器)"
我的代码如下(星号表示我删除代码并重新制作游戏的地方运行):
class obj_Actor:
def __init__(self, x, y, name_object, sprite, creature = None, ai = None):
self.x = x #map address
self.y = y #map address
self.sprite = sprite
self.creature = creature
if creature:
creature.owner = self
**self.ai = ai
if ai:
ai.owner = self**
def draw(self):
SURFACE_MAIN.blit(self.sprite, (self.x*constants.CELL_WIDTH, self.y*constants.CELL_HEIGHT))
def move(self, dx, dy):
if GAME_MAP[self.x + dx][self.y + dy].block_path == False:
self.x += dx
self.y += dy
**class ai_Test:
def take_turn(self):
self.owner.move(-1, 0)**
def game_main_loop():
game_quit = False
#player action definition
player_action = 'no-action'
while not game_quit:
#handle player input
player_action = game_handle_keys()
if player_action == 'QUIT':
game_quit == True
**if player_action != 'no-action':
for obj in GAME_OBJECTS:
obj.ai.take_turn()**
#TODO draw the game
draw_game()
#quit the game
pygame.quit()
exit()
def game_initialize():
#This function, initializes main window, and pygame
global SURFACE_MAIN, GAME_MAP, PLAYER, ENEMY, GAME_OBJECTS
#initialize pygame
pygame.init()
SURFACE_MAIN = pygame.display.set_mode( (constants.GAME_WIDTH,constants.GAME_HEIGHT) )
GAME_MAP = map_create()
creature_com1 = com_Creature('Greg')
PLAYER = obj_Actor(0, 0, "Human", constants.S_PLAYER, creature = creature_com1)
creature_com2 = com_Creature('Skeletor')
**ai_com = ai_Test()**
ENEMY = obj_Actor(15, 15, 'Skeleton', constants.S_ENEMY, **ai = ai_com)**
GAME_OBJECTS = [PLAYER, ENEMY]
#execute game
def game_handle_keys():
#gets player input
events_list = pygame.event.get()
#process player input
for event in events_list:
if event.type == pygame.QUIT:
return 'QUIT'
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
PLAYER.move(0, -1)
return 'player-moved'
if event.key == pygame.K_DOWN:
PLAYER.move(0, 1)
return 'player-moved'
if event.key == pygame.K_LEFT:
PLAYER.move(-1, 0)
return 'player-moved'
if event.key == pygame.K_RIGHT:
PLAYER.move (1, 0)
return 'player-moved'
return "no-action"
if __name__ == '__main__':
game_initialize()
game_main_loop()
Traceback (most recent call last):
File "/Users/wills/Desktop/my-pygame/my_pygame.py", line 152, in <module>
game_main_loop()
File "/Users/wills/Desktop/my-pygame/my_pygame.py", line 93, in game_main_loop
obj.ai.take_turn()
AttributeError: obj_Actor instance has no attribute 'ai'
我认为你的问题出在这里:
I thought by not assigning it a specific ai, PLAYER which is initialized in the initialize function would ignore the "take turn" function.
如果您将某些内容设置为 None
,它不会忽略您对其调用的所有内容,它会在您尝试调用任何内容时引发 AttributeError
。
一个选项是在调用之前检查值:
for obj in GAME_OBJECTS:
if obj.ai:
obj.ai.take_turn()
如果这绝对是您唯一会使用 ai
属性的地方,那么这可能是最佳答案。
但是如果你打算在多个地方使用它,那么很容易在 7 个地方进行检查而忘记第 8 个地方并且得到只在奇怪的情况下才会发生的神秘错误。在那种情况下,您确实希望它按照您期望的方式运行,而这样做的方法是分配一些自动忽略 "take turn" 函数的 "dummy" 对象。
最简单的版本是:
class DummyPlayer:
def take_turn(self):
pass
然后,当您将播放器分配给 None
时,将其分配给 DummyPlayer
实例。我想就在这里:
class obj_Actor:
def __init__(self, x, y, name_object, sprite, creature = None, ai = None):
# etc.
if ai:
ai.owner = self
else:
ai = DummyPlayer()
self.ai = ai
# etc.
现在,self.ai
总是带有 take_turn
方法的东西——要么是真正的 AI,要么是 DummyPlayer
——所以不检查就调用该方法总是安全的。