共计 3878 个字符,预计需要花费 10 分钟才能阅读完成。
飞机大战置信大家都玩过,好多同学甚至本人写过,不论你是用 js 还是用 java,是用原生代码实现还是应用游戏引擎实现。无非就是应用鼠标或者手指触控来在屏幕上拖动飞机挪动来打飞机,但我置信你应该还没有玩过应用手势隔空来管制飞机吧。
那明天咱们就来开发一款飞机大战游戏,而后应用手势隔空操控飞机。
先上 demo:飞机大战
留神:须要开启电脑摄像头
MediaPipe
为了实现手势管制,咱们就须要可能通过电脑摄像头来辨认手部的动作。这里咱们应用到了 MediaPip。
MediaPipe 是一款由 Google Research 开发并开源的多媒体机器学习模型利用框架。在谷歌,一系列重要产品,如、Google Lens、ARCore、Google Home 以及,都已深度整合了 MediaPipe。
作为一款跨平台框架,MediaPipe 不仅能够被部署在服务器端,更能够在多个挪动端(安卓和苹果 iOS)和嵌入式平台(Google Coral 和树莓派)中作为设施端机器学习推理(On-device Machine Learning Inference)框架
Media Pip 反对应用 js 实现人脸网格拓扑,人脸检测,手部检测,全身检测和姿态辨认等。
手部辨认
为了实现应用手势管制飞机,那么咱们须要辨认出手部动作。
MediaPip 能够辨认人手,并且将手部构造按关节进行拓扑,辨认后果为保留在两个对象中:
- MULTI_HAND_LANDMARKS:保留了每个手的关节信息
- MULTI_HANDEDNESS:保留多个手部信息,比方是左手还是右手
手势管制飞机原理
原理很简略,就是应用摄像头手别手部,MediaPip 能够辨认手部 21 个关节,咱们能够应用食指尖这个点来管制飞机挪动。即下标为 8 的点:INDEX_FINGER_TIP的坐标赋值给飞机。其实就相当于应用食指代替了鼠标。
代码实现
好,原理分明之后,上代码:
创立 html 文件,引入三个 js 库:
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_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>
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_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>
<link rel="stylesheet" href="demo.css">
</head>
<body>
<div class="container">
<!-- 小飞机 -->
![](./img/hero.png)
<!-- video 用来开启摄像头 -->
<video class="input_video"></video>
<!-- 用来绘制辨认内容 -->
<canvas class="output_canvas" width="1280px" height="720px" ></canvas>
<!-- loading 成果,当摄像头开启胜利后会暗藏 -->
<div class="loading">
<div class="spinner"></div>
<div class="message">
Loading
</div>
</div>
</div>
<script src="./demo.js"></script>
</body>
</html>
创立 Hands 对象:
const hands = new Hands({locateFile: (file) => {return `https://cdn.jsdelivr.net/npm/@mediapipe/hands@0.1/${file}`;
}
});
外面这个 file 是为了辨认手须要加载的资源文件。
设置默认选项:
hands.setOptions({
selfieMode: true, // 是否自拍,即是否应用前置摄像头
maxNumHands: 1, // 最大辨认手部数量
minDetectionConfidence: 0.5, // 辨认精度,这个数值越高,则要求图像高评分能力被辨认 默认 0.5
minTrackingConfidence: 0.5 // 跟踪速度,数值越高,破费工夫越长
});
开启摄像头,把摄像头捕获的画面传给 hands 对象:
const camera = new Camera(videoElement, {onFrame: async () => {await hands.send({ image: videoElement});
},
width: 1280,
height: 720
});
camera.start();
获取辨认后果:
function onResults(results) {
// 暗藏 loading 动画
document.body.classList.add('loaded');
// Draw the overlays.
canvasCtx.save();
// 清空画布
canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
// 绘制摄像头捕获画面
canvasCtx.drawImage(results.image, 0, 0, canvasElement.width, canvasElement.height);
// 辨认后果保留在 multiHandLandmarks 和 multiHandedness 对象中,如果这两个对象不为 null,则阐明辨认胜利
if (results.multiHandLandmarks && results.multiHandedness) {
// 遍历 multiHandLandmarks,取得每个 hand 的信息
for (let index = 0; index < results.multiHandLandmarks.length; index++) {const classification = results.multiHandedness[index];
const isRightHand = classification.label === 'Right';
// 一个手的关节信息
const landmarks = results.multiHandLandmarks[index];
// 下标为 8 的关节就是食指, 坐标值为宽高的百分比,和画布宽高相乘就失去坐标
let x = landmarks[8].x * 1280;
let y = landmarks[8].y * 720;
// 把手指坐标赋值非小飞机
hero.style.left = x - 50 + 'px';
hero.style.top = y - 40 + 'px';
// 绘制手部拓扑图
drawConnectors(
canvasCtx, landmarks, HAND_CONNECTIONS,
{color: isRightHand ? '#00FF00' : '#FF0000'}),
drawLandmarks(canvasCtx, landmarks, {
color: isRightHand ? '#00FF00' : '#FF0000',
fillColor: isRightHand ? '#FF0000' : '#00FF00',
radius: (x) => {return lerp(x.from.z, -0.15, .1, 10, 1);
}
});
}
}
canvasCtx.restore();}
hands.onResults(onResults);
辨认后果保留在 multiHandLandmarks 和 multiHandedness 对象中:
multiHandLandmarks是一个二维数组,每一个数组中保留了 21 个关节坐标信息。把食指坐标赋值给飞机,就能够管制飞机挪动了。
而后再加一点点细节,咱们的飞机大战就实现了:
好了实现了。
后话
这里咱们只实现了简略的追随成果。如果再通过计算关节之间的地位关系和静止方向,那么就能够辨认更简单的手势,比方实现手势翻页,点击按钮,相似华为手机的手势辨认。
不过除此之外,咱们还能够做得更多,加上面部辨认和体态辨认,你甚至能够开发体感游戏。
前期我也会尝试开发一些更有意思的利用,欢送大家继续关注。
残缺代码
关注公众号 H5Talks,在公众号后盾回复: 飞机大战 获取残缺代码。
如果本文对你有帮忙,欢送关注、点赞、评论。