分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 教程案例

Canvas+Js制作动量守恒的小球碰撞

发布时间:2023-09-06 02:26责任编辑:赖小花关键词:暂无标签

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

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

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

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

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

好吧,老规矩,先上图!

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

话不多说,开始教程。

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

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

然后是Js代码

//声明画布大小为屏幕的1/3 ???var 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,ctx ???var 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/3 ???var 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,ctx ???var 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>

欢迎交流学习!!!

不定时随缘更新。

Canvas+Js制作动量守恒的小球碰撞

原文地址:https://www.cnblogs.com/tcxq/p/10118927.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved