热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

向量的几何意义及编程应用(4)

转载自:http:blog.csdn.netpopy007articledetails3769442-D物体间的碰撞响应-Twinsen编写-本人水平有限&#x

转载自:http://blog.csdn.net/popy007/article/details/376944

<4>2-D物体间的碰撞响应
-Twinsen编写

-本人水平有限&#xff0c;疏忽错误在所难免&#xff0c;还请各位数学高手、编程高手不吝赐教
-我的Email-address: popyy&#64;netease.com

 

这次我要分析两个球体之间的碰撞响应&#xff0c;这样我们就可以结合以前的知识来编写一款最基本的2-D台球游戏了&#xff0c;虽然粗糙了点&#xff0c;但却是个很好的开始&#xff0c;对吗&#xff1f;

一、初步分析

中学时候上物理课能够认真听讲的人&#xff08;我&#xff1f;哦&#xff0c;不包括我&#xff09;应该很熟悉的记得&#xff1a;当两个球体在一个理想环境下相撞之后&#xff0c;它们的总动量保持不变&#xff0c;它们的总机械能也守恒。但这个理想环境是什么样的呢&#xff1f;理想环境会不会影响游戏的真实性&#xff1f;对于前者我们做出在碰撞过程中理想环境的假设&#xff1a;

1&#xff09;首先我们要排除两个碰撞球相互作用之外的力&#xff0c;也就是假设没有外力作用于碰撞系统。
2&#xff09;假设碰撞系统与外界没有能量交换。
3&#xff09;两个球体相互作用的时间极短&#xff0c;且相互作用的内力很大。

有了这样的假设&#xff0c;我们就可以使用动量守恒和动能守恒定律来处理它们之间的速度关系了&#xff0c;因为1&#xff09;确保没有外力参与&#xff0c;碰撞系统内部动量守恒&#xff0c;我们就可以使用动量守恒定律。2&#xff09;保证了我们的碰撞系统的总能量不会改变&#xff0c;我们就可以使用动能守恒定律。3&#xff09;两球发生完全弹性碰撞&#xff0c;不会粘在一起&#xff0c;没有动量、能量损失。

而对于刚才的第二个问题&#xff0c;我的回答是不会&#xff0c;经验告诉我们&#xff0c;理想环境的模拟看起来也是很真实的。除非你是在进行科学研究&#xff0c;否则完全可以这样理想的去模拟。

现在&#xff0c;我们可以通过方程来观察碰撞前后两球的速度关系。当两球球心移动方向共线(1-D处理)时的速度&#xff0c;或不共线(2-D处理)时共线方向的速度分量满足&#xff1a;

(1)m1 * v1 &#43; m2 * v2 &#61; m1 * v1&#39; &#43; m2 * v2&#39; &#xff08;动量守恒定律&#xff09;
(2)1/2 * m1 * v1^2 &#43; 1/2 * m2 * v2^2 &#61; 1/2 * m1 * v1&#39;^2 &#43; 1/2 * m2 * v2&#39;^2 &#xff08;动能守恒定律&#xff09;

这里m1和m2是两球的质量&#xff0c;是给定的&#xff0c;v1和v2是两球的初速度也是我们已知的&#xff0c;v1&#39;和v2&#39;是两球的末速度&#xff0c;是我们要求的。好&#xff0c;现在我们要推导出v1&#39;和v2&#39;的表达式&#xff1a;

由(1)&#xff0c;得到v1&#39; &#61; (m1 * v1 &#43; m2 * v2 - m2 * v2&#39;) / m1&#xff0c;代入(2)&#xff0c;得
1/2 * m1 * v1^2 &#43; 1/2 * m2 * v2^2 &#61; 1/2 * m1 * (m1 * v1 &#43; m2 * v2 - m2 * v2&#39;)^2 &#43; 1/2 * m2 * v2&#39;^2

&#61;> v2&#39; &#61; (2 * m2 * v1 &#43; v2 * (m1 - m2)) / (m1 &#43; m2)
&#xff0c;
&#61;> v1&#39; &#61; (2 * m1 * v2 &#43; v1 * (m1 - m2)) / (m1 &#43; m2)

我们现在得到的公式可以用于处理当两球球心移动方向共线(1-D处理)时的速度关系&#xff0c;或者不共线(2-D处理)时共线方向的速度分量的关系。不管是前者还是后者&#xff0c;我们都需要把它们的速度分解到同一个轴上才能应用上述公式进行处理。

