这两天在研究canvas碰撞

先把小球开始运动的图拿出来

参考了一下别的的代码,在两个小球碰撞处理上,我觉得不完善

怎么样处理才算完善呢,当然是要用高中物理学的动量守恒了和机械能守恒了

机械能守恒我其实忘了,特地百度了下

用高中老师的话就是,联立,解得,PS:结果我是网上找的,也存在看错的可能

碰撞的逻辑我来简要所以下

1.当小球撞到墙,对应的x轴或者y轴的速度成 -1,效果是反弹

2.当两个小球碰撞时,由上面的公式,我们会分别计算speedX和speedY

由于动量守恒,我们再效果图中能发现,同一方向相撞,小球会马上获得一个大的速度,而打球减速并不明显

最后慢慢传递,很多球都停止了,但是最后一般来说,还是有一个球载运动的

最后小球还是会有重叠的情况,我再分析下。。。

我觉得像子弹打物块一样,接触物体的发生了变化,但是子弹还是有向前的速度,且速度比物块大

两个小球接触的时候也是这样,球1撞到球2,但是球1的速度还是比2快,于是球1就叠到球2上了

然后在叠的过程中,在逻辑里还是处于碰撞,还在发生能量转移。

事实证明,叠起来的球过了几秒就静止了,

通常是速度大的小球,接触到速度小的大球,接触后小球的速度还是别大球快。于是叠在一起,叠在一起后,还在进行能量转换,最后保持平衡,

静止,或者用同样的速度运行。所以出现了叠在一起不分开的情况

当一个小球的速度够快,碰撞大球的时候才会出现以上情况

当我把球的半径改成一样

应该就不会发生了

  1. <script type="text/javascript">
  2. var canvas = document.getElementById("canvas1");
  3. var ctx = canvas.getContext("2d");
  4. //随机函数
  5. function randomNum (m,n) {
  6. return Math.floor(Math.random() * (n - m + 1) + m);
  7. }
  8. //创建小球类
  9. function Ball () {
  10. //随机小球半径
  11. this.r = randomNum(20,30);
  12. //随机颜色
  13. this.color = 'rgb(' + randomNum(0,255) + ',' + randomNum(0,255) + ',' + randomNum(0,255) + ')';
  14. //随机小球的位置
  15. this.x = randomNum(this.r,canvas.width-this.r);
  16. this.y = randomNum(this.r,canvas.height-this.r);
  17. //小球速度X轴1和-1;
  18. this.speedX = randomNum(2,5) * randomNum(0,1) ? 1 : -1;
  19. this.speedY = randomNum(2,5) * randomNum(0,1) ? 1 : -1;
  20.  
  21. }
  22. //小球移动
  23. Ball.prototype.move = function () {
  24. this.x += this.speedX;
  25. this.y += this.speedY;
  26. //判断是否碰到边界
  27. //左边界
  28. if (this.x <= this.r) {
  29. this.x = this.r;
  30. //反弹
  31. this.speedX *= -1;
  32. }
  33. //右边界
  34. if (this.x >= canvas.width-this.r) {
  35. this.x = canvas.width-this.r;
  36. this.speedX *= -1;
  37. }
  38. if (this.y <= this.r) {
  39. this.y = this.r;
  40. this.speedY *= -1;
  41. }
  42. if (this.y >= canvas.height-this.r) {
  43. this.y = canvas.height-this.r;
  44. this.speedY *= -1;
  45. }
  46. }
  47. //绘制小球
  48. Ball.prototype.drawBall = function () {
  49. ctx.beginPath();
  50. ctx.arc(this.x,this.y,this.r,0,Math.PI*2,false);
  51. ctx.fillStyle = this.color;
  52. ctx.fill();
  53. }
  54. //创建小球的对象
  55. var balls = [];
  56. for (var i = 0;i < 5;i++) {
  57. var ball = new Ball();
  58. balls.push(ball);
  59. }
  60. //让小球移动
  61. setInterval(function () {
  62. ctx.clearRect(0,0,canvas.width,canvas.height);
  63. for (var i = 0;i < balls.length;i++) {
  64. balls[i].move();
  65. balls[i].drawBall();
  66. //移动后检测小球碰撞反弹
  67. for (j = 0;j < balls.length;j++) {
  68. //判断不是同一个球
  69. if (balls[i] == balls[j]) {
  70. continue;//不做碰撞检测
  71. }
  72. //碰撞检测
  73. if (ballCrash(balls[i],balls[j])) {
  74. /*
  75. 1.物理公式动量守恒,假设每个球的质地均匀,那么小球的质量与半径有关
  76. 2.我们用1一次方的算法,实际平面球质量和r的平方有关,立体球和r的三次方有关
  77. 3.由动量守恒,m1*v1+m2*v2=m1*v1'+m2*v2'
  78. 4.机械能守恒,平方我就不写了,两个方程联立
  79. */
  80. var fzx=(balls[i].r - balls[j].r)*balls[i].speedX + 2*balls[j].r*balls[j].speedX;
  81. var fzx2=2*balls[i].r*balls[i].speedX+(balls[i].r - balls[j].r)*balls[j].speedX;
  82. var fzy=(balls[i].r - balls[j].r)*balls[i].speedY + 2*balls[j].r*balls[j].speedY;
  83. var fzy2=2*balls[i].r*balls[i].speedY+(balls[i].r - balls[j].r)*balls[j].speedY;
  84. var fm=balls[i].r + balls[j].r;
  85.  
  86. balls[i].speedX=(fzx/fm);
  87. balls[i].speedY=(fzy/fm);
  88. balls[j].speedX=(fzx2/fm);
  89. balls[j].speedY=(fzy2/fm);
  90. }
  91. }
  92. }
  93. },0.1)
  94.  
  95. //碰撞检测
  96. function ballCrash (ball1,ball2) {
  97. //两个小球之间的距离
  98. var distance = Math.sqrt(Math.pow(ball1.x - ball2.x,2) + Math.pow(ball1.y - ball2.y,2));
  99. //两球的距离小于两个半径的和即为碰撞
  100. if (distance <= ball1.r + ball2.r) {
  101. return true;//碰撞
  102. } else{
  103. return false;//没有碰撞
  104. }
  105. }
  106. </script>

