0.0.0-alpha.1 • Published 5 months ago

srm-engine-mars v0.0.0-alpha.1

Weekly downloads
-
License
MIT
Repository
-
Last release
5 months ago

Galacean Engine Mars

在 Galacean 环境下加载并渲染 Mars 动效

使用步骤

1、安装依赖

$ npm i @galacean/engine --save
# 安装 Galacean 的 Mars 组件
$ npm i @galacean/engine-mars --save

1、Galacean 场景初始化

在 Galacean 中实现 Mars 首先要创建一个 Galacean 场景(如果你没有创建 Engine 对象的话):

import { Camera, WebGLEngine, WebGLMode } from '@galacean/engine';
import { setEngine } from '@galacean/engine-mars';

// 创建一个 canvas
const canvas = document.createElement('canvas');
// 创建一个 engine 对象,WebGL 版本可选
const engine = await WebGLEngine.create({ canvas, graphicDeviceOptions: { webGLMode: WebGLMode.WebGL2 } });
const rootEntity = engine.sceneManager.activeScene.createRootEntity();
const cameraEntity = rootEntity.createChild('camera');
// 创建一个相机对象
const camera = cameraEntity.addComponent(Camera);

engine.canvas.resizeByClientSize();

camera.fieldOfView = 60;
camera.nearClipPlane = 0.1;
camera.farClipPlane = 1000;

camera.enableFrustumCulling = false;
cameraEntity.transform.setPosition(0, 0, 8);

// 对于 engine 的全局初始化
setEngine();

2、实例化 GalaceanDisplayComponent 并加载 Mars 资源

Mars 在 Galacean 场景中渲染(使用场景如氛围粒子等)

import { GalaceanDisplayComponent } from '@galacean/engine-mars';

// 创建一个空的 Entity 对象
const entity = rootEntity.createChild();
const displayComponent = entity.addComponent(GalaceanDisplayComponent);

// 初始化时把当前 engine 中的相机传递过去
displayComponent.initialize(engine._hardwareRenderer.gl, { camera });
// 加载 Mars 的资源
const scene = await displayComponent.loadScene('./xxx.json');

// RTS调用
const transform = displayComponent.entity.transform;
// 调整平移
transform.position.y = 5; // transform.setPosition(0,5,0);
// 调整旋转
transform.rotation.x = 90; // transform.setRotation(90,0,0);
// 调整缩放
transform.scale.x = 2; // transform.setScale(2,1,1);

// 播放 Mars 资源
await displayComponent.play(scene);

Mars 和编辑器渲染效果同步(使用场景如弹窗、UI 层组件等)

import { GalaceanDisplayComponent } from '@galacean/engine-mars';

// 创建一个空的 Entity 对象
const entity = rootEntity.createChild();
const displayComponent = entity.addComponent(GalaceanDisplayComponent);

// 初始化不传入 Galacean 相机则默认使用Mars自带相机和编辑器保持同步
displayComponent.initialize(engine._hardwareRenderer.gl);
// 加载 Mars 的资源
const scene = await displayComponent.loadScene('./xxx.json');

// RTS 调用
// 以第一个合成为例
const transform = displayComponent.compositions[0].rootTransform;
// 调整平移
transform.position[1] = 5; // transform.setPosition(0,5,0);
// 调整旋转
transform.setRotation(90,0,0);
// 调整缩放
transform.scale[0] = 2; // transform.setScale(2,1,1);


// 播放 Mars 资源
await displayComponent.play(scene);

Tips

  • 如果你想创建多个 Mars 只需要重复上述步骤就可以了
  • 单独暂停 Mars:displayComponent.pause();
  • 单独继续播放 Mars:displayComponent.resume();
  • 单独销毁操作:在渲染 Mars 中不需要用户关心 Mars 的销毁,如果想强行销毁 Mars 请调用 displayComponent.dispose(name?),其中 name 参数可选,销毁指定的 composition,默认全部销毁
  • 当然也可以使用这样的方式播放 Mars:displayComponent.loadScene('./xxx.json').then(scene => displayComponent.play(scene));

