回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页
best-icon

剑诀修炼模拟器——一起凡人修仙吧!(行空板K10+二哈识图2) 简单

头像 小含糊online 2025.09.29 79 0

9月30日 更新

上传了程序附件

--------------------------------------------------------------------

作为《凡人修仙传》的粉丝,动漫中的各种手诀真的是很喜欢,幻想着有一天能够修仙飞升(当然那是不可能滴),不过捏捏剑诀什么的自我满足一下还是可以滴,刚好用手头的二哈2和K10做一个剑诀修炼模拟器。

IMG_20250929_175416.jpg
IMG_20250929_175426.jpg

思路如下图

剑诀修炼模拟器.png

关于人物:

(作品中人物均取自动漫《凡人修仙转》人物造型)

小师妹——宋玉饰

邪祟——玄骨饰

材料清单

  • 行空板K10 X1
  • 二哈识图2 X1
  • 舵机 X7
  • 纸盒 X1
  • 垃圾袋 X1
  • 热熔胶枪 X1
  • 充电宝 X1

步骤1 确定主题,绘制流程图

主要一个是喜欢《凡人修仙传》,一个是新品二哈识图2要多用起来

其实很想研究二哈2的实例分割这个功能,但是贪多嚼不烂,先把手势识别多用用再说别的功能吧!

整个作品流程并不复杂,故事背景就是:

你扮演一个修仙的凡人,在一次跟师妹练习剑诀的时候不小心捏了一个禁忌剑诀,从而解除了某个邪祟的封印,然后你通过复杂的(其实就三个……)剑诀组合,以及坚持不懈(程序中大概不到5秒的时间)与邪祟抗衡,最终重新镇压邪祟的剧情。

步骤2 编写程序

程序写起来不难,主要是思路要清晰。分模块编写,测试,然后整合。

大致步骤如下:

1.寻找合适的图片,使用豆包帮助改图;

image.png

2.编写纯软件部分程序,实现语音识别、简单的手势识别功能;

3.加入图片,建立函数,实现较复杂程序内容(能够识别不同剑诀,并且进行解读);

image.png

4.进一步创建邪祟出现、灭杀等相关函数,借用串口调试等工具(也可以使用行空板屏幕调试);

image.png

5.单独编写舵机控制程序;

image.png

6.整合程序,修改bug

步骤3 测试舵机

1.这里我分成了八种情况

image.png

舵机0°认物卡片隐藏在盒子里面,舵机90°人物卡片出现在视野中。

2.根据表格,创建函数并测试

image.png

注意:每个函数都是7个舵机绑定在一起作为一个整体的系统进行程序编写(特殊情况除外)

IMG_20250928_101029.jpg
IMG_20250928_123706.jpg

(哈哈哈,简陋的测试)

测试视频见分享视频2P

步骤4 制作人物卡片、舞台、连接硬件

1.制作人物卡片

使用WPS演示抠图排版,用相纸打印,最后裁剪好轮廓

IMG_20250929_083209.jpg

2.舞台

2.1 安置舵机

手边刚好有个纸盒,直接拿来做舞台,裁剪好舵机的位置,放置好舵机(热熔胶枪)

IMG_20250929_143142.jpg
IMG_20250929_123820.jpg
IMG_20250929_141731.jpg

2.2 使用垃圾袋+卡片装饰舞台(没错,刚好看到了垃圾袋,就拿来用了……)

IMG_20250929_190433.jpg

3.二哈2+K10

手头刚好有二哈一代的支架,拿来安装在K10上也勉强ok,就是螺丝不合适,上不紧,刚好手边有纸盒子,剪下来一点做一个应急垫片,妥妥的

IMG_20250929_130413.jpg
IMG_20250929_130655.jpg

步骤5 测试改bug,补细节

贴上部分程序截图(太长了,不好弄)

初始化

image.png

主循环

image.png

灭杀邪祟

image.png

代码
/*!
 * MindPlus
 * esp32s3bit
 *
 */
#include "asr.h"
#include "unihiker_k10.h"
#include <Microbit_Motor.h>
#include "arduino_image_cache.h"
#include "DFRobot_HuskylensV2.h"

// 动态变量
volatile float mind_n_BiaoJi, mind_n_MoShi, mind_n_ShiShen, mind_n_YuGui, mind_n_QingXin,
               mind_n_MieShaJinDu, mind_n_XieSuiZhuangTai;
