中的draw函数_在processing中模拟星系的诞生

本文介绍了如何在Processing中使用draw函数和物理库模拟星系的诞生。程序利用fisica库进行引力仿真,handy库实现手绘效果,背景透明度控制及镜头缩放提供独特视觉体验。行星间的引力交互、合并与碰撞效果丰富了模拟的动态性。文章还提供了源码获取方式及调整参数的建议。
摘要由CSDN通过智能技术生成

源码获取:直接到 源码链接。或者联系作者(当然是我啦)获得源码。

目录:

  • 程序效果展示与说明
  • 运行环境
  • 程序说明
  • 程序详解
  • 调整参数
  • 物理库设置:实现高效引力仿真
  • 利用handy库
  • 背景透明度与镜头控制
  • 还可以做什么

程序效果展示与说明

5da12250f822b8aacab1b754b0735370.png
https://www.zhihu.com/video/1176584601122942976

运行环境

运行环境还是我们最熟悉的processing(Python Mode)。安装教程参考专栏目录 。

程序主要使用到了我们常用的fisica物理库,关于它的初级教程可以看一下我之前的文章:

忘荃的趣味编程:趣味编程:processing物理库fisica入门教程​zhuanlan.zhihu.com
ee7c072128a9d346b9d70baefd37d886.png

另外还使用到了用于自定义镜头的ocd库,以及用于将图形渲染得像是手画的一样的handy库。

程序说明

在程序的最开始阶段,除了一直固定在屏幕中心不动的恒星,开始快速连续加入速度随机的小行星。

每个行星之间有引力,而各个行星还受到恒星的引力,而且受恒星的引力占据了主要因素,使得大部分行星都能围绕恒星做运动。

行星之间距离过近的时候,会合并为一个行星。而行星撞上恒星的话,也会消失。

程序还会实时的在命令行print显示现存的行星的个数。

8aa273b4d5522e61cfd17d434a76f046.png
命令行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()

还可以做什么

  1. 调整参数。
  2. 在创建行星的时候,对行星的密度也进行随机化设置
  3. 完善两个行星的碰撞并合并为一个行星的处理过程。
  4. 其他你能想到的有趣的改变。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值