-2

我正在使用 pygame 和 libtcodpy 库使用 python 2.7 创建一个类似流氓的游戏。这是一个基于图块的游戏,当我尝试实现一个名为“轮流”的功能时,它会在玩家每次移动时将敌人向左移动一个空间 - 它对玩家应用相同的功能,结果非常错误并让“PLAYER”也左移一格。错误发生在第 101 行。我正在查看是否有人可以指出该缺陷。我试图用这个建议来解决它,但不知道他想让我把代码行放在哪里:

“即使我把self.ai = aiif 语句放在外面,我仍然会收到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'

4

1 回答 1

1

我认为你的问题在这里:

我认为通过不为其分配特定的 ai,在初始化函数中初始化的 PLAYER 将忽略“轮流”功能。

如果您将某些内容设置为None,它不会忽略您调用的所有内容,它会在AttributeError您尝试调用任何内容时引发 a 。


一种选择是在调用之前检查值:

for obj in GAME_OBJECTS:
    if obj.ai:
        obj.ai.take_turn()

如果这绝对是您将使用该属性的唯一地方ai,那么这可能是最好的答案。


但是,如果您要在多个地方使用它,那么在 7 个地方进行检查就太容易了,而忘记了第 8 个地方并得到仅在奇怪情况下发生的神秘错误。在这种情况下,您确实希望它按照您期望的方式运行,而这样做的方法是分配一些自动忽略“轮流”功能的“虚拟”对象。

最简单的版本是:

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所以在不检查的情况下调用该方法总是安全的。

于 2018-07-09T23:54:56.783 回答