3、执行 Galacean 渲染

// 当然你也可以先执行渲染,再实例化 Mars
engine.run();

高级用法

数据模版支持

下面给出如何使用 Mars 中的数据模板:

import { GalaceanDisplayComponent } from '@galacean/engine-mars';

// 创建一个空的 Entity 对象
const entity = rootEntity.createChild();
const displayComponent = entity.addComponent(GalaceanDisplayComponent);

// 初始化时把当前 engine 中的相机传递过去
displayComponent.initialize(engine._hardwareRenderer.gl, { camera });
// 加载 Mars 的资源
const scene = await displayComponent.loadScene('./xxx.json',{
  variables:{
    // 动态图片,支持传入图片地址或地址数组(1.1.36后支持)
    background: 'https://mdn.alipayobjects.com/mars/afts/img/A*-XqlTLrGy1YAAAAAAAAAAAAADlB4AQ/original', // 如果图片加载失败,将会触发加载失败
    image_avatar: ['https://mdn.alipayobjects.com/mars/afts/img/A*-XqlTLrGy1YAAAAAAAAAAAAADlB4AQ/original', 'https://mdn.alipayobjects.com/mars/afts/img/A*-XqlTLrGy1YAAAAAAAAAAAAADlB4AQ/original'], // 如果第一个加载失败,将尝试使用第二个地址,都失败将会触发加载失败
    // 动态文本
    amount: 88.8,
    name: 'abc',
  },
  // 缩放比例,如果图片比较糊,可以用2(但会增大图片内存)
  templateScale: 1,
});

// 播放 Mars 资源
await displayComponent.play(scene);

和直接在 MarsPlayer 中的使用类似,更多使用方法参考 Mars 的开发者文档:https://yuque.antfin.com/huoxing/knaszl/tiuh8k7zgktrz68l

多 DisplayComponent 的播放

在 Galacean Mars 中允许创建多个 DisplayComponent,多个 DisplayComponent 也是可以一起播放 Mars 的,下面给出多个 DisplayComponent 如何一起播放 Mars

import { GalaceanDisplayComponent } from '@galacean/engine-mars';

// 创建一个空的 Entity 对象
const entity0 = rootEntity.createChild();
const displayComponent0 = entity.addComponent(GalaceanDisplayComponent);

// 初始化不传入 Galacean 相机则默认使用Mars自带相机和编辑器保持同步
displayComponent0.initialize(engine._hardwareRenderer.gl);
// 加载 Mars 的资源
const scene0 = await displayComponent0.loadScene('./xxx.json');

// RTS 调用
// 以第一个合成为例
const transform = displayComponent0.compositions[0].rootTransform;
// 调整平移
transform.position[1] = 5; // transform.setPosition(0,5,0);
// 调整旋转
transform.setRotation(90,0,0);
// 调整缩放
transform.scale[0] = 2; // transform.setScale(2,1,1);


// 播放 Mars 资源
await displayComponent0.play(scene0);

const entity1 = rootEntity.createChild();
const displayComponent1 = entity.addComponent(GalaceanDisplayComponent);

// 初始化不传入 Galacean 相机则默认使用Mars自带相机和编辑器保持同步
displayComponent1.initialize(engine._hardwareRenderer.gl);
// 加载 Mars 的资源
const scene1 = await displayComponent.loadScene('./xxx.json');


// 播放 Mars 资源,这样 displayComponent1 中的 Mars 都会置于 displayComponent0 的上层
await displayComponent1.play(scene, { componentRenderOrder:2 });

多合成播放

下面给出如何使用 Mars 中的多合成播放:

import { GalaceanDisplayComponent } from '@galacean/engine-mars';

// 创建一个空的 Entity 对象
const entity = rootEntity.createChild();
const displayComponent = entity.addComponent(GalaceanDisplayComponent);
const json = [
  './xxx.json',
  './xxx.json',
  './xxx.json'
]

