完全弹性斜碰:

本文讨论两个考虑质量的小球间完全弹性斜碰。

完全弹性正碰可直接通过动能定理和动量守恒即解决。

完全弹性斜碰稍微复杂一点,具体计算过程如下:

首先拿两小球记为A球和B球,A球B球属性有质量,速度大小,速度方向。

建立坐标系(后面会用到):

1)以A球圆心为原点,以水平方向向右为X轴,逆时针偏转PI/2为Y轴,建立A坐标系。

2)以B球圆心为原点,以水平方向向右为X轴,逆时针偏装PI/2为Y轴,建立B坐标系。

3)以A球B球圆心连线为X轴,方向由A到B,逆时针偏装PI/2为Y轴,建立AB坐标系。

碰撞过程中涉及到的变量:(下文会逐一介绍)

angleA        VA          VAX         VAY        mA      angleAB

angleNA      VNA       VNAX      VNAY

anglePNA    VPNA    VPNAX    VPNAY

angleZA       VZA       VZAX      VZAY

angleB        VB          VBX         VBY        mB      angleAB

angleNB      VNB       VNBX      VNBY

anglePNB    VPNB    VPNBX    VPNBY

angleZB       VZB       VZBX      VZBY

碰撞的计算过程:

已知:A球和B球的初速度和方向。

angleA,VA,angleB,VB。

第零步:给变量改名。

第一步:求XAB的角度,即B相对于A的角度。

第二步:记录XAB坐标系中VB的角度,并求出XAB坐标系中X轴Y轴的分速度。

第三步:XAB坐标系中,Y轴速度不变,X轴速度满足完全弹性正碰。

第四步:合成新速度,并计算XAB中的角度。

第五步:转化为水平坐标系中的速度和角度。

第六步:赋值操作。



第零步:给变量改名(变量多改名便于记忆)

A球的运动方向记为angleA,速度大小记为VA。

A球在坐标系A中X轴的角度记为VAX = VA * cos(angleA)

A球在坐标系A中Y轴的角度记为VAY = VA * sin(angleA)

同理可得B球的angleB,VB,VBX,VBY。

第一步:求XAB坐标系X轴与水平方向的角度angleAB,并求出A球B球在XAB坐标系中的速度大小和方向

获得A球B球的圆心实际坐标positionA,positionB。【圆心坐标是个列表,存放球A相对与窗口左上角的坐标x和y】【注意,此坐标系X轴向右为正,Y轴向下为正】

圆心B相对于圆心A的坐标为(x,y)=(positionB[0] - positionA[0] , positionA[1]  - positionB[1])

【新建的坐标系与数学中的坐标系一样,而实际坐标所在坐标系X轴以右为正,Y轴以下为正,所以Y轴坐标应该反过来相减】

计算angleAB

cos(angleAB)= x / sqrt(x*x + y*y)

angleAB = arccos( x / sqrt(x*x + y*y))【此时求出来到只是与水平方向的角度,并未考虑正向负向】

angleAB = arccos( x / sqrt(x*x + y*y))* y / abs(y)【通过y的正负确定angle是顺时针偏转还是逆时针偏转,abs()是求绝对值的函数】

第1.5步:为防止小球粘连,碰撞前调整两球位置【此步骤最后添加】

碰撞时理想状况下,是边缘与边缘相碰。

但实际上检测出来的碰撞大部分两小球已经有部分重叠了,则此时应该先将两向球反向移开,移动到边缘碰边缘即可。

具体过程详见后面的代码。

第二步:将A球B球的速度大小方向由各自坐标系中转化为在共同坐标系XAB中的速度大小和方向

在XAB坐标系中A球的新角度        angleNA = angleA - angleAB

在XAB坐标系中A球的新速度        VNA = VA

在XAB坐标系中A球的新X轴速度  VNAX = VNA * cos(angleNA)

在XAB坐标系中A球的新Y轴角度  VNAY = VNA * sin(angleNA)

同理可得

在XAB坐标系中B球的新角度        angleNB = angleB - angleAB

在XAB坐标系中B球的新速度        VNB = VB

在XAB坐标系中B球的新X轴速度  VNBX = VNB * cos(angleNB)

