# 二维游戏使用参考
# 概述
本参考将会实现一个大量渲染元素,移动增删,执行帧动画的用例,案例素材来自kenney.nl
。
# 背景与基础UI布局
参考UI系统使用指引
,实现背景地图以及基础的摇杆,人物之类的U功能。
# 用户开发脚本的引入
详情可参考
脚本开发
文档
import engine from "engine"
// 基本的ScriptComponent
@engine.decorators.serialize("Main")
export default class Main extends engine.Script {
public onStart(): void {}
public onEnable(): void {}
public onDisable(): void {}
public onUpdate(): void {}
}
将开发的Typescript文件放置于/assets
目录或子目录下,然后在对应节点挂载需要的ScriptComponet
,运行时会与普通组件一致,根据生命周期执行逻辑。
# 资源绑定与加载
详情可参考
资源系统
文档
将需要使用的素材加入到工程中。
在onStart阶段,加载需要的所有资源,可以利用loadTask上的current
和total
或根据回调统计,开发进度条,详情可以参考LoadTask
的使用。
// 根据资源路径加载资源,缓存入对应的SpriteFrame组中。
const task1 = engine.loader.load("gameTexture/zombie.spriteframe");
task1.promise.then(spriteFrame => {
this.zombieActionSpriteFrames[0] = spriteFrame as engine.SpriteFrame;
this.loadedNumber++;
});
加载完毕后,update节点创建Zombie节点并挂到场上,场上active节点会马上进入当帧的渲染逻辑。
// Zombie类的内部实现
export class Zombie extends Charater {
constructor() {
super();
// 创建二维节点
this.entity = engine.game.createEntity2D('zombie' + zombieIndex);
// 二维节点大小设置
this.entity.transform2D.size = tmpVec2.setValue(this.width, this.height);
// 二维节点添加UISripte组件用于图片绘制
this.sprite = this.entity.addComponent(engine.UISprite) as engine.UISprite;
zombieIndex++;
}
public setStartPosition(x: number, y: number) {
this.entity.transform2D.position = tmpVec2.setValue(x, y);
}
public setStartSpriteFrame(spriteFrame: engine.SpriteFrame) {
this.startSpriteFrame = spriteFrame;
this.sprite.spriteFrame = spriteFrame;
}
public setSpriteFrame(spriteFrame: engine.SpriteFrame) {
this.sprite.spriteFrame = spriteFrame;
}
public setAnimationSpriteFrame(spriteFrames: engine.SpriteFrame[]) {
this.animationFrames = spriteFrames;
}
}
const addZombieNumber = 20;
for (let i = 0; i < addZombieNumber; i++ ) {
// Zombie起始位置,基于人物位置的一个区域内的随机位置
const x = this.playerTransform2D.positionX + Math.ceil(Math.random() * this.areaX - this.areaX/2);
const y = this.playerTransform2D.positionY + Math.ceil(Math.random() * this.areaY - this.areaY/2);
// 创建Zombie类
const zombie = new Zombie();
zombie.setStartPosition(x, y);
zombie.setStartSpriteFrame(this.zombieActionSpriteFrames[0]);
zombie.setAnimationSpriteFrame(this.zombieActionSpriteFrames);
// 将Zombie元素加到场上
this.worldTransform2D.addChild(zombie.entity.transform2D);
this.zombies.push(zombie);
}
# 渲染元素帧动画管理
运行阶段,或根据需要,在额外的计时器内统一执行需要帧动画切换的元素即可。
// SpriteFrame切换
public updateSpriteFrame() {
if (this.useFrameAniamtion) {
const nextFrameIndex = (this.frameIndex + 1) % this.animationFrames.length;
this.setSpriteFrame(this.animationFrames[nextFrameIndex]);
this.frameIndex = nextFrameIndex;
} else {
if (this.sprite.spriteFrame !== this.startSpriteFrame) {
this.setSpriteFrame(this.startSpriteFrame);
}
}
}
// 动画计时器
this.animationTimer = setInterval(() => {
for (let i = 0; i < this.zombies.length; i++) {
const zombie = this.zombies[i];
zombie.updateSpriteFrame();
}
this.player.updateSpriteFrame();
}, 160);
# 节点添加销毁与移动
public updatePosition(tx: number, ty: number) {
const disX = tx - this.entity.transform2D.positionX;
const disY = ty - this.entity.transform2D.positionY;
const absDx = Math.abs(disX);
const absDy = Math.abs(disY);
const widthArea = this.width * 4 / 5;
const heightArea = this.height * 4 / 5;
if (absDx <= widthArea && absDy <= heightArea) {
// 销毁节点
this.entity.destroy();
return true;
} else {
// ...
}
}
# 摇杆与触摸事件
编写对应的ScriptComponent,并绑定到摇杆节点,然后配合TouchInputComponent组件使用即可。
import engine from "engine";
declare type TouchInputEvent = import("engine/input/touch").TouchInputEvent;
declare type Entity2D = import("engine/scene/scene").Entity2D;
@engine.decorators.serialize("Control")
export default class Control extends engine.Script {
constructor(public readonly entity: Entity2D) {
super(entity);
this.touchStartHandler = this.touchStartHandler.bind(this);
this.touchEndHandler = this.touchEndHandler.bind(this);
this.touchMoveHandler = this.touchMoveHandler.bind(this);
this.touchCancelHandler = this.touchCancelHandler.bind(this);
}
public onEnable(): void {
// ...
}
public onDisable(): void {
// ...
}
public touchStartHandler(t: engine.TouchInputComponent, e: TouchInputEvent): void {
// ...
}
public touchEndHandler(t: engine.TouchInputComponent, e: TouchInputEvent): void {
// ...
}
public touchMoveHandler(t: engine.TouchInputComponent, e: TouchInputEvent): void {
// ...
}
public touchCancelHandler(t: engine.TouchInputComponent, e: TouchInputEvent): void {
// ...
}
}