// 初始化时把当前 engine 中的相机传递过去
displayComponent.initialize(engine._hardwareRenderer.gl, { camera });

// 加载compositions
const compositions = await Promise.all(json.map(json => displayComponent.loadScene(json)));
// 尽量不要用index来获取合成
const com = compositions[1];
// 给所有的 composition 添加 onEnd 监听
displayComponent.handleEnd = async () => {
  await displayComponent.play(com, {
    multipleCompositions: true, // 【重要】多合成播放标志位打开
    // 【重要】红包雨点击时间段播放多次,则需要打开
    baseRenderOrder: 1, // 播放的层级顺序,默认后续播放的在上层
  });
}

// 给单独的 composition 添加 onEnd 监听,composition 顺序和 json 顺序一致
compositions[0].handleEnd = async () => {
  await displayComponent.play(com, {
    multipleCompositions: true, // 【重要】多合成播放标志位打开
    // 【重要】红包雨点击时间段播放多次,则需要打开
    baseRenderOrder: 1, // 播放的层级顺序,默认后续播放的在上层
  });
  displayComponent.gc();
}
// 播放 Mars 资源
await displayComponent.play(compositions[0], {
  multipleCompositions: true, // 【重要】多合成播放标志位打开
  // 【重要】红包雨点击时间段播放多次,则需要打开
  baseRenderOrder: 1, // 播放的层级顺序,默认后续播放的在上层
});

交互元素

开发和设计约定好交互元素名称后,便可以通过交互回调来监听渲染中的交互元素了,下面给出如何使用 Mars 中的交互元素:

import { GalaceanDisplayComponent } from '@galacean/engine-mars';

// 创建一个空的 Entity 对象
const entity = rootEntity.createChild();
const displayComponent = entity.addComponent(GalaceanDisplayComponent);

// 初始化时把当前 engine 中的相机传递过去
displayComponent.initialize(engine._hardwareRenderer.gl, { camera });
// 加载 Mars 的资源
const composition = await displayComponent.loadScene('./xxx.json');

displayComponent.handleMessageItem = (item: MessageItem) => {
  console.log(item.name); //设置多个交互元素需要根据name判断是否指定元素
  if (item.phrase === spec.MESSAGE_ITEM_PHRASE_BEGIN) {
    // 元素创建
  } else if (item.phrase === spec.MESSAGE_ITEM_PHRASE_END) {
    // 元素销毁
  }
};

// 播放 Mars 资源
await displayComponent.play(scene);

displayComponent.handleItemClicked = (item) => {
  // 设置多个元素的点击交互需要根据name判断是否指定元素
  console.log('trigger onItemClicked')
  console.log(item.name);
},

和直接在 MarsPlayer 中的使用类似,更多使用方法参考 Mars 的开发者文档:https://yuque.antfin.com/huoxing/knaszl/us047ue7mef3k08a

Tips

  • 不需要 interactive 参数作为开关了

Spine 插件

// 引入 spine 插件
// ES Module
import '@galacean/engine-mars/plugin-spine';
// 非 ES Module
import '@galacean/engine-mars/dist/plugin-spine';

注意事项

蒙版问题

默认背景颜色下,蒙版可能会和编辑器上不一致,如果想要和编辑器中效果一致的话,请调整背景颜色为黑色,代码如下:

// 设置背景颜色
engine.sceneManager.activeScene.background.solidColor.set(0, 0, 0, 1);

API 文档

http://creation.alipay.net/engine-mars/

开发

环境准备

  • Node.js >= 16.0.0
  • Pnpm latest
    • 安装:
      • npm install -g pnpm
    • 升级:
      • pnpm install -g pnpm

本地开发

开始开发

# 1. 安装依赖(首次)
pnpm install
# 2. demo
pnpm dev

浏览器打开:http://localhost:8080/demo/

低端设备测试

# demo 的 legacy 版本
pnpm preview