目的:通过js实现小球碰撞并实现动量守恒

canvas我们就不多说了,有用着呢。

我们可以通过canvas画2D图形(圆、方块、三角形等等)3D图形(球体、正方体等待)。

当然这只是基础的皮毛而已,canvas的强大之处在于可以做游戏,导入模型,粒子效果,实现漫游又或者全景和VR。

这里我们介绍纯js写的2D小球碰撞。(主要是博主的Three.js不咋地)

好吧,老规矩,先上图!

额。。。很尴尬的是博主的截图功底不咋地,没有截下碰撞的瞬间。

话不多说,开始教程。

首先我们需要创建画布给它一个id方便后面监听处理。

<body>
<canvas id="myCanvas"></canvas>
</body>

然后是Js代码

//声明画布大小为屏幕的1/3var width = window.innerWidth/3;var  height = window.innerHeight/3;var canvas = document.getElementById("myCanvas");canvas.width = width;canvas.height = height;//创建2d画笔var ctx = canvas.getContext("2d");//填充颜色设置为黑色(背景色)ctx.fillStyle = "#000";//将整个画布填充ctx.fillRect(0,0,width,height);

这是Canvas最基本的操作,我们解释一下fillRect(x,y,width,height);这个函数。

x和y填充的起始坐标点,width和height是填充区域的宽和高。

由于我们创建的是带有物理性质的小球,所以我们用一个函数封装创建小球的代码。

以后创建小球直接调用它就行了。

function Ball(x,y,vx,vy,ax,ay,size,rou,color,ctx){//参数传值//x,y为坐标点 vx,vy为小球水平和垂直方向上的速度 ax,ay为加速度 //size 为大小 rou为密度 color颜色 ctx画笔this.x = x;this.y = y;this.vx = vx;this.vy = vy;this.rou = rou;this.size = size;this.ax = ax;this.ay = ay;this.m = Math.PI*this.size*this.size*rou;//求出质量this.draw = function(ctx){ctx.fillStyle=color;//console.log(this.x, this.y,this.size);
        ctx.beginPath();ctx.arc(this.x, this.y, this.size, 0, Math.PI*2,false);//画圆
        ctx.fill();ctx.closePath();}this.draw(ctx);
}

接下来实例化出两个小球。

//碰撞检测 动量守恒//x,y,vx,vy,ax,ay,size,rou,color,ctxvar balla = new Ball(20,0.5*height,5,-3,0,0,8,1,"#ff0",ctx);var ballb = new Ball(width-20,0.5*height,-3,5,0,0,13,1,"#0ff",ctx);var ballc = new Ball(width/2,0.5*height,7,4,0,0,13,1,"#0ff",ctx);

然后我们封装了一个函数来实现小球是实时更新。

function animation(){//小球的速度等于速度加上加速度balla.vx+= balla.ax;balla.vy+=balla.ay;//小球的位移等于小球现在的坐标加上速度balla.x+= balla.vx;balla.y+=balla.vy;ballb.vx+= ballb.ax;ballb.vy+=ballb.ay;ballb.x+= ballb.vx;ballb.y+=ballb.vy;//基于距离的碰撞检测var pointdis=(balla.x-ballb.x)*(balla.x-ballb.x)+(balla.y-ballb.y)*(balla.y-ballb.y);//坐标距离var pointsize=(balla.size+ballb.size)*(balla.size+ballb.size);//半径距离if( pointdis <= pointsize){console.log("haha");//这里是能量守恒公式var ballavx =((balla.m-ballb.m)*balla.vx+2*ballb.m*ballb.vx)/(balla.m+ballb.m);var ballavy =((balla.m-ballb.m)*balla.vy+2*ballb.m*ballb.vy)/(balla.m+ballb.m);var ballbvx=((ballb.m-balla.m)*ballb.vx+2*balla.m*balla.vx)/(balla.m+ballb.m);var ballbvy=((ballb.m-balla.m)*ballb.vy+2*balla.m*balla.vy)/(balla.m+ballb.m);balla.vx = ballavx;balla.vy = ballavy;ballb.vx = ballbvx;ballb.vy = ballbvy;//小Bug改进if(Math.abs(balla.vx-ballb.vx)<0.01&&Math.abs(balla.vy-ballb.vy)<0.01){console.log(balla.vx);balla.vx=-balla.vx;balla.vy=-balla.vy;return;}}//判断是否碰撞到画布的边缘if(balla.x+balla.size>=width||balla.x-balla.size<=0){balla.vx*=-0.98;}if(balla.y+balla.size>=height||balla.y-balla.size<=0){balla.vy*=-0.98;}if(ballb.x+ballb.size>=width||ballb.x-ballb.size<=0){ballb.vx*=-0.98;}if(ballb.y+ballb.size>=height||ballb.y-ballb.size<=0){ballb.vy*=-0.98;}//清空画布,画出小球ctx.fillStyle = "#000";ctx.fillRect(0,0,width,height);balla.draw(ctx);ballb.draw(ctx);//console.log(ballb.vy);
}

