实现球体碰撞,使用这个库就够了

一、简述

大家在用Canvas实现球体碰撞的动画场景时是否感觉无从下手,或者是知道怎么去实现,但是要进行大量的计算,考虑非常多的细节,比如要考虑将外力分解为水平和垂直两个方向,然后考虑各种碰撞的检测,发生重叠后的修正,还有可能考虑引力方向和大小、透明度渐变等等这些,思考这些个计算逻辑时真的很让人头大,今天我就和大家分享一个非常好用的库,一个专门用于在Canvas上实现球体碰撞和球体交互场景的库–sphere-collision,通过简单配置便可快速实现碰撞效果,而且还提供了钩子函数,扩展性极强,让你实现想要的效果。

二、案例展示

下面展示几个案例的实现效果,这些都是使用这个库实现的动画效果,只要涉及到球体碰撞或球体交互的场景都可以使用这个库。

1.探照灯效果

2.球体碰撞交互效果



3.消灭行星小游戏

在这里插入图片描述

4.各类球体自由落体交互效果

在这里插入图片描述

5. 炫酷倒计时动画



以上案例源码均在visualization-collection开源项目中,github地址:https://github.com/hepengwei/visualization-collection

三、基本用法

安装

npm i sphere-collision

使用

import SphereCollision from "sphere-collision";

const canvasWidth = 600; // 画布宽度
const canvasHeight = 600; // 画布高度
const globuleRadius = 60; // 球半径

const beforeDrawGlobules = (sphereCollision) => {
    const { ctx } = sphereCollision;
    // 绘制整个画布的背景色
    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
    ctx.beginPath();
    ctx.fillStyle = "#000000";
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);
};

const canvas = document.getElementById("myCanvas");
if (canvas) {
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;
    const ctx = canvas.getContext("2d");

    // 实例化SphereCollision对象
    const sphereCollision = new SphereCollision(
        ctx,
        canvas,
        [
            {
                initX: 400,
                initY: 400,
                vx: 6,
                vy: 3,
                radius: globuleRadius,
            },
        ],
        { beforeDrawGlobules }
    );

    // 开使执行动画
    sphereCollision.start();
}

四、API文档

SphereCollisionC

参数(顺序从上往下依次传入)数据类型说明默认值是否必需
ctxCanvasRenderingContext2DContext对象null
canvasHTMLCanvasElementCanvas对象null
globuleOptionsListGlobuleOptions[]初始化球体的配置列表[]
optionsSphereCollisionOptions配置参数SphereCollisionOptions
属性
ctxCanvasRenderingContext2DContext对象
canvasHTMLCanvasElementCanvas对象
frameIdnumberrequestAnimationFrame方法返回的ID
globuleListGlobuleC[]保存所有球体实例的列表
animationStateenum AnimationState{“waitStart”,“inAnimation”,“stop”}当前动画状态
mousePosMousePos当前鼠标在Canvas中的位置坐标
prevMousePos(v1.1.0新增)MousePos前一次鼠标在Canvas中的位置坐标
isMouseDown(v1.1.0新增)boolean当前鼠标在Canvas中是否按下
mouseDownPos(v1.1.0新增)MousePos鼠标在Canvas中按下时的位置坐标
mouseInGlobuleList(v1.1.0新增)GlobuleC[]当前鼠标所在球体中的球体实例列表
方法
start() => void必须调用该方法,Canvas才渲染,开始执行相关动画
createGlobule(globuleOptions: GlobuleOptions) => Globule创建球体实例的方法
updateGlobuleList(newGlobuleList: GlobuleC[]) => void更新球体实例列表,用于动态增加或减少球体实例
stop() => void停止整个frame动画

GlobuleOptions

属性数据类型说明默认值是否必需
idany任意值,可存放数据
initXnumber初始x坐标(向右为正方向)0
initYnumber初始y坐标(向下为正方向)0
vxnumber在水平方向的速度(向右为正方向)0
vynumber在垂直方向的速度(向下为正方向)0
radiusnumber半径10
colorstring颜色“#666666”
isPureColor(v1.1.3新增)boolean是否为纯色false
alphanumber透明度1
alphaChangeVnumber透明度改变的速度(正数增加,负数减小)0
bgImgstring背景图片“”
collisionLossVnumber碰撞时的速度损失0
moveLossVnumber移动时的速度损失0
gDirection“toInit” | “toBottom” | “toTop” | “toLeft” | “toRight”引力方向。“toInit”,指向球体的初始位置;“toBottom”,指向正下方;“toTop”,指向正上方;“toLeft”,指向正左方;“toRight”,指向正右方(后四个为v1.1.0新增)
gCoefficientnumber引力系数0
requiredMouseInteractionboolean是否需要鼠标交互false
mouseInteractionBehavior(v1.1.0新增)“over” | “drag”鼠标交互行为。“over”,鼠标穿过;“drag”,鼠标拖拽当requiredMouseInteraction为true时,默认值为"over",当为false时,则没有默认值
fixedPosboolean是否固定位置false
receiveOutForceboolean是否接受外力true
receiveWallForceboolean是否接受墙的力(与墙体发生碰撞)true
resistanceWallDirection(v1.1.3新增)Direction[]有阻力的墙的方向[“bottom”, “top”, “left”, “right”]
onlyCheckCollisionboolean当不接受外力时,是否检测碰撞(检测碰撞相关状态但不获取外力)false
perfectlyElasticCollision(v1.1.10 新增)boolean是否完全弹性碰撞false
maxMouseOutForcenumber鼠标交互时能提供的最大力限制null
maxMoveVnumber最大移动速度null
beforeDrawGlobule(globule: GlobuleC) => void每一帧绘制该球体之前执行的钩子函数null
afterDrawGlobule(globule: GlobuleC) => void每一帧绘制该球体之后执行的钩子函数null
afterCalculateNextFrameGlobule(nextFrameGlobule: GlobuleC) => void每一帧绘制球体后,计算并修改为下一帧状态后执行的钩子函数null

SphereCollisionOptions

属性数据类型说明
collisionRectXnumber球体发生碰撞的矩形区域的左上角x坐标(向右为正方向)0
collisionRectYnumber球体发生碰撞的矩形区域的左上角y坐标(向下为正方向)0
collisionRectWidthnumber球体发生碰撞的矩形区域的宽度canvas.width
collisionRectHeightnumber球体发生碰撞的矩形区域的高度canvas.height
monitorMousePosboolean是否监听鼠标的位置false
beforeDrawGlobules(sphereCollision: SphereCollisionC) => void每一帧绘制所有球体之前执行的钩子函数null
afterDrawGlobules(sphereCollision: SphereCollisionC) => void每一帧绘制所有球体之后执行的钩子函数null
onMouseDownCanvas(v1.1.0新增)(event: MouseEvent, sphereCollision: SphereCollisionC) => void鼠标按下时执行的钩子函数null
onMouseMoveCanvas(v1.1.0新增)(event: MouseEvent, sphereCollision: SphereCollisionC) => void鼠标移动时执行的钩子函数null
onMouseUpCanvas(v1.1.0新增)(event: MouseEvent, sphereCollision: SphereCollisionC) => void鼠标松开时执行的钩子函数null
onMouseLeaveCanvas(v1.1.0新增)(event: MouseEvent, sphereCollision: SphereCollisionC) => void鼠标离开时执行的钩子函数null

MousePos

属性数据类型说明
mouseXnumber | null鼠标在Canvas中的x坐标(向右为正方向)
mouseYnumber | null鼠标在Canvas中的y坐标(向下为正方向)

Direction

属性数据类型说明
Direction“bottom” | “top” | “left” | “right”方向

GlobuleC

