feat: 获取单次虚拟按键

This commit is contained in:
unanmed 2024-01-18 17:07:03 +08:00
parent 899d1fa68e
commit 89f1f4a948
5 changed files with 88 additions and 25 deletions

View File

@ -6,7 +6,7 @@ import {
import { KeyCode } from '@/plugin/keyCodes';
import { gameKey } from '../init/hotkey';
import { unwarpBinary } from './hotkey';
import { deleteWith } from '@/plugin/utils';
import { deleteWith, flipBinary } from '@/plugin/utils';
import { cloneDeep } from 'lodash-es';
import { shallowReactive } from 'vue';
@ -22,12 +22,6 @@ interface KeyboardItem {
y: number;
width: number;
height: number;
active?: boolean;
}
interface AssistManager {
symbol: symbol;
end(): void;
}
interface VirtualKeyEmit {
@ -46,6 +40,8 @@ interface VirtualKeyboardEvent extends EmitableEvent {
remove: (item: KeyboardItem) => void;
extend: (extended: Keyboard) => void;
emit: VirtualKeyEmitFn;
scopeCreate: (scope: symbol) => void;
scopeDispose: (scope: symbol) => void;
}
/**
@ -62,6 +58,7 @@ export class Keyboard extends EventEmitter<VirtualKeyboardEvent> {
scope: symbol = Symbol();
private scopeStack: symbol[] = [];
private onEmitKey: Record<symbol, Listener<VirtualKeyEmitFn>[]> = {};
private scopeAssist: Record<symbol, number> = {};
constructor(id: string) {
super();
@ -93,19 +90,11 @@ export class Keyboard extends EventEmitter<VirtualKeyboardEvent> {
/**
*
* @param assist
* @returns
*/
withAssist(assist: number): AssistManager {
const thisAssist = this.assist;
withAssist(assist: number) {
this.assist = assist;
const symbol = this.createScope();
return {
symbol,
end: () => {
this.assist = thisAssist;
}
};
return symbol;
}
/**
@ -113,6 +102,7 @@ export class Keyboard extends EventEmitter<VirtualKeyboardEvent> {
* @returns
*/
createScope() {
const last = this.scopeStack.at(-1);
const symbol = Symbol();
this.scope = symbol;
this.scopeStack.push(symbol);
@ -120,6 +110,12 @@ export class Keyboard extends EventEmitter<VirtualKeyboardEvent> {
this.onEmitKey[symbol] = ev;
// @ts-ignore
this.events = ev;
this.emit('scopeCreate', symbol);
if (!!last) {
this.scopeAssist[symbol] = this.assist;
}
this.assist = 0;
this.scopeAssist[symbol] = 0;
return symbol;
}
@ -134,9 +130,12 @@ export class Keyboard extends EventEmitter<VirtualKeyboardEvent> {
}
const now = this.scopeStack.pop()!;
delete this.onEmitKey[now];
delete this.scopeAssist[now];
const symbol = this.scopeStack.at(-1);
this.emit('scopeDispose', now);
if (!symbol) return;
this.scope = symbol;
this.assist = this.scopeAssist[symbol];
// @ts-ignore
this.events = this.onEmitKey[symbol];
}
@ -168,6 +167,13 @@ export class Keyboard extends EventEmitter<VirtualKeyboardEvent> {
this.emit('emit', key, this.assist, index, { preventDefault });
if (!prevent) {
if (key.key === KeyCode.Ctrl) {
this.assist = flipBinary(this.assist, 0);
} else if (key.key === KeyCode.Shift) {
this.assist = flipBinary(this.assist, 1);
} else if (key.key === KeyCode.Alt) {
this.assist = flipBinary(this.assist, 2);
}
const ev = generateKeyboardEvent(key.key, this.assist);
gameKey.emitKey(key.key, this.assist, 'up', ev);
}
@ -188,3 +194,7 @@ export function generateKeyboardEvent(key: KeyCode, assist: number) {
return ev;
}
export function isAssist(key: KeyCode) {
return key === KeyCode.Ctrl || key === KeyCode.Shift || key === KeyCode.Alt;
}

View File

@ -0,0 +1,15 @@
import { Keyboard } from '../custom/keyboard';
import KeyboardUI from '@/panel/keyboard.vue';
interface VirtualKeyProps {
keyboard: Keyboard;
}
export function VirtualKey(props: VirtualKeyProps) {
return (
<KeyboardUI
style="align-self: center"
keyboard={props.keyboard}
></KeyboardUI>
);
}

View File

@ -1,4 +1,5 @@
import * as UI from '@ui/.';
import * as MiscUI from './misc';
import { GameUi, UiController } from '../custom/ui';
import { hook } from '../game';
@ -17,7 +18,8 @@ mainUi.register(
new GameUi('achievement', UI.Achievement),
new GameUi('bgm', UI.BgmList),
new GameUi('hotkey', UI.Hotkey),
new GameUi('toolEditor', UI.ToolEditor)
new GameUi('toolEditor', UI.ToolEditor),
new GameUi('virtualKey', MiscUI.VirtualKey)
// todo: 把游戏主 div 加入到 mainUi 里面
);
mainUi.showAll();

View File

@ -4,7 +4,7 @@
v-for="(key, i) of keyboard.keys"
class="keyboard-item"
@click="keyboard.emitKey(key, i)"
:active="!!key.active"
:active="checkAssist(assist, key.key)"
:style="{
left: `${key.x}px`,
top: `${key.y}px`,
@ -20,27 +20,46 @@
</template>
<script lang="ts" setup>
import { checkAssist } from '@/core/main/custom/hotkey';
import { Keyboard } from '@/core/main/custom/keyboard';
import { KeyboardEmits } from '@/core/main/custom/keyboard';
import { KeyCodeUtils } from '@/plugin/keyCodes';
import { onUnmounted, ref } from 'vue';
const props = defineProps<{
keyboard: Keyboard;
}>();
const fontSize = props.keyboard.fontSize;
const assist = ref(props.keyboard.assist);
const fontSize = `${props.keyboard.fontSize}px`;
const [width, height] = (() => {
const key = props.keyboard;
const mw = Math.max(...key.keys.map(v => v.x));
const mh = Math.max(...key.keys.map(v => v.y));
let mw = 0;
let mh = 0;
for (const k of key.keys) {
if (k.x + k.width > mw) mw = k.x + k.width;
if (k.y + k.height > mh) mh = k.y + k.height;
}
return [mw, mh];
return [`${mw}px`, `${mh}px`];
})();
function onAssist(_: any, ass: number) {
new Promise<void>(res => {
assist.value = ass;
res();
});
}
props.keyboard.on('emit', onAssist);
const emits = defineEmits<{
(e: 'keyup', data: KeyboardEmits): void;
}>();
onUnmounted(() => {
props.keyboard.off('emit', onAssist);
});
</script>
<style lang="less" scoped>
@ -49,6 +68,7 @@ const emits = defineEmits<{
height: v-bind(height);
display: block;
font-size: v-bind(fontSize);
position: relative;
}
.keyboard-item {

View File

@ -7,7 +7,8 @@ import { EVENT_KEY_CODE_MAP, KeyCode } from './keyCodes';
import axios from 'axios';
import { decompressFromBase64 } from 'lz-string';
import { parseColor } from './webgl/utils';
import { KeyboardEmits } from '@/core/main/custom/keyboard';
import { isAssist, Keyboard, KeyboardEmits } from '@/core/main/custom/keyboard';
import { mainUi } from '@/core/main/init/ui';
type CanParseCss = keyof {
[P in keyof CSSStyleDeclaration as CSSStyleDeclaration[P] extends string
@ -357,6 +358,21 @@ export function getVitualKeyOnce(
assist: number = 0
): Promise<KeyboardEmits> {
return new Promise(res => {
res({ key: KeyCode.Unknown, assist: 0 });
const key = Keyboard.get('qwe')!;
key.withAssist(assist);
const id = mainUi.open('virtualKey', { keyboard: key });
key.on('emit', (item, assist, index, ev) => {
ev.preventDefault();
if (emitAssist) {
res({ key: item.key, assist: 0 });
key.disposeScope();
} else {
if (!isAssist(item.key)) {
res({ key: item.key, assist });
key.disposeScope();
}
}
mainUi.close(id);
});
});
}