游戏介绍

最近比较忙,周末正好有时间写了python版本的愤怒的小鸟,使用了物理引擎pymunk,图片资源是从github上下载的,实现了一个可玩的简单版本。

功能实现如下:

支持小鸟类型:红色小鸟,蓝色小鸟,黄色小鸟。

支持障碍物的类型:玻璃,木头,石头。

支持障碍物的形状:各种长度的长方形,正方形和圆形。

使用json文件保存关卡信息,设置小猪和障碍物的位置。

游戏截图如下:

图2

图3

完整代码

游戏实现代码的github链接 愤怒的小鸟

这边是csdn的下载链接 愤怒的小鸟

Pymunk介绍

pymunk是一个2D的物理引擎, 它实际是封装了 c语言写的2D物理引擎Chipmunk,可以实现碰撞,旋转等物理运动。

安装pymunk,可以直接使用pip工具,安装最新的pymunk 5.5.0:

1 pip install pymunk

介绍下在pymunk中会使用到的四个基本的类:

刚体 (pymunk.Body):一个刚体具有物体的物理属性(质量、坐标、旋转角度、速度等),它自己是没有形状的。

碰撞形状 (pymunk.Circle, pymunk.Segment and pymunk.Poly):通过将形状附加到实体,你可以定义一个实体的形状。你可以将多个形状附加到单个实体上来定义一个复杂的形状,如果不需要形状,则可以不附加任何形状。

约束/关节 (pymunk.constraint.PinJoint, pymunk.constraint.SimpleMotor):你可以在两个实体之间附加关节以约束它们的行为。比如在两个实体间保持一个固定的距离。

空间 (pymunk.Space): 空间是pymunk中基本的模拟单元。你可以添加实体,形状和关节到空间,然后整体更新空间。pymunk会控制空间中所有的实体,形状和关节如何相互作用。

代码实现

将物理引擎相关的代码单独放在了一个文件 (source\component\physics.py)中,减少代码的耦合。

定义了一个Physics类,向外提供所有物理引擎相关的函数。

这篇文章只介绍physics.py 中pymunk相关的代码。

pymunk相关初始化

reset 函数初始化了 空间类(pm.Space), 设置了两个参数

gravity : 重力

dt (Time step length) : 表示pymunk中每次更新的时间段值,比如dt值是0.002,表示时间段是0.002秒。

setup_lines函数设置了一条直线,作为地面。

Segment类创建了一条从点a 到 点b的直线。

1 class pymunk.Segment(body, a, b, radius)

2 Bases: pymunk.shapes.Shape

3 A line segment shape between two point. Meant mainly as a static shape.

交流群:632408235

1 import pymunk as pm

2

3 class Physics():

4 def __init__(self):

5 self.reset()

6

7 def reset(self, level=None):

8 self.level = level

9 # init space: set gravity and dt

10 self.space = pm.Space()

11 self.space.gravity = (0.0, -700.0)

12 self.dt = 0.002

13 self.birds = []

14 self.pigs = []

15 self.blocks = []

16 self.path_timer = 0

17 self.check_collide = False

18 self.setup_lines()

19 self.setup_collision_handler()

20

21 def setup_lines(self):

22 # Static Ground

23 x, y = to_pymunk(c.SCREEN_WIDTH, c.GROUND_HEIGHT)

24 static_body = pm.Body(body_type=pm.Body.STATIC)

25 static_lines = [pm.Segment(static_body, (0.0, y), (x, y), 0.0)]

26

27 for line in static_lines:

28 line.elasticity = 0.95

29 line.friction = 1

30 line.collision_type = COLLISION_LINE

31 self.space.add(static_lines)

32 self.static_lines = static_lines

setup_collision_handler 函数用来设置在两种类型的物体在碰撞发生时,可以由用户使用的回调函数。

add_collision_handler 函数添加两种类型物体a和b碰撞时会调用的handler。比如小猪和小鸟这两种类型物体的注册函数就是:add_collision_handler(COLLISION_PIG, COLLISION_BIRD)

1 add_collision_handler(collision_type_a, collision_type_b)

2 Return the CollisionHandler for collisions between objects of type collision_type_a and collision_type_b.

我们这里只用到了 post_solve 回调函数,在两个物体碰撞结束后,获取碰撞冲击力(collision impulse)。