重叠的情况用下面代码可以避免,但是有时候会出别的bug

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>小球碰撞反弹</title>
  6. <style type="text/css">
  7. #canvas1{
  8. border: 4px dashed black;
  9. margin: 0 auto;
  10. display: block;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <canvas id="canvas1" width="600" height="600"></canvas>
  16. </body>
  17. <script type="text/javascript">
  18. var canvas = document.getElementById("canvas1");
  19. var ctx = canvas.getContext("2d");
  20. //随机函数
  21. function randomNum (m,n) {
  22. return Math.floor(Math.random() * (n - m + 1) + m);
  23. }
  24. //创建小球类
  25. function Ball () {
  26. //随机小球半径
  27. this.r = randomNum(15,30);
  28. //随机颜色
  29. this.color = 'rgb(' + randomNum(0,255) + ',' + randomNum(0,255) + ',' + randomNum(0,255) + ')';
  30. //随机小球的位置
  31. this.x = randomNum(this.r,canvas.width-this.r);
  32. this.y = randomNum(this.r,canvas.height-this.r);
  33. //小球速度X轴1和-1;
  34. this.speedX = randomNum(2,5) * randomNum(0,1) ? 1 : -1;
  35. this.speedY = randomNum(2,5) * randomNum(0,1) ? 1 : -1;
  36.  
  37. }
  38. //小球移动
  39. Ball.prototype.move = function () {
  40. this.x += this.speedX;
  41. this.y += this.speedY;
  42. //判断是否碰到边界
  43. //左边界
  44. if (this.x <= this.r) {
  45. this.x = this.r;
  46. //反弹
  47. this.speedX *= -1;
  48. }
  49. //右边界
  50. if (this.x >= canvas.width-this.r) {
  51. this.x = canvas.width-this.r;
  52. this.speedX *= -1;
  53. }
  54. if (this.y <= this.r) {
  55. this.y = this.r;
  56. this.speedY *= -1;
  57. }
  58. if (this.y >= canvas.height-this.r) {
  59. this.y = canvas.height-this.r;
  60. this.speedY *= -1;
  61. }
  62. }
  63. //绘制小球
  64. Ball.prototype.drawBall = function () {
  65. ctx.beginPath();
  66. ctx.arc(this.x,this.y,this.r,0,Math.PI*2,false);
  67. ctx.fillStyle = this.color;
  68. ctx.fill();
  69. }
  70. //创建小球的对象
  71. var balls = [];
  72. for (var i = 0;i < 10;i++) {
  73. var ball = new Ball();
  74. balls.push(ball);
  75. }
  76. //让小球移动
  77. setInterval(function () {
  78. ctx.clearRect(0,0,canvas.width,canvas.height);
  79. for (var i = 0;i < balls.length;i++) {
  80. balls[i].move();
  81. balls[i].drawBall();
  82. //移动后检测小球碰撞反弹
  83. for (j = 0;j < balls.length;j++) {
  84. //判断不是同一个球
  85. if (balls[i] == balls[j]) {
  86. continue;//不做碰撞检测
  87. }
  88. //碰撞检测
  89. if (ballCrash(balls[i],balls[j])) {
  90.  
  91. /*
  92. 1.物理公式动量守恒,假设每个球的质地均匀,那么小球的质量与半径有关
  93. 2.我们用1一次方的算法,实际平面球质量和r的平方有关,立体球和r的三次方有关
  94. 3.由动量守恒,m1*v1+m2*v2=m1*v1'+m2*v2'
  95. 4.机械能守恒,平方我就不写了,两个方程联立
  96. */
  97. var fzx=(balls[i].r - balls[j].r)*balls[i].speedX + 2*balls[j].r*balls[j].speedX;
  98. var fzx2=2*balls[i].r*balls[i].speedX+(balls[i].r - balls[j].r)*balls[j].speedX;
  99. var fzy=(balls[i].r - balls[j].r)*balls[i].speedY + 2*balls[j].r*balls[j].speedY;
  100. var fzy2=2*balls[i].r*balls[i].speedY+(balls[i].r - balls[j].r)*balls[j].speedY;
  101. var fm=balls[i].r + balls[j].r;
  102.  
  103. balls[i].speedX=(fzx/fm);
  104. balls[i].speedY=(fzy/fm);
  105. balls[j].speedX=(fzx2/fm);
  106. balls[j].speedY=(fzy2/fm);
  107. }
  108. }
  109. }
  110. },1)
  111.  
  112. //碰撞检测
  113. function ballCrash (ball1,ball2) {
  114.  
  115. //两个小球之间的距离
  116. var distance = Math.sqrt(Math.pow(ball1.x - ball2.x,2) + Math.pow(ball1.y - ball2.y,2));
  117. //两球的距离小于两个半径的和即为碰撞
  118. if (distance == ball1.r + ball2.r) {
  119.  
  120. return true;//碰撞
  121. }else if( distance < ball1.r + ball2.r){
  122. if(Math.pow(ball1.speedX,2)+Math.pow(ball1.speedY,2)>Math.pow(ball2.speedX,2)+Math.pow(ball2.speedY,2)){
  123. if(ball1.speedX>0){
  124. ball2.x=ball2.x+ball1.r + ball2.r - distance;
  125. if(ball1.speedY > 0){
  126. ball2.y=ball2.y+ball1.r + ball2.r - distance;
  127. }else{
  128. ball2.y=ball2.y-ball1.r - ball2.r + distance;
  129. }
  130. }else{
  131. ball2.x=ball2.x-ball1.r - ball2.r + distance;
  132. if(ball1.speedY > 0){
  133. ball2.y=ball2.y+ball1.r + ball2.r - distance;
  134. }else{
  135. ball2.y=ball2.y-ball1.r - ball2.r + distance;
  136. }
  137. }
  138.  
  139. }else{
  140. if(ball2.speedX>0){
  141. ball1.x=ball1.x+ball1.r + ball2.r - distance;
  142. if(ball2.speedY > 0){
  143. ball1.y=ball1.y+ball1.r + ball2.r - distance;
  144. }else{
  145. ball1.y=ball1.y-ball1.r - ball2.r + distance;
  146. }
  147. }else{
  148. ball1.x=ball1.x-ball1.r - ball2.r + distance;
  149. if(ball2.speedY > 0){
  150. ball1.y=ball1.y+ball1.r + ball2.r - distance;
  151. }else{
  152. ball1.y=ball1.y-ball1.r - ball2.r + distance;
  153. }
  154. }
  155. }
  156. return true;
  157. }
  158. else{
  159. return false;//没有碰撞
  160. }
  161. }
  162.  
  163. </script>
  164. </html>

