编程模拟自然(七):力学矢量与牛顿定律

  旧书有云:古者十日并出,草木焦槁,一曰后羿者射日,太阳里之九鸟皆死,救苍生于涂炭。

  传闻后羿所用箭矢加持了力学模拟系统,可实现深空精确制导,才得以击落太阳。

  ...

  “星星挂在天边,就像梦想遥不可现...”元哼唧着。

  “猿叔你在哼什么曲子啊?”

  “...星星消失在天边,就像诺言来不及实现...”元对无名儿捂着双耳选择无视。

  “咳咳,我这是在朗诵诗人小刚的诗歌呢!”

  ...

第零章

  “星星挂在天...你爸曾经射落过太阳?”元刚要继续深情朗诵,似乎想到了什么。

  “是的,听娘说爹地最厉害了。”

  “我不信,那你说他是怎么办到的?”元不禁抬头望了望天际那颗水蓝色星球。

  “用的是力学系统...”

  “猿叔,你手中的粒子系统就内嵌着呢!”无名儿继续回答道

第一节 随机游走类

  假设你站在一根独木桥上,每10秒钟抛一枚硬币:如果硬币正面朝上,你向前走一步;背面朝上,则向后退一步。这就是随机游走——由一系列随机步骤构成的运动轨迹。然后,从独木桥转移到地面,你就可以做二维的随机游走了,不过每走一步需要抛掷两次硬币,而且需要按如下规则

第一次抛掷 第二次抛掷 结果
正面 正面 向前走一步
反面 正面 向右走一步
正面 反面 向左走一步
反面 反面 向后走一步

  这是一个很简单的规则,但是随机游走可以对现实世界中的各种现象建模:从气体分子的运动到小孩一整天的玩耍活动不一而足。

  现在我们建立Walker对象,它表示一个可以随机游走的对象,具有以下特点:即维持了自身数据(位置),又能够执行某些动作(比如绘制自身或者移动一步)

  首先,我们定义一个Walker类——Walker对象的模板

‘‘‘ <summary>
‘‘‘ 表示一个随机游走对象
‘‘‘ </summary>
Public Class Walker
    Public X As Integer
    Public Y As Integer
End Class

  构造函数负责对象的初始化

    ‘‘‘ <summary>
    ‘‘‘ 初始化当前对象的位置
    ‘‘‘ </summary>
    ‘‘‘ <param name="initX">指定的对象位置X分量</param>
    ‘‘‘ <param name="initY">指定的对象位置Y分量</param>
    Public Sub New(initX As Single, initY As Single)
        Me.X = initX
        Me.Y = initY
    End Sub

  新建一个Move()方法实现控制对象移动

    ‘‘‘ <summary>
    ‘‘‘ 当前对象随机移动一帧
    ‘‘‘ </summary>
    Public Sub RndMove()
        Dim chioce As Integer = Rnd.Next(4) ‘随机值0、1、2或3
        If chioce = 0 Then
            X = X + 1
        ElseIf chioce = 1 Then
            X = X - 1
        ElseIf chioce = 2 Then
            Y = Y + 1
        Else
            Y = Y - 1
        End If
    End Sub

  新建一个Walker实例,并在一个过程里循环调用它的RndMove()方法,每次调用完毕就输出到屏幕,我们就可以看到它的随机运动轨迹

第二节 向量

  这里指的是欧几里得向量,即几何向量。它的定义是:一个既有大小又有方向的几何对象。在编程中,引入向量并不会给我们添加新工作,它会简化你的代码,而对于在运动模拟中经常出现的数学运算,向量提供了很多现成的函数。

  现在,将上述Walker类中的变量用向量等效替换。