1 post_solve

2 Two shapes are touching and their collision response has been processed.

3 func(arbiter, space, data)

4 You can retrieve the collision impulse or kinetic energy at this time if you want to use it to calculate sound volumes or damage amounts. See Arbiter for more info.

比如handle_pig_collide函数在小猪和障碍物碰撞后,会根据冲击力的大小来相应减去小猪的生命。

1 COLLISION_BIRD = 1

2 COLLISION_PIG = 2

3 COLLISION_BLOCK = 3

4 COLLISION_LINE = 4

5

6 def setup_collision_handler(self):

7 def post_solve_bird_line(arbiter, space, data):

8 if self.check_collide:

9 bird_shape = arbiter.shapes[0]

10 my_phy.handle_bird_collide(bird_shape, True)

11 def post_solve_pig_bird(arbiter, space, data):

12 if self.check_collide:

13 pig_shape = arbiter.shapes[0]

14 my_phy.handle_pig_collide(pig_shape, MAX_IMPULSE)

15 def post_solve_pig_line(arbiter, space, data):

16 if self.check_collide:

17 pig_shape = arbiter.shapes[0]

18 my_phy.handle_pig_collide(pig_shape, arbiter.total_impulse.length, True)

19 def post_solve_pig_block(arbiter, space, data):

20 if self.check_collide:

21 if arbiter.total_impulse.length > MIN_DAMAGE_IMPULSE:

22 pig_shape = arbiter.shapes[0]

23 my_phy.handle_pig_collide(pig_shape, arbiter.total_impulse.length)

24 def post_solve_block_bird(arbiter, space, data):

25 if self.check_collide:

26 block_shape, bird_shape = arbiter.shapes

27 my_phy.handle_bird_collide(bird_shape)

28 if arbiter.total_impulse.length > 1100:

29 my_phy.handle_block_collide(block_shape, arbiter.total_impulse.length)

30

31 self.space.add_collision_handler(

32 COLLISION_BIRD, COLLISION_LINE).post_solve = post_solve_bird_line

33

34 self.space.add_collision_handler(

35 COLLISION_PIG, COLLISION_BIRD).post_solve = post_solve_pig_bird

36

37 self.space.add_collision_handler(

38 COLLISION_PIG, COLLISION_LINE).post_solve = post_solve_pig_line

39

40 self.space.add_collision_handler(

41 COLLISION_PIG, COLLISION_BLOCK).post_solve = post_solve_pig_block

42

43 self.space.add_collision_handler(

44 COLLISION_BLOCK, COLLISION_BIRD).post_solve = post_solve_block_bird

45

46 def handle_pig_collide(self, pig_shape, impulse, is_ground=False):

47 for pig in self.pigs:

48 if pig_shape == pig.phy.shape:

49 if is_ground:

50 pig.phy.body.velocity = pig.phy.body.velocity * 0.8

51 else:

52 damage = impulse // MIN_DAMAGE_IMPULSE

53 pig.set_damage(damage)

54

55 # must init as a global parameter to use in the post_solve handler

56 my_phy = Physics()

创建一个pymunk物体

创建物体一般有下面五个步骤

moment_for_circle

函数根根据质量和转动惯量来创建一个刚体(pymunk.Body)。

1 pymunk.moment_for_circle(mass, inner_radius, outer_radius, offset=(0, 0))

2 Calculate the moment of inertia for a hollow circle

3 inner_radius and outer_radius are the inner and outer diameters. (A solid circle has an inner diameter of 0)

据质量(mass), 圆的半径 来计算出刚体的转动惯量(Moment Of Inertia),惯量就像刚体的旋转质量。

1 class pymunk.Body(mass=0, moment=0, body_type=)

根据刚体,和形状类型创建一个碰撞形状,比如圆形就是 pymunk.Circle。

1 class pymunk.Circle(body, radius, offset=(0, 0))Bases: pymunk.shapes.ShapeA circle shape defined by a radius

设置形状的一些属性

摩擦系数(friction)

1 Friction coefficient.

2 Pymunk uses the Coulomb friction model, a value of 0.0 is frictionless.

3 A value over 1.0 is perfectly fine.

弹力 (elasticity)

1 Elasticity of the shape.

2 A value of 0.0 gives no bounce, while a value of 1.0 will give a ‘perfect’ bounce.