(canvas)两小球碰撞后的速度问题研究的更多相关文章

  1. HTML5 Canvas彩色小球碰撞运动特效

    脚本简介 HTML5 Canvas彩色小球碰撞运动特效是一款基于canvas加面向对象制作的运动小球动画特效.   效果展示 http://hovertree.com/texiao/html5/39/ ...

  2. canvas动态小球重叠效果

    前面的话 在javascript运动系列中,详细介绍了各种运动,其中就包括碰壁运动.但是,如果用canvas去实现,却是另一种思路.本文将详细介绍canvas动态小球重叠效果 效果展示 静态小球 首先 ...

  3. Canvas 动态小球重叠效果

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  4. 第七讲:HTML5中的canvas两个小球全然弹性碰撞

    <html> <head> <title>小球之间的碰撞(全然弹性碰撞)</title> <script src="../js/jsce ...

  5. uniapp中用canvas实现小球碰撞的小动画

    uniapp 我就不想喷了,踩了很多坑,把代码贡献出来让大家少踩些坑. 实现的功能: 生成n个球在canvas中运动,相互碰撞后会反弹,反弹后的速度计算我研究过了,可以参考代码直接用 防止球出边框 防 ...

  6. 第八讲:HTML5中canvas实现小球击打小方块游戏

    源码:http://download.csdn.net/detail/liumingm900913/7469969 游戏开发流程: 1.创建画布: 将画布放在div标签里面,这样能够控制画布居中的位置 ...

  7. canvas 模拟小球上抛运动的物理效果

    最近一直想用学的canvas做一个漂亮的小应用,但是,发现事情并不是想的那么简单.比如,游戏的逼真效果,需要自己来coding…… 所以,自己又先做了一个小demo,算是体验一下亲手打造物理引擎的感觉 ...

  8. Android画图之抗锯齿 paint 和 Canvas 两种方式

    在画图的时候,图片如果旋转或缩放之后,总是会出现那些华丽的锯齿.其实Android自带了解决方式.    方法一:给Paint加上抗锯齿标志.然后将Paint对象作为参数传给canvas的绘制方法. ...

  9. HashMap两种遍历方式的深入研究

    转自:http://swiftlet.net/archives/1259 HashMap的遍历有两种方式,如下所示:第一种利用entrySet的方式:   1 2 3 4 5 6 7 Map map ...