二、深入分析

首先我要说明一件事情&#xff1a;当两球碰撞时&#xff0c;它们的速度可以分解为球心连线方向的分速度和碰撞点切线方向的分速度。而由于它们之间相互作用的力只是在切点上&#xff0c;也就是球心连线方向上&#xff0c;因此我们只用处理这个方向上的力。而在切线方向上&#xff0c;它们不存在相互作用的力&#xff0c;而且在理想环境下也没有外力&#xff0c;因此这个方向上的力在碰撞前后都不变&#xff0c;因此不处理。好&#xff0c;知道了这件事情之后&#xff0c;我们就知道该如何把两球的速度分解到同一个轴上进行处理。

现在看上面的分析图&#xff0c;s和t是我们根据两个相碰球m1和m2的位置建立的辅助轴&#xff0c;我们一会就将把速度投影到它们上面。v1v2分别是m1和m2的初速度&#xff0c;v1&#39;v2&#39;是它们碰撞后的末速度&#xff0c;也就是我们要求的。s&#39;是两球球心的位置向量&#xff0c;t&#39;是它的逆时针正交向量。s1s&#39;的单位向量&#xff0c;t1t&#39;的单位向量。

我们的思路是这样的&#xff1a;首先我们假设两球已经相碰&#xff08;在程序中可以通过计算两球球心之间的距离来判断&#xff09;。接下来我们计算一下s&#39;t&#39;&#xff0c;注意s&#39;t&#39;的方向正反无所谓&#xff08;一会将解释&#xff09;&#xff0c;现在设m1球心为(m1x, m1y)&#xff0c;m2球心为(m2x, m2y)&#xff0c;则s&#39;为(m1x-m2x, m1y-m2y)&#xff0c;t&#39;为&#xff08;m2y-m1y, m1x-m2x)(第一篇的知识&#xff09;。

则设
sM &#61; sqrt((m1x-m2x)^2&#43;(m1y-m2y)^2)&#xff0c;
tM &#61; sqrt((m2y-m1y)^2&#43;(m1x-m2x)^2)&#xff0c;有

s1
&#61; ((m1x-m2x)/sM, (m1y-m2y)/sM) &#61; (s1x, s1y)
t1 &#61; ((m2y-m1y)/tM, (m1x-m2x)/tM) &#61; (t1x, t1y)

现在s和t轴的单位向量已经求出了&#xff0c;我们根据向量点乘的几何意义&#xff0c;计算v1v2s1t1方向上的投影值&#xff0c;然后将s轴上投影值代
入公式来计算s方向碰撞后的速度。注意&#xff0c;根据刚才的说明&#xff0c;t方向的速度不计算&#xff0c;因为没有相互作用的力&#xff0c;因此&#xff0c;t方向的分速度不变。
所以我们要做的就是&#xff1a;把v1投影到s和t方向上&#xff0c;再把v2投影到s和t方向上&#xff0c;用公式分别计算v1v2在s方向上的投影的末速度&#xff0c;然后把得到的末速度在和原来v1v2在t方向上的投影速度再合成&#xff0c;从而算出v1&#39;v2&#39;。好&#xff0c;我们接着这个思路做下去&#xff1a;

先算v1&#xff08;v1x, v1y)在s和t轴的投影值&#xff0c;分别设为v1s和v1t&#xff1a;

v1s &#61; v1.s1
&#61;> v1s &#61; v1x * s1x &#43; v1y * s1y

v1t &#61; v1.t1
&#61;> v1t &#61; v1x * t1x &#43; v1y * t1y

再算v2&#xff08;v2x, v2y)在s和t轴的投影值&#xff0c;分别设为v2s和v2t&#xff1a;

v2s &#61; v2.s1
&#61;> v2s &#61; v2x * s1x &#43; v2y * s1y

v2t &#61; v2.t1
&#61;> v2t &#61; v2x * t1x &#43; v2y * t1y

接下来用公式

v1&#39; &#61; (2 * m1 * v2 &#43; v1 * (m1 - m2)) / (m1 &#43; m2)

v2&#39; &#61; (2 * m2 * v1 &#43; v2 * (m1 - m2)) / (m1 &#43; m2)

计算v1s和v2s的末值v1s&#39;和v2s&#39;&#xff0c;重申v1t和v2t不改变&#xff1a;