Imports System.Numerics
‘‘‘ <summary>
‘‘‘ 表示一个随机游走对象
‘‘‘ </summary>
Public Class Walker
    Public Location As Vector2
    Public Shared Rnd As New Random
    ‘‘‘ <summary>
    ‘‘‘ 初始化当前对象的位置
    ‘‘‘ </summary>
    ‘‘‘ <param name="initX">指定的对象位置X分量</param>
    ‘‘‘ <param name="initY">指定的对象位置Y分量</param>
    Public Sub New(initX As Single, initY As Single)
        Location = New Vector2(initX, initY)
    End Sub
    ‘‘‘ <summary>
    ‘‘‘ 当前对象随机移动一帧
    ‘‘‘ </summary>
    Public Sub RndMove()
        Dim chioce As Integer = Rnd.Next(4) ‘随机值0、1、2或3
        If chioce = 0 Then
            Location = Location + New Vector2(1, 0)
        ElseIf chioce = 1 Then
            Location = Location + New Vector2(-1, 0)
        ElseIf chioce = 2 Then
            Location = Location + New Vector2(0, 1)
        Else
            Location = Location + New Vector2(0, -1)
        End If
    End Sub
End Class

  新增加速度和速度属性,并添加方法NormalMove(),

    Public Velocity As Vector2
    Public Acceleration As Vector2
    ‘‘‘ <summary>
    ‘‘‘  当前对象物理仿真移动一帧
    ‘‘‘ </summary>
    Public Sub NormalMove()
        Velocity = Velocity + Acceleration ‘更新速度
        Location = Location + Velocity ‘更新位置
    End Sub

  容易知道三个向量间的作用关系是一种“涓滴”效应,加速度影响速度,进而影响位置。

  新建多个Walker实例,并在一个过程里循环调用它的NormalMove()方法,并记录下轨迹。

第三节 力与牛顿定律

  我们首先要了解力在现实世界中的概念,力可以指代力量的强度,比如“她用力的推动那块大石头”,或者“他有力地说出那句话”。但是这里是更书面化的概念,它源自牛顿运动定律:

  力是一个向量,它使有质量的物体产生加速。

  当看到定义的第一部分——力是一个向量,你应该由衷的感到喜悦,同位置或加速度一样,这在编程中可轻松被描述。

  结合力的概念,我们需要看看牛顿三大运动定律。

  牛顿第一运动定律通常简要的描述为:

  物体有保持静止或运动的趋势。

  这个表述遗漏了外力的作用,可以扩展为:

  除非有不均衡外力的作用,负责物体保持静止或匀速直线运动状态。

  而在编程中,我们可以这样表述牛顿第一定律:

  在平衡状态下,对象的速度向量(Vector类型)始终都是常量。

  然后先跳过牛顿第二定律,直接牛顿第三定律,它通常表述为:

  每个作用力都有一个大小相等、方向相反的反作用力

  这个表述容易引起误解,可以更好的表述为:

  力总是成对出现的,且这两个力大小相等,方向相反

  同样地,这个表述也会引起误解,因为它看起来像是说:成对出现的力总是会互相抵消,事实并非如此,成对出现的力不是作用在同一物体上的。

  从编程角度表述牛顿第三定律:

  若要计算一个由A施加在B上的作用力F(Vector类型),必须额外施加一个由B作用在A上的反作用力-F

  有时候不一定要遵循上述说法,比如模拟风力效果时,就不需要计算物体作用在空气上的反作用力,因为根本不用去模拟空气。

  下面是牛顿第二定律,它被表述为:

  合力等于质量乘以加速度:F=M*A

  现在我们用编程去模拟这条定律,结合力的累加原理和牛顿第二定律,新增ApplyForce()方法

    Public Property Mass As Single = 10.0 ‘质量大小
    ‘‘‘ <summary>
    ‘‘‘ 指定的力作用于当前对象
    ‘‘‘ </summary>
    ‘‘‘ <param name="fVec">指定的力</param>
    Public Sub ApplyForce(fVec As Vector2)
        Acceleration = Acceleration + fVec / Mass
    End Sub

  更新NormalMove()方法,需要将加速度清零

    ‘‘‘ <summary>
    ‘‘‘  当前对象物理仿真移动一帧
    ‘‘‘ </summary>
    Public Sub NormalMove()
        Velocity = Velocity + Acceleration ‘更新速度
        Location = Location + Velocity ‘更新位置
        Acceleration = New Vector2(0, 0) ‘加速度清零
    End Sub

  现在,你可以创建任意的或者使用符合现实物理规律的一个力,并将它作用于Walker对象。

