AI真好玩系列-Three.js手势控制游戏开发教程 | Interactive Game Development with Three.js Hand Controls

news/2025/12/7 0:13:15/文章来源:https://www.cnblogs.com/sugartang/p/19316902

@

目录
  • 💖 提示词
  • 📚 项目代码(项目剖析和简介都在下面哦)
  • 🌟 项目简介 | Project Introduction
  • 📌 前提条件 | Prerequisites
  • 🚀 核心技术栈 | Core Technologies
  • 👐 手势控制原理 | Hand Control Principle
  • 🧩 核心代码片段 | Core Code Snippets
    • 1. 游戏场景初始化 | Scene Initialization
    • 2. 手势识别配置 | Hand Detection Configuration
    • 3. 手势控制逻辑 | Hand Control Logic
    • 4. 游戏主循环 | Main Game Loop
  • 🎮 游戏机制 | Game Mechanics
  • 🛠️ 使用指南 | Run Guide
    • 本地运行 | Local Run
  • 🔧 定制项 | Customization Options
  • 🐛 常见问题 | Troubleshooting
  • 📚 扩展学习资源 | Extended Resources
  • Conclusion | 结语

周末的深夜,睡不着觉,闲来无事,打开Gemini哈基米玩一把,废话不多说,先上图看最终效果~

碎碎念:我很想上传视频,但是好像有的博客不支持,这里先放个图片

视频地址:https://www.bilibili.com/video/BV1Pt2RB1EkS?t=2.4

在这里插入图片描述

在这里插入图片描述

💖 提示词

请使用Three.js,创建一个完整的"手势玩游戏"3D交互游戏网页。

