用Python和Pygame写游戏-从入门到精通(16)

By | 2011/07/19

经历了长年的艰苦卓绝的披星戴月的惨绝人寰的跋山涉水,我们终于接近了AI之旅的尾声(好吧,实际上我们这才是刚刚开始)。这一次真正展示一下这几回辛勤工作的结果,最后的画面会是这个样子:

蚁巢系统AI演示

下面给出完整代码(注意需要gameobjects库才可以运行,参考之前的向量篇):

这个程序的长度超过了以往任何一个,甚至可能比我们写的加起来都要长一些。然而它可以展现给我们的也前所未有的惊喜。无数勤劳的小蚂蚁在整个地图上到处觅食,随机出现的叶子一旦被蚂蚁发现,就会搬回巢穴,而蜘蛛一旦出现在巢穴范围之内,就会被蚂蚁们群起而攻之,直到被驱逐出地图范围或者挂了,蜘蛛的尸体也会被带入巢穴。

这个代码写的不够漂亮,没有用太高级的语法,甚至都没有注释天哪……基本代码都在前面出现了,只是新引入了四个新的状态,AntStateExploringAntStateSeekingAntStateDeliveringAntStateHunting,意义的话前面已经说明。比如说AntStateExploring,继承了基本的Stat,这个状态的动作平时就是让蚂蚁以一个随机的速度走向屏幕随机一个点,在此过程中,check_conditions会不断检查周围的环境,发现了树叶或蜘蛛都会采取相应的措施(进入另外一个状态)。

游戏设计艺术中,创建一个漂亮的AI是非常有挑战性也非常有趣的事情。好的AI能让玩家沉浸其中,而糟糕的AI则让人感到非常乏味(有的时候AI中的一些bug被当作秘籍使用,也挺有意思的,不过如果到处是“秘籍”,可就惨了)。而且,AI是否足够聪明有时候并不与代码量直接相关,看看我们这个演示,感觉上去蚂蚁会合作攻击蜘蛛,而实际上它们都是独立行动的,不过就结果而言蚂蚁们看起来都很聪明。

对AI而已,状态机是个很有力的工具(当然状态机不仅仅用在这里),因为状态机可以把复杂的系统分割成几个容易实现的小段。而这每一小部分都是对一些简单思考或动作的模拟,即便不是那么容易转化为代码,也很容易模拟。在游戏中,我们只需要模拟就足够了。

我们这几次讲述的东西相当有用,尽管不是那么直观,但对于游戏设计至关重要,而此次的蚁巢演示,也给我们揭示了AI系统的种种,至少这个系统式可以运作的了,不错不错~ 参天大树也是从小树苗开始的。

本次使用的图像资源:

叶子:leaf.png
蚂蚁:ant.png
蜘蛛:spider.png

下一次,我们开始更加激动人心的项目,3D图像!

>> 用Python和Pygame写游戏-从入门到精通(17)

