canvas画布中小球碰撞简单处理
位置:
首页 >
代码集锦[ 发布时间: 2024.4.12 作者: 马黑 阅读: 357 ]
效果:点击方框任意处生成小球,限量10个 ——
代码:
<style>
#mama {
margin: 20px auto;
width: 600px;
height: 400px;
border: 1px solid gray;
position: relative;
}
</style>
<div id="mama"></div>
<script>
//创建画布
var canv = document.createElement('canvas');
//画布尺寸及宽高变量与父元素一致
var ww = canv.width = mama.offsetWidth;
var hh = canv.height = mama.offsetHeight;
//mama添加画布
mama.appendChild(canv);
//获得画笔
var ctx = canv.getContext('2d');
/* 小球数组 用于实时记录小球数据
小球个体以对象形式存储圆心坐标、半径、颜色、xy方向移动速度
{x: x, y: y, r: r, color: color, speedX: speedX, speedY: speedY}
*/
var balls = [];
//动画标识,小球总数
var raf = null, total = 10;
//获取运动速度函数 -1 或 1
var speed = () => Math.random() < 0.5 ? -1 : 1;
//绘制小球函数 圆心坐标+半径+填充颜色
var drawBall = (x,y,r,color) => {
ctx.save();
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(x,y,r,0,2*Math.PI);
ctx.fill();
ctx.restore();
};
//小球运动函数 依据圆心坐标和半径绘制
var move = (ball) => {
var x = ball.x,
y = ball.y,
r = ball.r,
color = ball.color,
spdX = ball.speedX,
spdY = ball.speedY;
x += spdX;
y += spdY;
//边界处理
if(x - r < 0 || x + r > ww) spdX = - spdX;
if(y - r < 0 || y + r > hh) spdY = - spdY;
//记录小球变更数据
ball.x = x;
ball.y = y;
ball.speedX = spdX;
ball.speedY = spdY;
//绘制变更后的小球
drawBall(x,y,r,color);
};
//渲染函数
var render = () => {
ctx.clearRect(0,0,ww,hh); //擦除画布
//双for循环检测球与球间是否碰撞
for(var j = 0; j < balls.length; j ++) {
for(var k = 0; k < balls.length; k ++) {
//两球间的圆心点坐标间距
var dx = balls[j].x - balls[k].x, dy = balls[j].y - balls[k].y;
//两球间的圆心距离
var distance = Math.sqrt(dx * dx + dy * dy);
//若距离小于两球半径之和则判为碰撞,令运动方向和原来的互反
if(distance < (balls[j].r + balls[k].r)) {
balls[j].speedX = -balls[j].speedX;
balls[j].speedY = -balls[j].speedY;
balls[k].speedX = -balls[k].speedX;
balls[k].speedY = -balls[k].speedY;
}
}
move(balls[j]); //移动小球
}
//请求关键帧动画
raf = requestAnimationFrame(render);
};
//画布单击时生成小球
canv.onclick = (e) => {
total --;
if(total < 0) return;
cancelAnimationFrame(raf);
var x = e.offsetX, y = e.offsetY, r = 20, color = `#${Math.random().toString(16).substr(-6)}`;
//防止小球太靠近边缘
if(x < 25) x = 25;
if(x > ww - 25) x = ww - 25;
if(y < 25) y = 25;
if(y > hh - 25) y = hh - 25;
balls.push({x: x, y: y, r: r, color: color, speedX: speed(), speedY: speed()});
render();
};
</script>
前一篇: canvas放大镜(两种机制)
下一篇: 在canvas画布中绘制二次贝塞尔曲线
发表评论:
评论列表 [2条]
#2 | 飞飞 于 2024-4-13 10:37 发布: 这也太好玩了……小球颜色随机,挺好看的,自由自在跟鱼一样四处游弋……这次点出10个……
#1 | 悄然 于 2024-4-13 10:34 发布: 小球随机碰撞,手机点击生成7个,自由运动,碰撞返回,完美显示……