这两天在研究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)两小球碰撞后的速度问题研究的更多相关文章

  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. 使用Spring时web.xml中的配置

    使用Spring时web.xml中的配置: <?xml version="1.0" encoding="UTF-8"?> <web-app x ...

  2. ScrollView match_parent不起作用

    昨天在项目中遇到一个以前没遇到过的问题,就是ScrollView的match_parent不起作用了.所以记录一下 开始的时候我的布局是: <ScrollView android:layout_ ...

  3. [ZJOI2012]波浪弱化版(带技巧的DP)

    题面 \(solution:\) 这道确实挺难的,情况特别多,而且考场上都没想到如何设置状态.感觉怎么设状态不能很好的表示当前情况并转移,考后发现是对全排列的构造方式不熟而导致的,而这一题的状态也是根 ...

  4. html5移动端页面分辨率设置及相应字体大小设置的靠谱使用方式

    对于html5移动端网页编写CSS网上有很多介绍的文章,但在实际使用过程中还是会纠结. 网上的资料太多,且大多都是技术介绍型,特别是针对android上,网上写的各种麻烦,各种复杂,各种不接地气儿.. ...

  5. 解决:[DCC Fatal Error] **.dpk : E2202 Required package '***' not found

    //[DCC Fatal Error] **.dpk : E2202 Required package '***' not found 意思是:[DCC致命错误] *:e2202需包***没有发现 D ...

  6. SpringMVC的JSON数据交互(七)-@Response,@RestController,@RequestBody用法

    1.@RequestBody   (自动将请求的数据封装为对象) 作用: @RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConve ...

  7. CMake 实践教程

    本篇博客是根据 <<CMake Practice>> 一文编写, 目的有三: 其一: 提取出其中的精要部分; 其二: 对其中不易理解的地方进行简要说明; 其三: 方便后续查找复 ...

  8. Eclipse中项目不会自动编译问题的坑和注意点

    最近接受了几个又小有老的项目,用eclipse反而比idea方便,但是好长时间不用eclipse了,还有有些问题的! 主要是碰到了classnotfound这个难缠的问题:这里记录一下几个坑,避免以后 ...

  9. MR运动静止用户区分

    1.客户端打开菜单[MR]-[MR室内室外判定设置] 设置主小区是室外站且主小区信号比较强时RSRP门限 2.设置"上报数据用户临小区切换次数门限设置"值为15 mysql中t_m ...

  10. Epoll模型

    Epoll模型 相比于select,epoll最大的好处在于它不会随着监听fd数目的增长而降低效率.因为在内核中的select实现中,它是采用轮询来处理的,轮询的fd数目越多,自然耗时越多.并且,在l ...