最后我们让他30毫秒更新一次。

    setInterval(animation,30);

OK,又大功告成了。自己动手试试吧!

懒人福利!!!

完整代码。

<html>
<head>
<style>
body{margin:0;}
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
<script>//声明画布大小为屏幕的1/3var width = window.innerWidth/3;var  height = window.innerHeight/3;var canvas = document.getElementById("myCanvas");canvas.width = width;canvas.height = height;//创建2d画笔var ctx = canvas.getContext("2d");//填充颜色设置为黑色(背景色)
    ctx.fillStyle = "#000";//将整个画布填充
    ctx.fillRect(0,0,width,height);//碰撞检测 动量守恒//x,y,vx,vy,ax,ay,size,rou,color,ctxvar balla = new Ball(20,0.5*height,5,-3,0,0,8,1,"#ff0",ctx);var ballb = new Ball(width-20,0.5*height,-3,5,0,0,13,1,"#0ff",ctx);var ballc = new Ball(width/2,0.5*height,7,4,0,0,13,1,"#0ff",ctx);
    setInterval(animation,30);function animation(){//小球的速度等于速度加上加速度
        balla.vx+= balla.ax;balla.vy+=balla.ay;//小球的位移等于小球现在的坐标加上速度
        balla.x+= balla.vx;balla.y+=balla.vy;ballb.vx+= ballb.ax;ballb.vy+=ballb.ay;ballb.x+= ballb.vx;ballb.y+=ballb.vy;//基于距离的碰撞检测var pointdis=(balla.x-ballb.x)*(balla.x-ballb.x)+(balla.y-ballb.y)*(balla.y-ballb.y);//坐标距离var pointsize=(balla.size+ballb.size)*(balla.size+ballb.size);//半径距离if( pointdis <= pointsize){console.log("haha");//这里是能量守恒公式var ballavx =((balla.m-ballb.m)*balla.vx+2*ballb.m*ballb.vx)/(balla.m+ballb.m);var ballavy =((balla.m-ballb.m)*balla.vy+2*ballb.m*ballb.vy)/(balla.m+ballb.m);var ballbvx=((ballb.m-balla.m)*ballb.vx+2*balla.m*balla.vx)/(balla.m+ballb.m);var ballbvy=((ballb.m-balla.m)*ballb.vy+2*balla.m*balla.vy)/(balla.m+ballb.m);
            balla.vx = ballavx;balla.vy = ballavy;ballb.vx = ballbvx;ballb.vy = ballbvy;//小Bug改进if(Math.abs(balla.vx-ballb.vx)<0.01&&Math.abs(balla.vy-ballb.vy)<0.01){console.log(balla.vx);balla.vx=-balla.vx;balla.vy=-balla.vy;return;}}//判断是否碰撞到画布的边缘if(balla.x+balla.size>=width||balla.x-balla.size<=0){balla.vx*=-0.98;}if(balla.y+balla.size>=height||balla.y-balla.size<=0){balla.vy*=-0.98;}if(ballb.x+ballb.size>=width||ballb.x-ballb.size<=0){ballb.vx*=-0.98;}if(ballb.y+ballb.size>=height||ballb.y-ballb.size<=0){ballb.vy*=-0.98;}//清空画布,画出小球
        ctx.fillStyle = "#000";ctx.fillRect(0,0,width,height);balla.draw(ctx);ballb.draw(ctx);//console.log(ballb.vy);
}
function Ball(x,y,vx,vy,ax,ay,size,rou,color,ctx){//参数传值//x,y为坐标点 vx,vy为小球水平和垂直方向上的速度 ax,ay为加速度 //size 为大小 rou为密度 color颜色 ctx画笔this.x = x;this.y = y;this.vx = vx;this.vy = vy;this.rou = rou;this.size = size;this.ax = ax;this.ay = ay;this.m = Math.PI*this.size*this.size*rou;//求出质量this.draw = function(ctx){ctx.fillStyle=color;//console.log(this.x, this.y,this.size);
        ctx.beginPath();ctx.arc(this.x, this.y, this.size, 0, Math.PI*2,false);//画圆
        ctx.fill();ctx.closePath();}this.draw(ctx);
}
</script>
</html>

欢迎交流学习!!!

不定时随缘更新。

转载于:https://www.cnblogs.com/tcxq/p/10118927.html