最后将这个刚体和碰撞形状都添加到空间中。

1 pymunk.Space.add(*objs)

2 Add one or many shapes, bodies or joints to the space

1 class PhyPig():

2 def __init__(self, x, y, radius, space):

3 mass = 5

4 inertia = pm.moment_for_circle(mass, 0, radius, (0, 0))

5 body = pm.Body(mass, inertia)

6 body.position = x, y

7 shape = pm.Circle(body, radius, (0, 0))

8 shape.elasticity = 0.95

9 shape.friction = 1

10 shape.collision_type = COLLISION_PIG

11 space.add(body, shape)

12 self.body = body

13 self.shape = shape

PhyPig 类的初始化函数创建了一个小猪物体,参数有物体的位置(x,y), 可以将小猪作为一个圆形物体,所以参数有圆的半径(radius), 参数space就是我们上面创建的空间类。

pymunk 状态更新

update函数是更新函数,代码只显示了小猪相关的代码。

step 函数的参数dt值就是上面设置的时间段值,表示这次调用 该空间经过了多少时间,pymunk 根据这个时间值更新空间中的所有物体的状态(比如速度,位置等)。按照pymunk 文档的说明,将dt值设小一点,每次调用多次会使得模拟更稳定和精确,所以这里每次调用5次step函数。

1 pymunk.Space.step(dt)

2 Update the space for the given time step.

遍历所有的小猪:

检查小猪的状态,如果生命小于零或者y轴位置超出了范围,删除这个小猪。

更新小猪的位置

pygame 和 pymunk 中对于位置的值是不同的, y轴的坐标需要进行转换,具体看 to_pygame 函数,600是高度。pymunk 中 body.position的值是物体的中间位置,对应pygame 中 rect 的centerx 和 centery,所以需要转成[left, top]位置。

pygame中,以左上角的位置为(0,0)

pymunk中,以左下角的位置为(0,0)

1 def to_pygame(p):

2 """Convert position of pymunk to position of pygame"""

3 return int(p.x), int(-p.y+600)

4

5 def update(self, game_info, level, mouse_pressed):

6 pigs_to_remove = []

7

8 #From pymunk doc:Performing multiple calls with a smaller dt

9 # creates a more stable and accurate simulation

10 #So make five updates per frame for better stability

11 for x in range(5):

12 self.space.step(self.dt)

13 ...

14 for pig in self.pigs:

15 pig.update(game_info)

16 if pig.phy.body.position.y < 0 or pig.life <= 0:

17 pigs_to_remove.append(pig)

18 poly = pig.phy.shape

19 p = to_pygame(poly.body.position)

20 x, y = p

21 w, h = pig.image.get_size()

22 # change to [left, top] position of pygame

23 x -= w * 0.5

24 y -= h * 0.5

25 angle_degree = math.degrees(poly.body.angle)

26 pig.update_position(x, y, angle_degree)

27

28 for pig in pigs_to_remove:

29 self.space.remove(pig.phy.shape, pig.phy.shape.body)

30 self.pigs.remove(pig)

31 level.update_score(c.PIG_SCORE)

32 ...

完善后的代码已打包成python教程,交流群:632408235 可到当中获取

编译环境

python3.7 + pygame1.9 + pymunk 5.5.0

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[Python 愤怒的小鸟代码实现:物理引擎pymunk使用]http://www.zyiz.net/tech/detail-98711.html

