基于 **Three.js** 开发的 3D 炮弹发射特效系统

这是一个基于 Three.js 开发的 3D 炮弹发射特效系统,核心功能是模拟炮弹发射、飞行轨迹、落地爆炸的完整视觉效果,还包含了 UI 交互、性能统计等辅助功能。下面从「核心结构、功能拆解、技术细节」三方面详细解释:

一、核心结构(类与主要属性)

这是一个面向对象的封装类 CannonEffect,所有功能都集成在类内部,结构清晰:

核心属性 作用
scene/camera/renderer Three.js 三要素(场景/相机/渲染器)
cannons/explosions 存储活跃的炮弹、爆炸效果实例
clock Three.js 时钟,用于计算帧间隔(物理更新)
cannonCount/explosionCount 统计炮弹发射数、爆炸数(UI 展示)
fps/frameCount 实时计算帧率(性能监控)

二、核心功能拆解(按方法分类)

1. 初始化流程(init() 入口)

初始化时按顺序执行以下步骤,搭建 3D 场景基础:

javascript 复制代码
this.createScene();    // 场景/相机/渲染器初始化
this.createLights();   // 灯光系统(环境光+方向光+爆炸点光源)
this.createGround();   // 地面+草地装饰
this.createCannonBase();// 炮台底座+炮管
this.setupUI();        // UI 交互绑定
this.animate();        // 启动渲染循环
2. 场景基础搭建(createScene()
  • 场景 :设置深蓝色雾效(Fog),增强空间纵深感;
  • 相机 :透视相机(视野75°,近裁切面0.1,远裁切面1000),初始位置 (0,10,20) 看向原点;
  • 渲染器 :WebGL 渲染器(开启抗锯齿、透明背景),支持阴影(PCFSoftShadowMap 软阴影);
  • 窗口适配:监听窗口 resize 事件,更新相机宽高比和渲染器尺寸。
3. 灯光系统(createLights()

三种灯光组合,保证视觉效果:

  • 环境光(AmbientLight):亮度 0.6,照亮场景所有物体,避免纯黑阴影;
  • 方向光(DirectionalLight):模拟太阳光,位置 (10,20,10),开启阴影(阴影贴图 2048x2048);
  • 爆炸点光源(PointLight):初始亮度 0,爆炸时激活,模拟爆炸闪光。
4. 地面与炮台(createGround()/createCannonBase()
  • 地面:大平面(100x100)+ 随机小草地(20个),草地半透明(opacity 0.7)增加层次感;
  • 炮台
    • 底座:圆柱体(上径1.5,下径2,高0.5),深灰色金属材质;
    • 炮管:圆柱体(径0.3-0.4,长3),深灰色金属材质,旋转 90° 水平朝向。
5. 炮弹核心逻辑(createCannonball()/updateCannonballs()
(1)创建炮弹(createCannonball(power, angle)
  • 接收两个参数:power(发射力度)、angle(发射角度);
  • 炮弹数据结构:包含 3D 网格(红色发光球体)、速度向量、位置、重力、轨迹数组;
  • 初始速度计算:将角度转为弧度,按力度计算水平(x轴)和垂直(y轴)速度;
  • 附加效果:炮弹自带点光源,模拟发热发光。
(2)更新炮弹(updateCannonballs(deltaTime)

每帧执行物理模拟:

  • 重力作用:垂直速度(y轴)叠加重力加速度(-9.8)× 帧间隔;
  • 位置更新:按速度 × 帧间隔更新炮弹位置,同步 3D 网格;
  • 轨迹绘制:记录最近 20 个位置,用半透明小黄点绘制轨迹(旧轨迹自动删除);
  • 碰撞检测:当炮弹 y 坐标 ≤ 0.3(触地),触发爆炸,移除炮弹网格。
6. 爆炸效果(createExplosion()/updateExplosions()
(1)创建爆炸(createExplosion(position)
  • 接收爆炸位置参数,创建 50 个爆炸粒子;
  • 粒子特性:随机方向速度(x/z 轴 ±5,y轴 0-10)、随机大小(0.1-0.3)、橙红色发光材质;
  • 激活爆炸点光源:亮度设为 5,模拟闪光。
(2)更新爆炸(updateExplosions(deltaTime)

每帧更新爆炸状态:

  • 粒子物理:受重力影响(y轴速度衰减),位置随速度更新;
  • 粒子衰减:生命值(life)按衰减率减少,同步降低透明度(opacity)和尺寸(scale);
  • 爆炸光衰减:按爆炸持续时间(2秒)线性降低点光源亮度;
  • 生命周期结束:爆炸持续 2 秒后,移除所有粒子和爆炸实例。
7. UI 交互与性能统计
(1)UI 交互(setupUI()
  • 绑定页面滑块(power/angle)与数值显示(power-value/angle-value);
  • 外部调用:fireCannon() 函数(供 HTML 按钮/空格键触发),读取滑块值发射炮弹。
(2)性能统计(updateStats()
  • 实时更新:当前活跃炮弹数、爆炸数、帧率(FPS);
  • 帧率计算:每 1 秒统计一次帧数量,计算 FPS 并四舍五入。
8. 渲染循环(animate()

Three.js 核心渲染循环,每帧执行:

  • 请求下一帧:requestAnimationFrame 保证流畅循环;
  • 计算帧间隔:clock.getDelta() 获取当前帧与上一帧的时间差(用于物理更新);
  • 更新逻辑:炮弹物理、爆炸效果;
  • 相机动画:相机绕 y 轴缓慢旋转(sin/cos 控制 x/z 位置),始终看向 (0,5,0)
  • 渲染场景:renderer.render(scene, camera) 输出画面;
  • 帧率统计:每 1 秒计算一次 FPS 并更新 UI。

三、外部交互与使用

1. 页面依赖

需要 HTML 中包含以下元素:

  • 容器:<div id="canvas-container"></div>(渲染器画布挂载点);
  • 滑块:<input type="range" id="power">(力度)、<input type="range" id="angle">(角度);
  • 数值显示:<span id="power-value"></span><span id="angle-value"></span>
  • 统计显示:<span id="cannon-count"></span><span id="explosion-count"></span><span id="fps"></span>
  • 发射按钮:<button onclick="fireCannon()">发射</button>(或按空格键发射)。
2. 触发方式
  • 点击发射按钮;
  • 按下空格键(通过 keydown 事件监听,阻止默认行为避免页面滚动)。

四、技术亮点

  1. 物理模拟:实现了重力作用下的抛体运动(炮弹飞行)和粒子运动(爆炸);
  2. 视觉效果:雾效、阴影、发光材质、轨迹绘制、爆炸闪光,多层级视觉叠加;
  3. 性能优化 :限制轨迹点数量(20个)、自动移除失效炮弹/粒子、帧率适配(devicePixelRatio 限制为 2);
  4. 交互友好:滑块控制参数、实时统计数据、键盘+按钮双发射方式。

五、总结

这个代码是一个完整的 Three.js 3D 交互特效案例,核心是「抛体运动物理模拟」+「粒子爆炸视觉效果」,结构上采用面向对象封装,逻辑清晰,从场景搭建、物体创建、物理更新到 UI 交互、性能监控都包含在内,可直接集成到网页中作为互动特效(比如游戏、宣传页动画)。

相关推荐
SuperEugene18 分钟前
Vue3 + Element Plus 表格实战:批量操作、行内编辑、跨页选中逻辑统一|表单与表格规范篇
开发语言·前端·javascript
极梦网络无忧42 分钟前
基于 Vite + Vue3 的组件自动注册功能
前端·javascript·vue.js
love530love1 小时前
ComfyUI-3D-Pack:Windows 下手动编译 mesh_inpaint_processor C++ 加速模块
c++·人工智能·windows·python·3d·hunyuan3d·comfyui-3d-pack
软弹1 小时前
深入理解 React Ref 机制:useRef 与 forwardRef 的协作原理
前端·javascript·react.js
雪碧聊技术1 小时前
前端vue代码架子搭建
前端·javascript·vue.js·前端项目代码框架搭建
han_2 小时前
JavaScript设计模式(二):策略模式实现与应用
前端·javascript·设计模式
x***r1512 小时前
Notepad++ 8.6 安装教程:详细步骤+自定义安装路径(附注意事项)
linux·前端·javascript
格林威2 小时前
工业相机图像采集:Grab Timeout 设置建议——拒绝“假死”与“丢帧”的黄金法则
开发语言·人工智能·数码相机·计算机视觉·c#·机器视觉·工业相机
Hilaku2 小时前
为什么很多工作 5 年的前端,身价反而卡住了?🤷‍♂️
前端·javascript·面试
执行部之龙2 小时前
JS手写——call bind apply
前端·javascript