在XAB坐标系中B球的新Y轴角度  VNBY = VNB * sin(angleNB)

第三步:发生完全弹性斜碰时,在XAB坐标系中,两球Y轴速度不变,X轴速度满足完全弹性正碰。

计算碰撞后两球的新速度

碰撞后A球X轴的分速度  VPNAX = [ (mA - mB) * VNAX + 2 * mB * VNBX ] / (mA + mB)

碰撞后B球X轴的分速度  VPNBX = [ (mB - mA) * VNBX + 2 * mA * VNAX ] / (mA + mB)

碰撞后A球Y轴的分速度  VPNAY = VNAY

碰撞后B球Y轴的分速度  VPNBY = VNBY

第四步:合成两球的新速度,并计算当前两球在坐标系XAB中的角度。

A球碰撞后速度大小  VPNA = sqrt(VPNAX * VPNAX + VPNAY * VPNAY)

B球碰撞后速度大小  VPNB = sqrt(VPNBX * VPNBX + VPNBY * VPNBY)

A球碰撞后速度角度  anglePNA = arccos(VPNAX / VPNA)* VPNAY / abs(VPNAY)    【公式由动能定理和动量守恒推导得出,此处省略推导过程】

B球碰撞后速度角度  anglePNB = arccos(VPNBX / VPNB)* VPNBY / abs(VPNBY)

第五步:将两球速度转化为各自坐标系中的速度

A球最终角度  angleZA = anglePNA + angleAB

A球最终速度  VZA = VPNA

A球最终X轴分速度  VZAX = VZA * cos(angleZA)

A球最终Y轴分速度  VZAY = VZA * sin(angleZA)* (-1)

【-1 的作用是转化为实际坐标系中的坐标, 计算过程中的坐标系都是数学中常规的坐标系,而程序中实际坐标系是坐上方顶点为原点,向右为X,向下为Y,两个坐标系中Y轴是相反的,所以乘格 -1】

同理可得:

B球最终角度  angleZB = anglePNB + angleAB

B球最终速度  VZB = VPNB

B球最终X轴分速度  VZBX = VZB * cos(angleZB)

B球最终Y轴分速度  VZBY = VZB * sin(angleZB)* (-1)

第六步:赋值操作

将俩球的速度大小方向付给程序中的对象。【大功告成啦】