// 函数声明
void DF_DuoJiChuShiHua();
void DF_DuoJiShiShenJue();
void DF_DuoJiShiMeiZiXin();
void DF_ChuShiHua();
void DF_DuoJiYuGuiJue();
void DF_DuoJiQingXinJue();
void DF_ShiMeiJingKong();
void DF_DuoJiXieSuiChuXian();
void DF_DuoJiChengGongMieSha();
void DF_XieSuiChuXian();
void DF_JianJueShiBie();
void DF_MieShaXieSui();
void DF_JieDuJianJue();
// 创建对象
Microbit_Motor motorbit;
UNIHIKER_K10   k10;
uint8_t        screen_dir=2;
ASR            asr;
HuskylensV2    huskylens;


// 主程序开始
void setup() {
	k10.begin();
	Serial.begin(9600);
	k10.initScreen(screen_dir);
	k10.creatCanvas();
	asr.setAsrSpeed(2);
	asr.asrInit(CONTINUOUS, CN_MODE, 6000);
	while(asr._asrState == 0){delay(100);}
	Wire.begin();
  while (!huskylens.begin(Wire)) {
    delay(100);
  }
	DF_ChuShiHua();
}
void loop() {
	huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
	// 特殊情况:一开始就是用禁忌剑诀
	if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==5)) {
		DF_XieSuiChuXian();
		DF_MieShaXieSui();
	}
	while (!(mind_n_MoShi==1)) {
		huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
		DF_JianJueShiBie();
		DF_JieDuJianJue();
	}
	while (!(mind_n_MoShi==0)) {
		DF_MieShaXieSui();
	}
}


