(canvas)两小球碰撞后的速度问题研究
这两天在研究canvas碰撞
先把小球开始运动的图拿出来
参考了一下别的的代码,在两个小球碰撞处理上,我觉得不完善
怎么样处理才算完善呢,当然是要用高中物理学的动量守恒了和机械能守恒了
机械能守恒我其实忘了,特地百度了下
用高中老师的话就是,联立,解得,PS:结果我是网上找的,也存在看错的可能
碰撞的逻辑我来简要所以下
1.当小球撞到墙,对应的x轴或者y轴的速度成 -1,效果是反弹
2.当两个小球碰撞时,由上面的公式,我们会分别计算speedX和speedY
由于动量守恒,我们再效果图中能发现,同一方向相撞,小球会马上获得一个大的速度,而打球减速并不明显
最后慢慢传递,很多球都停止了,但是最后一般来说,还是有一个球载运动的
最后小球还是会有重叠的情况,我再分析下。。。
我觉得像子弹打物块一样,接触物体的发生了变化,但是子弹还是有向前的速度,且速度比物块大
两个小球接触的时候也是这样,球1撞到球2,但是球1的速度还是比2快,于是球1就叠到球2上了
然后在叠的过程中,在逻辑里还是处于碰撞,还在发生能量转移。
事实证明,叠起来的球过了几秒就静止了,
通常是速度大的小球,接触到速度小的大球,接触后小球的速度还是别大球快。于是叠在一起,叠在一起后,还在进行能量转换,最后保持平衡,
静止,或者用同样的速度运行。所以出现了叠在一起不分开的情况
当一个小球的速度够快,碰撞大球的时候才会出现以上情况
当我把球的半径改成一样
应该就不会发生了
- <script type="text/javascript">
- var canvas = document.getElementById("canvas1");
- var ctx = canvas.getContext("2d");
- //随机函数
- function randomNum (m,n) {
- return Math.floor(Math.random() * (n - m + 1) + m);
- }
- //创建小球类
- function Ball () {
- //随机小球半径
- this.r = randomNum(20,30);
- //随机颜色
- this.color = 'rgb(' + randomNum(0,255) + ',' + randomNum(0,255) + ',' + randomNum(0,255) + ')';
- //随机小球的位置
- this.x = randomNum(this.r,canvas.width-this.r);
- this.y = randomNum(this.r,canvas.height-this.r);
- //小球速度X轴1和-1;
- this.speedX = randomNum(2,5) * randomNum(0,1) ? 1 : -1;
- this.speedY = randomNum(2,5) * randomNum(0,1) ? 1 : -1;
- }
- //小球移动
- Ball.prototype.move = function () {
- this.x += this.speedX;
- this.y += this.speedY;
- //判断是否碰到边界
- //左边界
- if (this.x <= this.r) {
- this.x = this.r;
- //反弹
- this.speedX *= -1;
- }
- //右边界
- if (this.x >= canvas.width-this.r) {
- this.x = canvas.width-this.r;
- this.speedX *= -1;
- }
- if (this.y <= this.r) {
- this.y = this.r;
- this.speedY *= -1;
- }
- if (this.y >= canvas.height-this.r) {
- this.y = canvas.height-this.r;
- this.speedY *= -1;
- }
- }
- //绘制小球
- Ball.prototype.drawBall = function () {
- ctx.beginPath();
- ctx.arc(this.x,this.y,this.r,0,Math.PI*2,false);
- ctx.fillStyle = this.color;
- ctx.fill();
- }
- //创建小球的对象
- var balls = [];
- for (var i = 0;i < 5;i++) {
- var ball = new Ball();
- balls.push(ball);
- }
- //让小球移动
- setInterval(function () {
- ctx.clearRect(0,0,canvas.width,canvas.height);
- for (var i = 0;i < balls.length;i++) {
- balls[i].move();
- balls[i].drawBall();
- //移动后检测小球碰撞反弹
- for (j = 0;j < balls.length;j++) {
- //判断不是同一个球
- if (balls[i] == balls[j]) {
- continue;//不做碰撞检测
- }
- //碰撞检测
- if (ballCrash(balls[i],balls[j])) {
- /*
- 1.物理公式动量守恒,假设每个球的质地均匀,那么小球的质量与半径有关
- 2.我们用1一次方的算法,实际平面球质量和r的平方有关,立体球和r的三次方有关
- 3.由动量守恒,m1*v1+m2*v2=m1*v1'+m2*v2'
- 4.机械能守恒,平方我就不写了,两个方程联立
- */
- var fzx=(balls[i].r - balls[j].r)*balls[i].speedX + 2*balls[j].r*balls[j].speedX;
- var fzx2=2*balls[i].r*balls[i].speedX+(balls[i].r - balls[j].r)*balls[j].speedX;
- var fzy=(balls[i].r - balls[j].r)*balls[i].speedY + 2*balls[j].r*balls[j].speedY;
- var fzy2=2*balls[i].r*balls[i].speedY+(balls[i].r - balls[j].r)*balls[j].speedY;
- var fm=balls[i].r + balls[j].r;
- balls[i].speedX=(fzx/fm);
- balls[i].speedY=(fzy/fm);
- balls[j].speedX=(fzx2/fm);
- balls[j].speedY=(fzy2/fm);
- }
- }
- }
- },0.1)
- //碰撞检测
- function ballCrash (ball1,ball2) {
- //两个小球之间的距离
- var distance = Math.sqrt(Math.pow(ball1.x - ball2.x,2) + Math.pow(ball1.y - ball2.y,2));
- //两球的距离小于两个半径的和即为碰撞
- if (distance <= ball1.r + ball2.r) {
- return true;//碰撞
- } else{
- return false;//没有碰撞
- }
- }
- </script>
重叠的情况用下面代码可以避免,但是有时候会出别的bug
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>小球碰撞反弹</title>
- <style type="text/css">
- #canvas1{
- border: 4px dashed black;
- margin: 0 auto;
- display: block;
- }
- </style>
- </head>
- <body>
- <canvas id="canvas1" width="600" height="600"></canvas>
- </body>
- <script type="text/javascript">
- var canvas = document.getElementById("canvas1");
- var ctx = canvas.getContext("2d");
- //随机函数
- function randomNum (m,n) {
- return Math.floor(Math.random() * (n - m + 1) + m);
- }
- //创建小球类
- function Ball () {
- //随机小球半径
- this.r = randomNum(15,30);
- //随机颜色
- this.color = 'rgb(' + randomNum(0,255) + ',' + randomNum(0,255) + ',' + randomNum(0,255) + ')';
- //随机小球的位置
- this.x = randomNum(this.r,canvas.width-this.r);
- this.y = randomNum(this.r,canvas.height-this.r);
- //小球速度X轴1和-1;
- this.speedX = randomNum(2,5) * randomNum(0,1) ? 1 : -1;
- this.speedY = randomNum(2,5) * randomNum(0,1) ? 1 : -1;
- }
- //小球移动
- Ball.prototype.move = function () {
- this.x += this.speedX;
- this.y += this.speedY;
- //判断是否碰到边界
- //左边界
- if (this.x <= this.r) {
- this.x = this.r;
- //反弹
- this.speedX *= -1;
- }
- //右边界
- if (this.x >= canvas.width-this.r) {
- this.x = canvas.width-this.r;
- this.speedX *= -1;
- }
- if (this.y <= this.r) {
- this.y = this.r;
- this.speedY *= -1;
- }
- if (this.y >= canvas.height-this.r) {
- this.y = canvas.height-this.r;
- this.speedY *= -1;
- }
- }
- //绘制小球
- Ball.prototype.drawBall = function () {
- ctx.beginPath();
- ctx.arc(this.x,this.y,this.r,0,Math.PI*2,false);
- ctx.fillStyle = this.color;
- ctx.fill();
- }
- //创建小球的对象
- var balls = [];
- for (var i = 0;i < 10;i++) {
- var ball = new Ball();
- balls.push(ball);
- }
- //让小球移动
- setInterval(function () {
- ctx.clearRect(0,0,canvas.width,canvas.height);
- for (var i = 0;i < balls.length;i++) {
- balls[i].move();
- balls[i].drawBall();
- //移动后检测小球碰撞反弹
- for (j = 0;j < balls.length;j++) {
- //判断不是同一个球
- if (balls[i] == balls[j]) {
- continue;//不做碰撞检测
- }
- //碰撞检测
- if (ballCrash(balls[i],balls[j])) {
- /*
- 1.物理公式动量守恒,假设每个球的质地均匀,那么小球的质量与半径有关
- 2.我们用1一次方的算法,实际平面球质量和r的平方有关,立体球和r的三次方有关
- 3.由动量守恒,m1*v1+m2*v2=m1*v1'+m2*v2'
- 4.机械能守恒,平方我就不写了,两个方程联立
- */
- var fzx=(balls[i].r - balls[j].r)*balls[i].speedX + 2*balls[j].r*balls[j].speedX;
- var fzx2=2*balls[i].r*balls[i].speedX+(balls[i].r - balls[j].r)*balls[j].speedX;
- var fzy=(balls[i].r - balls[j].r)*balls[i].speedY + 2*balls[j].r*balls[j].speedY;
- var fzy2=2*balls[i].r*balls[i].speedY+(balls[i].r - balls[j].r)*balls[j].speedY;
- var fm=balls[i].r + balls[j].r;
- balls[i].speedX=(fzx/fm);
- balls[i].speedY=(fzy/fm);
- balls[j].speedX=(fzx2/fm);
- balls[j].speedY=(fzy2/fm);
- }
- }
- }
- },1)
- //碰撞检测
- function ballCrash (ball1,ball2) {
- //两个小球之间的距离
- var distance = Math.sqrt(Math.pow(ball1.x - ball2.x,2) + Math.pow(ball1.y - ball2.y,2));
- //两球的距离小于两个半径的和即为碰撞
- if (distance == ball1.r + ball2.r) {
- return true;//碰撞
- }else if( distance < ball1.r + ball2.r){
- if(Math.pow(ball1.speedX,2)+Math.pow(ball1.speedY,2)>Math.pow(ball2.speedX,2)+Math.pow(ball2.speedY,2)){
- if(ball1.speedX>0){
- ball2.x=ball2.x+ball1.r + ball2.r - distance;
- if(ball1.speedY > 0){
- ball2.y=ball2.y+ball1.r + ball2.r - distance;
- }else{
- ball2.y=ball2.y-ball1.r - ball2.r + distance;
- }
- }else{
- ball2.x=ball2.x-ball1.r - ball2.r + distance;
- if(ball1.speedY > 0){
- ball2.y=ball2.y+ball1.r + ball2.r - distance;
- }else{
- ball2.y=ball2.y-ball1.r - ball2.r + distance;
- }
- }
- }else{
- if(ball2.speedX>0){
- ball1.x=ball1.x+ball1.r + ball2.r - distance;
- if(ball2.speedY > 0){
- ball1.y=ball1.y+ball1.r + ball2.r - distance;
- }else{
- ball1.y=ball1.y-ball1.r - ball2.r + distance;
- }
- }else{
- ball1.x=ball1.x-ball1.r - ball2.r + distance;
- if(ball2.speedY > 0){
- ball1.y=ball1.y+ball1.r + ball2.r - distance;
- }else{
- ball1.y=ball1.y-ball1.r - ball2.r + distance;
- }
- }
- }
- return true;
- }
- else{
- return false;//没有碰撞
- }
- }
- </script>
- </html>
(canvas)两小球碰撞后的速度问题研究的更多相关文章
- HTML5 Canvas彩色小球碰撞运动特效
脚本简介 HTML5 Canvas彩色小球碰撞运动特效是一款基于canvas加面向对象制作的运动小球动画特效. 效果展示 http://hovertree.com/texiao/html5/39/ ...
- canvas动态小球重叠效果
前面的话 在javascript运动系列中,详细介绍了各种运动,其中就包括碰壁运动.但是,如果用canvas去实现,却是另一种思路.本文将详细介绍canvas动态小球重叠效果 效果展示 静态小球 首先 ...
- Canvas 动态小球重叠效果
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- 第七讲:HTML5中的canvas两个小球全然弹性碰撞
<html> <head> <title>小球之间的碰撞(全然弹性碰撞)</title> <script src="../js/jsce ...
- uniapp中用canvas实现小球碰撞的小动画
uniapp 我就不想喷了,踩了很多坑,把代码贡献出来让大家少踩些坑. 实现的功能: 生成n个球在canvas中运动,相互碰撞后会反弹,反弹后的速度计算我研究过了,可以参考代码直接用 防止球出边框 防 ...
- 第八讲:HTML5中canvas实现小球击打小方块游戏
源码:http://download.csdn.net/detail/liumingm900913/7469969 游戏开发流程: 1.创建画布: 将画布放在div标签里面,这样能够控制画布居中的位置 ...
- canvas 模拟小球上抛运动的物理效果
最近一直想用学的canvas做一个漂亮的小应用,但是,发现事情并不是想的那么简单.比如,游戏的逼真效果,需要自己来coding…… 所以,自己又先做了一个小demo,算是体验一下亲手打造物理引擎的感觉 ...
- Android画图之抗锯齿 paint 和 Canvas 两种方式
在画图的时候,图片如果旋转或缩放之后,总是会出现那些华丽的锯齿.其实Android自带了解决方式. 方法一:给Paint加上抗锯齿标志.然后将Paint对象作为参数传给canvas的绘制方法. ...
- HashMap两种遍历方式的深入研究
转自:http://swiftlet.net/archives/1259 HashMap的遍历有两种方式,如下所示:第一种利用entrySet的方式: 1 2 3 4 5 6 7 Map map ...
随机推荐
- ATS 自定义日志格式
字段解释 %<chi> 客户端IP %<caun> The username of the authenticated client. A hyphen (-) means t ...
- C# 时间戳与时间相互转化
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 时间戳d ...
- 第14月第23天 uitextfield文字下移
1. http://www.jianshu.com/p/641a0cbcabb0
- mysql 原理 ~ innodb恢复机制
举例说明 机制 数据页A的lsn为100,数据页B的lsn为200,checkpoint lsn为150,系统lsn为300,表示当前系统已经更新到300,小于150的数据页已经被刷到磁盘上,因此数据 ...
- bootstrap-table前端修改数据
使用bootstrap-table显示数据,后台传回数据以后,可能需要对其做调整,如需要前端为数据添加单位 调整数据代码 $("#"+tableId).bootstrapTable ...
- 为什么Docker比虚拟机快?
1.Docker有着比虚拟机更少的抽象层,由于Docker不需要Hypervisor实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源,因此在Cpu.内存利用率上Do ...
- windows安装anaconda 报错failed to create anacoda menu ?
windows安装anaconda 报错failed to create anacoda menu ? 装了无数次,每次都是 failed to create anacoda menu然后无选择忽略, ...
- 005_nginx414_nginx 414 Request-URI Too Large
一.开发请求一个非常长的请求参数 https://jiaju.jyall.me/backend/dish/getSales/?dishId=167271&dishId=166975&d ...
- HTTP基础知识1
HTTP 简介 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准,它是基于TCP/IP ...
- Ex 6_12 凸多边形的最优三角剖分..._第六次作业
假设顶点的总数为n,从0到n-1. 从序号为0的顶点开始以逆时针方向排序,对于 令子问题A[i,j]为包含顶点i,i+1, . . . j的凸多边形的最小三角剖分代价,dist(i,j)为顶点i到顶点 ...