下面是碰撞部分的Python代码:

    # 碰撞函数def collide(self, collideBall, isChessman):# 第0步:转换变量名B = copy.copy(self)A = copy.copy(collideBall)angleB = B.angleVB     = B.velocity# VBX    = B.velocity_x# VBY    = -B.velocity_yMB     = B.massangleA = A.angleVA     = A.velocity# VAX    = A.velocity_x# VAY    = -A.velocity_yMA     = A.mass# 第1步:求 XAB 轴的角度,即 B 相对于 A 的角度positionA = collideBall.rect.left + collideBall.rect.width / 2, collideBall.rect.top  + collideBall.rect.height / 2 positionB = self.rect.left + self.rect.width / 2, self.rect.top  + self.rect.height / 2x = positionB[0] - positionA[0]y = positionA[1] - positionB[1]if x == 0 and y == 0:print("错误120:两球发生重叠!")angleAB = 0elif y != 0:angleAB = math.acos(  x  / math.sqrt(x ** 2 + y ** 2)) *   y  / math.fabs( y)# angleBA = math.acos((-x) / math.sqrt(x ** 2 + y ** 2)) * (-y) / math.fabs(-y)else:angleAB = math.acos(  x  / math.sqrt(x ** 2 + y ** 2))# angleBA = math.acos((-x) / math.sqrt(x ** 2 + y ** 2))# 第1.5步:为防止粘连现象,调整小球位置actualCenterDistance       = math.sqrt((self.rect.center[0] - collideBall.rect.center[0]) ** 2 + (self.rect.center[1] - collideBall.rect.center[1]) ** 2)idealCenterDistance        = self.radius + collideBall.radiusoneBallNeedMoveDistance    = (idealCenterDistance - actualCenterDistance) / 2selfBallNeedMoveDistance_x = oneBallNeedMoveDistance * math.cos(angleAB)selfBallNeedMoveDistance_y = oneBallNeedMoveDistance * math.sin(angleAB)self.centerPosition[0] += selfBallNeedMoveDistance_x * 2self.centerPosition[1] -= selfBallNeedMoveDistance_y * 2self.rect.center = self.centerPositionif isChessman:collideBall.centerPosition[0] -= selfBallNeedMoveDistance_xcollideBall.centerPosition[1]+= selfBallNeedMoveDistance_ycollideBall.rect.center = collideBall.centerPositionelse:self.centerPosition[0] += selfBallNeedMoveDistance_x * 2self.centerPosition[1] -= selfBallNeedMoveDistance_y * 2self.rect.center = self.centerPosition# 第2步:记录 XAB 坐标系中 VB VA 的角度#       并求出 XAB 坐标系中 X Y 轴的分速度angleNB = angleB - angleAB##if angleNB <= -math.pi:##    angleNB += 2 * math.piVNB  = VBVNBX = VNB * math.cos(angleNB)VNBY = VNB * math.sin(angleNB)angleNA = angleA - angleAB##if angleNA <= -math.pi:##    angleNA += 2 * math.piVNA  = VAVNAX = VNA * math.cos(angleNA)VNAY = VNA * math.sin(angleNA)# 第3步:XAB( 坐标系中,Y 轴速度不变,X 轴速度满足完全弹性正碰#       计算 X 轴上碰撞后的新速度VPNBX = ((MB - MA) * VNBX + 2 * MA * VNAX) / (MA + MB)VPNBY = VNBYVPNAX = ((MA - MB) * VNAX + 2 * MB * VNBX) / (MA + MB)VPNAY = VNAY# 第4步:合成碰撞后的新速度,并计算 XAB中的新角度VPNB = math.sqrt(VPNBX ** 2 + VPNBY ** 2)if VPNBX == 0 and VPNBY == 0:#print("错误121:碰撞后B新速度为0")anglePNB = 0elif VPNBY != 0:anglePNB = math.acos(VPNBX / VPNB) * VPNBY / math.fabs(VPNBY)else:anglePNB = math.acos(VPNBX / VPNB)VPNA = math.sqrt(VPNAX ** 2 + VPNAY ** 2)if VPNAX == 0 and VPNAY == 0:#print("错误122:碰撞后A新速度为0")anglePNA = 0elif VPNAY != 0:anglePNA = math.acos(VPNAX / VPNA) * VPNAY / math.fabs(VPNAY)else:anglePNA = math.acos(VPNAX / VPNA)# 第5步:将 XAB 坐标系转化为 XB XA 坐标系中的速度和角度angleZB = anglePNB + angleAB##if angleZB > math.pi:##    angleZB -= 2 * math.piVZB  = VPNBVZBX = VZB * math.cos(angleZB)VZBY = VZB * math.sin(angleZB)angleZA = anglePNA + angleAB##if angleZA > math.pi:##    angleZA -= 2 * math.piVZA  = VPNAVZAX = VZA * math.cos(angleZA)VZAY = VZA * math.sin(angleZA)# 第5.9步:检测角度范围,调整到(-pi, pi]if angleZA > math.pi:angleZA -= 2 * math.pielif angleZA <= -math.pi:angleZA += 2 * math.piif angleZB > math.pi:angleZB -= 2 * math.pielif angleZB <= -math.pi:angleZB += 2 * math.pi# 第6步:赋值操作self.angle      = angleZBself.velocity   = VZBself.velocity_x = VZBXself.velocity_y = -VZBYself.isCollide  = Trueif isChessman:collideBall.angle      = angleZAcollideBall.velocity   = VZAcollideBall.velocity_x = VZAXcollideBall.velocity_y = -VZAYcollideBall.isCollide  = True