📚 项目代码(项目剖析和简介都在下面哦)

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>Three.js 手势控制游戏 - 太空捕手</title><style>body { margin: 0; overflow: hidden; background-color: #000; font-family: 'Arial', sans-serif; }#canvas-container { width: 100%; height: 100vh; display: block; }#video-container {position: absolute;top: 10px;left: 10px;width: 160px;height: 120px;z-index: 100;border: 2px solid #00ffcc;border-radius: 8px;overflow: hidden;opacity: 0.7;}#input-video {width: 100%;height: 100%;transform: scaleX(-1); /* 镜像翻转,让操作更直观 */object-fit: cover;}#ui-layer {position: absolute;top: 20px;right: 20px;color: #fff;text-align: right;pointer-events: none;}h1 { margin: 0; font-size: 24px; text-transform: uppercase; letter-spacing: 2px; color: #00ffcc; }#score-board { font-size: 40px; font-weight: bold; }#loading {position: absolute;top: 50%; left: 50%;transform: translate(-50%, -50%);color: white;font-size: 20px;background: rgba(0,0,0,0.8);padding: 20px;border-radius: 10px;text-align: center;}</style><!-- 引入 Three.js --><script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script><!-- 引入 MediaPipe Hands --><script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/@mediapipe/control_utils/control_utils.js" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.js" crossorigin="anonymous"></script>
</head>
<body><!-- 3D 场景容器 --><div id="canvas-container"></div><!-- 摄像头预览 (用于确认手势) --><div id="video-container"><video id="input-video"></video></div><!-- UI 界面 --><div id="ui-layer"><h1>Cosmic Catcher</h1><div>Score</div><div id="score-board">0</div></div><div id="loading">正在加载 AI 模型和摄像头...<br>请允许摄像头权限</div><script>// --- 游戏状态 ---let score = 0;let gameRunning = false;const sceneWidth = 20; // 游戏世界的宽度范围const playerY = -8;// --- 1. Three.js 场景设置 ---const scene = new THREE.Scene();scene.background = new THREE.Color(0x1a1a2e);// 添加一些迷雾增加深邃感scene.fog = new THREE.FogExp2(0x1a1a2e, 0.03);const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.z = 10;camera.position.y = 2;camera.lookAt(0, 0, 0);const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);document.getElementById('canvas-container').appendChild(renderer.domElement);// 灯光const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);scene.add(ambientLight);const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);dirLight.position.set(5, 10, 7);scene.add(dirLight);// --- 2. 创建游戏对象 ---// 玩家 (滑块)const playerGeometry = new THREE.BoxGeometry(3, 0.5, 1);const playerMaterial = new THREE.MeshPhongMaterial({ color: 0x00ffcc, emissive: 0x004444 });const player = new THREE.Mesh(playerGeometry, playerMaterial);player.position.y = playerY;scene.add(player);// 掉落物管理器const fallingObjects = [];const objectGeometry = new THREE.IcosahedronGeometry(0.6, 0);const objectMaterial = new THREE.MeshPhongMaterial({ color: 0xff0055, shininess: 100 });function spawnObject() {if (!gameRunning) return;const obj = new THREE.Mesh(objectGeometry, objectMaterial.clone());// 随机颜色obj.material.color.setHSL(Math.random(), 1.0, 0.5);// 随机 X 位置obj.position.x = (Math.random() - 0.5) * sceneWidth; obj.position.y = 10; // 从上方掉落obj.position.z = 0;// 随机旋转速度obj.userData = {rotSpeed: {x: Math.random() * 0.1,y: Math.random() * 0.1},speed: 0.1 + Math.random() * 0.1 // 掉落速度};scene.add(obj);fallingObjects.push(obj);}// --- 3. MediaPipe Hands 设置 (手势识别) ---const videoElement = document.getElementById('input-video');const loadingElement = document.getElementById('loading');// 映射函数:将视频中的坐标 (0-1) 映射到 3D 场景坐标 (-10 到 10)function mapRange(value, inMin, inMax, outMin, outMax) {return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;}function onResults(results) {loadingElement.style.display = 'none';if (!gameRunning) gameRunning = true;if (results.multiHandLandmarks && results.multiHandLandmarks.length > 0) {// 获取第一只手const landmarks = results.multiHandLandmarks[0];// 获取食指指尖 (索引为 8)const indexFingerTip = landmarks[8];// MediaPipe 的 x 坐标是 0(左) 到 1(右)。// 注意:我们在 CSS 里镜像翻转了视频,但数据本身没有翻转。// 在游戏里,为了直观,如果你向右移手,我们希望 x 变大。// 原生数据:屏幕左边是0,右边是1。// 映射到 3D 场景:x 从 -10 到 10。// 平滑移动 (Lerp) 以减少抖动const targetX = mapRange(1 - indexFingerTip.x, 0, 1, -sceneWidth/2, sceneWidth/2); // 1-x 因为自拍模式通常是镜像player.position.x += (targetX - player.position.x) * 0.2;}}const hands = new Hands({locateFile: (file) => {return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;}});hands.setOptions({maxNumHands: 1,modelComplexity: 1,minDetectionConfidence: 0.5,minTrackingConfidence: 0.5});hands.onResults(onResults);const cameraUtils = new Camera(videoElement, {onFrame: async () => {await hands.send({image: videoElement});},width: 320,height: 240});cameraUtils.start();// --- 4. 游戏主循环 ---const scoreEl = document.getElementById('score-board');let frameCount = 0;function animate() {requestAnimationFrame(animate);if (gameRunning) {frameCount++;// 每 60 帧生成一个新物体if (frameCount % 60 === 0) {spawnObject();}// 更新掉落物for (let i = fallingObjects.length - 1; i >= 0; i--) {const obj = fallingObjects[i];obj.position.y -= obj.userData.speed;obj.rotation.x += obj.userData.rotSpeed.x;obj.rotation.y += obj.userData.rotSpeed.y;// 碰撞检测 (简单的 AABB 或 距离检测)// 检查 Y 轴高度是否到达玩家高度if (obj.position.y < playerY + 1 && obj.position.y > playerY - 1) {// 检查 X 轴距离if (Math.abs(obj.position.x - player.position.x) < 2.0) {// 接住了!score += 10;scoreEl.innerText = score;// 特效:玩家发光一下player.material.emissive.setHex(0xffffff);setTimeout(() => player.material.emissive.setHex(0x004444), 100);// 移除物体scene.remove(obj);fallingObjects.splice(i, 1);continue;}}// 掉出屏幕if (obj.position.y < -10) {scene.remove(obj);fallingObjects.splice(i, 1);}}}renderer.render(scene, camera);}// 窗口大小调整适配window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);});animate();</script>
</body>
</html>

🌟 项目简介 | Project Introduction

这是一个基于 Three.js 和 MediaPipe Hands 构建的前端交互式游戏项目。通过摄像头捕捉你的手势,你可以直接用食指控制屏幕上的太空飞船,接住从天而降的能量球来得分。整个游戏过程无需任何物理控制器,只需要你的手就可以完成所有操作,带来前所未有的沉浸式体验!🚀

📌 前提条件 | Prerequisites

  1. 现代浏览器: Chrome/Firefox/Safari 最新版
  2. 摄像头设备: 内置或外接摄像头
  3. 基础 HTML/CSS/JS 知识: 有助于理解代码结构

🚀 核心技术栈 | Core Technologies

技术 用途 链接
Three.js WebGL 3D 渲染引擎 threejs.org
MediaPipe 手部关键点识别 mediapipe.dev
HTML5 Canvas 3D场景渲染容器 -

👐 手势控制原理 | Hand Control Principle

通过 MediaPipe 获取手部 21 个关键点坐标,我们重点关注食指指尖(索引8)的位置信息,将其映射到3D场景坐标系中,实现精准控制。

  • 食指指尖(Index Finger Tip): 索引 8
  • 坐标映射: 将摄像头画面坐标(0-1)映射到游戏世界坐标(-10至10)

🧩 核心代码片段 | Core Code Snippets

1. 游戏场景初始化 | Scene Initialization

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1a1a2e);
// 添加一些迷雾增加深邃感
scene.fog = new THREE.FogExp2(0x1a1a2e, 0.03);const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 10;
camera.position.y = 2;
camera.lookAt(0, 0, 0);