Canvas+Js制作动量守恒的小球碰撞相关推荐

  1. js实现多个小球碰撞

    实现思路:小球的移动,是通过改变小球的left和top值来改变,坐标分别为(x,y)当x/y值加到最大,即加到父级的宽度或者高度时,使x值或者y值减小,同理当x值或者y值减到最小时,同样的使x值或者y ...

  2. vue canvas插件_基于vue.js 制作在线桌椅定制选择交互特效源码

    码农那点事儿 关注我们,一起学习进步 基于vue.js写的在线桌子椅子垫子选择拼成的自己理想的书桌椅图像,这是一款交互式的课桌椅在线定制选择功能.非常不错,感兴趣的朋友前来下载使用. 下载源码(提取码 ...

  3. JS实现小球碰撞边界反弹-点击消失(详细解析实现思路)

    本篇文章给大家带来的是原生JS实现小球碰到边界就反弹,点击小球时小球被会销毁,并重新创建一个小球,让小球的数量一直保持在初始的数量,按照思路按步骤进行讲解,只需要源码的小伙伴可以定位到文本末尾直接复制 ...

  4. js 小球碰壁反弹and小球碰撞

    好像好几天没有更博了呢,最近有点变懒了,这样不好,不好~~我们要做热爱学习的好孩子,嘻嘻,今天下午补上... 我们在学习js的时候,一个很经典的案例就是小球的碰壁反弹效果啦~简单的小球碰壁效果可以慢慢 ...

  5. js小球碰撞js特效

    下载地址 小球碰撞特效.引用test.js文件.我目前做的是10个小球同时出现,你也可以根据你的需要进行修改.如果你想要小球随机出现的话,你只需要把58行的代码解注,然后57行的注释就行了.这个写法还 ...

  6. 绘制canvas彩色泡泡小球碰撞

    globalCompositeOperation带来的不一样的烟花 一.知识点 1.动画: setInterval(             function(){                 d ...

  7. js实现简单的小球与边框碰撞反弹改变运动方向及颜色,并且继续运动的特效

    js实现简单的小球与边框碰撞反弹改变运动方向及颜色,并且继续运动的特效 (代码可以直接复制使用,只需要把body中的div的id换成对应的就行,css中可以设置小球的大小和初始位置,修改小球大小之后需 ...

  8. 用html做个猜字游戏,HTML5 Canvas API制作简单的猜字游戏

    这篇文章主要介绍了借助HTML5 Canvas API制作一个简单的猜字游戏的实例分享,游戏中每局会自动生成一个字母,玩家按键盘来猜测该字母是哪一个,需要的朋友可以参考下 二话不说,先上效果图以及源代 ...

  9. 纯JS制作的窗户雨滴效果

    今天本站推荐的代码是用JS制作的窗户雨滴效果,绚丽的效果不亚于FLASH,由于不知出处在哪,总而言之, 在此感谢作者的慷慨分享. function demo() { var engine = new ...

最新文章

  1. 胜任素质--哈佛大学教授麦克里兰 (McClelland)有效地预测外交官实际工作业绩的人员选拔方法...
  2. 今天开始,GitHub将启用main作为默认分支名,master将成为历史!
  3. hdu4096(模拟)
  4. 【ARM】Tiny4412裸板编程之ADC
  5. select、poll、epoll之间的区别(搜狗面试)
  6. 逆序数问题,用归并排序而非树状数组求解
  7. browser.html – HTML 实现 Firefox UI
  8. ZTree相关使用的例子
  9. 终极之战:Linux Windows
  10. 容器Docker详解
  11. 华为NP课程笔记25-SDN简介
  12. Android studio连接网易MuMu模拟器
  13. 注册表怎么用计算机管理打开,如何打开注册表,详细教您如何打开电脑注册表管理器...
  14. 计算机视觉 – Computer Vision | CV
  15. struct和typedef struct彻底明白了,引用自https://www.cnblogs.com/qyaizs/articles/2039101.html
  16. Adversarial Learning
  17. 2017算法实习生应聘经验总结
  18. win10电脑耳机没有声音 如何在不重启电脑情况下耳机重新有声音
  19. mysql 表名 复数,数据库表命名,复数或单数
  20. Visual Studio2019自定义项目模板

热门文章

  1. 基于html5的在线教育平台的设计与实现,网络在线教学系统设计与实现.doc
  2. 啊哈C——学习3.4一起来找茬
  3. 黎明纪元-3D魔幻世界角色扮演游戏
  4. 3.会计等式与复式记账
  5. 百度地图api之创建自定义控件
  6. Supporting Online Material for Lab Experiments for the Study of Social-Ecological Systems
  7. 小熊派移植 TencentOS-tiny+EC20+SAL框架对接 TCP/UDP 服务器
  8. 前端怎么加粗字体_泣血总结,死磕前端知识点
  9. python 全排列 递归中的两种实现
  10. Port 8082 is already in use端口被占用问题