属性数据类型说明
idany任意值,可存放数据
ctxCanvasRenderingContext2DContext对象
canvasHTMLCanvasElementCanvas对象
requiredMouseInteractionboolean是否需要鼠标交互
mouseInteractionBehavior(v1.1.0新增)“over” | “drag”鼠标交互行为。“over”,鼠标穿过;“drag”,鼠标拖拽
maxMouseOutForcenumber | null鼠标交互时能提供的最大力限制
initXnumber初始x坐标(向右为正方向)
initYnumber初始y坐标(向下为正方向)
xnumberx坐标(向右为正方向)
ynumbery坐标(向下为正方向)
previousX(v1.1.8 新增)number | null前一帧 x 坐标(向右为正方向)
previousY(v1.1.8 新增)number | null前一帧 y 坐标(向右为正方向)
vxnumber在水平方向的速度(向右为正方向)
vynumber在垂直方向的速度(向下为正方向)
radiusnumber半径
colorstring颜色
isPureColor(v1.1.3新增)boolean是否为纯色
alphanumber透明度
alphaChangeVnumber透明度改变的速度(正数增加,负数减小)
bgImgstring背景图片
collisionLossVnumber碰撞时的速度损失
moveLossVnumber移动时的速度损失
gDirection“toInit” | “toBottom” | “toTop” | “toLeft” | “toRight”引力方向。“toInit”,指向球体的初始位置;“toBottom”,指向正下方;“toTop”,指向正上方;“toLeft”,指向正左方;“toRight”,指向正右方(后四个为v1.1.0新增)
gCoefficientnumber引力系数
fixedPosboolean是否固定位置
receiveOutForceboolean是否接受外力
receiveWallForceboolean是否接受墙的力(与墙体发生碰撞)
resistanceWallDirection(v1.1.3新增)Direction[]有阻力的墙的方向
onlyCheckCollisionboolean当不接受外力时,是否检测碰撞(检测碰撞相关状态但不获取外力)
perfectlyElasticCollision(v1.1.10 新增)boolean是否完全弹性碰撞
mousePosMousePos鼠标相对于canvas的位置坐标
maxMoveVnumber | null最大移动速度
controlledByMouse(v1.1.0新增)boolean当前是否受鼠标控制(被鼠标拖拽)
inCollisionGlobuleboolean是否与其他球体发生碰撞的状态
inCollisionGlobuleListGlobuleC[]与其他球体碰撞的其他球体实例列表
inCollisionWallboolean是否与墙体发生碰撞的状态
beforeDrawGlobule(globule: GlobuleC) => void | null每一帧绘制该球体之前执行的钩子函数
afterDrawGlobule(globule: GlobuleC) => void | null每一帧绘制该球体之后执行的钩子函数
afterCalculateNextFrameGlobule(nextFrameGlobule: GlobuleC) => void | null每一帧绘制球体后,计算并修改为下一帧状态后执行的钩子函数
方法
addOutForce(outForceVX: number, outForceVY: number, isCollision?:boolean = false) => void添加外力。用于动态增加或减小球体的速度