后记

  “猿叔,你在做什么?”

  “起草一份文书...”

  “我问过我娘了,她不愿多说爹地的事情。”无名儿说话时有些失落。

  “哈哈,就说是你编的嘛,射日的事我是不会相信的!”

  “你最厉害,行了吧。”

  “那是当然,我可是创世神,谁能比我厉害。”元一副不可一世的样子。

  “哟,还创世神,你咋不上天咧?”

  “....”

  “你怎么知道我要上天?”元晃了晃手中的文稿。

  中文名称:后羿工程

  英文名称:Hou Yi Project

  别称:星际载人火箭登地工程

  首席工程师:元

  工程阶段:论证中

  工程目标:实现可载人登地

  “唉,现在月球上好多偏远地方的孩子还上不起学;”无名儿努力皱了皱眉。

  “...”

  “吴刚叔每天辛苦砍树却没人给他发工资;”接着叹了口气。

  “...”

  “登地这种事又有什么意义呢?”

  “所以?”元瞧了眼无名儿稚嫩的脸庞。

  “你不要走呗,不然没人陪我玩了。”

附录

1.预知前情,请看上回分解。也可以浏览目录导航

2.资源推荐:https://github.com/shiffman/The-Nature-of-Code-Examples

3.参考书籍:《The Nature of Code》[美] Daniel Shiffman 著

时间: 2024-10-20 11:48:53

编程模拟自然(七):力学矢量与牛顿定律的相关文章

【目录导航】编程模拟自然系列博文

