Canvas实现碧蓝航线语音效果(粗制滥造)

9 篇文章 0 订阅
7 篇文章 0 订阅
本文介绍了一位开发者尝试使用HTML5 Canvas技术模仿碧蓝航线游戏中的角色交互效果,通过几何体近似和逻辑判断实现鼠标点击触发不同音效。作者分享了实现思路、代码示例,并提出使用曲线近似以适应更多图片形状的改进方案。
摘要由CSDN通过智能技术生成

因为在网络上浏览信息时,总会看到一些网页(博客园居多)会带有一个小女孩的样式,鼠标移入不同位置会显示不同的文字,这个东西很有趣。经过查阅,发现这种技术叫做live2D,它在某些类型的游戏中使用很多。提起游戏我又想起来,有一款叫做碧蓝航线的游戏,它的人物可以通过触摸来出发音效,不过我没有玩过,只是在视频里面见过。因为我最近做了几个关于canvas的玩具,所以我准备来试试使用canvas来复刻一下碧蓝航线里面的那种效果。不过,这里需要先指出,我的标题已经明确了,这是一个粗制滥造的复刻,哈哈,具体效果,仁者见仁智者见智吧。

一、视频演示

这是我的B站视频,视频的噪声较大(我都笔记本已经老了),建议佩戴耳机进行观看,效果会好一点。

强烈推荐你观看演示视频,毕竟这里涉及到了声音,这是无法使用文字进行表达的信息。

canvas实现碧蓝航线语音(粗制滥造)

二、实现思路

1.几何体近似

对于一个具体的人物,我们需要将它切分成几个部分,针对某一个部分进行判断。那如何切分呢?一个简单的想法是使用集合体进行近似。作为一个理工男,这就需要发挥我们的抽象思维了。下面放一张图片来展示我所理解的抽象,这张图片应该很好理解的,我就不做具体说明了。针对具体的图片使用这些几何体进行近似,基本上就是这样了。

在这里插入图片描述

2.逻辑判断

这里涉及到逻辑判断的问题,具体就是如何判断鼠标点击到了哪一个部位呢?这就需要我们前面的几何体近视了,几何体其实就是表示的某一个部位。当鼠标点击时,依次绘制上述的几何体,绘制完成一个之后,就进行判断是否鼠标点击的点在该几何体内部,如果在的话,就触发相应的音效。

在这里插入图片描述

三、代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>抽象版</title>
		<style>
			body, div {
				margin: 0;
                padding: 0;
			}
		</style>
	</head>
	<body>
		<div id="cas" style="margin: 0 auto;">
			<canvas id="cs" width="600" height="700" style="border: 2px solid green"></canvas>
		</div>
		
		<script type="text/javascript">
			'use strict'
			let canvas = document.getElementById("cs");
			// 获取canvas的宽高
			let width = canvas.width;
			let height = canvas.height;
			let ctx = canvas.getContext("2d");
			// 设置背景完全透明
			ctx.strokeStyle = "red";
			ctx.strokeStyle = "rgba(255, 255, 255, 0)";

			let current = -1;
			let rewidth = 600;  // 重定义图片的宽度
			
			let imgs = [];
			// 创建img元素
			Array.from({length: 1}, (a, i)=>i).forEach(index => {
				let img = document.createElement("img")
				img.src = "test.png";
				// 当图片加载完成之后,将其绘制到canvas上,图片没有加载完成时,
				// 图片的宽高是0,因为这时候图片其实是空的
				img.onload = () => {
					let h = resize(img, rewidth);
					img.width = rewidth;
					img.height = h;
					drawCanvas(img);
				};
			});
			
			
			function drawHeader(x, y) {
			    ctx.beginPath();
				ctx.rect(245, 20, 78, 88);
				ctx.stroke();
				
				if (!ctx.isPointInPath(x, y)) {
					return ;
				}
				console.log("点击了头");
				playAudio("./1.mp3");
			}
			
			function drawNeck(x, y) {
				ctx.beginPath();
				ctx.rect(270, 110, 30, 21);
				ctx.stroke();
				
				if (!ctx.isPointInPath(x, y)) {
					return ;
				}
				console.log("点击了脖子");
				playAudio("./2.mp3");
			}
			
			function drawUpperHalf(x, y) {
			    ctx.beginPath();
				ctx.rect(245, 133, 80, 165);
				ctx.stroke();
				
				if (!ctx.isPointInPath(x, y)) {
					return ;
				}
				console.log("点击了上半身");
				playAudio("./3.mp3");
			}
			
			function drawLegs(x, y) {
			    ctx.beginPath();
				ctx.rect(228, 300, 45, 368);
				ctx.rect(292, 300, 45, 368);
				ctx.stroke();				
				
				if (!ctx.isPointInPath(x, y)) {
					return ;
				}
				console.log("点击了腿");
				playAudio("./4.mp3");
			}
			
			function drawArms(x, y) {
			    ctx.beginPath();
				ctx.rotate(40*Math.PI/180);
				ctx.rect(250, -40, 30, 220);
				ctx.rotate(280*Math.PI/180);				
				ctx.rect(160, 320, 30, 170);
				ctx.rotate(40*Math.PI/180);
				ctx.stroke();
				
				if (!ctx.isPointInPath(x, y)) {
					return ;
				}
				console.log("点击了胳膊");
				playAudio("./5.mp3");
			}
			
			function drawPlate(x, y) {
			    ctx.beginPath();
				ctx.moveTo(516, 322);
				ctx.arc(465, 322, 51, 0, Math.PI*2);
				ctx.stroke();
				
				if (!ctx.isPointInPath(x, y)) {
					return ;
				}
				console.log("点击了盘子");
				playAudio("./6.mp3");
			}
			
			function playAudio(path) {
				let url = path;
				let audio = new Audio(url)
				audio.addEventListener("canplaythrough", event => {
					audio.play();
				});
			}
			
			// 添加鼠标事情,来实现图片的拖放功能。
			// 当鼠标按下时,获取当前的坐标
			canvas.onmousedown = e => {
				console.log("鼠标按下")
				let x = e.pageX-canvas.offsetLeft; // 后面这个是偏移量,但是在这里为0
				let y = e.pageY-canvas.offsetTop;
				console.log(x + " -> " + y);
				drawHeader(x, y);  // 绘制头部
				drawNeck(x, y);    // 绘制脖子
				drawUpperHalf(x, y);  // 绘制上半身
				drawLegs(x, y);    // 绘制腿
				drawArms(x, y);       // 绘制胳膊
				drawPlate(x, y);      // 绘制盘子			
			};

			function drawCanvas(img) {
			    ctx.drawImage(img, 0, 0, img.width, img.height);
			}
			
			// 根据传如的指定宽度,自动调整高度
			function resize(img, width) {
				let w = img.width;
				let h = img.height;
				return parseInt(h*width/w);
			}
		</script>
	</body>
</html>

四、补充

上面这种几何体进行近似实际上面临很多不方便之处,因为很多人物图片都不是这样正面的。所以其实符合的图片很难找,这就是图片需要符合程序了。但是,应当是程序符合图片才对,所以我又想了其它的方法,我觉得可以使用曲线进行近似。具体的做法就是使用鼠标,在图片上面进行绘制,然后拿到曲线的坐标,每次绘制曲线的坐标,不再是几何体了,这样做理论上可以适合机会所有的图片了。不过我还没有进行尝试,目前仅仅是一个不成熟的想法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值