小球间完全弹性斜碰(赋Python代码)相关推荐

  1. python好学吗 小木虫-25行Python代码完成人脸识别

    以下是Shantnu Tiwari的客座文章,作者有着在底层编程和嵌入式领域十年的工作经验.在发现Python语言之前的几年时间里,Shantnu Tiwari一直忍受着C/C++语言编程的不便,但P ...

  2. python代码技巧_几个小技巧让你的Python代码更Pythonic

    Python是一门非常灵活的语言,很多语法是其他语言不具备的,特别是对于从C.Java等语言转向Python的人来说,很容易按照C.Java等语言的写法来写Python,对于初学者来说,如果对Pyth ...

  3. python 代码换行_你一定不知道的Python小技巧,提升你Python代码的可读性

    Python的初学者,开发者都应该知道的代码可读性提高技巧,本篇主要介绍了如下内容: PEP 8是什么以及它存在的原因 为什么你应该编写符合PEP 8标准的代码 如何编写符合PEP 8的代码 为什么我 ...

  4. 一行python代码能干_几个小例子告诉你, 一行Python代码能干哪些事

    首先你要了解一下Python之禅,一行代码输出"The Zen of Python": python -c "import this" "" ...

  5. 几个小例子告诉你, 一行Python代码能干哪些事

    首先你要了解一下Python之禅,一行代码输出"The Zen of Python": python -c "import this" "" ...

  6. 小案例:13行python代码实现对微信进行推送消息

    一.前言: Python可以实现给QQ邮箱.企业微信.微信等等软件推送消息,今天咱们实现一下Python直接给微信推送消息. 这里咱们使用了一个第三方工具pushplus 二.单人推送 实现步骤: 1 ...

  7. python打地鼠脚本_制作一个打地鼠的小游戏!100行Python代码轻松搞定

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. 以下文章来源于萝卜大杂烩 ,作者周萝卜 游戏画面 首先先进行游戏画面排版, classTopWin ...

  8. 1000行python代码_GitHub - kill1000/LearnPython: 以撸代码的形式学习Python

    LearnPython 以撸代码的形式学习Python, 具体说明在知乎专栏-撸代码,学知识 ===================================================== ...

  9. 弹球游戏python代码含记分模式_python编写弹球游戏的实现代码

    用Blender制作一个兵乓球小游戏,要编写Python代码需要安装pygame 包没有面对困难的勇气,也就没有享受快乐的权利. python 怎么写双人弹球游戏最难过的事不是别人又得罪你了,而是你自 ...

最新文章

  1. Invoke()/BeginInvoke()区别
  2. 给交叉编译工具建立软连接用脚本
  3. 计算机组成知识试题及答案,《计算机组成与结构复习题及答案.doc
  4. 创新学习对象1-陕西省网络与系统安全重点实验室研究员的李光夏老师
  5. FreeRTOS时间管理
  6. 每一个问题都是一把锁
  7. vue 如何处理两个组件异步问题_Vue异步组件使用详解
  8. Material Theme
  9. 学习《TCP/IP详解 卷一协议》第九章的一点心得
  10. 灵悟礼品网上专卖店——新建数据库
  11. springboot网上订餐管理系统设计与实现.rar(项目源码)
  12. C 语言中 scanf() 的用法
  13. 文献解读-Physics Informed Deep Learning(PINN)
  14. vue路由守卫以及用法
  15. 深入学习卷积神经网络(CNN)的原理知识
  16. Java线程游戏(模拟弹弹堂)
  17. Cocos Creator 3D麻将 v2.1.1
  18. 一个视频发布在三个平台上,可以赚三份收益,自媒体如何发布视频
  19. What is 虫洞攻击?
  20. Windows10重装设置(个人)

热门文章

  1. 机器翻译评价指标之BLEU原理介绍及代码实现
  2. word如何添加行号_如何将行号添加到Microsoft Word文档
  3. java做一个简单的文件管理器
  4. android 保持socket连接,android – 如何保持websocket连接活着?
  5. android集合方法,android中intent传递list或者对象的方法
  6. java毕业生设计选课系统计算机源码+系统+mysql+调试部署+lw
  7. 简单实用 微信授权登陆(网页版)
  8. 内网安全-域横向CobaltStrikeSPNRDP
  9. FineReport表格软件-CSS动态切换年月日查询报表
  10. 用.bat文件多开微信及打开固定浏览器浏览固定页面 开机自启