有26人评论 用Python和Pygame写游戏-从入门到精通(16)

  1. fliks

    请问有编译好的exe吗,博主用什么编译exe呢,我试了几个都不好用

    回复
  2. solu

    跟着例子修修改改,终于运行起来了,效果不错。:)

    回复
  3. nanjingyueliang

    代码311行中,spider.destination = Vector2(w+50, randint(0, h)),其中(w+50),这个50是的功能是啥??

    回复
  4. heloo

    不知道有没有人和我有一样的错误。
    pYthon版本3.3,提示字典在操作过程中长度发生了变化。
    解决方法:
    import copy
    在出错行前写entities2 = copy.copy(self.entity)
    将下面的self.entity改成 entities2
    这样就避免了直接操作在循环内会改变的字典,而是使用了一个拷贝。
    如果直接用赋值语句的话可能会因为内存位置没变而导致还是一样的问题。

    回复
      1. NEW

        感谢,不过不是把那个函数改成这个样子吗?
        def process(self, time_passed):
        time_passed_seconds = time_passed / 1000.0
        entities2 = copy.copy(self.entities)
        for entity in entities2.values():
        entity.process(time_passed_seconds)

        回复
  5. 白杰

    distance = location.get_distance_to(entity.location) 这个我一直报错,’Vector2′ object has no attribute ‘get_distance_to’
    我的Vector2确实没有这个方法,能给下这方法的代码么?初学,好多东西都不明白

    回复
    1. heloo

      很明显就是距离的意思嘛
      Import个math
      使用math.sqrt 和**2就解决问题了

      回复
  6. 赵林林

    Py2EXE打包报错:
    Traceback (most recent call last):
    File “C:\Users\Administrator\Desktop\python\pygame\PyGame_Py2exe.py”, line 172, in
    BuildExe().run()
    File “C:\Users\Administrator\Desktop\python\pygame\PyGame_Py2exe.py”, line 163, in run
    data_files = extra_datas,
    File “C:\Python27\lib\distutils\core.py”, line 169, in setup
    raise SystemExit, “error: ” + str(msg)
    SystemExit: error: command ‘C:\Python27\pythonw.exe’ failed with exit status 1

    这是什么意思啊?

    回复
  7. LiuMiu

    第276行 self.speed 改为 self.ant.speed.
    感谢作者,有趣的例子。

    回复
  8. 欧阳灵

    Traceback (most recent call last):
    File “E:\Python27\ant_game.py”, line 325, in
    run()
    File “E:\Python27\ant_game.py”, line 319, in run
    world.process(time_passed)
    File “E:\Python27\ant_game.py”, line 75, in process
    entity.process(time_passed_seconds)
    File “E:\Python27\ant_game.py”, line 111, in process
    self.brain.think()
    File “E:\Python27\ant_game.py”, line 40, in think
    new_state_name = self.active_state.check_conditions()
    File “E:\Python27\ant_game.py”, line 197, in check_conditions
    leaf = self.ant.world.get_close_entity(“leaf”, self.ant.location)
    File “E:\Python27\ant_game.py”, line 83, in get_close_entity
    location = Vector2(*location)
    TypeError: type object argument after * must be a sequence, not Vector2

    请问楼主,这是什么错啊

    回复
    1. xishui 作者

      不知道是否因为库有更新还是阁下输入有误造成的,代码的83行,location必须是个序列,而不能是Vector2类型

      回复
      1. 欧阳灵

        我就是你运行上面的16章中的这段代码,运行时码报的错,win7 64位系统。这个*location本来就是将location的坐标展开。之前的代码中这样用比如把鼠标位置的点展开传给Vector2( *pygame.mouse.get_pos() )也没有报错。在这里报错了我实在理解不了。请楼主帮忙分析一下

        回复
      2. 欧阳灵

        我修改了一下Vector2的代码,上面的问题解决了。但是在 函数迭代的时候报错:运行一会儿之后就会报错
        def render(self, surface):
        surface.blit(self.background, (0, 0))
        for entity in self.entities.itervalues():
        entity.render(surface)

        File “E:\Python27\test_ant.py”, line 63, in process
        for entity in self.entities.itervalues():
        RuntimeError: dictionary changed size during iteration

        回复
        1. xishui 作者

          这样看不出来哦,只看提示的话dict在遍历的时候被修改了?

          回复
  9. nbWoman

    楼主很厉害,不过我看的画面有点恶心,讨厌虫子

    回复
  10. wangwlj

    感谢上面的评论,让我这个小白在python3.5下也弄成功了
    下面总结一下修改的地方:
    1. 出错AttributeError: ‘dict’ object has no attribute ‘itervalues’
    80、75行(附近)修改为:for entity in self.entities.values(): #去掉inter即可
    2.出错RuntimeError: dictionary changed size during iteration
    解决方法:(借用上面评论的大哥)
    import copy
    在出错行前写entities2 = copy.copy(self.entities) ——70行附近
    将下面的self.entity改成 entities2
    这样就避免了直接操作在循环内会改变的字典,而是使用了一个拷贝。

    3.还有一个xrange 改为range就好了

    回复
  11. Pingback: 用Python和Pygame写游戏从入门到精通(16) | 演道网

  12. 杭州夜未央

    按照楼主和各位大侠的代码,运行的时候只有蜘蛛在运动,蚂蚁不动,请问谁知道是怎么回事?谢谢

    回复
    1. 杭州夜未央

      一个状态机的check_conditions函数名写错了,造成没有调用,汗~~~~~

      回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注