编程模拟自然(八):几种常见力的建模

序·牛郎织女篇

  古书记载:大河之东,有美丽佳人,乃天帝之子,机杼女工,年年劳役,织成云雾绢缣之衣,天帝怜其独处,嫁与河西牵牛为妻。

  自此即废织紝之功,留恋不归。天帝大怒,责归河东,令他们每年只有七月七日可以相会一次。

  (前情提要:元计划离开月球,并为此不断努力着...)

第零章 实例化一个长整型

  “无名儿,来个睡前故事吧。”

  “猿叔,我才是小孩子唉!”

  “你当然是小屁孩,我这是培养你的语言表达能力。”

  “哦,那给你讲个牵牛星和织女星的故事。”

  ...

  “从前有个出身码农世家的孩子,爹娘给他取了 NewLong 的名字。”

  “不愧码农世家,完全符合驼峰命名法。”

  “...后来 NewLong 和一位下凡的仙女成为夫妻。”

  “码农怎么可能有女朋友?”元惊讶不已。

  “从此夫妻过着男编女织的生活...”

  “......”元陷入了沉思。

  “直到有一天从天而降的天神打破了原有的平静...”

  “我预感到接下来就是转折。”

  “...天神带走了仙女,NewLong 失去了妻子。”

  “哈哈哈哈,我就说码农怎么能有女朋友。”

第一章 重力

  失去妻子后,NewLong 对生活失去了信心,从此没日没夜地写着代码。

  一天儿子 Newton 哭着从外面回来,说一颗苹果从树上落下砸到了自己。

  NewLong 一边安慰着儿子,一边想“为什么苹果不往天上掉,砸死那天神呢?”

  在现实中,我们可能会有一种错觉:质量越大的物体下落速度越快。当然这是错的,通常我们认为物体重力加速度恒定(在编程中,重力的模长=常量系数*质量)。

  如果你登上比萨斜塔的顶层,让两个质量不同的铁球同时从上面落下,那个铁球会先着地?伽利略已经在 1589 年做过这个测试,他发现两个铁球下落加速度相等,最后同时击中地面。

  我们在编程中可以简单的模拟重力。

    Dim gravityVec As New Vector2(0, 0.1 * SubWalker.Mass)
    SubWalker.ApplyForce(gravityVec)

  再模拟一个向右的风力。

    Dim windVec As New Vector2(0.1, 0)
    Dim gravityVec As New Vector2(0, 0.01 * SubWalker.Mass)
    SubWalker.ApplyForce(windVec)
    SubWalker.ApplyForce(gravityVec)

图8-1 物体受重力、向右风力作用

  尽管物理下落的速度相等,但质量越小的物体向右运动的加速度越大,因为风力作用的加速度和物体的质量相关。

第二章 摩擦力

  在发现重力后,NewLong 对生活恢复了一些信心,继续没日没夜的写着代码。

  一天儿子 Newton 又哭着从外面回来,说从土坡上滑下来磨破了裤子。

  NewLong 一边缝补着裤子,一边想“只要土坡‘足够光滑’,裤子还会破吗?”

  摩擦力是一种耗散力。耗散力的定义是:在运动中使系统总能量减少的力。比如说开车时,脚踩刹车板会让车通过摩擦力使轮胎减速,在这个过程中,动能被转化为热能。

  只要两个物体的表面相互接触并有相对运动的趋势,它们之间就有摩擦力。摩擦力可分为静摩擦力(物体相对于表面静止不动)和动摩擦力(物体在表面上发生运动)。

  这里我们只对动摩擦力进行模拟。

  Dim frictionMag As Single = 0.1 '系数
  Dim frictionVec As New Vector2(SubWalker.Velocity.X, SubWalker.Velocity.Y) '由当前速度向量初始化
  frictionVec = -frictionVec '向量反向
  frictionVec.SetMag(frictionMag) '重新设定向量长度
  SubWalker.ApplyForce(frictionVec)

图8-1 物体受重力、向右风力和摩擦力作用

  物体受摩擦力,反弹后无法回到原来的高度。

