mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-31 23:29:27 +08:00
refactor: 移动 & 按键微调
This commit is contained in:
parent
433c4580fe
commit
b0f9e9d17d
@ -900,6 +900,7 @@ control.prototype._moveHero_moving = function () {
|
||||
// ------ 我已经看不懂这个函数了,反正好用就行23333333
|
||||
core.status.heroStop = false;
|
||||
core.status.automaticRoute.moveDirectly = false;
|
||||
|
||||
var move = function () {
|
||||
if (!core.status.heroStop) {
|
||||
if (core.hasFlag('debug') && core.status.ctrlDown) {
|
||||
|
@ -69,6 +69,7 @@ import { Camera } from './render/camera';
|
||||
import { Image, Text } from './render/preset/misc';
|
||||
import { RenderItem } from './render/item';
|
||||
import { texture } from './render/cache';
|
||||
import { RenderAdapter } from './render/adapter';
|
||||
|
||||
// ----- 类注册
|
||||
Mota.register('class', 'AudioPlayer', AudioPlayer);
|
||||
@ -154,7 +155,8 @@ Mota.register('module', 'Render', {
|
||||
Camera,
|
||||
Text,
|
||||
Image,
|
||||
RenderItem
|
||||
RenderItem,
|
||||
RenderAdapter
|
||||
});
|
||||
|
||||
main.renderLoaded = true;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { KeyCode } from '@/plugin/keyCodes';
|
||||
import { deleteWith, generateBinary, spliceBy } from '@/plugin/utils';
|
||||
import { deleteWith, generateBinary, keycode, spliceBy } from '@/plugin/utils';
|
||||
import { EventEmitter } from '../../common/eventEmitter';
|
||||
|
||||
// todo: 按下时触发,长按(单次/连续)触发,按下连续触发,按下节流触发,按下加速节流触发
|
||||
@ -9,7 +9,13 @@ interface HotkeyEvent {
|
||||
emit: (key: KeyCode, assist: number, type: KeyEmitType) => void;
|
||||
}
|
||||
|
||||
type KeyEmitType = 'down' | 'up';
|
||||
type KeyEmitType =
|
||||
| 'down'
|
||||
| 'up'
|
||||
| 'down-repeat'
|
||||
| 'down-throttle'
|
||||
| 'down-accelerate'
|
||||
| 'down-timeout';
|
||||
|
||||
interface AssistHoykey {
|
||||
ctrl: boolean;
|
||||
@ -44,6 +50,13 @@ export interface HotkeyJSON {
|
||||
assist: number;
|
||||
}
|
||||
|
||||
export interface HotkeyEmitConfig {
|
||||
type: KeyEmitType;
|
||||
throttle?: number;
|
||||
accelerate?: number;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
export class Hotkey extends EventEmitter<HotkeyEvent> {
|
||||
static list: Hotkey[];
|
||||
|
||||
@ -51,6 +64,8 @@ export class Hotkey extends EventEmitter<HotkeyEvent> {
|
||||
name: string;
|
||||
data: Record<string, HotkeyData> = {};
|
||||
keyMap: Map<KeyCode, HotkeyData[]> = new Map();
|
||||
/** 每个指令的配置信息 */
|
||||
configData: Map<string, HotkeyEmitConfig> = new Map();
|
||||
/** id to name */
|
||||
groupName: Record<string, string> = {
|
||||
none: '未分类按键'
|
||||
@ -102,8 +117,9 @@ export class Hotkey extends EventEmitter<HotkeyEvent> {
|
||||
* 实现一个按键按下时的操作
|
||||
* @param id 要实现的按键id,可以不包含数字后缀
|
||||
* @param func 按键按下时执行的函数
|
||||
* @param config 按键触发配置,默认为按键抬起时触发
|
||||
*/
|
||||
realize(id: string, func: HotkeyFunc) {
|
||||
realize(id: string, func: HotkeyFunc, config?: HotkeyEmitConfig) {
|
||||
const toSet = Object.values(this.data).filter(v => {
|
||||
const split = v.id.split('_');
|
||||
const last = !isNaN(Number(split.at(-1)));
|
||||
@ -175,6 +191,7 @@ export class Hotkey extends EventEmitter<HotkeyEvent> {
|
||||
* 触发一个按键
|
||||
* @param key 要触发的按键
|
||||
* @param assist 辅助按键,三位二进制数据,从低到高依次为`ctrl` `shift` `alt`
|
||||
* @returns 是否有按键被触发
|
||||
*/
|
||||
emitKey(
|
||||
key: KeyCode,
|
||||
@ -209,10 +226,11 @@ export class Hotkey extends EventEmitter<HotkeyEvent> {
|
||||
* @param id 组的id
|
||||
* @param name 组的名称
|
||||
*/
|
||||
group(id: string, name: string) {
|
||||
group(id: string, name: string, keys?: RegisterHotkeyData[]) {
|
||||
this.grouping = id;
|
||||
this.groupName[id] = name;
|
||||
this.groups[id] ??= [];
|
||||
keys?.forEach(v => this.register(v));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -272,6 +290,22 @@ export class Hotkey extends EventEmitter<HotkeyEvent> {
|
||||
}
|
||||
}
|
||||
|
||||
// todo
|
||||
/**
|
||||
* 热键控制器,用于控制按下时触发等操作
|
||||
*/
|
||||
export class HotkeyController {
|
||||
/** 所有按下的按键 */
|
||||
private pressed: Set<KeyCode> = new Set();
|
||||
|
||||
/** 当前控制器管理的热键实例 */
|
||||
hotkey: Hotkey;
|
||||
|
||||
constructor(hotkey: Hotkey) {
|
||||
this.hotkey = hotkey;
|
||||
}
|
||||
}
|
||||
|
||||
export function unwarpBinary(bin: number): AssistHoykey {
|
||||
return {
|
||||
ctrl: !!(bin & (1 << 0)),
|
||||
@ -293,3 +327,67 @@ export function checkAssist(bin: number, key: KeyCode) {
|
||||
export function isAssist(key: KeyCode) {
|
||||
return key === KeyCode.Ctrl || key === KeyCode.Shift || key === KeyCode.Alt;
|
||||
}
|
||||
|
||||
export const gameKey = new Hotkey('gameKey', '游戏按键');
|
||||
|
||||
// ----- Listening
|
||||
document.addEventListener('keyup', e => {
|
||||
const assist = generateBinary([e.ctrlKey, e.shiftKey, e.altKey]);
|
||||
const code = keycode(e.keyCode);
|
||||
if (gameKey.emitKey(code, assist, 'up', e)) {
|
||||
e.preventDefault();
|
||||
} else {
|
||||
// polyfill样板
|
||||
if (
|
||||
main.dom.startPanel.style.display == 'block' &&
|
||||
(main.dom.startButtons.style.display == 'block' ||
|
||||
main.dom.levelChooseButtons.style.display == 'block')
|
||||
) {
|
||||
if (e.keyCode == 38 || e.keyCode == 33)
|
||||
// up/pgup
|
||||
main.selectButton((main.selectedButton || 0) - 1);
|
||||
else if (e.keyCode == 40 || e.keyCode == 34)
|
||||
// down/pgdn
|
||||
main.selectButton((main.selectedButton || 0) + 1);
|
||||
else if (e.keyCode == 67 || e.keyCode == 13 || e.keyCode == 32)
|
||||
// C/Enter/Space
|
||||
main.selectButton(main.selectedButton);
|
||||
else if (
|
||||
e.keyCode == 27 &&
|
||||
main.dom.levelChooseButtons.style.display == 'block'
|
||||
) {
|
||||
// ESC
|
||||
core.showStartAnimate(true);
|
||||
e.preventDefault();
|
||||
}
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
if (main.dom.inputDiv.style.display == 'block') {
|
||||
if (e.keyCode == 13) {
|
||||
setTimeout(function () {
|
||||
main.dom.inputYes.click();
|
||||
}, 50);
|
||||
} else if (e.keyCode == 27) {
|
||||
setTimeout(function () {
|
||||
main.dom.inputNo.click();
|
||||
}, 50);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (
|
||||
core &&
|
||||
core.isPlaying &&
|
||||
core.status &&
|
||||
(core.isPlaying() || core.status.lockControl)
|
||||
)
|
||||
core.onkeyUp(e);
|
||||
}
|
||||
});
|
||||
document.addEventListener('keydown', e => {
|
||||
const assist = generateBinary([e.ctrlKey, e.shiftKey, e.altKey]);
|
||||
const code = keycode(e.keyCode);
|
||||
if (gameKey.emitKey(code, assist, 'down', e)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
@ -1,22 +1,42 @@
|
||||
import { KeyCode } from '@/plugin/keyCodes';
|
||||
import { Hotkey, HotkeyJSON } from '../custom/hotkey';
|
||||
import {
|
||||
generateBinary,
|
||||
keycode,
|
||||
openDanmakuPoster,
|
||||
tip
|
||||
} from '@/plugin/utils';
|
||||
import { gameKey, HotkeyJSON } from '../custom/hotkey';
|
||||
import { openDanmakuPoster, tip } from '@/plugin/utils';
|
||||
import { hovered } from './fixed';
|
||||
import { hasMarkedEnemy, markEnemy, unmarkEnemy } from '@/plugin/mark';
|
||||
import { mainUi } from './ui';
|
||||
import { GameStorage } from '../storage';
|
||||
|
||||
export const mainScope = Symbol.for('@key_main');
|
||||
export const gameKey = new Hotkey('gameKey', '游戏按键');
|
||||
|
||||
// todo: 读取上一个手动存档,存档至下一个存档栏
|
||||
// ----- Register
|
||||
gameKey
|
||||
// --------------------
|
||||
.group('game', '游戏按键')
|
||||
.register({
|
||||
id: 'moveUp',
|
||||
type: 'down',
|
||||
name: '上移',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: 'moveDown',
|
||||
type: 'down',
|
||||
name: '下移',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: 'moveLeft',
|
||||
type: 'down',
|
||||
name: '左移',
|
||||
defaults: KeyCode.LeftArrow
|
||||
})
|
||||
.register({
|
||||
id: 'moveRight',
|
||||
type: 'down',
|
||||
name: '右移',
|
||||
defaults: KeyCode.RightArrow
|
||||
})
|
||||
// --------------------
|
||||
.group('ui', 'ui界面')
|
||||
.register({
|
||||
@ -580,65 +600,3 @@ gameKey.on('set', (id, key, assist) => {
|
||||
keyStorage.setValue(id, { key, assist });
|
||||
});
|
||||
gameKey.fromJSON(keyStorage.toJSON());
|
||||
|
||||
// ----- Listening
|
||||
document.addEventListener('keyup', e => {
|
||||
const assist = generateBinary([e.ctrlKey, e.shiftKey, e.altKey]);
|
||||
const code = keycode(e.keyCode);
|
||||
if (gameKey.emitKey(code, assist, 'up', e)) {
|
||||
e.preventDefault();
|
||||
} else {
|
||||
// polyfill样板
|
||||
if (
|
||||
main.dom.startPanel.style.display == 'block' &&
|
||||
(main.dom.startButtons.style.display == 'block' ||
|
||||
main.dom.levelChooseButtons.style.display == 'block')
|
||||
) {
|
||||
if (e.keyCode == 38 || e.keyCode == 33)
|
||||
// up/pgup
|
||||
main.selectButton((main.selectedButton || 0) - 1);
|
||||
else if (e.keyCode == 40 || e.keyCode == 34)
|
||||
// down/pgdn
|
||||
main.selectButton((main.selectedButton || 0) + 1);
|
||||
else if (e.keyCode == 67 || e.keyCode == 13 || e.keyCode == 32)
|
||||
// C/Enter/Space
|
||||
main.selectButton(main.selectedButton);
|
||||
else if (
|
||||
e.keyCode == 27 &&
|
||||
main.dom.levelChooseButtons.style.display == 'block'
|
||||
) {
|
||||
// ESC
|
||||
core.showStartAnimate(true);
|
||||
e.preventDefault();
|
||||
}
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
if (main.dom.inputDiv.style.display == 'block') {
|
||||
if (e.keyCode == 13) {
|
||||
setTimeout(function () {
|
||||
main.dom.inputYes.click();
|
||||
}, 50);
|
||||
} else if (e.keyCode == 27) {
|
||||
setTimeout(function () {
|
||||
main.dom.inputNo.click();
|
||||
}, 50);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (
|
||||
core &&
|
||||
core.isPlaying &&
|
||||
core.status &&
|
||||
(core.isPlaying() || core.status.lockControl)
|
||||
)
|
||||
core.onkeyUp(e);
|
||||
}
|
||||
});
|
||||
document.addEventListener('keydown', e => {
|
||||
const assist = generateBinary([e.ctrlKey, e.shiftKey, e.altKey]);
|
||||
const code = keycode(e.keyCode);
|
||||
if (gameKey.emitKey(code, assist, 'down', e)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
type AdapterFunction<T> = (item: T, ...params: any[]) => Promise<any>;
|
||||
type SyncAdapterFunction<T> = (item: T, ...params: any[]) => any;
|
||||
|
||||
/**
|
||||
* 渲染适配器,用作渲染层与数据层沟通的桥梁,用于在数据层等待渲染层执行,常用与动画等。
|
||||
@ -14,6 +15,7 @@ export class RenderAdapter<T> {
|
||||
id: string;
|
||||
|
||||
private execute: Map<string, AdapterFunction<T>> = new Map();
|
||||
private syncExecutes: Map<string, SyncAdapterFunction<T>> = new Map();
|
||||
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
@ -42,6 +44,14 @@ export class RenderAdapter<T> {
|
||||
this.execute.set(id, fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置同步执行函数
|
||||
* @param fn 对于每个元素执行的函数
|
||||
*/
|
||||
recieveSync(id: string, fn: SyncAdapterFunction<T>): void {
|
||||
this.syncExecutes.set(id, fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对所有元素执行函数,当所有元素都运行完毕后兑现,类似于Promise.all
|
||||
* @returns 包含每个元素运行结果的数组
|
||||
@ -72,6 +82,19 @@ export class RenderAdapter<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对所有元素执行同步函数
|
||||
* @returns 包含每个元素运行结果的数组
|
||||
*/
|
||||
syncAll<R = any>(fn: string, ...params: any[]): R[] {
|
||||
const execute = this.syncExecutes.get(fn);
|
||||
if (!execute) {
|
||||
return [];
|
||||
} else {
|
||||
return [...this.items].map(v => execute!(v, ...params));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁这个adapter
|
||||
*/
|
||||
|
@ -77,14 +77,19 @@ class TextureCache extends EventEmitter<TextureCacheEvent> {
|
||||
/** 自动元件额外连接信息,用于对非自身图块进行连接 */
|
||||
autoConn: Map<number, Set<number>> = new Map();
|
||||
/** 行走图朝向绑定 */
|
||||
characterDirection: Record<Dir, number> = {
|
||||
characterDirection: Record<Dir2, number> = {
|
||||
down: 0,
|
||||
left: 1,
|
||||
right: 2,
|
||||
up: 3
|
||||
up: 3,
|
||||
leftup: 1,
|
||||
leftdown: 1,
|
||||
rightup: 2,
|
||||
rightdown: 2
|
||||
};
|
||||
/** 行走图转向顺序 */
|
||||
characterTurn: Dir[] = ['up', 'right', 'down', 'left'];
|
||||
characterTurn2: Dir2[] = ['leftup', 'rightup', 'rightdown', 'leftdown'];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -45,7 +45,7 @@ export class HeroRenderer
|
||||
/** 上一次帧数切换的时间 */
|
||||
private lastFrameTime: number = 0;
|
||||
/** 当前的移动方向 */
|
||||
private moveDir: Move = 'down';
|
||||
private moveDir: Move2 = 'down';
|
||||
/** 上一步走到格子上的时间 */
|
||||
private lastStepTime: number = 0;
|
||||
/** 是否已经执行了当前步移动 */
|
||||
@ -54,11 +54,11 @@ export class HeroRenderer
|
||||
* 这一步的移动方向,与{@link moveDir}不同的是,在这一步走完之前,它都不会变,
|
||||
* 当这一步走完之后,才会将其设置为{@link moveDir}的值
|
||||
*/
|
||||
private stepDir: Dir = 'down';
|
||||
private stepDir: Dir2 = 'down';
|
||||
/** 每步的格子增量 */
|
||||
private stepDelta: Loc = { x: 0, y: 1 };
|
||||
/** 动画显示的方向,用于适配后退 */
|
||||
private animateDir: Dir = 'down';
|
||||
// private animateDir: Dir = 'down';
|
||||
|
||||
/**
|
||||
* 设置勇士所用的图片资源
|
||||
@ -105,9 +105,9 @@ export class HeroRenderer
|
||||
* 根据方向获取勇士的裁切信息
|
||||
* @param dir 方向
|
||||
*/
|
||||
getRenderFromDir(dir: Move): [number, number, number, number][] {
|
||||
getRenderFromDir(dir: Move2): [number, number, number, number][] {
|
||||
if (!this.cellWidth || !this.cellHeight) return [];
|
||||
let resolved: Dir;
|
||||
let resolved: Dir2;
|
||||
if (dir === 'forward') resolved = this.dir;
|
||||
else if (dir === 'backward') resolved = backDir(this.dir);
|
||||
else resolved = dir;
|
||||
@ -157,6 +157,8 @@ export class HeroRenderer
|
||||
if (progress >= 1) {
|
||||
this.renderable.x = x + dx;
|
||||
this.renderable.y = y + dy;
|
||||
console.log(x, y, dx, dy, this.renderable.x, this.renderable.y);
|
||||
|
||||
this.emit('stepEnd');
|
||||
} else {
|
||||
const rx = dx * progress + x;
|
||||
@ -175,14 +177,14 @@ export class HeroRenderer
|
||||
if (this.moveDir === 'backward') this.stepDir = backDir(this.stepDir);
|
||||
else if (this.moveDir !== 'forward') this.stepDir = this.moveDir;
|
||||
this.lastStepTime = Date.now();
|
||||
this.stepDelta = core.utils.scan[this.stepDir];
|
||||
this.stepDelta = core.utils.scan2[this.stepDir];
|
||||
this.turn(this.stepDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动勇士
|
||||
*/
|
||||
move(dir: Move): Promise<void> {
|
||||
move(dir: Move2): Promise<void> {
|
||||
if (this.status !== 'moving') {
|
||||
logger.error(
|
||||
12,
|
||||
@ -225,12 +227,19 @@ export class HeroRenderer
|
||||
* 勇士转向,不填表示顺时针转一个方向
|
||||
* @param dir 移动方向
|
||||
*/
|
||||
turn(dir?: Dir): void {
|
||||
turn(dir?: Dir2): void {
|
||||
if (!dir) {
|
||||
const index = texture.characterTurn.indexOf(this.stepDir) + 1;
|
||||
const index = texture.characterTurn2.indexOf(this.stepDir);
|
||||
if (index === -1) {
|
||||
const length = texture.characterTurn.length;
|
||||
const index = texture.characterTurn.indexOf(
|
||||
this.stepDir as Dir
|
||||
);
|
||||
const next = texture.characterTurn[index % length];
|
||||
return this.turn(next);
|
||||
} else {
|
||||
return this.turn(texture.characterTurn[index]);
|
||||
}
|
||||
}
|
||||
this.moveDir = dir;
|
||||
if (!this.renderable) return;
|
||||
@ -333,3 +342,7 @@ adapter.recieve(
|
||||
return item.moveAs(x, y, time, fn);
|
||||
}
|
||||
);
|
||||
adapter.recieve('setMoveSpeed', (item, speed: number) => {
|
||||
item.setMoveSpeed(speed);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
@ -163,16 +163,16 @@ Mota.require('var', 'hook').once('reset', () => {
|
||||
layer.requestAfterFrame(() => {
|
||||
hero.setImage(core.material.images.images['hero2.png']);
|
||||
});
|
||||
hero.readyMove();
|
||||
layer.delegateTicker(
|
||||
() => {
|
||||
hero.move('right');
|
||||
},
|
||||
10000,
|
||||
() => {
|
||||
hero.endMove();
|
||||
}
|
||||
);
|
||||
// hero.readyMove();
|
||||
// layer.delegateTicker(
|
||||
// () => {
|
||||
// hero.move('right');
|
||||
// },
|
||||
// 10000,
|
||||
// () => {
|
||||
// hero.endMove();
|
||||
// }
|
||||
// );
|
||||
|
||||
camera.move(240, 240);
|
||||
render.update();
|
||||
|
@ -27,7 +27,6 @@ import type { Danmaku } from '@/core/main/custom/danmaku';
|
||||
import type * as misc from './mechanism/misc';
|
||||
import type { MotaCanvas2D } from '@/core/fx/canvas2d';
|
||||
import type * as portal from '@/core/fx/portal';
|
||||
import type { HeroRenderer } from '@/core/render/hero';
|
||||
import type { texture } from '@/core/render/cache';
|
||||
import type { MotaRenderer } from '@/core/render/render';
|
||||
import type { Container } from '@/core/render/container';
|
||||
@ -35,6 +34,7 @@ import type { Sprite } from '@/core/render/sprite';
|
||||
import type { Camera } from '@/core/render/camera';
|
||||
import type { Image, Text } from '@/core/render/preset/misc';
|
||||
import type { RenderItem } from '@/core/render/item';
|
||||
import type { RenderAdapter } from '@/core/render/adapter';
|
||||
|
||||
interface ClassInterface {
|
||||
// 渲染进程与游戏进程通用
|
||||
@ -105,15 +105,15 @@ interface ModuleInterface {
|
||||
Portal: typeof portal;
|
||||
};
|
||||
Render: {
|
||||
heroRender: HeroRenderer;
|
||||
texture: typeof texture;
|
||||
MotaRenderer: MotaRenderer;
|
||||
Container: Container;
|
||||
Sprite: Sprite;
|
||||
Camera: Camera;
|
||||
Text: Text;
|
||||
Image: Image;
|
||||
RenderItem: RenderItem;
|
||||
MotaRenderer: typeof MotaRenderer;
|
||||
Container: typeof Container;
|
||||
Sprite: typeof Sprite;
|
||||
Camera: typeof Camera;
|
||||
Text: typeof Text;
|
||||
Image: typeof Image;
|
||||
RenderItem: typeof RenderItem;
|
||||
RenderAdapter: typeof RenderAdapter;
|
||||
};
|
||||
}
|
||||
|
||||
@ -166,12 +166,12 @@ interface PluginInterface {
|
||||
|
||||
interface PackageInterface {
|
||||
axios: typeof import('axios');
|
||||
'chart.js': typeof import('chart.js');
|
||||
// 'chart.js': typeof import('chart.js');
|
||||
jszip: typeof import('jszip');
|
||||
lodash: typeof import('lodash-es');
|
||||
'lz-string': typeof import('lz-string');
|
||||
'mutate-animate': typeof import('mutate-animate');
|
||||
vue: typeof import('vue');
|
||||
// vue: typeof import('vue');
|
||||
}
|
||||
|
||||
export interface IMota {
|
||||
|
203
src/plugin/game/fallback.ts
Normal file
203
src/plugin/game/fallback.ts
Normal file
@ -0,0 +1,203 @@
|
||||
import type { RenderAdapter } from '@/core/render/adapter';
|
||||
import type { HeroRenderer } from '@/core/render/preset/hero';
|
||||
import { backDir } from './utils';
|
||||
|
||||
interface Adapters {
|
||||
'hero-adapter'?: RenderAdapter<HeroRenderer>;
|
||||
}
|
||||
|
||||
const adapters: Adapters = {};
|
||||
|
||||
export function init() {
|
||||
if (!main.replayChecking) {
|
||||
const Adapter = Mota.require('module', 'Render').RenderAdapter;
|
||||
const hero = Adapter.get<HeroRenderer>('hero-adapter');
|
||||
|
||||
adapters['hero-adapter'] = hero;
|
||||
}
|
||||
|
||||
function onMoveEnd(callback?: () => void) {
|
||||
core.setHeroLoc('x', core.nextX(), true);
|
||||
core.setHeroLoc('y', core.nextY(), true);
|
||||
|
||||
var direction = core.getHeroLoc('direction');
|
||||
core.control._moveAction_popAutomaticRoute();
|
||||
core.status.route.push(direction);
|
||||
|
||||
core.moveOneStep();
|
||||
core.checkRouteFolding();
|
||||
callback?.();
|
||||
}
|
||||
|
||||
// ----- 勇士移动相关
|
||||
|
||||
control.prototype._moveAction_moving = function (callback?: () => void) {
|
||||
const adapter = adapters['hero-adapter'];
|
||||
if (!adapter) {
|
||||
onMoveEnd(callback);
|
||||
return;
|
||||
} else {
|
||||
adapter
|
||||
.all('readyMove')
|
||||
.then(() => {
|
||||
return adapter.all('move', 'forward');
|
||||
})
|
||||
.then(() => {
|
||||
onMoveEnd(callback);
|
||||
return adapter.all('endMove');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const dir8to4: Record<Dir2, Dir> = {
|
||||
up: 'up',
|
||||
down: 'down',
|
||||
left: 'left',
|
||||
right: 'right',
|
||||
leftup: 'left',
|
||||
leftdown: 'left',
|
||||
rightup: 'right',
|
||||
rightdown: 'right'
|
||||
};
|
||||
|
||||
events.prototype.eventMoveHero = async function (
|
||||
steps: string[],
|
||||
time?: number,
|
||||
callback?: () => void
|
||||
) {
|
||||
time = time || core.values.moveSpeed;
|
||||
|
||||
// const render = Mota.require('module', 'Render').heroRender;
|
||||
var step = 0,
|
||||
moveSteps = (steps || [])
|
||||
.map(function (t) {
|
||||
return [t.split(':')[0], parseInt(t.split(':')[1] || '1')];
|
||||
})
|
||||
.filter(function (t) {
|
||||
return (
|
||||
[
|
||||
'up',
|
||||
'down',
|
||||
'left',
|
||||
'right',
|
||||
'forward',
|
||||
'backward',
|
||||
'leftup',
|
||||
'leftdown',
|
||||
'rightup',
|
||||
'rightdown',
|
||||
'speed'
|
||||
// @ts-ignore
|
||||
].indexOf(t[0]) >= 0 && !(t[0] == 'speed' && t[1] < 16)
|
||||
);
|
||||
});
|
||||
|
||||
if (main.replayChecking) {
|
||||
// 录像验证中,直接算出来最终位置瞬移过去即可
|
||||
const steps = moveSteps;
|
||||
let { x: nx, y: ny, direction: nowDir } = core.status.hero.loc;
|
||||
while (steps.length > 0) {
|
||||
const [dir, count] = steps.shift()! as [string, number];
|
||||
if (dir === 'speed') continue;
|
||||
let resolved: Dir2;
|
||||
if (dir === 'forward' || dir === 'backward') resolved = nowDir;
|
||||
else resolved = dir as Dir2;
|
||||
|
||||
nowDir = dir8to4[resolved];
|
||||
|
||||
const { x, y } = core.utils.scan2[resolved];
|
||||
nx += x * count;
|
||||
ny += y * count;
|
||||
}
|
||||
core.setHeroLoc('x', nx, true);
|
||||
core.setHeroLoc('y', ny, true);
|
||||
core.setHeroLoc('direction', nowDir, true);
|
||||
core.updateFollowers();
|
||||
core.status.heroMoving = 0;
|
||||
core.drawHero();
|
||||
callback?.();
|
||||
} else {
|
||||
const adapter = adapters['hero-adapter'];
|
||||
if (!adapter) return;
|
||||
const steps: string[] = [];
|
||||
moveSteps.forEach(([dir, count]) => {
|
||||
if (dir === 'speed') {
|
||||
steps.push(`speed:${count}`);
|
||||
} else {
|
||||
steps.push(...Array(count as number).fill(dir as string));
|
||||
}
|
||||
});
|
||||
await adapter.all('readyMove');
|
||||
for (const dir of steps) {
|
||||
if (dir.startsWith('speed')) {
|
||||
const speed = parseInt(dir.slice(6));
|
||||
await adapter.all('setMoveSpeed', speed);
|
||||
} else {
|
||||
await adapter.all('move', dir as Move2);
|
||||
}
|
||||
}
|
||||
await adapter.all('endMove');
|
||||
core.status.heroMoving = 0;
|
||||
core.drawHero();
|
||||
callback?.();
|
||||
}
|
||||
// core.status.heroMoving = -1;
|
||||
// // render.move(false);
|
||||
// var _run = function () {
|
||||
// var cb = function () {
|
||||
// core.status.heroMoving = 0;
|
||||
// // render.move(false);
|
||||
// core.drawHero();
|
||||
// if (callback) callback();
|
||||
// };
|
||||
|
||||
// var animate = window.setInterval(
|
||||
// function () {
|
||||
// if (moveSteps.length == 0) {
|
||||
// delete core.animateFrame.asyncId[animate];
|
||||
// clearInterval(animate);
|
||||
// cb();
|
||||
// } else {
|
||||
// if (
|
||||
// step == 0 &&
|
||||
// moveSteps[0][0] == 'speed' &&
|
||||
// moveSteps[0][1] >= 16
|
||||
// ) {
|
||||
// time = moveSteps[0][1];
|
||||
// moveSteps.shift();
|
||||
// clearInterval(animate);
|
||||
// delete core.animateFrame.asyncId[animate];
|
||||
// _run();
|
||||
// } else if (
|
||||
// core.events._eventMoveHero_moving(++step, moveSteps)
|
||||
// )
|
||||
// step = 0;
|
||||
// }
|
||||
// },
|
||||
// core.status.replay.speed == 24
|
||||
// ? 1
|
||||
// : time / 8 / core.status.replay.speed
|
||||
// );
|
||||
|
||||
// core.animateFrame.lastAsyncId = animate;
|
||||
// core.animateFrame.asyncId[animate] = cb;
|
||||
// };
|
||||
// _run();
|
||||
};
|
||||
|
||||
control.prototype.turnHero = function (direction?: Dir) {
|
||||
if (direction) {
|
||||
core.setHeroLoc('direction', direction);
|
||||
core.drawHero();
|
||||
core.status.route.push('turn:' + direction);
|
||||
return;
|
||||
}
|
||||
core.setHeroLoc('direction', core.turnDirection(':right') as Dir);
|
||||
core.drawHero();
|
||||
core.status.route.push('turn');
|
||||
core.checkRouteFolding();
|
||||
if (!main.replayChecking) {
|
||||
adapters['hero-adapter']?.all('turn', direction);
|
||||
}
|
||||
};
|
||||
}
|
@ -16,6 +16,7 @@ import * as utils from './utils';
|
||||
import * as chase from './chase';
|
||||
import * as remainEnemy from './enemy/remainEnemy';
|
||||
import * as checkBlock from './enemy/checkblock';
|
||||
import * as fallback from './fallback';
|
||||
import './hook';
|
||||
|
||||
Mota.Plugin.register('utils_g', utils);
|
||||
@ -37,6 +38,8 @@ Mota.Plugin.register('remainEnemy_g', remainEnemy);
|
||||
Mota.Plugin.register('checkBlock_g', checkBlock, checkBlock.init);
|
||||
// todo: 这几个不应该放到插件
|
||||
Mota.Plugin.register('ui_g', ui, ui.init);
|
||||
// 用于暂时向后兼容的插件,若干个版本后会删除
|
||||
Mota.Plugin.register('fallback_g', fallback, fallback.init);
|
||||
|
||||
// export {
|
||||
// halo,
|
||||
|
@ -17,13 +17,19 @@ export function slide<T>(arr: T[], delta: number): T[] {
|
||||
return arr;
|
||||
}
|
||||
|
||||
export function backDir(dir: Dir): Dir {
|
||||
return {
|
||||
const backDirMap: Record<Dir2, Dir2> = {
|
||||
up: 'down',
|
||||
down: 'up',
|
||||
left: 'right',
|
||||
right: 'left'
|
||||
}[dir] as Dir;
|
||||
right: 'left',
|
||||
leftup: 'rightdown',
|
||||
rightup: 'leftdown',
|
||||
leftdown: 'rightup',
|
||||
rightdown: 'leftup'
|
||||
};
|
||||
|
||||
export function backDir(dir: Dir2): Dir2 {
|
||||
return backDirMap[dir];
|
||||
}
|
||||
|
||||
export function has<T>(v: T): v is NonNullable<T> {
|
||||
|
1
src/types/control.d.ts
vendored
1
src/types/control.d.ts
vendored
@ -1092,6 +1092,7 @@ interface Control {
|
||||
offset: Loc & { offset: number },
|
||||
frame?: number
|
||||
): void;
|
||||
_moveAction_popAutomaticRoute(): void;
|
||||
}
|
||||
|
||||
declare const control: new () => Control;
|
||||
|
2
src/types/util.d.ts
vendored
2
src/types/util.d.ts
vendored
@ -604,6 +604,8 @@ type TextPosition = 'up' | 'center' | 'down';
|
||||
*/
|
||||
type Move = 'forward' | 'backward' | Dir;
|
||||
|
||||
type Move2 = Move | Dir2;
|
||||
|
||||
/**
|
||||
* 缓动模式,不过在高级动画插件面前不堪一击(
|
||||
*/
|
||||
|
@ -48,7 +48,7 @@ import { LeftOutlined } from '@ant-design/icons-vue';
|
||||
import { ToShowEnemy, detailInfo } from '../plugin/ui/book';
|
||||
import { getDetailedEnemy } from '../plugin/ui/fixed';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
import { mainSetting } from '@/core/main/setting';
|
||||
import { isMobile } from '@/plugin/use';
|
||||
|
@ -83,7 +83,7 @@ import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
|
||||
import EnemyCritical from '../panel/enemyCritical.vue';
|
||||
import EnemyTarget from '../panel/enemyTarget.vue';
|
||||
import { detailInfo } from '../plugin/ui/book';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
|
||||
const props = defineProps<{
|
||||
fromBook?: boolean;
|
||||
|
@ -163,7 +163,7 @@ import { GameUi } from '@/core/main/custom/ui';
|
||||
import { sleep } from 'mutate-animate';
|
||||
import { fixedUi } from '@/core/main/init/ui';
|
||||
import { calStringSize, tip } from '@/plugin/utils';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { isNil } from 'lodash-es';
|
||||
import { stringifyCSS, parseCss, getIconHeight } from '@/plugin/utils';
|
||||
import { logger, LogLevel } from '@/core/common/logger';
|
||||
|
@ -23,7 +23,7 @@ import desc from '../data/desc.json';
|
||||
import { splitText } from '../plugin/utils';
|
||||
import Colomn from '../components/colomn.vue';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -195,7 +195,7 @@ import { has, tip, type } from '../plugin/utils';
|
||||
import { cancelGlobalDrag, isMobile, useDrag } from '../plugin/use';
|
||||
import { hyper } from 'mutate-animate';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { getStatusLabel } from '../plugin/utils';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
|
@ -100,7 +100,7 @@ import {
|
||||
import { debounce } from 'lodash-es';
|
||||
import { tip } from '../plugin/utils';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { createChangable } from '@/plugin/ui/common';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
import { mainSetting } from '@/core/main/setting';
|
||||
|
@ -44,7 +44,7 @@ import { computed, onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
import { KeyCode, KeyCodeUtils } from '@/plugin/keyCodes';
|
||||
import { generateBinary, keycode } from '@/plugin/utils';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
|
||||
interface HotkeyKeys {
|
||||
index: number;
|
||||
|
@ -84,7 +84,7 @@ import { RightOutlined, LeftOutlined } from '@ant-design/icons-vue';
|
||||
import { splitText } from '../plugin/utils';
|
||||
import Scroll from '../components/scroll.vue';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
|
@ -173,7 +173,7 @@ import { splitText, tip } from '../plugin/utils';
|
||||
import Scroll from '../components/scroll.vue';
|
||||
import BoxAnimate from '../components/boxAnimate.vue';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -84,7 +84,7 @@ import Scroll from '../components/scroll.vue';
|
||||
import { has, splitText, tip } from '../plugin/utils';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import { sleep } from 'mutate-animate';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
|
@ -69,7 +69,7 @@ import { doByInterval, keycode } from '../plugin/utils';
|
||||
import { triggerFullscreen } from '../plugin/utils';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
import { CustomToolbar } from '@/core/main/custom/toolbar';
|
||||
import { mainSetting } from '@/core/main/setting';
|
||||
|
@ -116,9 +116,8 @@ import { isMobile } from '../plugin/use';
|
||||
import { type, keycode, has } from '../plugin/utils';
|
||||
import { hyper, sleep } from 'mutate-animate';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { KeyCode } from '../plugin/keyCodes';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
import { gameKey } from '@/core/main/custom/hotkey';
|
||||
import { mainUi } from '@/core/main/init/ui';
|
||||
|
||||
const props = defineProps<{
|
||||
|
Loading…
Reference in New Issue
Block a user