愤怒的小鸟python代码_Python 愤怒的小鸟代码实现:物理引擎pymunk使用相关推荐

  1. python 物理引擎 摩擦力_Python 愤怒的小鸟代码实现:物理引擎pymunk使用

    游戏介绍 最近比较忙,周末正好有时间写了python版本的愤怒的小鸟,使用了物理引擎pymunk,图片资源是从github上下载的,实现了一个可玩的简单版本. 功能实现如下:支持小鸟类型:红色小鸟,蓝 ...

  2. Python 愤怒的小鸟代码实现(1):物理引擎pymunk使用

    python 愤怒的小鸟代码实现(1):物理引擎pymunk使用 游戏介绍 完整代码 Pymunk介绍 代码实现 pymunk相关初始化 创建一个pymunk物体 pymunk 状态更新 编译环境 游 ...

  3. pygame教程实例(五)物理引擎pymunk

    上一篇:pygame教程实例(四)小球弹跳(事件) 下一篇:pygame教程实例(六)你从来没玩过的俄罗斯方块 本教程使用python3 在前几个教程中,我们模拟了小球和星球的运动. 但是,在游戏中我 ...

  4. python折叠代码_Python实现代码块儿折叠

    Python实现代码块儿折叠 在python中方法和类都是可以折叠的,但是很多时候需要按照实现的功能将一部分代码折叠起来. 可以用着样的注释代码实现: # ''' your code ''' # 很简 ...

  5. python画画的代码_python画画代码

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! life is short, just use python.自从08年接触py ...

  6. python人物代码_Python 超级玛丽代码实现:人物行走和碰撞检测

    功能介绍 人物行走 人物的行走速度这边分成水平方向(X轴)和竖直方向(Y轴),水平方向的速度要考虑加速度和摩擦力,竖直方向的速度要考虑重力加速度.水平方向:设定X轴向右走的速度为大于0,向左走的速度为 ...

  7. python 新闻_Python一行代码竟能干这种事,同学都欢呼:要向女神表白!

    @数据分析师攻略 公众号 关注.学习更多数据分析的知识与资讯 ------ Python的语法十分简洁,简洁到只需要一行代码,即可输出意想不到的效果.一行代码到底有什么独特的魅力,下面一起来感受一下吧 ...

  8. python box2d 教程_python下的Box2d物理引擎的配置

    I come back! 由于已经大四了,正在找工作 导致了至今以来第二长的时间内没有更新博客.向大家表示道歉 前言 Box2d物理引擎 Box2d是一款开源的2d物理引擎,存在很多的版本,C++,J ...

  9. python写了代码_Python写代码的用法建议

    1.Mutable and immutable types Python有两种内置或用户定义的类型 可变类型是允许就地修改内容的类型.典型的可变列表是列表和词典:所有列表都有变异方法,如 list.a ...

  10. python 小甲鱼 代码_Python小代码

    先自我介绍一下,本人是正在自学Python的小白,没事分享一下自己写的小代码,欢迎在评论区补充. 游戏管理系统: 代码如下: def healthe(m):if m=="Y"or ...

最新文章

  1. kinect+java3d+robot开发备忘录
  2. 疯狂python讲义视频 百度云-疯狂Python讲义 PDF 含源码工具版
  3. jzoj3500-物语【最短路】
  4. linux telnet smtp,如何使用Telnet测试IMAP与SMTP
  5. 照葫芦画瓢之老男孩购物车程序
  6. (转载)valgrind,好东西,一般人我不告诉他~~ 选项
  7. stm32 整数加法循环时间_剑指 Offer 65. 不用加减乘除做加法 leetcode 剑指offer系列...
  8. 学习记录542@阿里云OCR身份证识别具体实现
  9. 英语高考听力测试软件,高考英语听力训练app
  10. python 用列表筛选法求素数
  11. MATLAB subplot子图分块绘制的方法
  12. 市场上的智能语音助理,主要的工作原理是什么?
  13. 关机一直显示正在关闭服务器,电脑关机后,显示正在关机,但等半天也关不了 怎么办...
  14. Linux远程连接工具Xmanager Xbrowser--Win10远程连接CentOS6.9桌面
  15. 四、Storm入门之Spout
  16. 教程-ftp21端口,OpenSSH,22,内部敏感服务对外开放存在风险
  17. vite+vue3+TS项目引入antd-vue的问题记录
  18. 我在哪?要到哪里去?怎么去?
  19. Mini-NDN 安装
  20. 微信小程序云开发教程-小程序端调用云函数

热门文章

  1. Spark 概念学习系列之从spark架构中透视job(十六)
  2. window环境下杀死tomcat
  3. fg、bg、jobs、、nohup、ctrl + z命令
  4. Echarts-地图扩展-标准geoJson格式扩展地图-例子
  5. .NET URL 301转向方法的实现
  6. socket 和 TCP/IP 协议的关系
  7. Oracle ORA-01033: ORACLE initialization or shutdown in progress 错误解决办法Windows版(手贱强制重启电脑的后果)...
  8. 深入分析SQL字符串限制长度漏洞
  9. C# 启动与停止进程
  10. 城域容灾体系的突破性进展