mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-02-28 17:37:07 +08:00
feat: 获取单次虚拟按键
This commit is contained in:
parent
899d1fa68e
commit
89f1f4a948
@ -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;
|
||||
}
|
||||
|
15
src/core/main/init/misc.tsx
Normal file
15
src/core/main/init/misc.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user