2. 手势识别配置 | Hand Detection Configuration

const hands = new Hands({locateFile: (file) => {return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
}});hands.setOptions({maxNumHands: 1,modelComplexity: 1,minDetectionConfidence: 0.5,minTrackingConfidence: 0.5
});
hands.onResults(onResults);

3. 手势控制逻辑 | Hand Control Logic

function onResults(results) {loadingElement.style.display = 'none';if (!gameRunning) gameRunning = true;if (results.multiHandLandmarks && results.multiHandLandmarks.length > 0) {// 获取第一只手const landmarks = results.multiHandLandmarks[0];// 获取食指指尖 (索引为 8)const indexFingerTip = landmarks[8];// MediaPipe 的 x 坐标是 0(左) 到 1(右)。// 注意:我们在 CSS 里镜像翻转了视频,但数据本身没有翻转。// 在游戏里,为了直观,如果你向右移手,我们希望 x 变大。// 原生数据:屏幕左边是0,右边是1。// 映射到 3D 场景:x 从 -10 到 10。// 平滑移动 (Lerp) 以减少抖动const targetX = mapRange(1 - indexFingerTip.x, 0, 1, -sceneWidth/2, sceneWidth/2); // 1-x 因为自拍模式通常是镜像player.position.x += (targetX - player.position.x) * 0.2;}
}

4. 游戏主循环 | Main Game Loop

function animate() {requestAnimationFrame(animate);if (gameRunning) {frameCount++;// 每 60 帧生成一个新物体if (frameCount % 60 === 0) {spawnObject();}// 更新掉落物for (let i = fallingObjects.length - 1; i >= 0; i--) {const obj = fallingObjects[i];obj.position.y -= obj.userData.speed;obj.rotation.x += obj.userData.rotSpeed.x;obj.rotation.y += obj.userData.rotSpeed.y;// 碰撞检测 (简单的 AABB 或 距离检测)// 检查 Y 轴高度是否到达玩家高度if (obj.position.y < playerY + 1 && obj.position.y > playerY - 1) {// 检查 X 轴距离if (Math.abs(obj.position.x - player.position.x) < 2.0) {// 接住了!score += 10;scoreEl.innerText = score;// 特效:玩家发光一下player.material.emissive.setHex(0xffffff);setTimeout(() => player.material.emissive.setHex(0x004444), 100);// 移除物体scene.remove(obj);fallingObjects.splice(i, 1);continue;}}// 掉出屏幕if (obj.position.y < -10) {scene.remove(obj);fallingObjects.splice(i, 1);}}}renderer.render(scene, camera);
}

🎮 游戏机制 | Game Mechanics

  1. 手势控制: 使用食指控制底部的太空飞船左右移动
  2. 物品收集: 接住从天而降的能量球获得分数
  3. 视觉反馈: 成功接住物品时飞船会发出光芒
  4. 实时计分: 右上角显示当前得分

🛠️ 使用指南 | Run Guide

本地运行 | Local Run

  1. 将代码保存为 demo02.html
  2. 用现代浏览器直接打开即可(需允许摄像头权限)

🔧 定制项 | Customization Options

项目 修改方法 效果预览
飞船颜色 更改 color: 0x00ffcc 🟢 青色飞船 → 🟣 紫色飞船
掉落物样式 修改 IcosahedronGeometry 🔺 正二十面体 → 🎈 球体
游戏难度 调整 frameCount % 60 🐌 慢速 → ⚡ 快速
场景主题 更改 scene.background 🌃 深蓝 → 🌌 黑色

🐛 常见问题 | Troubleshooting

  1. 摄像头无法启动?

    • 检查浏览器权限设置
    • 确保没有其他程序占用摄像头
  2. 手势识别不准确?

    • 保持手部在摄像头清晰可见范围内
    • 调整环境光线避免过暗或过曝
  3. 游戏运行卡顿?

    • 降低掉落物生成频率
    • 关闭其他占用资源的程序

📚 扩展学习资源 | Extended Resources

  • Three.js 官方文档
  • MediaPipe Hands 文档
  • WebGL Fundamentals 教程

Conclusion | 结语

  • That's all for today~ - | 今天就写到这里啦~

  • Guys, ( ̄ω ̄( ̄ω ̄〃 ( ̄ω ̄〃)ゝ See you tomorrow~~ | 小伙伴们,( ̄ω ̄( ̄ω ̄〃 ( ̄ω ̄〃)ゝ我们明天再见啦~~

  • Everyone, be happy every day! 大家要天天开心哦

  • Welcome everyone to point out any mistakes in the article~ | 欢迎大家指出文章需要改正之处~

  • Learning has no end; win-win cooperation | 学无止境,合作共赢

  • Welcome all the passers-by, boys and girls, to offer better suggestions! ~~~ | 欢迎路过的小哥哥小姐姐们提出更好的意见哇~~

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/990676.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CF2175

A: 考虑什么时候我们操作不会影响这个集合。 当我们加入颜色种类数在集合中时,我们就可以了。因为 \(a_{i}\le 1000\),所以我们直接暴力,然后 break 就行了。因为插入的次数最多就是 \(max(a_{i})\) 级别的 B: 区间…

WPF学习之MVVM

介绍: MVVM是(Model-View-ViewModel)的简写,分别为:Model(模型)、View(视图)和ViewModel(视图模型)。他是WPF常用的一种开发设计模型思想。将应用程序的业务和表示逻辑与用户界面 (UI) 清晰分离。 官方文档:…

2025 最新数据中心建设服务商 / 厂家 TOP5 评测!智能生态 + 全周期服务权威榜单发布,科技赋能重构工业基建新范式

随着工业数字化转型加速,数据中心作为智慧工厂的核心枢纽,其建设质量直接决定企业数字化运营效能。本榜单基于技术完整性、行业适配深度、全周期服务能力三大维度(德尔智慧新增“资产健康管理”维度),结合行业权威…

走向价值共生:AI元人文的内观照叙事动力学与元治理范式

走向价值共生:AI元人文的内观照叙事动力学与元治理范式 摘要 当前人工智能伦理研究深陷“价值对齐”范式的根本困境,其症结在于将动态、多元的人类价值静态化、指标化地预设为AI系统的优化目标。本文提出“AI元人文”…

2025 最新数字孪生服务商 / 厂家 TOP5 评测!科技赋能 + 全周期服务权威榜单发布,引领智慧工厂建设新生态

随着工业4.0的深入推进,数字孪生技术已成为智慧工厂建设的核心驱动力,为企业实现高效、智能、绿色运营提供关键支撑。本榜单基于技术创新力、行业适配性、服务覆盖度、全周期能力四大维度(德尔智慧新增“AI算法赋能…

自愈型RAG系统:从脆弱管道到闭环智能体的工程实践

RAG系统在生产环境中有个老大难问题:脆弱。演示时用精心准备的问题去问,效果看起来很惊艳。但真正上线后,用户的问题五花八门,向量数据库返回的文档语义上相似但实际答非所问,LLM又特别喜欢讨好,拿着一堆噪音数据…

【有手就行】自己花20分钟从0开始训练一个“大模型”

一、说在前面 训练基座大模型那都是大公司们的事情,普通人、普通公司肯定是玩不起的,但是作为一个技术人,你可以不去做真正的大模型训练,但是你还是有必要知道和了解一下一个大模型是如何训练出来的。 而GPT_teach…

test

SegmentTree

CEF系列技术文章:菜单隐藏实现

核心逻辑与 ID 说明 CEF(Chromium Embedded Framework)中可通过硬编码指定菜单项 ID,结合菜单可见性判断接口,精准隐藏指定 Chrome 原生菜单;同时支持工具栏按钮的显隐控制,以下为核心实现与关键 ID 说明。 核心…

2025最新灯塔工厂建设服务商/厂家TOP5评测!科技赋能+全周期服务权威榜单发布,引领智能制造新生态

随着全球制造业向智能化、绿色化转型加速,灯塔工厂建设已成为企业提升核心竞争力的关键路径。本榜单基于技术创新力、行业适配性、服务完整性、落地成效四大维度,结合行业权威报告与企业实地案例调研,深度解析2025年…

AI真好玩系列-WebGL爱心粒子手势互动教程 | Interactive Heart Particles with Hand Gestures

AI真好玩系列-WebGL爱心粒子手势互动教程 | Interactive Heart Particles with Hand Gestures 周末的深夜,睡不着觉,闲来无事,打开Gemini哈基米玩一把,废话不多说,先上图看最终效果~ 碎碎念:我很想上传视频,但是…

大数据分析基础及应用案例:第八周学习报告——深度学习与金融案例入门

在金融科技飞速发展的当下,深度学习技术正深刻重塑着金融领域的研究与应用范式。第七周的学习围绕 “深度学习与金融案例入门” 展开,从 LSTM 模型到情感计算分析基础,再到证券文本情感分析的背景与数据来源预习,每…

第47天(简单题中等题 数据结构)

打卡第四十七天 2道简单题+1道中等题题目:思路:代码: class Solution { public:vector<bool> isArraySpecial(vector<int>& nums, vector<vector<int>>& queries) {vector<int&…

SpyCloud数据揭示:企业用户遭遇钓鱼攻击的可能性是恶意软件的三倍

SpyCloud的最新研究报告显示,针对企业用户的钓鱼攻击在一年内激增了400%,成为比恶意软件更主要的初始入侵手段。文章分析了这种攻击趋势的转变,并探讨了身份数据暴露带来的后续风险以及企业所需的综合防护策略。Spy…

nccl-1_initialization bootstrap

nccl学习-1: 初始化communicator与bootstrap 网络 在nccl的例子中,当我们获取了设备的数量,为每一个设备分配了一个ncclComm_t后,需要根据已经固定的通信拓扑,对每一个算子进行配置。目前,针对communicator的初始…

2025年国内TOP5会计培训机构推荐,引领专业提升之路

在当前的会计培训市场中,各类机构提供了丰富的选择,以满足不同学员的需求。比如,成都环宇知了科技有限公司专注于基础课程,适合初学者。而超有爱教育培训则为在职人员开设了实用性强的课程,结合真实案例帮助学员提…

2025年国内TOP5会计培训机构推荐,引领专业提升之路

在当前的会计培训市场中,各类机构提供了丰富的选择,以满足不同学员的需求。比如,成都环宇知了科技有限公司专注于基础课程,适合初学者。而超有爱教育培训则为在职人员开设了实用性强的课程,结合真实案例帮助学员提…

2025年评价高的草本床垫供应厂家TOP5推荐

在2025年,市场上的草本床垫供应厂家层出不穷,每一家公司都在努力提升产品质量与用户体验。从材料选择到设计理念,众多厂家在不断创新。其中,四川宅逸居家居有限公司凭借其独特的草本助眠技术广受好评;而芬驰家居则…

2025 最新智能运维服务商/ 厂家 TOP5 评测!科技赋能 + 全周期服务权威榜单发布,引领智慧工厂运维新生态

随着智能制造的深入发展,智能运维作为保障工厂高效、稳定、绿色运行的核心环节,其重要性日益凸显。本榜单基于技术创新力、行业适配性、服务覆盖度、实战效果四大维度,结合行业权威数据与客户反馈,对2025年智能运维…

人生第一篇博客:千里之行,始于足下

现在是2025年12月6日晚,大二的我像一个刚闯入森林的探险者,好奇的注册了这个博客网站,四处打量着各个大佬写的高级的东西(看不懂)据说写博客是很多学计算机的人的好习惯,用来记录和监督自己一天的学习或者思考,…