// 自定义函数
void DF_DuoJiChuShiHua() {
	motorbit.servo(S1, 0);
	motorbit.servo(S2, 0);
	motorbit.servo(S3, 0);
	motorbit.servo(S4, 0);
	motorbit.servo(S5, 0);
	motorbit.servo(S6, 0);
	motorbit.servo(S7, 0);
}
void DF_DuoJiShiShenJue() {
	motorbit.servo(S1, 0);
	motorbit.servo(S2, 90);
	motorbit.servo(S3, 0);
	motorbit.servo(S4, 0);
	motorbit.servo(S5, 0);
	motorbit.servo(S6, 0);
	motorbit.servo(S7, 0);
}
void DF_DuoJiShiMeiZiXin() {
	motorbit.servo(S1, 90);
	motorbit.servo(S2, 0);
	motorbit.servo(S3, 0);
	motorbit.servo(S4, 0);
	motorbit.servo(S5, 0);
	motorbit.servo(S6, 0);
	motorbit.servo(S7, 0);
}
void DF_ChuShiHua() {
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data1);
	k10.canvas->updateCanvas();
	Serial.println("标题画面载入完毕。");
	asr.addASRCommand(0+1, "kai shi xiu lian");
	while (!asr.isDetectCmdID(0+1)) {}
	DF_DuoJiChuShiHua();
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data2);
	k10.canvas->canvasText("师兄,又来练习剑诀啦!", 40, 260, 0xFFCCCC, k10.canvas->eCNAndENFont16, 20, false);
	k10.canvas->updateCanvas();
	asr.speak("师兄,又来练习剑诀啦!");
	DF_DuoJiShiMeiZiXin();
	delay(3000);
	k10.canvas->canvasClear();
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data3);
	k10.canvas->canvasText("待我准备一下!", 40, 260, 0xFFCCCC, k10.canvas->eCNAndENFont16, 20, false);
	k10.canvas->updateCanvas();
	asr.speak("待我准备一下!");
	Serial.println("初始化二哈2……");
	DF_DuoJiChuShiHua();
	huskylens.switchAlgorithm(ALGORITHM_HAND_RECOGNITION);
	Serial.println("二哈2初始化完毕,载入标题画面……");
	Serial.println("重置标记变量与模式变量……");
	mind_n_BiaoJi = 0;
	mind_n_MoShi = 0;
	Serial.println("标记变量与模式变量重置完毕。");
	Serial.println((String("当前标记值:") + String(mind_n_BiaoJi)));
	Serial.println((String("当前模式值:") + String(mind_n_MoShi)));
	delay(3000);
	DF_DuoJiShiMeiZiXin();
	k10.canvas->canvasClear();
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data4);
	k10.canvas->canvasText("准备好啦!按下A键开始吧!", 40, 260, 0xFFCCCC, k10.canvas->eCNAndENFont16, 20, false);
	k10.canvas->updateCanvas();
	asr.speak("准备好啦!按下A键开始吧!");
	while (!(k10.buttonA->isPressed())) {}
	k10.canvas->canvasClear();
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data5);
	k10.canvas->updateCanvas();
	asr.speak("请出剑诀!");
}
void DF_DuoJiYuGuiJue() {
	motorbit.servo(S1, 0);
	motorbit.servo(S2, 0);
	motorbit.servo(S3, 90);
	motorbit.servo(S4, 0);
	motorbit.servo(S5, 0);
	motorbit.servo(S6, 0);
	motorbit.servo(S7, 0);
}
void DF_DuoJiQingXinJue() {
	motorbit.servo(S1, 0);
	motorbit.servo(S2, 0);
	motorbit.servo(S3, 0);
	motorbit.servo(S4, 90);
	motorbit.servo(S5, 0);
	motorbit.servo(S6, 0);
	motorbit.servo(S7, 0);
}
void DF_ShiMeiJingKong() {
	motorbit.servo(S1, 0);
	motorbit.servo(S2, 0);
	motorbit.servo(S3, 0);
	motorbit.servo(S4, 0);
	motorbit.servo(S5, 90);
	motorbit.servo(S6, 0);
	motorbit.servo(S7, 0);
}
void DF_DuoJiXieSuiChuXian() {
	motorbit.servo(S1, 0);
	motorbit.servo(S2, 0);
	motorbit.servo(S3, 0);
	motorbit.servo(S4, 0);
	motorbit.servo(S5, 0);
	motorbit.servo(S6, 90);
	motorbit.servo(S7, 0);
}
void DF_DuoJiChengGongMieSha() {
	motorbit.servo(S1, 0);
	motorbit.servo(S2, 0);
	motorbit.servo(S3, 0);
	motorbit.servo(S4, 0);
	motorbit.servo(S5, 0);
	motorbit.servo(S6, 0);
	motorbit.servo(S7, 90);
}
void DF_XieSuiChuXian() {
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data6);
	DF_ShiMeiJingKong();
	k10.canvas->canvasText("师兄,这个剑诀不可以捏啊!", 65, 260, 0xFF6600, k10.canvas->eCNAndENFont16, 20, false);
	k10.canvas->updateCanvas();
	asr.speak("师兄,这个剑诀不可以捏啊!");
	delay(4000);
	mind_n_MoShi = 1;
	mind_n_ShiShen = 0;
	mind_n_YuGui = 0;
	mind_n_QingXin = 0;
	k10.canvas->canvasClear();
	DF_DuoJiXieSuiChuXian();
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data7);
	k10.canvas->updateCanvas();
	asr.speak("不好,有妖祟作怪,速速出剑诀!");
	delay(3000);
	k10.canvas->updateCanvas();
	asr.speak("请按照如下顺序捏诀");
	delay(3000);
	k10.canvas->updateCanvas();
	asr.speak("御鬼、清心、弑神");
	delay(2000);
	k10.canvas->updateCanvas();
	asr.speak("速速灭杀了邪魔外道吧!");
	delay(1000);
}
void DF_JianJueShiBie() {
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data8);
	k10.canvas->updateCanvas();
	if ((huskylens.available(ALGORITHM_HAND_RECOGNITION))) {
		if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==1)) {
			delay(50);
			huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
			if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==1)) {
				mind_n_BiaoJi = 1;
			}
		}
		if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==2)) {
			delay(50);
			huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
			if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==2)) {
				mind_n_BiaoJi = 2;
			}
		}
		if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==3)) {
			delay(50);
			huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
			if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==3)) {
				mind_n_BiaoJi = 3;
			}
		}
		if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==5)) {
			delay(50);
			huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
			if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==5)) {
				mind_n_BiaoJi = 5;
			}
		}
	}
}
void DF_MieShaXieSui() {
	k10.canvas->canvasClear();
	k10.canvas->canvasDrawBitmap(0,0,240,319,image_data9);
	k10.canvas->updateCanvas();
	while (!(mind_n_YuGui==1)) {
		huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
		// 不直接使用变量【标记】是因为,需要考虑一开始就是用禁忌剑诀的情况,那个时候还没有获取到标记变量
		if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==2)) {
			delay(50);
			huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
			if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==2)) {
				DF_DuoJiYuGuiJue();
				motorbit.servo(S6, 90);
				mind_n_YuGui = 1;
			}
		}
	}
	asr.speak("御鬼");
	delay(1000);
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data10);
	k10.canvas->updateCanvas();
	while (!(mind_n_QingXin==1)) {
		huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
		if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==3)) {
			delay(50);
			huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
			if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==3)) {
				DF_DuoJiQingXinJue();
				motorbit.servo(S6, 90);
				mind_n_QingXin = 1;
			}
		}
	}
	asr.speak("清心");
	delay(1000);
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data11);
	k10.canvas->updateCanvas();
	while (!(mind_n_ShiShen==1)) {
		huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
		if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==1)) {
			delay(50);
			huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
			if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==1)) {
				DF_DuoJiShiShenJue();
				motorbit.servo(S6, 90);
				mind_n_ShiShen = 1;
			}
		}
	}
	asr.speak("弑神");
	delay(1000);
	asr.speak("速速使用灭杀剑诀!");
	while (!((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==4)) {
		k10.canvas->canvasDrawBitmap(0,0,240,320,image_data12);
		k10.canvas->updateCanvas();
		huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
		delay(50);
	}
	k10.canvas->canvasClear();
	k10.setScreenBackground(0xFF0000);
	k10.canvas->canvasText("灭杀此獠,急急如律令!", 60, 120, 0xFFFF00, k10.canvas->eCNAndENFont16, 20, true);
	k10.canvas->updateCanvas();
	mind_n_MieShaJinDu = 0;
	mind_n_XieSuiZhuangTai = 90;
	while (!(((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==4) && (mind_n_MieShaJinDu==5))) {
		huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
		if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==4)) {
			delay(500);
			huskylens.getResult(ALGORITHM_HAND_RECOGNITION);
			if (((RET_ITEM_NUM(huskylens.getCachedCenterResult(ALGORITHM_HAND_RECOGNITION), Result, ID))==4)) {
				mind_n_MieShaJinDu += 1;
				mind_n_XieSuiZhuangTai -= 15;
				motorbit.servo(S6, mind_n_XieSuiZhuangTai);
				delay(100);
			}
			else {
				motorbit.servo(S5, 90);
				motorbit.servo(S6, 90);
				mind_n_MieShaJinDu = 0;
				mind_n_XieSuiZhuangTai = 90;
				asr.speak("师兄,坚持住!");
				delay(1000);
			}
		}
		DF_DuoJiChuShiHua();
	}
	mind_n_MoShi = 0;
	k10.canvas->canvasClear();
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data13);
	DF_DuoJiChengGongMieSha();
	k10.canvas->updateCanvas();
	asr.speak("邪魔外道已经灭杀,师兄可以继续练习了!");
	delay(2000);
	DF_DuoJiChuShiHua();
	k10.setScreenBackground(0xFFFFFF);
	k10.canvas->canvasClear();
	k10.canvas->canvasDrawBitmap(0,0,240,320,image_data14);
	k10.canvas->updateCanvas();
	asr.speak("请出剑诀!");
}
void DF_JieDuJianJue() {
	if ((mind_n_BiaoJi==1)) {
		DF_DuoJiShiShenJue();
		k10.canvas->canvasText("弑神诀,威力强大!", 65, 260, 0xFF6600, k10.canvas->eCNAndENFont16, 20, false);
		k10.canvas->updateCanvas();
		asr.speak("弑神诀,威力强大!");
		delay(1500);
	}
	if ((mind_n_BiaoJi==2)) {
		DF_DuoJiYuGuiJue();
		k10.canvas->canvasText("御鬼诀,小心使用!", 65, 260, 0xFF6600, k10.canvas->eCNAndENFont16, 20, false);
		k10.canvas->updateCanvas();
		asr.speak("御鬼诀,小心使用!");
		delay(1500);
	}
	if ((mind_n_BiaoJi==3)) {
		DF_DuoJiQingXinJue();
		k10.canvas->canvasText("清心诀,回复精力!", 65, 260, 0xFF6600, k10.canvas->eCNAndENFont16, 20, false);
		k10.canvas->updateCanvas();
		asr.speak("清心诀,回复精力!");
		delay(1500);
	}
	if ((mind_n_BiaoJi==5)) {
		mind_n_MoShi = 1;
		DF_XieSuiChuXian();
		DF_MieShaXieSui();
	}
	mind_n_BiaoJi = 0;
	delay(1000);
}

写在最后:

程序虽然不难,但是中间弯弯绕绕的,改了好多次,还是有很多地方不尽人意,想修改好然后加上3D打印,做个2.0版本的,看什么时候有机会吧……

image.png

上图是我在创作过程中的小笔记,仅供参考

关于改进措施,我也想了好多

image.png

以上就是“剑诀修炼模拟器”的全部内容啦!欢迎讨论!!

评论

user-avatar