随机推荐

  1. ATS 自定义日志格式

    字段解释 %<chi> 客户端IP %<caun> The username of the authenticated client. A hyphen (-) means t ...

  2. C# 时间戳与时间相互转化

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 时间戳d ...

  3. 第14月第23天 uitextfield文字下移

    1. http://www.jianshu.com/p/641a0cbcabb0

  4. mysql 原理 ~ innodb恢复机制

    举例说明 机制 数据页A的lsn为100,数据页B的lsn为200,checkpoint lsn为150,系统lsn为300,表示当前系统已经更新到300,小于150的数据页已经被刷到磁盘上,因此数据 ...

  5. bootstrap-table前端修改数据

    使用bootstrap-table显示数据,后台传回数据以后,可能需要对其做调整,如需要前端为数据添加单位 调整数据代码 $("#"+tableId).bootstrapTable ...

  6. 为什么Docker比虚拟机快?

    1.Docker有着比虚拟机更少的抽象层,由于Docker不需要Hypervisor实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源,因此在Cpu.内存利用率上Do ...

  7. windows安装anaconda 报错failed to create anacoda menu ?

    windows安装anaconda 报错failed to create anacoda menu ? 装了无数次,每次都是 failed to create anacoda menu然后无选择忽略, ...

  8. 005_nginx414_nginx 414 Request-URI Too Large

    一.开发请求一个非常长的请求参数 https://jiaju.jyall.me/backend/dish/getSales/?dishId=167271&dishId=166975&d ...

  9. HTTP基础知识1

    HTTP 简介 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准,它是基于TCP/IP ...

  10. Ex 6_12 凸多边形的最优三角剖分..._第六次作业

    假设顶点的总数为n,从0到n-1. 从序号为0的顶点开始以逆时针方向排序,对于 令子问题A[i,j]为包含顶点i,i+1, . . . j的凸多边形的最小三角剖分代价,dist(i,j)为顶点i到顶点 ...