第三章 空气和流体阻力

  物体通过流体或者气体时同样会受摩擦力的作用,这种摩擦力有很多名字,如粘滞力、阻力和流体阻力。流体阻力产生的效果和前述的摩擦力相同(物体会减速),但是计算阻力的方式却有些不同。

  简化的阻力计算公式:阻力=速度的平方*阻力系数

    Private Sub ApplyDrag(SubWalker As RndWalker)
        Dim vLen As Single = SubWalker.Velocity.Length
        Dim dragMag As Single = 0.05 * vLen * vLen '系数
        Dim dragVec As New Vector2(SubWalker.Velocity.X, SubWalker.Velocity.Y) '由当前速度向量初始化
        dragVec = -dragVec '向量反向
        dragVec.SetMag(dragMag) '重新设定向量长度
        SubWalker.ApplyForce(dragVec)
    End Sub

图8-2 物体受重力、流体阻力、向右外力(抛物线)

  不同物体反弹后升起的高度不再一致。

 图8-3 物体受重力、流体阻力(垂直下落)

  图中灰色区域是模拟物体落入水中,你会发现物体越小(质量越轻),速度减小的越快。

第四章 万有引力

  后来,NewLong 对生活找回了全部信心,他决定生活不再只是代码,还有诗。

  晚上 NewLong 陪着儿子 Newton 看星星,繁星漫天,有感而发:

  远远的街灯明了 / 好像闪着无数的明星

  天上的明星现了 / 好像点着无数的街灯

  虚无缥缈的空中 / 定然有她美丽的身影

  引力是最常见的力,当地球吸引苹果下落的同时,苹果对地球也有引力作用,只不过地球过于庞大,苹果的作用力完全可以忽略不计。

  由引力的计算公式我们可以知道:物体距离越远,引力越弱;物体距离越近,引力越强。

  现在,我们让鼠标指针吸引物体,并假设指针的质量为 1.0f

    Private Sub ApplyAttract(SubWalker As RndWalker, MouseVec As Vector2)
        Dim mouseMass As Single = 1.0f '鼠标质量
        Dim gValue As Single = 100f '引力常量
        Dim attractVec As Vector2 = MouseVec - SubWalker.Location '由二者向量差初始化
        Dim aLen As Single = attractVec.Length '距离
        Dim attractMag As Single = (gValue * mouseMass * SubWalker.Mass) / (aLen * aLen) '计算模长
        attractVec.SetMag(attractMag) '重置向量长度
        SubWalker.ApplyForce(attractVec)
    End Sub  

图8-4 鼠标吸引物体  

  附加题:观察图像并回答鼠标大致在什么位置。(5 分)

第五章 长征运载火箭

  当然生活不只是代码和诗,还有远方。NewLong 一直有个伟大的计划,他要去天上找回昔日的姑娘。

  --中文名:长整运载火箭

  --外文名:NewLong Rocket

  --是否拥有轨道舱:是

  --是否拥有返回舱:是

  就在 NewLong 准备上天前夜,一直默默无闻的老牛突然说话了:“我就要死了,但我一直有个飞天的梦想。”

  月纪 8 年,9 月1 日,元告别无名儿后离开了月球。

  9 月 20 日,元进入地月转移轨道。

  10 月 6 日,元抵达地球同步轨道。

  10 月 7 日,元与仍旧在轨的 NewLong 号返回舱完成对接。

  ...

  “返回舱返回程式重新生成中。”

  “生成成功 1 个,失败 0 个。”

  “部署成功 1 个,失败 0 个。”

  一切正常。

  “输出:助推火箭启动,尝试再入角修正。”

  “警告:推力计算时抛出了异常,发生除零运算。”

  元选择了继续。

  “输出:再入速度修正中,即将再入大气层。”

  …

  “输出:软着陆程式就绪,主伞开启。”

  元抬头看了看,原来是一块牛皮做的伞,这下牛皮真上天了。

后记

  “这是哪儿?”元爬出返回舱时下意识说了句话。

  视野内一片碧蓝,随后仿佛听到了些许鸟语。

  “一 Bug 还未平息,一 Bug 又来侵袭,茫茫码海狂风暴雨…”

  “…这里是 Sad Pacific Ocean。”

  元看清楚了,他眼前飘下来个鸟人。

附录

  预知后情,且看下回分解。了解更多请浏览目录导航

posted @ 2016-05-17 07:17  ExperDot  阅读(1637)  评论(6编辑  收藏  举报