五、特别说明

  • 球体的fixedPos属性为true时, 获取不了外力,所以球体不会移动,但还是会使其他球体受到外力,进行反弹。
  • 球体的receiveOutForce属性为false时,获取不了鼠标穿过和其他球体碰撞产生的外力,即使另一个球体的receiveOutForce属性为true。
  • 球体的receiveWallForce属性为false时,获取不了来自墙体的外力,所以不会与墙体发生碰撞。
  • 球体的beforeDrawGlobule和afterDrawGlobule两个钩子函数,主要作用是在绘制球体之前和之后分别去绘制其他元素,而afterCalculateNextFrameGlobule钩子函数是用于做一些其他的逻辑判断,因为只有这个函数里拿到的球体实例是带有是否发生碰撞等相关信息的
  • 如果实例化SphereCollision对象时传入了beforeDrawGlobules钩子函数,并且需要在每一帧绘制前要清除整个画布,则需要使用者自己清除,这是考虑到有些不需要清除的场景。
  • 如果要获取鼠标相关的信息或者想要实现鼠标交互,实例化SphereCollision对象时就必须在第四个参数options中传入monitorMousePos为true。
  • 如果给球体配置了 gDirection 和 gCoefficient 属性,建议就不要配置 collisionLossV 了。
  • 非完全弹性碰撞会有速度的抵消,可能碰撞后的 x 轴或 y 轴方向上的速度相互抵消为 0,球体可能会停下来;完全弹性碰撞则不会有速度的抵消,速度大小不会改变(速度为 0 除外,速度为 0 的,碰撞后会和撞它的另一球的速度大小一致),碰撞后仅改变方向; 在碰撞时如果其中有一个球体的 perfectlyElasticCollision 为 true,则两球均使用完全弹性碰撞算法进行计算。
  • 如果需要的话,可以在任何时候动态地修改球体实例的所有属性值,以满足自己的自定义需求。

六、关键版本更新日志

  • v1.1.10
  1. 新增支持球体完全弹性碰撞
  2. 优化代码

  • v1.1.8
  1. 优化碰撞算法
  2. 解决一些已知bug

  • v1.1.3
  1. 新增支持纯色球体
  2. 新增支持四面墙中只有部分墙面有阻力,与球体发生碰撞
  3. 解决一些已知bug

  • v1.1.0
  1. 考虑后续的功能扩展,修改了SphereCollision类的参数,将之前的第四个及之后的参数都统一放到options对象中,并作为第四个参数传入。
  2. 新增支持上下左右四个引力方向
  3. 新增支持球体进行鼠标拖拽交互
  4. 新增的相关属性及方法可自行查阅API文档

更多个人文章

  1. 两个跨域页面进行跳转传参的终极方案
  2. 彻底搞懂盒子模型
  3. hashHistory和browserHistory的区别
  4. 十分钟带你入门Chrome插件开发
  5. 面试秘籍之排序算法
解决ESP32烧录MicroPython时esptool.py未识别的错误 当出现esptool.py not recognized错误时,通常是由于环境变量未正确配置或工具未安装。以下是逐步解决方法: 1. 确认esptool.py是否安装 安装命令: Bash pip install esptool # 或使用Python3 pip3 install esptool 如果已安装但版本过旧,可升级: Bash pip install --upgrade esptool 2. 检查环境变量配置 Windows系统: Python脚本默认安装路径为C:\Users\<用户名>\AppData\Local\Programs\Python\PythonXX\Scripts(XX为版本号)。 将此路径添加到系统环境变量PATH中4。 修改后需重启命令行工具或IDE(如VS Code)。 Linux/macOS系统: Bash export PATH="$PATH:$HOME/.local/bin" 可将此命令添加到~/.bashrc或~/.zshrc中永久生效。 3. 通过Python模块直接运行 若环境变量未生效,可显式调用Python模块: Bash python -m esptool --help # 或指定Python3 python3 -m esptool --help 4. 检查开发环境配置 如果使用ESP-IDF框架,确保已执行环境初始化脚本: Bash # Linux/macOS . $IDF_PATH/export.sh # Windows %IDF_PATH%\export.bat 此步骤可能影响工具链路径的识别。 5. 验证命令格式 确保烧录命令正确,典型MicroPython烧录命令示例: Bash esptool.py --port COM3 erase_flash esptool.py --port COM3 --baud 460800 write_flash -z 0x1000 firmware.bin 替换COM3为实际串口号,firmware.bin为固件路径。 6. 重装或修复工具 若问题持续,尝试: 卸载后重装: Bash pip uninstall esptool pip install esptool 检查系统架构兼容性(如32/64位系统或文件损坏问题,参考文件格式错误解决方法35)。第二步的具体步骤
03-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值