From a109a3c51375f70f755b92c97e93e7dc3c59ffda Mon Sep 17 00:00:00 2001 From: Backpack Date: Mon, 14 Jul 2025 03:54:41 +0800 Subject: [PATCH] finish arrow control --- src-py/router/__pycache__/__init__.cpython-38.pyc | Bin 151 -> 151 bytes src-py/router/__pycache__/ws.cpython-38.pyc | Bin 7980 -> 6697 bytes src/hand_landmark/detector.ts | 33 ++++++++++++++++++ src/hand_landmark/gesture_handler.ts | 39 ++++++++++++++++++++-- src/view/mainWindow/MainWindow.vue | 2 +- 5 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src-py/router/__pycache__/__init__.cpython-38.pyc b/src-py/router/__pycache__/__init__.cpython-38.pyc index cb894a50ac3ffc4b71e7f0f23d976ce3a0e87c67..bd30296749ca70d3ca105aa399d010284eb0711d 100644 GIT binary patch delta 19 ZcmbQvIGvF@l$V!_0SLI5OD1yn001E016}|C delta 19 ZcmbQvIGvF@l$V!_0SGRCD4xjO0{|*A1rq=O diff --git a/src-py/router/__pycache__/ws.cpython-38.pyc b/src-py/router/__pycache__/ws.cpython-38.pyc index 1e6dcaa30e2a350ed5c5bf5f9da3c1f0d0e025b1..caeae962f7ef2a3155dde04befdae21a9a580ac7 100644 GIT binary patch delta 1377 zcmZux&2Jl35P!2@bvE9$vvz{N;-ab_*ri|~DJi9al%}Gggork@1ZZ&mHcg#kr*9Xm znstnn9*~eKswY)QG$@w1Q1xbs6H<}rKhRSpAE75yE?hx^nRP-7;yu0J&irO}_IW;h zd-A)n{qvS(GF+zWFK1JX{X)v)OGo8ZJl@0W`|mvOI-6-e)B)Gz&Q0J6p1i89!$QW* zx~7}rz=v;Ye1t!7Ra?k$IK>L7?$hv_3S%;(k87w$<$L;uI$N;hu<@z9W#m&y3?2bZ z)gavTRPd%VVII%4m9$wpr^?F8%9Z;K$w(!%$+dNoi@(_d?3Fa`~r^2 zQuGj%Wi{GB`RC|CaAn#e`MOnvi}DA{gBe+}cf&`>XS=KRHvm^;EdJT}VG8>)LO~N* zlG6x1ZN#l&Cmnk**w79R!F`vK?i zjfLo{a6QlEi(%k73O6a6$z5qjuV_9c!S_gf_((^VPOyq63h~41g8o9 zFIiJ)Sis{s2$*;!qB)u!?zojo39>h1&o;cp7aHYH+)BOXi~6Mk^adL4d9Pksas3LQ z&-S9PQ49Tq$Gax)rL)!M-hgeY9d?3oc%8KrUkj9g1+cF68DN()XIO1UW4^v(ig$p~ z=1_)rS#1ni1KH1kwNzlu5q}3)0`+UQp{zsS>kJ!5@0Plz%5#~M@kq}oS1RtRFD$%+ zn38ugPaSxaa7~;?x);0Pdj7}4U0g2L_$62LBE0OE7d>BK&WE&wEM^n!+w>zw5SVUb zY79^m8&Y6H1mcKd87JHD9k9D~fn2P&V5;0*ynOAu4IsQGnIn-*Snd%N)84bTC!5<6EqW>=LqrAzRvF zqsRuxS|OX+Vr^t^AREKzDn`d-Vi8Vax}h4!gntk0DAmCq;yBa5uofjWI%s-;wa~E^ z4%+lU->yYi2cxC0>1WAXIm@^q@8%B3-*eC5j3?xt(S7Z(b;mFV{r(*%DQx0{B!!*) zB1zQAz1YmDw`PxF({XoNh`I=8P*5!k#(%SZgx;cBJvNbH!-o^;qTxq8C2toZGZZYK zp+;c@qF`d05*!mfFkx1lKi T$mfQJ?VSBK_DNEKaR2!?jAads delta 2638 zcmZuzU2I&%6`nKqXMenV*Q~vpUE6Ui8UkxXfGVLR0kYI_2^7{L2?SPEw#&|q;~#d- z+?%+V>uiuMibRFdPK(mkpZ`3RV35`4?H39*z&MX6tsZ~@kXCYDd)^x|Dmp0g(~eWpfG2gYJ+UcXMuDfY`QTiJZtUo8|2Sj zUO75GHgWV&J08}K9iKR&PTIpmIb3NJOv42IZhlc(`=#CBa6p-{12CqFvH9V9v9%n! z7PeD$KSELcBenzful+lA5}=}v_q+fq?Y|x_s)zcI zH18utf#5K~4+$P3m>{^3fF_m{blF32guoWG5j;>?l+9J>JR6fLspjy3AOY|PR^N6-*1bYqE~=Pz|$d!h5QmpZTh z`P0Are*Xw2i;KvO{1T27nFPWhZ*i$1&><5t8HWK?J zVBS*1s(=LEgW3pcFCg7bqD`2JN}k2jLCt0Rp-AbjE@u1oy^lRTy3d&9;Gt@R%{eCf05}ju z3OgVr+6tC@3O}1;$vJf}l4(Xzx#5^mblJiOK0C#HSmgn0!Hc-?z??P~Ekx6|rtKLn z_Xm765?BKA43Xzq3s1WGZ@Mj_*y0Gbh!Mf-%Ux|8wWmU9CM03&1`rfG(|)-+oGj@CYkV2iKYF@7bC6ioMH ztiGW50rNA$S~`G3V;H}S#_UY|0?3^hNL!!V8DR(ZdLVTW%|-j1y%9uHeYWiuD5+fT zc3#+~9?ad?)R*NRabBxwTdBZ&ymPCamJqI3u|S-9g; zHl+R&&?k8z@{RaWuY&|xf+AxNZ)K1^*&As22#Yt0z#<&;!8Q_*MdrrW3)XwFq_Ljm zy@+X$)UPlsJ#~Hl$8bn3$k|M?mN+fLK~ diff --git a/src/hand_landmark/detector.ts b/src/hand_landmark/detector.ts index c8cf4c2..e06a136 100644 --- a/src/hand_landmark/detector.ts +++ b/src/hand_landmark/detector.ts @@ -31,6 +31,10 @@ export enum HandGesture { DELETE_GESTURE = "delete_gesture", OTHER = "other", + + // 游戏手势 + DIRECTION_RIGHT = "direction_right", + JUMP = "jump", // 食指 + 拇指上抬 } interface HandLandmark { @@ -203,6 +207,8 @@ export class Detector { const fingers = this._fingersUp(hand); const fingerState = fingers.join(","); + + // 定义手势映射表 const gestureMap = new Map([ // 食指举起,移动鼠标 @@ -226,6 +232,7 @@ export class Detector { // 其他手势 ["0,0,0,0,0", HandGesture.VOICE_GESTURE_STOP], + ["1,1,1,0,0", HandGesture.JUMP], ]); if (gestureMap.has(fingerState)) { @@ -237,6 +244,12 @@ export class Detector { return HandGesture.DELETE_GESTURE; } + // 检查右边手势 + if (this._isRightGesture(hand, fingers)) { + return HandGesture.DIRECTION_RIGHT; + } + + // 返回默认值 return HandGesture.OTHER; } @@ -262,6 +275,26 @@ export class Detector { return isThumbExtended && areOtherFingersClosed && isThumbLeftmost; } + + private static _isRightGesture(hand: HandInfo, fingers: number[]): boolean { + const THUMB_INDEX = 4; + const FINGER_TIPS = [8, 12, 16, 20]; + const distance_threshold = 0.05; + + const isThumbExtended = fingers[0] === 1; + const areOtherFingersClosed = fingers + .slice(1) + .every((finger) => finger === 0); + const isThumbRightmost = FINGER_TIPS.every( + (tipIndex) => + hand.landmarks[THUMB_INDEX].x < + hand.landmarks[tipIndex].x - distance_threshold + ); + + return isThumbExtended && areOtherFingersClosed && isThumbRightmost; + } + + /** * 处理检测结果并执行相应动作 */ diff --git a/src/hand_landmark/gesture_handler.ts b/src/hand_landmark/gesture_handler.ts index 69a75d9..bc9cc0a 100644 --- a/src/hand_landmark/gesture_handler.ts +++ b/src/hand_landmark/gesture_handler.ts @@ -157,6 +157,12 @@ export class GestureHandler { private lastDeleteTime: number = 0; + // 小游戏 + private lastArrowLeftTime = 0; + private lastArrowRightTime = 0; + private lastJumpTime = 0; + private readonly DIRECTION_INTERVAL = 500; // 防抖间隔(毫秒) + constructor() { this.triggerAction = new TriggerAction(); this.app_store = use_app_store(); @@ -326,7 +332,27 @@ export class GestureHandler { return; } this.lastDeleteTime = now; - this.triggerAction.sendKeys("backspace"); + this.triggerAction.sendKeys("left"); + } + + + private handleArrowRight() { + const now = Date.now(); + if (now - this.lastDeleteTime < 300) { + return; + } + this.lastDeleteTime = now; + this.triggerAction.sendKeys("right"); + } + + + private handleJump() { + const now = Date.now(); + if (now - this.lastDeleteTime < 300) { + return; + } + this.lastDeleteTime = now; + this.triggerAction.sendKeys("up"); } /** @@ -409,9 +435,18 @@ export class GestureHandler { case HandGesture.FOUR_FINGERS_UP: this.handleFourFingers(); break; + case HandGesture.DELETE_GESTURE: - this.handleDelete(); + this.handleDelete(); + break; + + case HandGesture.DIRECTION_RIGHT: + this.handleArrowRight(); + break; + case HandGesture.JUMP: + this.handleJump(); break; + } } } diff --git a/src/view/mainWindow/MainWindow.vue b/src/view/mainWindow/MainWindow.vue index bf84197..cd639d9 100644 --- a/src/view/mainWindow/MainWindow.vue +++ b/src/view/mainWindow/MainWindow.vue @@ -235,7 +235,7 @@ const statusText = computed(() => { @backpack -
@ninjakelly
+
@backpack