简介 博文名称:编程模拟自然 系列别称:奇幻元纪 主要角色:元.无名儿 角色设定:(按出场顺序) 元:故事主角,拥有创世能力的程序猿 亚和夏:生活在元创造的世界里的人类 NvWa:传说通过重构天阙代码完成补天的程序Yuan 盘古:上古程序架构师,后世传有生平语录<盘语>一书 吴刚:在月亮上中终日砍伐桂树的码农 无名儿:故事主角,一破小孩儿 嫦娥:奔月的仙子,身居广寒宫 天狗:妖物,来源不明 望舒:御车之神,管辖月宫禁地 VisualSnake:伊甸园里的可视化集成开发环境,外形同蛇 后羿:(下

编程模拟自然(九):元胞自动机

序 旧书有云:发鸠之山,其上多柘木.有鸟焉,其状如乌,文首.白喙.赤足,名曰精卫,其鸣自詨. 一日,精卫游于码海,溺而不返,后常衔西山之木石,以堙于海.有诗为证: 万事有不平,尔何空自苦: 长将一寸身,衔木到终古? 我愿平码海,身沉心不改: 码海无平期,我心无绝时. 呜呼!君不见,西山衔木众鸟多,鹊来燕去自成窠! (前情提要:主角元乘坐返回舱降落到了码海上,随后遇到了个鸟人...) “咳咳,远道的客人,我名精卫XIV,乃是先祖精卫鸟的第十四代后裔...”鸟人作自我介绍 “...你是谁,从哪里来又

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

序 古书记载:大河之东,有美丽佳人,乃天帝之子,机杼女工,年年劳役,织成云雾绢缣之衣,天帝怜其独处,嫁与河西牵牛为妻. 自此即废织紝之功,留恋不归.天帝大怒,责归河东,令他们每年只有七月七日可以相会一次.有诗云: 纤云弄巧,飞星传恨,银汉迢迢暗渡. 金风玉露一相逢,便胜却人间无数. 柔情似水,佳期如梦,忍顾鹊桥归路. 两情若是长久时,又岂在朝朝暮暮 第零章 实例化一个长整型 “无名儿,来个睡前故事吧.” “猿叔,我才是小孩子唉!” “你当然是小屁孩,我这是培养你的语言表达能力.” “哦,那给你讲

编程模拟自然(三):更好的静态树算法

序 旧言月中有桂,有蟾蜍,故异书言,月桂高五百丈,下有一人常斫之,树创随合. “汪...”一声猿啸从天际传来. 吴刚抬头看了看天,却没有发现什么,只当是出现了幻听. 第零章 提出问题 元来到这个世界已经好多天了,本想去找那树下的人探听一些消息,却不想竟然无法进入桂树百丈范围. 元在伊甸园里种过树的,但看到那桂树受创随即便愈合,倍感神奇.看来需要更新算法了. “这颗树的全称为Graphics User Interface Tree,中文简称:桂树.” 第一章 作出假设 每个树枝都是一个独立的结点,

编程模拟自然(一):如何画一颗静态树

序 万物初始之前,宇宙是无边无际混沌的黑暗,只有元之灵穿行其间.元对这无边的黑暗十分不满,就轻轻一敲键盘,说:“要有光”,于是世间就有了光.元称“光”为“昼”,称“黑暗”为“夜”.亮光隐去,黑暗重临,从此,世间就有了昼与夜的交替.这是元创世的第一天. 这个二次元世界诞生之初伴有一只程序猿,Ta的名字叫元. 第一章 二叉树必须是最好的树! 元就是这样想的,为了表达对这种数据结构的崇拜之情,决定在这个世界造出一颗真实的树,一开始的构想是这样的 “正所谓树极生三干,三干生六枝,六枝生十二叶.” 然而这

C#编程总结(七)数据加密——附源码

C#编程总结(七)数据加密——附源码 概述 数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容,通过这样的途径来达到保护数据不被非法人窃取.阅读的目的. 该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程.加密建立在对信息进行数学编码和解码的基础上.加密类型分为两种,对称加密与非对称加密,对称加密双方采用共同密钥.非对称加密,这种加密方式存在两个密钥,一个是公共密钥(对外公开),一种

Linux环境编程之进程(七):守护进程

守护进程也是一种进程,它由如下特性: 1.生存期较长,在系统自举时启动,仅在系统关闭时终止. 2.没有控制终端,在后台运行. 系统中有很多守护进程,它们执行日常事务活动.如日志进程syslogd.web服务器httpd.邮件服务器sendmail和数据块服务器mysqld等.大多数守护进程都是以超级用户(用户ID为0)特权运行.没有一个守护进程具有控制终端,其终端设置为问号(?),终端前台进程组ID设置为-1.内核守护进程以无控制终端方式启动.用户层守护进程缺少控制终端可能是守护进程调用了set

ActionScript3游戏中的图像编程(连载七)

1.2.1 RGB测试用例的书写 新建一个ActionScript项目,名为ShapeColorTransformTest,我在里面创建几个不同颜色的小圆,观察它们在应用了colorTransform之后的变化.代码如下: 1 package{ 2 [SWF(width = "800", height = "600")] 3 public class ShapeColorTransformTest extends Sprite{ 4 private var _tes

30、最高分是多少 老师想知道从某某同学当中,分数最高的是多少,现在请你编程模拟老师的询问。当然,老师有时候需要更新某位同学的成绩.

最高分是多少 老师想知道从某某同学当中,分数最高的是多少,现在请你编程模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. 输入描述: 输入包括多组测试数据. 每组输入第一行是两个正整数N和M(0 < N <= 30000,0 < M < 5000),分别代表学生的数目和操作的数目. 学生ID编号从1编到N. 第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩 接下来又M行,每一行有一个字符C(只取'Q'或'U'),和两个正整数A,B,当C为'Q