feat: 勇士及跟随者渲染

This commit is contained in:
AncTe committed 2025-11-22 23:48:59 +08:00
1 parent 37cd85cd1e
commit 8fe12634b0
43 files changed
+1472 -307

No files matched your search

@@ -0,0 +1,8 @@
import { state } from '@user/data-state';
import { MapRenderer } from './map/renderer';
import { materials } from '@user/client-base';
/** 主地图渲染器,用于渲染游戏画面 */
export const mainMapRenderer = new MapRenderer(materials, state.layer);
/** 副地图渲染器,用于渲染缩略图、浏览地图等 */
export const expandMapRenderer = new MapRenderer(materials, state.layer);
@@ -7,8 +7,9 @@ import { Icon, Winskin } from './misc';
import { Animate } from './animate';
import { createItemDetail } from './itemDetail';
import { logger } from '@motajs/common';
import { MapRender } from '../map/element';
import { MapRender, MapRenderer } from '../map';
import { state } from '@user/data-state';
import { materials } from '@user/client-base';
export function createElements() {
createCache();
@@ -72,14 +73,27 @@ export function createElements() {
tagMap.register('map-render', (_0, _1, props) => {
if (!props) {
logger.error(42);
return new MapRender(state.layer);
return new MapRender(
state.layer,
new MapRenderer(materials, state.layer)
);
}
const { layerState } = props;
const { layerState, renderer } = props;
if (!layerState) {
logger.error(42);
return new MapRender(state.layer);
logger.error(42, 'layerState');
return new MapRender(
state.layer,
new MapRenderer(materials, state.layer)
);
}
return new MapRender(layerState);
if (!renderer) {
logger.error(42, 'renderer');
return new MapRender(
state.layer,
new MapRenderer(materials, state.layer)
);
}
return new MapRender(layerState, renderer);
});
}
@@ -12,6 +12,7 @@ import { EAnimateEvent } from './animate';
import { EIconEvent, EWinskinEvent } from './misc';
import { IEnemyCollection } from '@motajs/types';
import { ILayerState } from '@user/data-state';
import { IMapRenderer } from '../map';
export interface AnimateProps extends BaseProps {}
@@ -63,6 +64,7 @@ export interface LayerProps extends BaseProps {
export interface MapRenderProps extends BaseProps {
layerState: ILayerState;
renderer: IMapRenderer;
}
declare module 'vue/jsx-runtime' {
@@ -1,19 +1,21 @@
import { MotaOffscreenCanvas2D, RenderItem } from '@motajs/render-core';
import { ILayerState, state } from '@user/data-state';
import { ILayerState } from '@user/data-state';
import { IMapRenderer } from './types';
import { MapRenderer } from './renderer';
import { materials } from '@user/client-base';
import { ElementNamespace, ComponentInternalInstance } from 'vue';
import { CELL_HEIGHT, CELL_WIDTH, MAP_HEIGHT, MAP_WIDTH } from '../shared';
export class MapRender extends RenderItem {
/** 地图渲染器 */
readonly renderer: IMapRenderer;
constructor(readonly layerState: ILayerState) {
/**
* @param layerState 地图状态对象
* @param renderer 地图渲染器对象
*/
constructor(
readonly layerState: ILayerState,
readonly renderer: IMapRenderer
) {
super('static');
this.renderer = new MapRenderer(materials, state.layer);
this.renderer.setLayerState(layerState);
this.renderer.useAsset(materials.trackedAsset);
this.renderer.setCanvasSize(this.width, this.height);
@@ -0,0 +1,473 @@
import {
degradeFace,
FaceDirection,
getFaceMovement,
IHeroState,
IHeroStateHooks,
IMapLayer,
state
} from '@user/data-state';
import { IMapRenderer, IMapRendererTicker, IMovingBlock } from '../types';
import { isNil } from 'lodash-es';
import { IHookController, logger } from '@motajs/common';
import { BlockCls, IMaterialFramedData } from '@user/client-base';
import {
ITexture,
ITextureSplitter,
TextureRowSplitter
} from '@motajs/render-assets';
import { IMapHeroRenderer } from './types';
import { TimingFn } from 'mutate-animate';
/** 默认的移动时长 */
const DEFAULT_TIME = 100;
interface HeroRenderEntity {
/** 移动图块对象 */
readonly block: IMovingBlock;
/** 标识符,用于判定跟随者 */
readonly identifier: string;
/** 目标横坐标,移动时有效 */
targetX: number;
/** 目标纵坐标,移动时有效 */
targetY: number;
/** 当前的移动朝向 */
direction: FaceDirection;
/** 下一个跟随者的移动方向 */
nextDirection: FaceDirection;
/** 当前是否正在移动 */
moving: boolean;
/** 当前是否正在动画,移动跟动画要分开,有的操作比如跳跃就是在移动中但是没动画 */
animating: boolean;
/** 帧动画间隔 */
animateInterval: number;
/** 当一次动画时刻 */
lastAnimateTime: number;
/** 当前的动画帧数 */
animateFrame: number;
/** 移动的 `Promise`,移动完成时兑现,如果停止,则一直是兑现状态 */
promise: Promise<void>;
}
export class MapHeroRenderer implements IMapHeroRenderer {
private static readonly splitter: ITextureSplitter<number> =
new TextureRowSplitter();
/** 勇士钩子 */
readonly controller: IHookController<IHeroStateHooks>;
/** 每个朝向的贴图对象 */
readonly textureMap: Map<FaceDirection, IMaterialFramedData> = new Map();
/** 勇士渲染实体,与 `entities[0]` 同引用 */
readonly heroEntity: HeroRenderEntity;
/**
* 渲染实体,索引 0 表示勇士,后续索引依次表示跟随的跟随者。
* 整体是一个状态机,而且下一个跟随者只与上一个跟随者有关,下一个跟随者移动的方向就是上一个跟随者移动前指向的方向。
*/
readonly entities: HeroRenderEntity[] = [];
/** 每帧执行的帧动画对象 */
readonly ticker: IMapRendererTicker;
constructor(
readonly renderer: IMapRenderer,
readonly layer: IMapLayer,
readonly hero: IHeroState
) {
this.controller = hero.addHook(new MapHeroHook(this));
this.controller.load();
const moving = this.addHeroMoving(renderer, layer, hero);
const heroEntity: HeroRenderEntity = {
block: moving,
identifier: '',
targetX: hero.x,
targetY: hero.y,
direction: hero.direction,
nextDirection: FaceDirection.Unknown,
moving: false,
animating: false,
animateInterval: 0,
lastAnimateTime: 0,
animateFrame: 0,
promise: Promise.resolve()
};
this.heroEntity = heroEntity;
this.entities.push(heroEntity);
this.ticker = renderer.requestTicker(time => this.tick(time));
}
/**
* 添加勇士对应的移动图块
* @param renderer 渲染器
* @param layer 图块所属图层
* @param hero 勇士状态对象
*/
private addHeroMoving(
renderer: IMapRenderer,
layer: IMapLayer,
hero: IHeroState
) {
if (isNil(hero.image)) {
logger.warn(88);
return renderer.addMovingBlock(layer, 0, hero.x, hero.y);
}
const image = this.renderer.manager.getImageByAlias(hero.image);
if (!image) {
logger.warn(89, hero.image);
return renderer.addMovingBlock(layer, 0, hero.x, hero.y);
}
this.updateHeroTexture(image);
const tex = this.textureMap.get(degradeFace(hero.direction));
if (!tex) {
return renderer.addMovingBlock(layer, 0, hero.x, hero.y);
}
return renderer.addMovingBlock(layer, tex, hero.x, hero.y);
}
/**
* 更新勇士贴图
* @param image 勇士使用的贴图,包含四个方向
*/
private updateHeroTexture(image: ITexture) {
const textures = [
...image.split(MapHeroRenderer.splitter, image.height / 4)
];
if (textures.length !== 4) {
logger.warn(90, hero.image);
return;
}
const faceList = [
FaceDirection.Down,
FaceDirection.Left,
FaceDirection.Right,
FaceDirection.Up
];
faceList.forEach((v, i) => {
const dirImage = textures[i];
const data: IMaterialFramedData = {
offset: dirImage.width / 4,
texture: dirImage,
cls: BlockCls.Unknown,
frames: 4
};
this.textureMap.set(v, data);
});
}
private tick(time: number) {
this.entities.forEach(v => {
if (!v.animating) {
v.animateFrame = 0;
return;
}
const dt = time - v.lastAnimateTime;
if (dt > v.animateInterval) {
v.animateFrame++;
v.lastAnimateTime = time;
v.block.useSpecifiedFrame(v.animateFrame);
}
});
}
setImage(image: ITexture): void {
this.updateHeroTexture(image);
const tex = this.textureMap.get(degradeFace(this.hero.direction));
if (!tex) return;
this.heroEntity.block.setTexture(tex);
}
setAlpha(alpha: number): void {
this.heroEntity.block.setAlpha(alpha);
}
setPosition(x: number, y: number): void {
this.heroEntity.block.setPos(x, y);
}
/**
* 移动指定渲染实体,不会影响其他渲染实体。多次调用时会按顺序依次移动
* @param entity 渲染实体
* @param direction 移动方向
* @param time 移动时长
*/
private moveEntity(
entity: HeroRenderEntity,
direction: FaceDirection,
time: number
) {
const { x: dx, y: dy } = getFaceMovement(direction);
if (dx === 0 && dy === 0) return;
const block = entity.block;
const tx = block.x + dx;
const ty = block.y + dy;
const nextTile = state.roleFace.getFaceOf(block.tile, direction);
const nextTex = this.renderer.manager.getIfBigImage(
nextTile?.identifier ?? block.tile
);
entity.promise = entity.promise.then(async () => {
entity.moving = true;
entity.animating = true;
entity.nextDirection = entity.direction;
entity.direction = direction;
if (nextTex) block.setTexture(nextTex);
await block.lineTo(tx, ty, time);
entity.moving = false;
entity.animating = false;
});
}
/**
* 生成跳跃曲线
* @param dx 横向偏移量
* @param dy 纵向偏移量
*/
private generateJumpFn(dx: number, dy: number): TimingFn<2> {
const distance = Math.hypot(dx, dy);
const peak = 3 + distance;
return (progress: number) => {
const x = dx * progress;
const y = progress * dy + (progress ** 2 - progress) * peak;
return [x, y];
};
}
/**
* 将指定渲染实体跳跃至目标点,多次调用时会按顺序依次执行,可以与 `moveEntity` 混用
* @param entity 渲染实体
* @param x 目标横坐标
* @param y 目标纵坐标
* @param time 跳跃时长
*/
private jumpEntity(
entity: HeroRenderEntity,
x: number,
y: number,
time: number
) {
const block = entity.block;
entity.promise = entity.promise.then(async () => {
const dx = block.x - x;
const dy = block.y - y;
const fn = this.generateJumpFn(dx, dy);
entity.moving = true;
entity.animating = false;
entity.animateFrame = 0;
await block.moveRelative(fn, time);
entity.moving = false;
entity.animating = false;
});
}
startMove(): void {
this.heroEntity.moving = true;
this.heroEntity.animating = true;
this.heroEntity.animateFrame = 1;
this.heroEntity.lastAnimateTime = this.ticker.timestamp;
this.heroEntity.block.useSpecifiedFrame(1);
}
async waitMoveEnd(waitFollower: boolean): Promise<void> {
if (waitFollower) {
await Promise.all(this.entities.map(v => v.promise));
return;
}
return this.heroEntity.promise;
}
stopMove(stopFollower: boolean): void {
if (stopFollower) {
this.entities.forEach(v => {
v.block.endMoving();
});
} else {
this.heroEntity.block.endMoving();
}
}
async move(direction: FaceDirection, time: number): Promise<void> {
this.moveEntity(this.heroEntity, direction, time);
for (let i = 1; i < this.entities.length; i++) {
const last = this.entities[i - 1];
this.moveEntity(this.entities[i], last.nextDirection, time);
}
await Promise.all(this.entities.map(v => v.promise));
}
async jumpTo(
x: number,
y: number,
time: number,
waitFollower: boolean
): Promise<void> {
// 首先要把所有的跟随者移动到勇士所在位置
for (let i = 1; i < this.entities.length; i++) {
// 对于每一个跟随者,需要向前遍历每一个跟随者,然后朝向移动,这样就可以聚集在一起了
const now = this.entities[i];
for (let j = i - 1; j >= 0; j--) {
const last = this.entities[j];
this.moveEntity(now, last.nextDirection, DEFAULT_TIME);
}
}
this.entities.forEach(v => {
this.jumpEntity(v, x, y, time);
});
if (waitFollower) {
await Promise.all(this.entities.map(v => v.promise));
} else {
return this.heroEntity.promise;
}
}
addFollower(image: number, id: string): void {
const last = this.entities[this.entities.length - 1];
if (last.moving) {
logger.warn(92);
return;
}
const nowFace = degradeFace(last.nextDirection, FaceDirection.Down);
const faced = state.roleFace.getFaceOf(image, nowFace);
const tex = this.renderer.manager.getIfBigImage(faced?.face ?? image);
if (!tex) {
logger.warn(91, image.toString());
return;
}
const { x: dxn, y: dyn } = getFaceMovement(last.nextDirection);
const { x: dx, y: dy } = getFaceMovement(last.direction);
const x = last.block.x - dxn;
const y = last.block.y - dyn;
const moving = this.renderer.addMovingBlock(this.layer, tex, x, y);
const entity: HeroRenderEntity = {
block: moving,
identifier: id,
targetX: last.targetX - dx,
targetY: last.targetY - dy,
direction: nowFace,
nextDirection: FaceDirection.Unknown,
moving: false,
animating: false,
animateInterval: 0,
lastAnimateTime: 0,
animateFrame: 0,
promise: Promise.resolve()
};
this.entities.push(entity);
}
async removeFollower(follower: string, animate: boolean): Promise<void> {
const index = this.entities.findIndex(v => v.identifier === follower);
if (index === -1) return;
if (this.entities[index].moving) {
logger.warn(93);
return;
}
if (index === this.entities.length - 1) {
this.entities.splice(index, 1);
return;
}
// 展示动画
if (animate) {
for (let i = index + 1; i < this.entities.length; i++) {
const last = this.entities[i - 1];
const moving = this.entities[i];
this.moveEntity(moving, last.nextDirection, DEFAULT_TIME);
}
this.entities.splice(index, 1);
await Promise.all(this.entities.map(v => v.promise));
return;
}
// 不展示动画
for (let i = index + 1; i < this.entities.length; i++) {
const last = this.entities[i - 1];
const moving = this.entities[i];
moving.block.setPos(last.block.x, last.block.y);
const nextFace = state.roleFace.getFaceOf(
moving.block.tile,
last.nextDirection
);
if (!nextFace) continue;
const tile = this.renderer.manager.getIfBigImage(
nextFace.identifier
);
if (!tile) continue;
moving.block.setTexture(tile);
moving.nextDirection = moving.direction;
moving.direction = last.nextDirection;
}
this.entities.splice(index, 1);
}
removeAllFollowers(): void {
this.entities.length = 1;
}
setFollowerAlpha(identifier: string, alpha: number): void {
const follower = this.entities.find(v => v.identifier === identifier);
if (!follower) return;
follower.block.setAlpha(alpha);
}
destroy() {
this.controller.unload();
}
}
class MapHeroHook implements Partial<IHeroStateHooks> {
constructor(readonly hero: MapHeroRenderer) {}
onSetImage(image: ImageIds): void {
const texture = this.hero.renderer.manager.getImageByAlias(image);
if (!texture) {
logger.warn(89, hero.image);
return;
}
this.hero.setImage(texture);
}
onSetPosition(x: number, y: number): void {
this.hero.setPosition(x, y);
}
onStartMove(): void {
this.hero.startMove();
}
onMoveHero(direction: FaceDirection, time: number): Promise<void> {
return this.hero.move(direction, time);
}
onEndMove(waitFollower: boolean): Promise<void> {
return this.hero.waitMoveEnd(waitFollower);
}
onJumpHero(
x: number,
y: number,
time: number,
waitFollower: boolean
): Promise<void> {
return this.hero.jumpTo(x, y, time, waitFollower);
}
onSetAlpha(alpha: number): void {
this.hero.setAlpha(alpha);
}
onAddFollower(follower: number, identifier: string): void {
this.hero.addFollower(follower, identifier);
}
onRemoveFollower(identifier: string, animate: boolean): void {
this.hero.removeFollower(identifier, animate);
}
onRemoveAllFollowers(): void {
this.hero.removeAllFollowers();
}
onSetFollowerAlpha(identifier: string, alpha: number): void {
this.hero.setFollowerAlpha(identifier, alpha);
}
}
@@ -0,0 +1,2 @@
export * from './hero';
export * from './types';
@@ -0,0 +1,89 @@
import { ITexture } from '@motajs/render-assets';
import { FaceDirection } from '@user/data-state';
export interface IMapHeroRenderer {
/**
* 设置勇士图片
* @param image 勇士使用的图片
*/
setImage(image: ITexture): void;
/**
* 添加跟随者
* @param image 跟随者图块数字
* @param id 跟随者的 id,用于删除操作
*/
addFollower(image: number, id: string): void;
/**
* 取消跟随者
* @param follower 跟随者的 id
* @param animate 填 `true` 的话,如果删除了中间的跟随者,后续跟随者会使用移动动画移动到下一格,否则瞬移至下一格
*/
removeFollower(follower: string, animate: boolean): Promise<void>;
/**
* 移除所有跟随者
*/
removeAllFollowers(): void;
/**
* 设置勇士位置
*/
setPosition(x: number, y: number): void;
/**
* 开始移动,在移动前需要调用此方法切换勇士状态
*/
startMove(): void;
/**
* 等待勇士移动停止后,将移动状态切换为停止
* @param waitFollower 是否也等待跟随者移动结束
*/
waitMoveEnd(waitFollower: boolean): Promise<void>;
/**
* 立刻停止移动,勇士瞬移到目标点
* @param stopFollower 是否也立刻停止跟随者的移动,此时跟随者也会瞬移到它们应该到达的地方
*/
stopMove(stopFollower: boolean): void;
/**
* 勇士朝某个方向移动
* @param direction 移动方向
*/
move(direction: FaceDirection, time: number): Promise<void>;
/**
* 跳跃勇士至目标点
* @param x 目标点横坐标
* @param y 目标点纵坐标
* @param time 跳跃时长
* @param waitFollower 是否等待跟随者也跳跃完毕
*/
jumpTo(
x: number,
y: number,
time: number,
waitFollower: boolean
): Promise<void>;
/**
* 设置勇士不透明度
* @param alpha 不透明度
*/
setAlpha(alpha: number): void;
/**
* 设置跟随者的不透明度
* @param identifier 跟随者标识符
* @param alpha 跟随者不透明度
*/
setFollowerAlpha(identifier: string, alpha: number): void;
/**
* 摧毁这个勇士渲染拓展,释放相关资源
*/
destroy(): void;
}
@@ -1,3 +1,9 @@
export * from './asset';
export * from './block';
export * from './constant';
export * from './element';
export * from './moving';
export * from './renderer';
export * from './status';
export * from './types';
export * from './vertex';
export * from './viewport';
@@ -24,11 +24,11 @@ export interface IMovingRenderer {
}
export class MovingBlock extends DynamicBlockStatus implements IMovingBlock {
readonly texture: IMaterialFramedData;
readonly tile: number;
readonly renderer: IMovingRenderer;
readonly layer: IMapLayer;
texture: IMaterialFramedData;
index: number;
x: number = 0;
y: number = 0;
@@ -100,12 +100,19 @@ export class MovingBlock extends DynamicBlockStatus implements IMovingBlock {
this.posUpdated = true;
}
setTexture(texture: IMaterialFramedData): void {
if (texture === this.texture) return;
this.texture = texture;
this.renderer.vertex.updateMoving(this, true);
}
lineTo(
x: number,
y: number,
time: number,
timing?: TimingFn
): Promise<this> {
if (!this.end) return Promise.resolve(this);
this.startX = this.x;
this.startY = this.y;
this.targetX = x;
@@ -129,6 +136,7 @@ export class MovingBlock extends DynamicBlockStatus implements IMovingBlock {
}
moveAs(curve: TimingFn<2>, time: number, timing?: TimingFn): Promise<this> {
if (!this.end) return Promise.resolve(this);
this.time = time;
this.line = false;
this.relative = false;
@@ -154,6 +162,7 @@ export class MovingBlock extends DynamicBlockStatus implements IMovingBlock {
time: number,
timing?: TimingFn
): Promise<this> {
if (!this.end) return Promise.resolve(this);
this.time = time;
this.line = false;
this.relative = false;
@@ -225,6 +234,25 @@ export class MovingBlock extends DynamicBlockStatus implements IMovingBlock {
return true;
}
endMoving(): void {
this.end = true;
if (this.line) {
this.x = this.targetX;
this.y = this.targetY;
} else {
const [x, y] = this.curve(1);
if (this.relative) {
this.x = x + this.startX;
this.y = y + this.startY;
} else {
this.x = x;
this.y = y;
}
}
this.promiseFunc();
this.posUpdated = true;
}
destroy(): void {
this.renderer.deleteMoving(this);
}
@@ -18,6 +18,7 @@ import {
IMapBackgroundConfig,
IMapRenderConfig,
IMapRenderer,
IMapRendererTicker,
IMapVertexGenerator,
IMapViewportController,
IMovingBlock,
@@ -161,6 +162,8 @@ export class MapRenderer
private needUpdateFrameCounter: boolean = true;
/** 帧动画速率 */
private frameSpeed: number = 300;
/** 帧动画列表 */
private tickers: Set<MapRendererTicker> = new Set();
/** 画布元素 */
readonly canvas: HTMLCanvasElement;
@@ -1494,6 +1497,16 @@ export class MapRenderer
}
}
requestTicker(fn: (timestamp: number) => void): IMapRendererTicker {
const ticker = new MapRendererTicker(this, fn, this.timestamp);
this.tickers.add(ticker);
return ticker;
}
removeTicker(ticker: MapRendererTicker): void {
this.tickers.delete(ticker);
}
updateTransform(): void {
this.needUpdateTransform = true;
}
@@ -1515,10 +1528,7 @@ export class MapRenderer
class RendererLayerStateHook implements Partial<ILayerStateHooks> {
constructor(readonly renderer: MapRenderer) {}
onChangeBackground(
_: IHookController<ILayerStateHooks>,
tile: number
): void {
onChangeBackground(tile: number): void {
this.renderer.setTileBackground(tile);
}
@@ -1531,7 +1541,6 @@ class RendererLayerStateHook implements Partial<ILayerStateHooks> {
}
onUpdateLayerArea(
_: IHookController<ILayerStateHooks>,
layer: IMapLayer,
x: number,
y: number,
@@ -1542,7 +1551,6 @@ class RendererLayerStateHook implements Partial<ILayerStateHooks> {
}
onUpdateLayerBlock(
_: IHookController<ILayerStateHooks>,
layer: IMapLayer,
block: number,
x: number,
@@ -1551,3 +1559,20 @@ class RendererLayerStateHook implements Partial<ILayerStateHooks> {
this.renderer.updateLayerBlock(layer, block, x, y);
}
}
class MapRendererTicker implements IMapRendererTicker {
constructor(
readonly renderer: MapRenderer,
readonly fn: (timestamp: number) => void,
public timestamp: number
) {}
tick(timestamp: number) {
this.timestamp = timestamp;
this.fn(timestamp);
}
remove(): void {
this.renderer.removeTicker(this);
}
}
@@ -198,6 +198,12 @@ export interface IMovingBlock extends IBlockStatus {
*/
setPos(x: number, y: number): void;
/**
* 设置此移动图块使用的贴图,最好预先打包至图集中,否则动态重建图集会很耗时间
* @param texture 贴图对象
*/
setTexture(texture: IMaterialFramedData): void;
/**
* 沿直线移动到目标点
* @param x 目标横坐标,可以填小数
@@ -236,12 +242,27 @@ export interface IMovingBlock extends IBlockStatus {
*/
stepMoving(timestamp: number): boolean;
/**
* 立刻停止移动
*/
endMoving(): void;
/**
* 摧毁这个移动图块对象,之后不会再显示到画面上
*/
destroy(): void;
}
export interface IMapRendererTicker {
/** 当前的时间戳 */
readonly timestamp: number;
/**
* 移除这个帧函数
*/
remove(): void;
}
export interface IMapRenderer {
/** 地图渲染器使用的资源管理器 */
readonly manager: IMaterialManager;
@@ -456,6 +477,12 @@ export interface IMapRenderer {
* 当前地图状态是否发生改变,需要更新
*/
needUpdate(): boolean;
/**
* 添加一个每帧执行的函数
* @param fn 每帧执行的函数
*/
requestTicker(fn: (timestamp: number) => void): IMapRendererTicker;
}
export interface IMapVertexArray {
@@ -48,6 +48,7 @@ import { mainUIController } from './controller';
import { LayerGroup } from '../elements';
import { isNil } from 'lodash-es';
import { materials } from '@user/client-base';
import { mainMapRenderer } from '../commonIns';
const MainScene = defineComponent(() => {
//#region 基本定义
@@ -261,6 +262,7 @@ const MainScene = defineComponent(() => {
return () => (
<container id="main-scene" width={MAIN_WIDTH} height={MAIN_HEIGHT}>
<sprite
hidden
render={testRender}
loc={[180, 0, 480, 480]}
zIndex={1000}
@@ -283,6 +285,7 @@ const MainScene = defineComponent(() => {
onMove={moveMap}
>
<map-render
renderer={mainMapRenderer}
layerState={state.layer}
loc={[0, 0, MAP_WIDTH, MAP_HEIGHT]}
/>