完善ui控制器

This commit is contained in:
unanmed 2023-08-22 00:02:18 +08:00
parent 41e0037bed
commit be2a22e574
4 changed files with 101 additions and 29 deletions

View File

@ -21,7 +21,7 @@
### 机制
[] 苍蓝之殿 1: 利用点光源,照到的位置与没照到的位置内容不同,玩家可以选择是否装备手电筒
[] 苍蓝之殿 1:
[] 苍蓝之殿 2:
[] 苍蓝之殿 3:
[] 苍蓝之殿 4:
@ -72,7 +72,7 @@ dam4.png ---- 存档 59
[] 区域名称显示特效,3D 粒子特效
[] 单独的工具栏,可以自定义按键
[] 完全 ts 化
[] 平行光
[] 平行光(待定)
[] 视角控制系统
[x] 重构设置界面
[] 优化开头动画
@ -96,5 +96,7 @@ dam4.png ---- 存档 59
[] 重构技能树结构
[] 技能树允许自动升级
[] 重构装备系统
[] 野外地图加入平行光
[] 弹幕系统
[] 优化各种 ui
[] 怪物脚下加入阴影
[] 着色器特效

View File

@ -135,11 +135,12 @@ export class Hotkey extends EventEmitter<HotkeyEvent> {
* @param hotkey 被继承的按键
* @param cover 继承时是否覆盖同id的按键
*/
extend(hotkey: Hotkey, cover: boolean) {
extend(hotkey: Hotkey, cover: boolean = false) {
Object.values(hotkey.list).forEach(v => {
if (v.id in this.list && !cover) return;
this.register(v.id, v.name, v);
});
return this;
}
private ensureKey(key: KeyCode) {
@ -177,7 +178,7 @@ hotkey
core.doSL('autoSave', 'load');
}
})
.register('redo', '撤销回退', {
.register('redo', '恢复', {
defaults: KeyCode.KeyW,
func: () => {
core.doSL('autoSave', 'reload');

View File

@ -1,4 +1,4 @@
import { Component, shallowReactive } from 'vue';
import { Component, h, shallowReactive } from 'vue';
import { EmitableEvent, EventEmitter } from '../../common/eventEmitter';
import { KeyCode } from '../../../plugin/keyCodes';
import { Hotkey } from './hotkey';
@ -19,9 +19,13 @@ export class Focus<T = any> extends EventEmitter<FocusEvent<T>> {
stack: T[];
focused: T | null = null;
constructor(react?: boolean) {
/** ui是否平等,在平等时,关闭ui不再会将其之后的ui全部删除,而是保留 */
readonly equal: boolean;
constructor(react: boolean = false, equal: boolean = false) {
super();
this.stack = react ? shallowReactive([]) : [];
this.equal = equal;
}
/**
@ -79,12 +83,15 @@ export class Focus<T = any> extends EventEmitter<FocusEvent<T>> {
*/
pop() {
const item = this.stack.pop() ?? null;
const last = this.stack.at(-1) ?? null;
if (!last) this.unfocus();
else this.focus(last);
this.emit('pop', item);
return item;
}
/**
* 从一个位置开始删除显示列表
* 从一个位置开始删除显示列表,如果ui平等,则只会删除一个,否则会将其之后的所有ui全部删除
* @param item 从哪开始删除,包括此项
*/
splice(item: T) {
@ -93,7 +100,13 @@ export class Focus<T = any> extends EventEmitter<FocusEvent<T>> {
this.emit('splice', []);
return;
}
this.emit('splice', this.stack.splice(index));
const last = this.stack.at(-1) ?? null;
if (!last) this.unfocus();
else this.focus(last);
this.emit(
'splice',
this.stack.splice(index, this.equal ? 1 : Infinity)
);
}
/**
@ -133,6 +146,9 @@ export class GameUi extends EventEmitter<GameUiEvent> {
hotkey?: Hotkey;
id: string;
vBind: any = {};
vOn: Record<string, (...params: any[]) => any> = {};
constructor(id: string, component: Component, hotkey?: Hotkey) {
super();
this.component = component;
@ -140,17 +156,53 @@ export class GameUi extends EventEmitter<GameUiEvent> {
this.id = id;
GameUi.uiList.push(this);
}
/**
* 双向数据绑定,即 vue 内的 v-bind
* @param data 要绑定的数据
*/
vbind(data: any) {
this.vBind = data;
}
/**
* 监听这个ui组件所触发的某种事件
* @param event 要监听的事件
* @param fn 事件触发时执行的函数
*/
von(event: string, fn: (...params: any[]) => any) {
this.vOn[event] = fn;
}
/**
* 取消监听这个ui组件所触发的某种事件
* @param event 要取消监听的事件
*/
voff(event: string) {
delete this.vOn[event];
}
}
export class UiController extends Focus<GameUi> {
constructor() {
super(true);
static list: UiController[] = [];
constructor(equal?: boolean) {
super(true, equal);
UiController.list.push(this);
this.on('splice', spliced => {
spliced.forEach(v => {
v.emit('close');
if (this.stack.length === 0) {
this.emit('end');
}
});
});
this.on('add', item => item.emit('open'));
this.on('add', item => {
if (this.stack.length === 1) {
this.emit('start');
}
item.emit('open');
});
}
/**
@ -171,7 +223,7 @@ export class UiController extends Focus<GameUi> {
}
/**
* 关闭一个ui,注意在其之后的ui都会同时关闭掉
* 关闭一个ui,注意如果不是平等模式,在其之后的ui都会同时关闭掉
* @param id 要关闭的ui的id
*/
close(id: string) {

View File

@ -10,26 +10,16 @@ import FixedDetail from '../../../ui/fixedDetail.vue';
import Shop from '../../../ui/shop.vue';
import Achievement from '../../../ui/achievement.vue';
import Bgm from '../../../ui/bgmList.vue';
import StatusBar from '../../../ui/statusBar.vue';
import Mark from '../../../ui/markedEnemy.vue';
import Fixed from '../../../ui/fixed.vue';
import Chapter from '../../../ui/chapter.vue';
import CompleteAchi from '../../../ui/completeAchievement.vue';
import Start from '../../../ui/start.vue';
import { GameUi, UiController } from '../custom/ui';
import { Hotkey } from '../custom/hotkey';
import { KeyCode } from '../../../plugin/keyCodes';
export const mainUi = new UiController();
mainUi.register(
new GameUi('book', Book),
new GameUi('toolbox', Toolbox),
new GameUi('equipbox', Equipbox),
new GameUi('settings', Settings),
new GameUi('desc', Desc),
new GameUi('skill', Skill),
new GameUi('skillTree', SkillTree),
new GameUi('fly', Fly),
new GameUi('fixedDetail', FixedDetail),
new GameUi('shop', Shop),
new GameUi('achievement', Achievement),
new GameUi('bgm', Bgm)
);
export const exitKey = new Hotkey('exitKey');
exitKey
.register('exit1', '退出', {
@ -44,3 +34,30 @@ exitKey
if (mainUi.focused) mainUi.splice(mainUi.focused);
}
});
export const mainUi = new UiController();
mainUi.register(
new GameUi('book', Book, exitKey),
new GameUi('toolbox', Toolbox, exitKey),
new GameUi('equipbox', Equipbox, exitKey),
new GameUi('settings', Settings, exitKey),
new GameUi('desc', Desc, exitKey),
new GameUi('skill', Skill, exitKey),
new GameUi('skillTree', SkillTree, exitKey),
new GameUi('fly', Fly, exitKey),
new GameUi('fixedDetail', FixedDetail, exitKey),
new GameUi('shop', Shop, exitKey),
new GameUi('achievement', Achievement, exitKey),
new GameUi('bgm', Bgm, exitKey),
new GameUi('start', Start)
// todo: 把游戏主 div 加入到 mainUi 里面
);
export const fixedUi = new UiController(true);
fixedUi.register(
new GameUi('statusBar', StatusBar),
new GameUi('markedEnemy', Mark),
new GameUi('fixed', Fixed),
new GameUi('chapter', Chapter),
new GameUi('completeAchi', CompleteAchi)
);