假设m1 &#61; m2 &#61; 1

v1s&#39; &#61; &#xff08;2 * 1 * v2s &#43; v1s * (1 - 1)) / (1 &#43; 1)
v2s&#39; &#61; &#xff08;2 * 1 * v1s &#43; v2s * (1 - 1)) / (1 &#43; 1)

&#61;> v1s&#39; &#61; v2s
&#61;> v2s&#39; &#61; v1s

好&#xff0c;下一步&#xff0c;将v1s&#39;和v1t再合成得到v1&#39;&#xff0c;将v2s&#39;和v2t再合成得到v2&#39;,我们用向量和来做&#xff1a;

首先求出v1t和v2t在t轴的向量v1t&#39;v2t&#39;&#xff08;将数值变为向量&#xff09;

v1t&#39; &#61; v1t * t1 &#61; (v1t * t1x, v1t * t1y)
v2t&#39; &#61; v2t * t1 &#61; (v2t * t1x, v2t * t1y)

再求出v1s&#39;和v2s&#39;在s轴的向量v1s&#39;v2s&#39;&#xff08;将数值变为向量&#xff09;

v1s&#39;
&#61; v1s&#39; * s1 &#61; (v1s&#39; * s1x, v1s&#39; * s1y)
v2s&#39;
&#61; v2s&#39; * s1 &#61; (v2s&#39; * s2x, v2s&#39; * s2y)

最后&#xff0c;合成&#xff0c;得

v1&#39; &#61; v1t&#39; &#43; v1s&#39; &#61; (v1t * t1x &#43; v1s&#39; * s1x, v1t * t1y &#43; v1s&#39; * s1y)
v2&#39; &#61; v2t&#39; &#43; v2s&#39; &#61; (v2t * t1x &#43; v2s&#39; * s2x, v2t * t1y &#43; v2s&#39; * s2y)

从而就求出了v1&#39;v2&#39;。下面解释为什么说s&#39;t&#39;的方向正反无所谓&#xff1a;不论我们在计算s&#39;时使用m1的球心坐标减去m2的球心坐标还是相反的相减顺序&#xff0c;由于两球的初速度的向量必有一个和s1是夹角大于90度小于270度的&#xff0c;而另外一个与s1的夹角在0度和90度之间或者说在270度到360度之间&#xff0c;则根据向量点积的定义|a|*|b|*cosA&#xff0c;计算的到的两个投影值一个为负另一个为正&#xff0c;也就是说&#xff0c;速度方向相反&#xff0c;这样就可以用上面的公式区求得末速度了。同时&#xff0c;求出的末速度也是方向相反的&#xff0c;从而在转换为v1s&#39;v2s&#39;时也是正确的方向。同样的&#xff0c;求t&#39;既可以是用s&#39;逆时针90度得到也可以是顺时针90度得到。

三、编写代码

按照惯例&#xff0c;该编写代码了&#xff0c;其实编写的代码和上面的推导过程极为相似。但为了完整&#xff0c;我还是打算写出来。

// 用于球体碰撞响应的函数&#xff0c;其中v1a和v2a为两球的初速度向量&#xff0c;
// v1f和v2f是两球的末速度向量。
// m1和m2是两球的位置向量
// s&#39;的分量为(sx, sy)&#xff0c;t&#39;的分量为&#xff08;tx, ty)
// s1是s的单位向量&#xff0c;分量为&#xff08;s1x, s1y)
// t1是t的单位向量&#xff0c;分量为(t1x, t1y)

