源码获取:直接到 源码链接。或者联系作者(当然是我啦)获得源码。
目录:
- 程序效果展示与说明
- 运行环境
- 程序说明
- 程序详解
- 调整参数
- 物理库设置:实现高效引力仿真
- 利用handy库
- 背景透明度与镜头控制
- 还可以做什么
程序效果展示与说明
运行环境
运行环境还是我们最熟悉的processing(Python Mode)。安装教程参考专栏目录 。
程序主要使用到了我们常用的fisica物理库,关于它的初级教程可以看一下我之前的文章:
忘荃的趣味编程:趣味编程:processing物理库fisica入门教程zhuanlan.zhihu.com另外还使用到了用于自定义镜头的ocd库,以及用于将图形渲染得像是手画的一样的handy库。
程序说明
在程序的最开始阶段,除了一直固定在屏幕中心不动的恒星,开始快速连续加入速度随机的小行星。
每个行星之间有引力,而各个行星还受到恒星的引力,而且受恒星的引力占据了主要因素,使得大部分行星都能围绕恒星做运动。
行星之间距离过近的时候,会合并为一个行星。而行星撞上恒星的话,也会消失。
程序还会实时的在命令行print显示现存的行星的个数。
程序详解
调整参数
所有需要调整的常数都被放在了程序的最开始,方便进行调整。下面给出了详细注释。
k_f = 1e3 # 行星间引力系数
max_f = 1e5 # 引力的最大值
v_max = 1e3 # 行星初始速度的值(方向随机不可控)
planet_show_size = 20 # 展示小行星的球体的大小
planet_f_size = 30 # 行星引力作用范围半径上限
planet_n = 200 # 行星数量
planet_show_ball = False # 是否展示小行星的球体
planet_show_line = True # 是否展示小行星的轨迹
planet_list = set()
sun_size = 30 # 恒星大小
k_f_sun = 1e9 # 恒星对行星引力系数
f_sun_max = 1e4 # 恒星对行星引力的最大值
cam_dis = 8e2 # 镜头距离
merge_dis = 30 # 行星间距离小于该值就会被合并
物理库设置:实现高效引力仿真
将行星和恒星的引力范围用设置成spirite的FCircle表示。
原因是根据引力公式,引力和距离的平方成反比。所以当两个物体的距离超过一定的值时候,他们之间的引力就可以忽略不计,也就是说引力可以近似看作是有范围的。
所以通过我们这种设置方式,当两个行星的引力范围重叠的时候,会出发碰撞事件,并进一步引发两个行星之间的引力。
而恒星对于行星引力的实现代码,则之间放在了Planet(行星)类的draw函数中。因为我们的程序会直接把超出恒星作用范围的行星给删除掉,所以可以认为存在的行星都是时时刻刻处于恒星的作用下的。而删除超出恒星引力范围的行星的代码同样放在了Planet(行星)类的draw函数中。
利用handy库
首先是引入库:
add_library('handy')
然后再draw()中对handy进行初始化:
H = HandyRenderer(this) # 初始化
H.setFillGap(1) # 设置相关参数
H.setFillWeight(5) # 设置相关参数
然后通过调用H.ellipse(), H.rect() 等函数就能够画出有手写效果的图形了。
另外我们将fisica的FCircle类继承为Planet类,并在类中重写其可视化函数draw,在draw中把展示半径从引力半径改为恒星大小半径,再利用H.ellipse()调用handy库的渲染效果。这个想法来自handy示例程序“Inherit”。
背景透明度与镜头控制
通过控制背景的透明度,我们能够实现残影效果。
而通过镜头控制,把镜头拉到一个更远的地方,就能够在相同的窗口获得更大的视野。
相关的代码段如下:
def setup():
global world, cam, PG1, H
fullScreen(P3D)
PG1 = createGraphics(width, height, P3D)
cam = Camera(this, width/2, height/2, cam_dis, width/2, height/2, 0)
def draw():
cam.feed()
PG1.beginDraw()
PG1.background(255, 50)
world.draw(PG1)
PG1.endDraw()
还可以做什么
- 调整参数。
- 在创建行星的时候,对行星的密度也进行随机化设置
- 完善两个行星的碰撞并合并为一个行星的处理过程。
- 其他你能想到的有趣的改变。