diff --git a/idea.md b/idea.md index 38f5a30..7458cd9 100644 --- a/idea.md +++ b/idea.md @@ -86,3 +86,4 @@ dam4.png ---- 存档 59 [] 优化游戏进程与渲染进程间的通讯 [] 优化资源分离,音乐放到 bgm 目录下 [] 一次性道具拾取与清怪 +[] 重构数据统计 diff --git a/src/core/main/custom/hotkey.ts b/src/core/main/custom/hotkey.ts new file mode 100644 index 0000000..71d5e6d --- /dev/null +++ b/src/core/main/custom/hotkey.ts @@ -0,0 +1,221 @@ +import { KeyCode } from '../../../plugin/keyCodes'; +import { deleteWith } from '../../../plugin/utils'; +import { EmitableEvent, EventEmitter } from '../../common/eventEmitter'; +import { GameStorage } from '../storage'; + +interface HotkeyEvent extends EmitableEvent { + emit: (key: KeyCode, e: KeyboardEvent) => void; + keyChange: (data: HotkeyData, before: KeyCode, after: KeyCode) => void; +} + +interface HotkeyData { + id: string; + name: string; + defaults: KeyCode; + key: KeyCode; + ctrl?: boolean; + alt?: boolean; + shift?: boolean; + func: (code: KeyCode, e: KeyboardEvent) => any; +} + +export class Hotkey extends EventEmitter { + keyMap: Map = new Map(); + list: Record = {}; + storage: GameStorage>; + + constructor(id: string) { + super(); + this.storage = new GameStorage(GameStorage.fromAncTe(id)); + } + + /** + * 注册一个按键操作 + * @param data 按键信息 + */ + register(id: string, data: Omit) { + const key = { + id, + key: this.storage.getValue(id, data.defaults), + ...data + }; + this.ensureKey(key.key).push(key); + this.list[id] = key; + return this; + } + + /** + * 设置一个操作的按键 + * @param data 要设置的操作 + * @param key 按键 + */ + setKey(data: string | HotkeyData, key: KeyCode): void { + if (typeof data === 'string') { + data = this.list[data]; + } + const map = this.keyMap.get(data.key)!; + deleteWith(map, data); + this.ensureKey(key).push(data); + const before = data.key; + data.key = key; + this.emit('keyChange', data, before, key); + } + + /** + * 获取一个按键可以触发的所有按键操作 + * @param key 要获取的按键 + */ + getData(key: KeyCode): HotkeyData[] { + return this.keyMap.get(key) ?? []; + } + + /** + * 执行一个按键操作 + * @param key 按下的按键 + */ + emitKey(key: KeyCode, e: KeyboardEvent): any[] { + this.emit('emit', key, e); + return this.getData(key).map(v => v.func(key, e)); + } + + private ensureKey(key: KeyCode) { + if (!this.keyMap.has(key)) { + this.keyMap.set(key, []); + } + return this.keyMap.get(key)!; + } +} + +export const hotkey = new Hotkey('gameKey'); + +hotkey + .register('book', { + name: '怪物手册', + defaults: KeyCode.KeyX, + func: () => {} + }) + .register('save', { + name: '存档界面', + defaults: KeyCode.KeyS, + func: () => {} + }) + .register('load', { + name: '读档界面', + defaults: KeyCode.KeyD, + func: () => {} + }) + .register('undo1', { + name: '撤回', + defaults: KeyCode.KeyA, + func: () => {} + }) + .register('undo2', { + name: '撤回', + defaults: KeyCode.Digit5, + func: () => {} + }) + .register('redo1', { + name: '重做', + defaults: KeyCode.KeyW, + func: () => {} + }) + .register('redo2', { + name: '重做', + defaults: KeyCode.Digit6, + func: () => {} + }) + .register('toolbox', { + name: '道具栏', + defaults: KeyCode.KeyT, + func: () => {} + }) + .register('equipbox', { + name: '装备栏', + defaults: KeyCode.KeyQ, + func: () => {} + }) + .register('fly', { + name: '楼层传送', + defaults: KeyCode.KeyG, + func: () => {} + }) + .register('turn', { + name: '勇士转向', + defaults: KeyCode.KeyZ, + func: () => {} + }) + .register('getNext1', { + name: '轻按', + defaults: KeyCode.Space, + func: () => {} + }) + .register('getNext2', { + name: '轻按', + defaults: KeyCode.Digit7, + func: () => {} + }) + .register('menu', { + name: '菜单', + defaults: KeyCode.Escape, + func: () => {} + }) + .register('replay', { + name: '录像回放', + defaults: KeyCode.KeyR, + func: () => {} + }) + .register('restart', { + name: '开始菜单', + defaults: KeyCode.KeyN, + func: () => {} + }) + .register('shop', { + name: '快捷商店', + defaults: KeyCode.KeyV, + func: () => {} + }) + .register('statistics', { + name: '数据统计', + defaults: KeyCode.KeyB, + func: () => {} + }) + .register('viewMap1', { + name: '浏览地图', + defaults: KeyCode.PageUp, + func: () => {} + }) + .register('viewMap2', { + name: '浏览地图', + defaults: KeyCode.PageDown, + func: () => {} + }) + .register('comment', { + name: '评论区', + defaults: KeyCode.KeyP, + func: () => {} + }) + .register('mark', { + name: '标记怪物', + defaults: KeyCode.KeyM, + func: () => {} + }) + .register('skillTree', { + name: '技能树', + defaults: KeyCode.KeyJ, + func: () => {} + }) + .register('desc', { + name: '百科全书', + defaults: KeyCode.KeyH, + func: () => {} + }) + .register('special', { + name: '鼠标位置怪物属性', + defaults: KeyCode.KeyE, + func: () => {} + }) + .register('critical', { + name: '鼠标位置怪物临界', + defaults: KeyCode.KeyC, + func: () => {} + }); diff --git a/src/core/main/setting.ts b/src/core/main/setting.ts index a03fbd0..b5b752f 100644 --- a/src/core/main/setting.ts +++ b/src/core/main/setting.ts @@ -5,6 +5,7 @@ import { loading } from '../loader/load'; import { hook } from './game'; import { isMobile } from '../../plugin/use'; import { GameStorage } from './storage'; +import { triggerFullscreen } from '../../plugin/utils'; type MotaSettingType = boolean | number | MotaSetting; @@ -269,22 +270,6 @@ mainSetting.on('valueChange', (key, n, o) => { } }); -export async function triggerFullscreen(full: boolean) { - const { maxGameScale } = core.plugin.utils; - if (!!document.fullscreenElement && !full) { - await document.exitFullscreen(); - requestAnimationFrame(() => { - maxGameScale(1); - }); - } - if (full && !document.fullscreenElement) { - await document.body.requestFullscreen(); - requestAnimationFrame(() => { - maxGameScale(); - }); - } -} - const root = document.getElementById('root') as HTMLDivElement; const root2 = document.getElementById('root2') as HTMLDivElement; diff --git a/src/plugin/utils.ts b/src/plugin/utils.ts index 105eed0..e460bb9 100644 --- a/src/plugin/utils.ts +++ b/src/plugin/utils.ts @@ -270,3 +270,19 @@ export function deleteWith(arr: T[], ele: T): T[] { arr.splice(index, 1); return arr; } + +export async function triggerFullscreen(full: boolean) { + const { maxGameScale } = core.plugin.utils; + if (!!document.fullscreenElement && !full) { + await document.exitFullscreen(); + requestAnimationFrame(() => { + maxGameScale(1); + }); + } + if (full && !document.fullscreenElement) { + await document.body.requestFullscreen(); + requestAnimationFrame(() => { + maxGameScale(); + }); + } +} diff --git a/src/ui/start.vue b/src/ui/start.vue index dc09e0b..38532c9 100644 --- a/src/ui/start.vue +++ b/src/ui/start.vue @@ -68,7 +68,7 @@ import { Matrix4 } from '../plugin/webgl/matrix'; import { doByInterval, keycode } from '../plugin/utils'; import { KeyCode } from '../plugin/keyCodes'; import { achievementOpened } from '../plugin/uiController'; -import { triggerFullscreen } from '../core/main/setting'; +import { triggerFullscreen } from '../plugin/utils'; import { loading } from '../core/loader/load'; import { isMobile } from '../plugin/use';