void Ball_Collision(v1a, v2a, &v1f, &v2f, m1, m2){

// 求出s&#39;
double sx &#61; m1.x - m2.x ;
double sy &#61; m1.y - m2.y ;

// 求出s1
double s1x &#61; sx / sqrt(sx*sx &#43; sy*sy) ;
double s1y &#61; sy / sqrt(sx*sx &#43; sy*sy) ;

// 求出t&#39;
double tx &#61; -sy ;
double ty &#61; sx ;

// 求出t1
double t1x &#61; tx / sqrt(tx*tx &#43; ty*ty) ;
double t1y &#61; ty / sqrt(tx*tx &#43; ty*ty) ;

// 求v1a在s1上的投影v1s
double v1s &#61; v1a.x * s1x &#43; v1a.y * s1y ;

// 求v1a在t1上的投影v1t
double v1t &#61; v1a.x * t1x &#43; v1a.y * t1y ;

// 求v2a在s1上的投影v2s
double v2s &#61; v2a.x * s1x &#43; v2a.y * s1y ;

// 求v2a在t1上的投影v2t
double v2t &#61; v2a.x * t1x &#43; v2a.y * t1y ;

// 用公式求出v1sf和v2sf
double v1sf &#61; v2s ;
double v2sf &#61; v1s ;

// 最后一步&#xff0c;注意这里我们简化一下&#xff0c;直接将v1sf,v1t和v2sf,v2t投影到x&#xff0c;y轴上&#xff0c;也就是v1&#39;和v2&#39;在x,y轴上的分量
// 先将v1sf和v1t转化为向量

double nsx &#61; v1sf * s1x ;
double nsy &#61; v1sf * s1y ;
double ntx &#61; v1t * t1x ;
double nty &#61; v1t * t1y ;

// 投影到x轴和y轴
// x轴单位向量为(1,0)&#xff0c;y轴为(0,1)
//
v1f.x &#61; 1.0 * (nsx * 1.0 &#43; nsy * 0.0) ;
// v1f.y &#61; 1.0 * (nsx * 0.0 &#43; nsy * 1.0) ;
// v1f.x&#43;&#61; 1.0 * (ntx * 1.0 &#43; nty * 0.0) ;
// v1f.y&#43;&#61; 1.0 * (ntx * 0.0 &#43; nty * 1.0) ;

v1f.x &#61; nsx &#43; ntx ;
v1f.y &#61; nsy &#43; nty ;

// 然后将v2sf和v2t转化为向量

nsx &#61; v2sf * s1x ;
nsy &#61; v2sf * s1y ;
ntx &#61; v2t * t1x ;
nty &#61; v2t * t1y ;

// 投影到x轴和y轴
// x轴单位向量为(1,0)&#xff0c;y轴为(0,1)
//
v2f.x &#61; 1.0 * (nsx * 1.0 &#43; nsy * 0.0) ;
// v2f.y &#61; 1.0 * (nsx * 0.0 &#43; nsy * 1.0) ;
// v2f.x&#43;&#61; 1.0 * (ntx * 1.0 &#43; nty * 0.0) ;
// v2f.y&#43;&#61; 1.0 * (ntx * 0.0 &#43; nty * 1.0) ;


v2f.x &#61; nsx &#43; ntx ;
v2f.y &#61; nsy &#43; nty ;

}// end of function

呼~~是不是感觉有点乱阿&#xff1f;不管怎么样&#xff0c;我有这种感觉。但我们确实完成了它。希望你能够理解这个计算的过程&#xff0c;你完全可以依照这个过程自己编写更高效的代码&#xff0c;让它看上去更清楚&#xff1a;&#xff09;至此位置&#xff0c;我们已经掌握了编写一个台球游戏的基本知识了&#xff0c;Let&#39;s make it!

事实上&#xff0c;一切才刚刚起步&#xff0c;我们还有很多没有解决的问题&#xff0c;比如旋转问题&#xff0c;击球的角度问题等等&#xff0c;你还会深入的研究一下&#xff0c;对吗&#xff1f;一旦你有了目标&#xff0c;坚持下去&#xff0c;保持激情&#xff0c;总会有成功的一天&#xff1a;&#xff09;这次就到这里&#xff0c;下次我们接着研究


推荐阅读
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • C++中的三角函数计算及其应用
    本文介绍了C++中的三角函数的计算方法和应用,包括计算余弦、正弦、正切值以及反三角函数求对应的弧度制角度的示例代码。代码中使用了C++的数学库和命名空间,通过赋值和输出语句实现了三角函数的计算和结果显示。通过学习本文,读者可以了解到C++中三角函数的基本用法和应用场景。 ... [详细]
  • Android日历提醒软件开源项目分享及使用教程
    本文介绍了一款名为Android日历提醒软件的开源项目,作者分享了该项目的代码和使用教程,并提供了GitHub项目地址。文章详细介绍了该软件的主界面风格、日程信息的分类查看功能,以及添加日程提醒和查看详情的界面。同时,作者还提醒了读者在使用过程中可能遇到的Android6.0权限问题,并提供了解决方法。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
author-avatar
mobiledu2502869373
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有