mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-11-27 13:42:58 +08:00
feat: 勇士移动兼容与修复
This commit is contained in:
parent
ac260e3ab3
commit
4f3154d497
@ -105,6 +105,8 @@ class TrackedAssetData
|
|||||||
|
|
||||||
private originSourceMap: Map<number, SizedCanvasImageSource> = new Map();
|
private originSourceMap: Map<number, SizedCanvasImageSource> = new Map();
|
||||||
|
|
||||||
|
private promises: Set<Promise<ImageBitmap>> = new Set();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly materials: IMaterialGetter,
|
readonly materials: IMaterialGetter,
|
||||||
readonly builder: AssetBuilder
|
readonly builder: AssetBuilder
|
||||||
@ -137,7 +139,10 @@ class TrackedAssetData
|
|||||||
this.sourceList.set(index, source);
|
this.sourceList.set(index, source);
|
||||||
this.skipRef.set(source, index);
|
this.skipRef.set(source, index);
|
||||||
} else {
|
} else {
|
||||||
const bitmap = await createImageBitmap(source);
|
const promise = createImageBitmap(source);
|
||||||
|
this.promises.add(promise);
|
||||||
|
const bitmap = await promise;
|
||||||
|
this.promises.delete(promise);
|
||||||
this.sourceList.set(index, bitmap);
|
this.sourceList.set(index, bitmap);
|
||||||
this.skipRef.set(bitmap, index);
|
this.skipRef.set(bitmap, index);
|
||||||
// 要把源也加到映射中,因为这里的 bitmap 与外部源并不同引用
|
// 要把源也加到映射中,因为这里的 bitmap 与外部源并不同引用
|
||||||
@ -146,5 +151,9 @@ class TrackedAssetData
|
|||||||
this.dirty(index);
|
this.dirty(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async then(): Promise<void> {
|
||||||
|
await Promise.all([...this.promises]);
|
||||||
|
}
|
||||||
|
|
||||||
close(): void {}
|
close(): void {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ export function createMaterial() {
|
|||||||
createAutotile();
|
createAutotile();
|
||||||
loading.once('loaded', () => {
|
loading.once('loaded', () => {
|
||||||
fallbackLoad();
|
fallbackLoad();
|
||||||
|
loading.emit('assetBuilt');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -442,6 +442,7 @@ export class MaterialManager implements IMaterialManager {
|
|||||||
store: this.assetStore
|
store: this.assetStore
|
||||||
};
|
};
|
||||||
this.checkAssetDirty(data);
|
this.checkAssetDirty(data);
|
||||||
|
texture.toAsset(data);
|
||||||
return assetData;
|
return assetData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,10 +568,10 @@ export class MaterialManager implements IMaterialManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assetContainsTexture(texture: ITexture): boolean {
|
assetContainsTexture(texture: ITexture): boolean {
|
||||||
return this.assetMap.has(texture);
|
return this.trackedAsset.skipRef.has(texture.source);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTextureAsset(texture: ITexture): number | undefined {
|
getTextureAsset(texture: ITexture): number | undefined {
|
||||||
return this.assetMap.get(texture);
|
return this.trackedAsset.skipRef.get(texture.source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -505,4 +505,9 @@ export interface ITrackedAssetData extends IDirtyTracker<Set<number>> {
|
|||||||
* 取消使用此图集,释放相关资源
|
* 取消使用此图集,释放相关资源
|
||||||
*/
|
*/
|
||||||
close(): void;
|
close(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 等待所有打包操作结束
|
||||||
|
*/
|
||||||
|
then(): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,21 @@
|
|||||||
import { state } from '@user/data-state';
|
import { state } from '@user/data-state';
|
||||||
import { MapRenderer } from './map/renderer';
|
|
||||||
import { materials } from '@user/client-base';
|
import { materials } from '@user/client-base';
|
||||||
|
import { MapRenderer, MapExtensionManager } from './map';
|
||||||
|
|
||||||
/** 主地图渲染器,用于渲染游戏画面 */
|
/** 主地图渲染器,用于渲染游戏画面 */
|
||||||
export const mainMapRenderer = new MapRenderer(materials, state.layer);
|
export const mainMapRenderer = new MapRenderer(materials, state.layer);
|
||||||
|
/** 主地图渲染器拓展 */
|
||||||
|
export const mainMapExtension = new MapExtensionManager(mainMapRenderer);
|
||||||
/** 副地图渲染器,用于渲染缩略图、浏览地图等 */
|
/** 副地图渲染器,用于渲染缩略图、浏览地图等 */
|
||||||
// export const expandMapRenderer = new MapRenderer(materials, state.layer);
|
// export const expandMapRenderer = new MapRenderer(materials, state.layer);
|
||||||
|
|
||||||
|
export async function createMainExtension() {
|
||||||
|
// 算是一种妥协吧,等之后加载系统重构之后应该会清晰很多
|
||||||
|
await materials.trackedAsset.then();
|
||||||
|
|
||||||
|
mainMapRenderer.useAsset(materials.trackedAsset);
|
||||||
|
const layer = state.layer.getLayerByAlias('event');
|
||||||
|
if (layer) {
|
||||||
|
mainMapExtension.addHero(state.hero, layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { createLegacy } from './legacy';
|
|||||||
import { sceneController } from './scene';
|
import { sceneController } from './scene';
|
||||||
import { GameTitleUI } from './ui/title';
|
import { GameTitleUI } from './ui/title';
|
||||||
import { createWeather } from './weather';
|
import { createWeather } from './weather';
|
||||||
|
import { createMainExtension } from './commonIns';
|
||||||
|
|
||||||
export function createGameRenderer() {
|
export function createGameRenderer() {
|
||||||
const App = defineComponent(_props => {
|
const App = defineComponent(_props => {
|
||||||
@ -33,11 +34,15 @@ export function createRender() {
|
|||||||
createLoopMap();
|
createLoopMap();
|
||||||
createWeather();
|
createWeather();
|
||||||
|
|
||||||
loading.on('loaded', () => {
|
loading.once('loaded', () => {
|
||||||
sceneController.open(GameTitleUI, {});
|
sceneController.open(GameTitleUI, {});
|
||||||
mainRenderer.show();
|
mainRenderer.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
loading.once('assetBuilt', () => {
|
||||||
|
createMainExtension();
|
||||||
|
});
|
||||||
|
|
||||||
hook.on('restart', () => {
|
hook.on('restart', () => {
|
||||||
sceneController.closeAll();
|
sceneController.closeAll();
|
||||||
sceneController.open(GameTitleUI, {});
|
sceneController.open(GameTitleUI, {});
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { MotaOffscreenCanvas2D, RenderItem } from '@motajs/render-core';
|
import { MotaOffscreenCanvas2D, RenderItem } from '@motajs/render-core';
|
||||||
import { ILayerState } from '@user/data-state';
|
import { ILayerState } from '@user/data-state';
|
||||||
import { IMapRenderer } from './types';
|
import { IMapRenderer } from './types';
|
||||||
import { materials } from '@user/client-base';
|
|
||||||
import { ElementNamespace, ComponentInternalInstance } from 'vue';
|
import { ElementNamespace, ComponentInternalInstance } from 'vue';
|
||||||
import { CELL_HEIGHT, CELL_WIDTH, MAP_HEIGHT, MAP_WIDTH } from '../shared';
|
import { CELL_HEIGHT, CELL_WIDTH, MAP_HEIGHT, MAP_WIDTH } from '../shared';
|
||||||
|
|
||||||
@ -14,10 +13,9 @@ export class MapRender extends RenderItem {
|
|||||||
readonly layerState: ILayerState,
|
readonly layerState: ILayerState,
|
||||||
readonly renderer: IMapRenderer
|
readonly renderer: IMapRenderer
|
||||||
) {
|
) {
|
||||||
super('static');
|
super('static', false, false);
|
||||||
|
|
||||||
this.renderer.setLayerState(layerState);
|
this.renderer.setLayerState(layerState);
|
||||||
this.renderer.useAsset(materials.trackedAsset);
|
|
||||||
this.renderer.setCanvasSize(this.width, this.height);
|
this.renderer.setCanvasSize(this.width, this.height);
|
||||||
this.renderer.setCellSize(CELL_WIDTH, CELL_HEIGHT);
|
this.renderer.setCellSize(CELL_WIDTH, CELL_HEIGHT);
|
||||||
this.renderer.setRenderSize(MAP_WIDTH, MAP_HEIGHT);
|
this.renderer.setRenderSize(MAP_WIDTH, MAP_HEIGHT);
|
||||||
|
|||||||
@ -127,7 +127,9 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
|||||||
if (!tex) {
|
if (!tex) {
|
||||||
return renderer.addMovingBlock(layer, 0, hero.x, hero.y);
|
return renderer.addMovingBlock(layer, 0, hero.x, hero.y);
|
||||||
}
|
}
|
||||||
return renderer.addMovingBlock(layer, tex, hero.x, hero.y);
|
const block = renderer.addMovingBlock(layer, tex, hero.x, hero.y);
|
||||||
|
block.useSpecifiedFrame(0);
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,23 +164,26 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
|||||||
|
|
||||||
private tick(time: number) {
|
private tick(time: number) {
|
||||||
this.entities.forEach(v => {
|
this.entities.forEach(v => {
|
||||||
if (!v.animating) {
|
if (v.animating) {
|
||||||
v.animateFrame = 0;
|
const dt = time - v.lastAnimateTime;
|
||||||
return;
|
if (dt > v.animateInterval) {
|
||||||
}
|
if (v.animateDirection === HeroAnimateDirection.Forward) {
|
||||||
const dt = time - v.lastAnimateTime;
|
v.animateFrame++;
|
||||||
if (dt > v.animateInterval) {
|
} else {
|
||||||
if (v.animateDirection === HeroAnimateDirection.Forward) {
|
v.animateFrame--;
|
||||||
v.animateFrame++;
|
if (v.animateFrame < 0) {
|
||||||
} else {
|
// 小于 0,则加上帧数的整数倍,就写个 10000 倍吧
|
||||||
v.animateFrame--;
|
v.animateFrame += v.block.texture.frames * 10000;
|
||||||
if (v.animateFrame < 0) {
|
}
|
||||||
// 小于 0,则加上帧数的整数倍,就写个 10000 倍吧
|
|
||||||
v.animateFrame += v.block.texture.frames * 10000;
|
|
||||||
}
|
}
|
||||||
|
v.lastAnimateTime = time;
|
||||||
|
v.block.useSpecifiedFrame(v.animateFrame);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (v.animateFrame !== 0) {
|
||||||
|
v.animateFrame = 0;
|
||||||
|
v.block.useSpecifiedFrame(0);
|
||||||
}
|
}
|
||||||
v.lastAnimateTime = time;
|
|
||||||
v.block.useSpecifiedFrame(v.animateFrame);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -221,14 +226,13 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
|||||||
const nextTex = this.renderer.manager.getIfBigImage(
|
const nextTex = this.renderer.manager.getIfBigImage(
|
||||||
nextTile?.identifier ?? block.tile
|
nextTile?.identifier ?? block.tile
|
||||||
);
|
);
|
||||||
|
entity.animateInterval = time;
|
||||||
entity.promise = entity.promise.then(async () => {
|
entity.promise = entity.promise.then(async () => {
|
||||||
entity.moving = true;
|
entity.moving = true;
|
||||||
entity.animating = true;
|
entity.animating = true;
|
||||||
entity.direction = direction;
|
entity.direction = direction;
|
||||||
if (nextTex) block.setTexture(nextTex);
|
if (nextTex) block.setTexture(nextTex);
|
||||||
await block.lineTo(tx, ty, time);
|
await block.lineTo(tx, ty, time);
|
||||||
entity.moving = false;
|
|
||||||
entity.animating = false;
|
|
||||||
entity.nextDirection = entity.direction;
|
entity.nextDirection = entity.direction;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -272,34 +276,41 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
|||||||
entity.animating = false;
|
entity.animating = false;
|
||||||
entity.animateFrame = 0;
|
entity.animateFrame = 0;
|
||||||
await block.moveRelative(fn, time);
|
await block.moveRelative(fn, time);
|
||||||
entity.moving = false;
|
|
||||||
entity.animating = false;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
startMove(): void {
|
startMove(): void {
|
||||||
this.heroEntity.moving = true;
|
this.heroEntity.moving = true;
|
||||||
this.heroEntity.animating = true;
|
this.heroEntity.animating = true;
|
||||||
this.heroEntity.animateFrame = 1;
|
|
||||||
this.heroEntity.lastAnimateTime = this.ticker.timestamp;
|
this.heroEntity.lastAnimateTime = this.ticker.timestamp;
|
||||||
this.heroEntity.block.useSpecifiedFrame(1);
|
this.heroEntity.block.useSpecifiedFrame(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private endEntityMoving(entity: HeroRenderEntity) {
|
||||||
|
entity.moving = false;
|
||||||
|
entity.animating = false;
|
||||||
|
entity.animateFrame = 0;
|
||||||
|
entity.block.useSpecifiedFrame(0);
|
||||||
|
}
|
||||||
|
|
||||||
async waitMoveEnd(waitFollower: boolean): Promise<void> {
|
async waitMoveEnd(waitFollower: boolean): Promise<void> {
|
||||||
if (waitFollower) {
|
if (waitFollower) {
|
||||||
await Promise.all(this.entities.map(v => v.promise));
|
await Promise.all(this.entities.map(v => v.promise));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return this.heroEntity.promise;
|
await this.heroEntity.promise;
|
||||||
|
this.entities.forEach(v => this.endEntityMoving(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
stopMove(stopFollower: boolean): void {
|
stopMove(stopFollower: boolean): void {
|
||||||
if (stopFollower) {
|
if (stopFollower) {
|
||||||
this.entities.forEach(v => {
|
this.entities.forEach(v => {
|
||||||
v.block.endMoving();
|
v.block.endMoving();
|
||||||
|
this.endEntityMoving(v);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.heroEntity.block.endMoving();
|
this.heroEntity.block.endMoving();
|
||||||
|
this.endEntityMoving(this.heroEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
export * from './hero';
|
export * from './hero';
|
||||||
|
export * from './manager';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
import { IHeroState, IMapLayer } from '@user/data-state';
|
||||||
|
import { IMapExtensionManager, IMapHeroRenderer } from './types';
|
||||||
|
import { IMapRenderer } from '../types';
|
||||||
|
import { MapHeroRenderer } from './hero';
|
||||||
|
import { logger } from '@motajs/common';
|
||||||
|
|
||||||
|
export class MapExtensionManager implements IMapExtensionManager {
|
||||||
|
/** 勇士状态至勇士渲染器的映射 */
|
||||||
|
readonly heroMap: WeakMap<IHeroState, IMapHeroRenderer> = new WeakMap();
|
||||||
|
|
||||||
|
constructor(readonly renderer: IMapRenderer) {}
|
||||||
|
|
||||||
|
addHero(state: IHeroState, layer: IMapLayer): void {
|
||||||
|
if (this.heroMap.has(state)) {
|
||||||
|
logger.error(45);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const heroRenderer = new MapHeroRenderer(this.renderer, layer, state);
|
||||||
|
this.heroMap.set(state, heroRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeHero(state: IHeroState): void {
|
||||||
|
const renderer = this.heroMap.get(state);
|
||||||
|
if (!renderer) return;
|
||||||
|
renderer.destroy();
|
||||||
|
this.heroMap.delete(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,25 @@
|
|||||||
import { ITexture } from '@motajs/render-assets';
|
import { ITexture } from '@motajs/render-assets';
|
||||||
import { FaceDirection, HeroAnimateDirection } from '@user/data-state';
|
import {
|
||||||
|
FaceDirection,
|
||||||
|
HeroAnimateDirection,
|
||||||
|
IHeroState,
|
||||||
|
IMapLayer
|
||||||
|
} from '@user/data-state';
|
||||||
|
|
||||||
|
export interface IMapExtensionManager {
|
||||||
|
/**
|
||||||
|
* 添加勇士渲染拓展
|
||||||
|
* @param state 勇士状态
|
||||||
|
* @param layer 勇士所在图层
|
||||||
|
*/
|
||||||
|
addHero(state: IHeroState, layer: IMapLayer): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除勇士渲染拓展
|
||||||
|
* @param state 勇士状态
|
||||||
|
*/
|
||||||
|
removeHero(state: IHeroState): void;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IMapHeroRenderer {
|
export interface IMapHeroRenderer {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
export * from './extension';
|
||||||
|
|
||||||
export * from './block';
|
export * from './block';
|
||||||
export * from './constant';
|
export * from './constant';
|
||||||
export * from './element';
|
export * from './element';
|
||||||
|
|||||||
@ -121,6 +121,7 @@ export class MovingBlock extends DynamicBlockStatus implements IMovingBlock {
|
|||||||
this.dy = y - this.y;
|
this.dy = y - this.y;
|
||||||
this.time = time;
|
this.time = time;
|
||||||
this.relative = false;
|
this.relative = false;
|
||||||
|
this.startTime = this.renderer.getTimestamp();
|
||||||
if (time === 0) {
|
if (time === 0) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
@ -142,6 +143,7 @@ export class MovingBlock extends DynamicBlockStatus implements IMovingBlock {
|
|||||||
this.relative = false;
|
this.relative = false;
|
||||||
this.startX = this.x;
|
this.startX = this.x;
|
||||||
this.startY = this.y;
|
this.startY = this.y;
|
||||||
|
this.startTime = this.renderer.getTimestamp();
|
||||||
if (time === 0) {
|
if (time === 0) {
|
||||||
const [tx, ty] = curve(1);
|
const [tx, ty] = curve(1);
|
||||||
this.x = tx;
|
this.x = tx;
|
||||||
@ -168,6 +170,7 @@ export class MovingBlock extends DynamicBlockStatus implements IMovingBlock {
|
|||||||
this.relative = false;
|
this.relative = false;
|
||||||
this.startX = this.x;
|
this.startX = this.x;
|
||||||
this.startY = this.y;
|
this.startY = this.y;
|
||||||
|
this.startTime = this.renderer.getTimestamp();
|
||||||
if (time === 0) {
|
if (time === 0) {
|
||||||
const [tx, ty] = curve(1);
|
const [tx, ty] = curve(1);
|
||||||
this.x = tx + this.startX;
|
this.x = tx + this.startX;
|
||||||
|
|||||||
@ -196,6 +196,9 @@ export class MapRenderer
|
|||||||
readonly manager: IMaterialManager,
|
readonly manager: IMaterialManager,
|
||||||
layerState: ILayerState
|
layerState: ILayerState
|
||||||
) {
|
) {
|
||||||
|
this.movingIndexPool.push(
|
||||||
|
...Array.from({ length: this.movingCount }, (_, i) => i).reverse()
|
||||||
|
);
|
||||||
this.canvas = document.createElement('canvas');
|
this.canvas = document.createElement('canvas');
|
||||||
this.gl = this.canvas.getContext('webgl2')!;
|
this.gl = this.canvas.getContext('webgl2')!;
|
||||||
this.transform = new Transform();
|
this.transform = new Transform();
|
||||||
@ -476,6 +479,7 @@ export class MapRenderer
|
|||||||
//#region 渲染设置
|
//#region 渲染设置
|
||||||
|
|
||||||
useAsset(asset: ITrackedAssetData): void {
|
useAsset(asset: ITrackedAssetData): void {
|
||||||
|
if (this.assetData === asset) return;
|
||||||
this.assetData = asset;
|
this.assetData = asset;
|
||||||
this.sortedLayers.forEach(v => {
|
this.sortedLayers.forEach(v => {
|
||||||
this.updateLayerArea(v, 0, 0, v.width, v.height);
|
this.updateLayerArea(v, 0, 0, v.width, v.height);
|
||||||
@ -483,6 +487,7 @@ export class MapRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
setRenderSize(width: number, height: number): void {
|
setRenderSize(width: number, height: number): void {
|
||||||
|
if (width === this.renderWidth && height === this.renderHeight) return;
|
||||||
this.renderWidth = width;
|
this.renderWidth = width;
|
||||||
this.renderHeight = height;
|
this.renderHeight = height;
|
||||||
this.sortedLayers.forEach(v => {
|
this.sortedLayers.forEach(v => {
|
||||||
@ -491,6 +496,7 @@ export class MapRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
setCellSize(width: number, height: number): void {
|
setCellSize(width: number, height: number): void {
|
||||||
|
if (width === this.cellWidth && height === this.cellHeight) return;
|
||||||
this.cellWidth = width;
|
this.cellWidth = width;
|
||||||
this.cellHeight = height;
|
this.cellHeight = height;
|
||||||
this.sortedLayers.forEach(v => {
|
this.sortedLayers.forEach(v => {
|
||||||
@ -544,6 +550,13 @@ export class MapRenderer
|
|||||||
const offset = data.texture.width / data.frames;
|
const offset = data.texture.width / data.frames;
|
||||||
pool.add(offset);
|
pool.add(offset);
|
||||||
}
|
}
|
||||||
|
// 还有勇士图片
|
||||||
|
for (const tex of this.manager.imageStore.values()) {
|
||||||
|
if (!this.manager.assetContainsTexture(tex)) continue;
|
||||||
|
const { w } = tex.render().rect;
|
||||||
|
pool.add(w / 4);
|
||||||
|
}
|
||||||
|
// 其他判断
|
||||||
if (pool.size > 64 && import.meta.env.DEV) {
|
if (pool.size > 64 && import.meta.env.DEV) {
|
||||||
logger.warn(82);
|
logger.warn(82);
|
||||||
}
|
}
|
||||||
@ -633,7 +646,7 @@ export class MapRenderer
|
|||||||
gl.disable(gl.CULL_FACE);
|
gl.disable(gl.CULL_FACE);
|
||||||
gl.enable(gl.DEPTH_TEST);
|
gl.enable(gl.DEPTH_TEST);
|
||||||
gl.enable(gl.BLEND);
|
gl.enable(gl.BLEND);
|
||||||
gl.depthFunc(gl.LESS);
|
gl.depthFunc(gl.LEQUAL);
|
||||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
const data: IContextData = {
|
const data: IContextData = {
|
||||||
@ -1238,6 +1251,7 @@ export class MapRenderer
|
|||||||
v.data.render();
|
v.data.render();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.vertex.renderDynamic();
|
||||||
|
|
||||||
if (area.dirty.length > 0) {
|
if (area.dirty.length > 0) {
|
||||||
// 如果需要更新顶点数组...
|
// 如果需要更新顶点数组...
|
||||||
@ -1491,6 +1505,8 @@ export class MapRenderer
|
|||||||
this.needUpdateFrameCounter = true;
|
this.needUpdateFrameCounter = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.tickers.forEach(v => void v.fn(timestamp));
|
||||||
|
|
||||||
// 图块移动
|
// 图块移动
|
||||||
if (this.movingBlock.size > 0) {
|
if (this.movingBlock.size > 0) {
|
||||||
const toUpdate: IMovingBlock[] = [];
|
const toUpdate: IMovingBlock[] = [];
|
||||||
|
|||||||
@ -26,7 +26,7 @@ void main() {
|
|||||||
vec2 pos = a_position.xy * a_tilePos.zw + a_tilePos.xy;
|
vec2 pos = a_position.xy * a_tilePos.zw + a_tilePos.xy;
|
||||||
vec2 texCoord = a_position.zw * a_texCoord.zw + a_texCoord.xy;
|
vec2 texCoord = a_position.zw * a_texCoord.zw + a_texCoord.xy;
|
||||||
// 偏移量
|
// 偏移量
|
||||||
float offset = a_texData.x < 0.0 ? mod(u_nowFrame, a_texData.y) : a_texData.x;
|
float offset = mod(a_texData.x < 0.0 ? u_nowFrame : a_texData.x, a_texData.y);
|
||||||
int offsetIndex = int(a_texData.z);
|
int offsetIndex = int(a_texData.z);
|
||||||
// 贴图偏移
|
// 贴图偏移
|
||||||
texCoord.x += u_offsetPool[offsetIndex] * offset;
|
texCoord.x += u_offsetPool[offsetIndex] * offset;
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import { IDirtyMark, IDirtyTracker } from '@motajs/common';
|
import { IDirtyMark, IDirtyTracker } from '@motajs/common';
|
||||||
import { ITextureRenderable } from '@motajs/render-assets';
|
import {
|
||||||
|
ITextureRenderable,
|
||||||
|
SizedCanvasImageSource
|
||||||
|
} from '@motajs/render-assets';
|
||||||
import { Transform } from '@motajs/render-core';
|
import { Transform } from '@motajs/render-core';
|
||||||
import {
|
import {
|
||||||
IAutotileProcessor,
|
IAutotileProcessor,
|
||||||
@ -373,6 +376,12 @@ export interface IMapRenderer {
|
|||||||
*/
|
*/
|
||||||
getLayerIndex(layer: IMapLayer): number;
|
getLayerIndex(layer: IMapLayer): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据图集的图像源获取其索引
|
||||||
|
* @param source 图像源
|
||||||
|
*/
|
||||||
|
getAssetSourceIndex(source: SizedCanvasImageSource): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取指定偏移值在偏移池中的索引
|
* 获取指定偏移值在偏移池中的索引
|
||||||
* @param offset 原始偏移值,非归一化偏移值
|
* @param offset 原始偏移值,非归一化偏移值
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import { DYNAMIC_RESERVE, MAP_BLOCK_HEIGHT, MAP_BLOCK_WIDTH } from '../shared';
|
|||||||
import { BlockSplitter } from './block';
|
import { BlockSplitter } from './block';
|
||||||
import { clamp, isNil } from 'lodash-es';
|
import { clamp, isNil } from 'lodash-es';
|
||||||
import { BlockCls, IMaterialFramedData } from '@user/client-base';
|
import { BlockCls, IMaterialFramedData } from '@user/client-base';
|
||||||
import { IRect, SizedCanvasImageSource } from '@motajs/render-assets';
|
import { IRect } from '@motajs/render-assets';
|
||||||
import { INSTANCED_COUNT } from './constant';
|
import { INSTANCED_COUNT } from './constant';
|
||||||
|
|
||||||
export interface IMapDataGetter {
|
export interface IMapDataGetter {
|
||||||
@ -36,12 +36,6 @@ export interface IMapDataGetter {
|
|||||||
/** 图块大小与格子大小判断方式 */
|
/** 图块大小与格子大小判断方式 */
|
||||||
readonly tileTestMode: MapTileSizeTestMode;
|
readonly tileTestMode: MapTileSizeTestMode;
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据图集的图像源获取其索引
|
|
||||||
* @param source 图像源
|
|
||||||
*/
|
|
||||||
getAssetSourceIndex(source: SizedCanvasImageSource): number;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染器是否包含指定的移动图块对象
|
* 渲染器是否包含指定的移动图块对象
|
||||||
* @param moving 移动图块对象
|
* @param moving 移动图块对象
|
||||||
@ -159,6 +153,11 @@ export class MapVertexGenerator
|
|||||||
staticCount * INSTANCED_COUNT,
|
staticCount * INSTANCED_COUNT,
|
||||||
count * INSTANCED_COUNT
|
count * INSTANCED_COUNT
|
||||||
);
|
);
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
const start = i * INSTANCED_COUNT;
|
||||||
|
this.instancedArray[start + 9] = 1;
|
||||||
|
this.instancedArray[start + 12] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private splitBlock() {
|
private splitBlock() {
|
||||||
@ -320,12 +319,12 @@ export class MapVertexGenerator
|
|||||||
}
|
}
|
||||||
case MapTileAlign.Center: {
|
case MapTileAlign.Center: {
|
||||||
// 左右居中对齐
|
// 左右居中对齐
|
||||||
left = cl + cwu - twu;
|
left = cl - cwu + twu;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MapTileAlign.End: {
|
case MapTileAlign.End: {
|
||||||
// 右对齐
|
// 右对齐
|
||||||
left = cl + cw - tw;
|
left = cl - cw + tw;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,12 +336,12 @@ export class MapVertexGenerator
|
|||||||
}
|
}
|
||||||
case MapTileAlign.Center: {
|
case MapTileAlign.Center: {
|
||||||
// 上下居中对齐
|
// 上下居中对齐
|
||||||
top = ct + chu - thu;
|
top = ct - chu + thu;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MapTileAlign.End: {
|
case MapTileAlign.End: {
|
||||||
// 下对齐
|
// 下对齐
|
||||||
top = ct + ch - th;
|
top = ct - ch + th;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { x: left, y: top, w: tw, h: th };
|
return { x: left, y: top, w: tw, h: th };
|
||||||
@ -378,7 +377,8 @@ export class MapVertexGenerator
|
|||||||
const layerIndex = this.renderer.getLayerIndex(index.layer);
|
const layerIndex = this.renderer.getLayerIndex(index.layer);
|
||||||
// 避免 z 坐标是 1 的时候被裁剪,因此范围选择 [-0.9, 0.9]
|
// 避免 z 坐标是 1 的时候被裁剪,因此范围选择 [-0.9, 0.9]
|
||||||
const layerStart = (layerIndex / layerCount) * 1.8 - 0.9;
|
const layerStart = (layerIndex / layerCount) * 1.8 - 0.9;
|
||||||
const zIndex = -layerStart - index.mapY / this.mapHeight;
|
const zIndex =
|
||||||
|
-layerStart - index.mapY / this.mapHeight / layerCount;
|
||||||
const { x, y, w, h } = this.getTilePosition(index, width, height);
|
const { x, y, w, h } = this.getTilePosition(index, width, height);
|
||||||
// 图块位置
|
// 图块位置
|
||||||
instancedArray[startIndex] = x;
|
instancedArray[startIndex] = x;
|
||||||
@ -398,10 +398,7 @@ export class MapVertexGenerator
|
|||||||
instancedArray[startIndex + 5] = texY;
|
instancedArray[startIndex + 5] = texY;
|
||||||
instancedArray[startIndex + 6] = texWidth;
|
instancedArray[startIndex + 6] = texWidth;
|
||||||
instancedArray[startIndex + 7] = texHeight;
|
instancedArray[startIndex + 7] = texHeight;
|
||||||
// 不透明度
|
|
||||||
instancedArray[startIndex + 9] = 1;
|
|
||||||
// 帧数、偏移、纹理索引
|
// 帧数、偏移、纹理索引
|
||||||
instancedArray[startIndex + 12] = -1;
|
|
||||||
instancedArray[startIndex + 13] = frames;
|
instancedArray[startIndex + 13] = frames;
|
||||||
instancedArray[startIndex + 14] = offsetIndex;
|
instancedArray[startIndex + 14] = offsetIndex;
|
||||||
instancedArray[startIndex + 15] = assetIndex;
|
instancedArray[startIndex + 15] = assetIndex;
|
||||||
|
|||||||
@ -11,6 +11,8 @@ interface GameLoadEvent {
|
|||||||
coreInit: [];
|
coreInit: [];
|
||||||
/** 当所有启动必要资源加载完毕后触发 */
|
/** 当所有启动必要资源加载完毕后触发 */
|
||||||
loaded: [];
|
loaded: [];
|
||||||
|
/** 当资源构建完毕后触发,后续需要用新的加载系统替代 */
|
||||||
|
assetBuilt: [];
|
||||||
/** 当客户端(渲染端)和数据端都挂载完毕后触发 */
|
/** 当客户端(渲染端)和数据端都挂载完毕后触发 */
|
||||||
registered: [];
|
registered: [];
|
||||||
/** 当数据端挂载完毕后触发 */
|
/** 当数据端挂载完毕后触发 */
|
||||||
|
|||||||
@ -2,12 +2,13 @@ import { Hookable, HookController, IHookController } from '@motajs/common';
|
|||||||
import { IHeroFollower, IHeroState, IHeroStateHooks } from './types';
|
import { IHeroFollower, IHeroState, IHeroStateHooks } from './types';
|
||||||
import { FaceDirection, getFaceMovement, nextFaceDirection } from '../common';
|
import { FaceDirection, getFaceMovement, nextFaceDirection } from '../common';
|
||||||
import { isNil } from 'lodash-es';
|
import { isNil } from 'lodash-es';
|
||||||
|
import { DEFAULT_HERO_IMAGE } from '../shared';
|
||||||
|
|
||||||
export class HeroState extends Hookable<IHeroStateHooks> implements IHeroState {
|
export class HeroState extends Hookable<IHeroStateHooks> implements IHeroState {
|
||||||
x: number = 0;
|
x: number = 0;
|
||||||
y: number = 0;
|
y: number = 0;
|
||||||
direction: FaceDirection = FaceDirection.Down;
|
direction: FaceDirection = FaceDirection.Down;
|
||||||
image?: ImageIds;
|
image: ImageIds = DEFAULT_HERO_IMAGE;
|
||||||
|
|
||||||
/** 当前勇士是否正在移动 */
|
/** 当前勇士是否正在移动 */
|
||||||
moving: boolean = false;
|
moving: boolean = false;
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import type {
|
|||||||
} from '@user/client-modules';
|
} from '@user/client-modules';
|
||||||
import { BluePalace, MiscData } from '../mechanism/misc';
|
import { BluePalace, MiscData } from '../mechanism/misc';
|
||||||
import { sleep } from '@motajs/common';
|
import { sleep } from '@motajs/common';
|
||||||
|
import { fromDirectionString, state } from '..';
|
||||||
|
|
||||||
// todo: 转身功能
|
// todo: 转身功能
|
||||||
|
|
||||||
@ -437,8 +438,6 @@ const enum HeroMoveCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class HeroMover extends ObjectMoverBase {
|
export class HeroMover extends ObjectMoverBase {
|
||||||
/** 勇士渲染适配器,用于等待动画等操作 */
|
|
||||||
static adapter?: RenderAdapter<HeroRenderer>;
|
|
||||||
/** 视角适配器 */
|
/** 视角适配器 */
|
||||||
static viewport?: RenderAdapter<FloorViewport>;
|
static viewport?: RenderAdapter<FloorViewport>;
|
||||||
|
|
||||||
@ -485,12 +484,10 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
|
|
||||||
protected async onMoveStart(controller: IMoveController): Promise<void> {
|
protected async onMoveStart(controller: IMoveController): Promise<void> {
|
||||||
this.beforeMoveSpeed = this.moveSpeed;
|
this.beforeMoveSpeed = this.moveSpeed;
|
||||||
const adapter = HeroMover.adapter;
|
|
||||||
const viewport = HeroMover.viewport;
|
const viewport = HeroMover.viewport;
|
||||||
if (!adapter || !viewport) return;
|
if (!viewport) return;
|
||||||
if (!core.isReplaying() || core.status.replay.speed <= 3) {
|
if (!core.isReplaying() || core.status.replay.speed <= 12) {
|
||||||
adapter.sync('startAnimate');
|
state.hero.startMove();
|
||||||
await adapter.all('readyMove');
|
|
||||||
}
|
}
|
||||||
// 这里要检查前面那一格能不能走,不能走则不触发平滑视角,以避免撞墙上视角卡住
|
// 这里要检查前面那一格能不能走,不能走则不触发平滑视角,以避免撞墙上视角卡住
|
||||||
if (!this.ignoreTerrain) {
|
if (!this.ignoreTerrain) {
|
||||||
@ -512,11 +509,9 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
protected async onMoveEnd(controller: IMoveController): Promise<void> {
|
protected async onMoveEnd(controller: IMoveController): Promise<void> {
|
||||||
this.moveSpeed = this.beforeMoveSpeed;
|
this.moveSpeed = this.beforeMoveSpeed;
|
||||||
this.onSetMoveSpeed(this.moveSpeed, controller);
|
this.onSetMoveSpeed(this.moveSpeed, controller);
|
||||||
const adapter = HeroMover.adapter;
|
|
||||||
const viewport = HeroMover.viewport;
|
const viewport = HeroMover.viewport;
|
||||||
if (!adapter || !viewport) return;
|
if (!viewport) return;
|
||||||
adapter.sync('endAnimate');
|
await state.hero.endMove();
|
||||||
await adapter.all('endMove');
|
|
||||||
viewport.sync('endMove');
|
viewport.sync('endMove');
|
||||||
core.clearContinueAutomaticRoute();
|
core.clearContinueAutomaticRoute();
|
||||||
core.stopAutomaticRoute();
|
core.stopAutomaticRoute();
|
||||||
@ -667,40 +662,43 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
speed: number,
|
speed: number,
|
||||||
_controller: IMoveController
|
_controller: IMoveController
|
||||||
): void {
|
): void {
|
||||||
const adapter = HeroMover.adapter;
|
this.moveSpeed = speed;
|
||||||
if (!adapter) return;
|
|
||||||
adapter.sync('setMoveSpeed', speed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移动动画
|
* 移动动画
|
||||||
* @param x 目标横坐标
|
* @param x 目标横坐标
|
||||||
* @param y 目标纵坐标
|
* @param y 目标纵坐标
|
||||||
* @param showDir 显示方向
|
* @param _showDir 显示方向
|
||||||
* @param moveDir 移动方向
|
* @param moveDir 移动方向
|
||||||
*/
|
*/
|
||||||
private async moveAnimate(
|
private async moveAnimate(
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
showDir: Dir,
|
_showDir: Dir,
|
||||||
moveDir: Dir2
|
moveDir: Dir2
|
||||||
) {
|
) {
|
||||||
const adapter = HeroMover.adapter;
|
|
||||||
const viewport = HeroMover.viewport;
|
const viewport = HeroMover.viewport;
|
||||||
if (!adapter || !viewport) return;
|
if (!viewport) return;
|
||||||
const replay = core.status.replay.speed;
|
const replay = core.status.replay.speed;
|
||||||
const speed = replay === 24 ? 1 : this.moveSpeed / replay;
|
const speed = replay === 24 ? 1 : this.moveSpeed / replay;
|
||||||
viewport.all('moveTo', x, y, speed * 1.6);
|
viewport.all('moveTo', x, y, speed * 1.6);
|
||||||
adapter.sync('setAnimateDir', showDir);
|
const replaying = core.isReplaying();
|
||||||
if (core.isReplaying() && core.status.replay.speed > 3) {
|
if (replaying) {
|
||||||
adapter.sync('endAnimate');
|
if (core.status.replay.speed > 12) {
|
||||||
await sleep(speed);
|
await state.hero.endMove();
|
||||||
await adapter.all('setHeroLoc', x, y);
|
await sleep(speed);
|
||||||
} else {
|
state.hero.setPosition(x, y);
|
||||||
if (core.isReplaying()) {
|
} else {
|
||||||
adapter.sync('startAnimate');
|
state.hero.startMove();
|
||||||
|
await state.hero.move(
|
||||||
|
fromDirectionString(moveDir),
|
||||||
|
this.moveSpeed / core.status.replay.speed
|
||||||
|
);
|
||||||
}
|
}
|
||||||
await adapter.all('move', moveDir);
|
} else {
|
||||||
|
state.hero.startMove();
|
||||||
|
await state.hero.move(fromDirectionString(moveDir), this.moveSpeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,101 +782,99 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
return { portal: false };
|
return { portal: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderHeroSwap(data: BluePalace.PortalTo) {
|
private renderHeroSwap(_data: BluePalace.PortalTo) {
|
||||||
const adapter = HeroMover.adapter;
|
// todo: 传送门
|
||||||
if (!adapter) return;
|
// const list = adapter.items;
|
||||||
const list = adapter.items;
|
// const { x: tx, y: ty, dir: toDir } = data;
|
||||||
const { x: tx, y: ty, dir: toDir } = data;
|
// const { x, y, direction } = core.status.hero.loc;
|
||||||
const { x, y, direction } = core.status.hero.loc;
|
// const { x: dx } = core.utils.scan[direction];
|
||||||
const { x: dx } = core.utils.scan[direction];
|
// const { x: tdx } = core.utils.scan[toDir];
|
||||||
const { x: tdx } = core.utils.scan[toDir];
|
|
||||||
|
|
||||||
const promises = [...list].map(v => {
|
// const promises = [...list].map(v => {
|
||||||
if (!v.renderable) return;
|
// if (!v.renderable) return;
|
||||||
const renderable = { ...v.renderable };
|
// const renderable = { ...v.renderable };
|
||||||
renderable.render = v.getRenderFromDir(toDir);
|
// renderable.render = v.getRenderFromDir(toDir);
|
||||||
renderable.zIndex = ty;
|
// renderable.zIndex = ty;
|
||||||
const heroDir = v.moveDir;
|
// const heroDir = v.moveDir;
|
||||||
|
|
||||||
const width = v.renderable.render[0][2];
|
// const width = v.renderable.render[0][2];
|
||||||
const height = v.renderable.render[0][3];
|
// const height = v.renderable.render[0][3];
|
||||||
const cell = v.layer.cellSize;
|
// const cell = v.layer.cellSize;
|
||||||
const restHeight = height - cell;
|
// const restHeight = height - cell;
|
||||||
if (!width || !height) return;
|
// if (!width || !height) return;
|
||||||
|
|
||||||
const originFrom = structuredClone(v.renderable.render);
|
// const originFrom = structuredClone(v.renderable.render);
|
||||||
const originTo = structuredClone(renderable.render);
|
// const originTo = structuredClone(renderable.render);
|
||||||
v.layer.moving.add(renderable);
|
// v.layer.moving.add(renderable);
|
||||||
v.layer.requestUpdateMoving();
|
// v.layer.requestUpdateMoving();
|
||||||
|
|
||||||
const start = Date.now();
|
// const start = Date.now();
|
||||||
return new Promise<void>(res => {
|
// return new Promise<void>(res => {
|
||||||
const tick = () => {
|
// const tick = () => {
|
||||||
const now = Date.now();
|
// const now = Date.now();
|
||||||
const progress = (now - start) / this.moveSpeed;
|
// const progress = (now - start) / this.moveSpeed;
|
||||||
const clipWidth = cell * progress;
|
// const clipWidth = cell * progress;
|
||||||
const clipHeight = cell * progress;
|
// const clipHeight = cell * progress;
|
||||||
const beforeWidth = width - clipWidth;
|
// const beforeWidth = width - clipWidth;
|
||||||
const beforeHeight = height - clipHeight;
|
// const beforeHeight = height - clipHeight;
|
||||||
|
|
||||||
v.renderable!.x = x;
|
// v.renderable!.x = x;
|
||||||
v.renderable!.y = y;
|
// v.renderable!.y = y;
|
||||||
if (heroDir === 'left' || heroDir === 'right') {
|
// if (heroDir === 'left' || heroDir === 'right') {
|
||||||
v.renderable!.x = x + (clipWidth / 2 / cell) * dx;
|
// v.renderable!.x = x + (clipWidth / 2 / cell) * dx;
|
||||||
v.renderable!.render.forEach((v, i) => {
|
// v.renderable!.render.forEach((v, i) => {
|
||||||
v[2] = beforeWidth;
|
// v[2] = beforeWidth;
|
||||||
if (heroDir === 'left') {
|
// if (heroDir === 'left') {
|
||||||
v[0] = originFrom[i][0] + clipWidth;
|
// v[0] = originFrom[i][0] + clipWidth;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
} else {
|
// } else {
|
||||||
v.renderable!.render.forEach((v, i) => {
|
// v.renderable!.render.forEach((v, i) => {
|
||||||
v[3] = beforeHeight;
|
// v[3] = beforeHeight;
|
||||||
if (heroDir === 'up') {
|
// if (heroDir === 'up') {
|
||||||
v[1] =
|
// v[1] =
|
||||||
originFrom[i][1] + clipHeight + restHeight;
|
// originFrom[i][1] + clipHeight + restHeight;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
renderable.x = tx;
|
// renderable.x = tx;
|
||||||
renderable.y = ty;
|
// renderable.y = ty;
|
||||||
if (toDir === 'left' || toDir === 'right') {
|
// if (toDir === 'left' || toDir === 'right') {
|
||||||
renderable.x = tx + (clipWidth / 2 / cell - 0.5) * tdx;
|
// renderable.x = tx + (clipWidth / 2 / cell - 0.5) * tdx;
|
||||||
renderable.render.forEach((v, i) => {
|
// renderable.render.forEach((v, i) => {
|
||||||
v[2] = clipWidth;
|
// v[2] = clipWidth;
|
||||||
if (toDir === 'right') {
|
// if (toDir === 'right') {
|
||||||
v[0] = originTo[i][0] + beforeWidth;
|
// v[0] = originTo[i][0] + beforeWidth;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
} else {
|
// } else {
|
||||||
if (toDir === 'down') renderable.y = ty - 1 + progress;
|
// if (toDir === 'down') renderable.y = ty - 1 + progress;
|
||||||
renderable.render.forEach((v, i) => {
|
// renderable.render.forEach((v, i) => {
|
||||||
v[3] = clipHeight + restHeight;
|
// v[3] = clipHeight + restHeight;
|
||||||
if (toDir === 'down') {
|
// if (toDir === 'down') {
|
||||||
v[1] = originTo[i][1] + clipHeight + restHeight;
|
// v[1] = originTo[i][1] + clipHeight + restHeight;
|
||||||
v[3] = clipHeight;
|
// v[3] = clipHeight;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
v.layer.delegateTicker(tick, this.moveSpeed, () => {
|
// v.layer.delegateTicker(tick, this.moveSpeed, () => {
|
||||||
v.renderable!.render = originFrom;
|
// v.renderable!.render = originFrom;
|
||||||
v.setAnimateDir(data.dir);
|
// v.setAnimateDir(data.dir);
|
||||||
v.layer.moving.delete(renderable);
|
// v.layer.moving.delete(renderable);
|
||||||
v.layer.requestUpdateMoving();
|
// v.layer.requestUpdateMoving();
|
||||||
res();
|
// res();
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderHeroLoop() {
|
private renderHeroLoop() {
|
||||||
const adapter = HeroMover.adapter;
|
|
||||||
const viewport = HeroMover.viewport;
|
const viewport = HeroMover.viewport;
|
||||||
if (!adapter || !viewport) return;
|
if (!viewport) return;
|
||||||
const MotaRenderer = Mota.require('@motajs/render').MotaRenderer;
|
const MotaRenderer = Mota.require('@motajs/render').MotaRenderer;
|
||||||
const render = MotaRenderer.get('render-main');
|
const render = MotaRenderer.get('render-main');
|
||||||
const group = render?.getElementById('layer-loop') as LayerGroup;
|
const group = render?.getElementById('layer-loop') as LayerGroup;
|
||||||
@ -952,10 +948,8 @@ loading.once('coreInit', () => {
|
|||||||
loading.once('coreInit', () => {
|
loading.once('coreInit', () => {
|
||||||
if (main.replayChecking || main.mode === 'editor') return;
|
if (main.replayChecking || main.mode === 'editor') return;
|
||||||
const Adapter = Mota.require('@motajs/render').RenderAdapter;
|
const Adapter = Mota.require('@motajs/render').RenderAdapter;
|
||||||
const adapter = Adapter.get<HeroRenderer>('hero-adapter');
|
|
||||||
const viewport = Adapter.get<FloorViewport>('viewport');
|
const viewport = Adapter.get<FloorViewport>('viewport');
|
||||||
const layerAdapter = Adapter.get<Layer>('layer');
|
const layerAdapter = Adapter.get<Layer>('layer');
|
||||||
HeroMover.adapter = adapter;
|
|
||||||
HeroMover.viewport = viewport;
|
HeroMover.viewport = viewport;
|
||||||
BlockMover.adapter = layerAdapter;
|
BlockMover.adapter = layerAdapter;
|
||||||
});
|
});
|
||||||
|
|||||||
2
packages-user/data-state/src/shared.ts
Normal file
2
packages-user/data-state/src/shared.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/** 默认的勇士图片 */
|
||||||
|
export const DEFAULT_HERO_IMAGE: ImageIds = 'hero1.png';
|
||||||
@ -49,9 +49,9 @@ export function create() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function createModule() {
|
async function createModule() {
|
||||||
LegacyUI.create();
|
|
||||||
ClientModules.create();
|
|
||||||
UserClientBase.create();
|
UserClientBase.create();
|
||||||
|
ClientModules.create();
|
||||||
|
LegacyUI.create();
|
||||||
|
|
||||||
await import('ant-design-vue/dist/antd.dark.css');
|
await import('ant-design-vue/dist/antd.dark.css');
|
||||||
main.renderLoaded = true;
|
main.renderLoaded = true;
|
||||||
|
|||||||
@ -44,6 +44,7 @@
|
|||||||
"42": "The '$1' property of map-render element is required.",
|
"42": "The '$1' property of map-render element is required.",
|
||||||
"43": "Cannot bind face direction to main block $1, please call malloc in advance.",
|
"43": "Cannot bind face direction to main block $1, please call malloc in advance.",
|
||||||
"44": "Cannot bind face direction to main block $1, since main direction cannot be override.",
|
"44": "Cannot bind face direction to main block $1, since main direction cannot be override.",
|
||||||
|
"45": "Cannot add hero renderer, sincehero renderer already exists for the given state.",
|
||||||
"1101": "Shadow extension needs 'floor-hero' extension as dependency.",
|
"1101": "Shadow extension needs 'floor-hero' extension as dependency.",
|
||||||
"1201": "Floor-damage extension needs 'floor-binder' extension as dependency.",
|
"1201": "Floor-damage extension needs 'floor-binder' extension as dependency.",
|
||||||
"1301": "Portal extension need 'floor-binder' extension as dependency.",
|
"1301": "Portal extension need 'floor-binder' extension as dependency.",
|
||||||
|
|||||||
@ -8,9 +8,10 @@ import { ITexture, ITextureSplitter, IRect } from './types';
|
|||||||
export class TextureRowSplitter implements ITextureSplitter<number> {
|
export class TextureRowSplitter implements ITextureSplitter<number> {
|
||||||
*split(texture: ITexture, data: number): Generator<ITexture> {
|
*split(texture: ITexture, data: number): Generator<ITexture> {
|
||||||
const lines = Math.ceil(texture.height / data);
|
const lines = Math.ceil(texture.height / data);
|
||||||
|
const { x, y } = texture.render().rect;
|
||||||
for (let i = 0; i < lines; i++) {
|
for (let i = 0; i < lines; i++) {
|
||||||
const tex = new Texture(texture.source);
|
const tex = new Texture(texture.source);
|
||||||
tex.clip(0, i * data, texture.width, data);
|
tex.clip(x, y + i * data, texture.width, data);
|
||||||
yield tex;
|
yield tex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -23,9 +24,10 @@ export class TextureRowSplitter implements ITextureSplitter<number> {
|
|||||||
export class TextureColumnSplitter implements ITextureSplitter<number> {
|
export class TextureColumnSplitter implements ITextureSplitter<number> {
|
||||||
*split(texture: ITexture, data: number): Generator<ITexture> {
|
*split(texture: ITexture, data: number): Generator<ITexture> {
|
||||||
const lines = Math.ceil(texture.width / data);
|
const lines = Math.ceil(texture.width / data);
|
||||||
|
const { x, y } = texture.render().rect;
|
||||||
for (let i = 0; i < lines; i++) {
|
for (let i = 0; i < lines; i++) {
|
||||||
const tex = new Texture(texture.source);
|
const tex = new Texture(texture.source);
|
||||||
tex.clip(i * data, 0, data, texture.height);
|
tex.clip(x + i * data, y, data, texture.height);
|
||||||
yield tex;
|
yield tex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,10 +42,11 @@ export class TextureGridSplitter implements ITextureSplitter<[number, number]> {
|
|||||||
const [w, h] = data;
|
const [w, h] = data;
|
||||||
const rows = Math.ceil(texture.width / w);
|
const rows = Math.ceil(texture.width / w);
|
||||||
const lines = Math.ceil(texture.height / h);
|
const lines = Math.ceil(texture.height / h);
|
||||||
for (let y = 0; y < lines; y++) {
|
const { x, y } = texture.render().rect;
|
||||||
for (let x = 0; x < rows; x++) {
|
for (let ny = 0; ny < lines; ny++) {
|
||||||
|
for (let nx = 0; nx < rows; nx++) {
|
||||||
const tex = new Texture(texture.source);
|
const tex = new Texture(texture.source);
|
||||||
tex.clip(x * w, y * h, w, h);
|
tex.clip(x + nx * w, y + ny * h, w, h);
|
||||||
yield tex;
|
yield tex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,7 +140,6 @@ export class TextureMaxRectsStreamComposer
|
|||||||
|
|
||||||
private nextCanvas() {
|
private nextCanvas() {
|
||||||
this.nowCanvas = document.createElement('canvas');
|
this.nowCanvas = document.createElement('canvas');
|
||||||
this.nowCanvas.id = `${Math.random()}`;
|
|
||||||
this.nowCtx = this.nowCanvas.getContext('2d')!;
|
this.nowCtx = this.nowCanvas.getContext('2d')!;
|
||||||
this.nowCanvas.width = this.maxWidth;
|
this.nowCanvas.width = this.maxWidth;
|
||||||
this.nowCanvas.height = this.maxHeight;
|
this.nowCanvas.height = this.maxHeight;
|
||||||
|
|||||||
@ -30,8 +30,8 @@ export class Texture implements ITexture {
|
|||||||
this.height = source.height;
|
this.height = source.height;
|
||||||
this.cl = 0;
|
this.cl = 0;
|
||||||
this.ct = 0;
|
this.ct = 0;
|
||||||
this.cr = 0;
|
this.cr = source.width;
|
||||||
this.cb = 0;
|
this.cb = source.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,16 +42,14 @@ export class Texture implements ITexture {
|
|||||||
* @param h 裁剪高度
|
* @param h 裁剪高度
|
||||||
*/
|
*/
|
||||||
clip(x: number, y: number, w: number, h: number) {
|
clip(x: number, y: number, w: number, h: number) {
|
||||||
const r = x + w;
|
const left = clamp(this.cl + x, this.cl, this.cr);
|
||||||
const b = y + h;
|
const top = clamp(this.ct + y, this.ct, this.cb);
|
||||||
if (x > this.width || y > this.height || r < 0 || b < 0) {
|
const right = clamp(this.cl + x + w, this.cl, this.cr);
|
||||||
|
const bottom = clamp(this.ct + y + h, this.ct, this.cb);
|
||||||
|
if (left === right || top === bottom) {
|
||||||
logger.warn(69);
|
logger.warn(69);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const left = Math.max(0, x);
|
|
||||||
const top = Math.max(0, y);
|
|
||||||
const right = Math.min(this.width, r);
|
|
||||||
const bottom = Math.min(this.height, b);
|
|
||||||
const width = right - left;
|
const width = right - left;
|
||||||
const height = bottom - top;
|
const height = bottom - top;
|
||||||
if (width <= 0 || height <= 0) {
|
if (width <= 0 || height <= 0) {
|
||||||
@ -60,6 +58,8 @@ export class Texture implements ITexture {
|
|||||||
}
|
}
|
||||||
this.cl = left;
|
this.cl = left;
|
||||||
this.ct = top;
|
this.ct = top;
|
||||||
|
this.cr = right;
|
||||||
|
this.cb = bottom;
|
||||||
this.width = right - left;
|
this.width = right - left;
|
||||||
this.height = bottom - top;
|
this.height = bottom - top;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user