赞 | 65 |
VIP | 231 |
好人卡 | 2 |
积分 | 19 |
经验 | 35171 |
最后登录 | 2024-9-15 |
在线时间 | 1554 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 1912
- 在线时间
- 1554 小时
- 注册时间
- 2013-4-13
- 帖子
- 917
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
大家都知道能够显示在游戏画面的有Sprite和各种Window,
实际上这些类都是从PIXI.Container继承而来的,
当我们要自己设计一个可显示对象的时候, 其实可以从Container这个级别开始
虽然会失去很多预设功能, 不过这些都可以自己按需求加回去
另一个问题是几个平行的可显示对象互相交互也需要互相引用
这里通过引用一个订阅者, 解决了这个问题
下面是具体玩法:
// 模拟异步行为的等待 const delay = (timeout) => { return new Promise((resolve) => { setTimeout(resolve, timeout); }); }; const buildTestObject = () => { // 实例一个建造者 const builder = GameObject.builder(); // 读取Bitmap const windowskin = ImageManager.loadSystem('Window'); const face = ImageManager.loadFace('Actor1'); // 随便弄俩精灵, 一个背景, 一个头像 windowBackSprite = new Sprite(); windowBackSprite.alpha = 192 / 255; windowContentsSprite = new Sprite(); windowContentsSprite.bitmap = new Bitmap(500, 500); // 开始建造 builder // 当一切加载完毕以后执行 // 这里初始化了绑定的数据和窗口大小 .setupHandler('start', (self) => { console.log('start'); self.initData({ faceIndex: 0 }); self.x = 50; self.y = 50; self.width = 200; self.height = 200; }) // 每次更新的时候执行 // 从data里获取faceIndex // 判断用户输入选择向左或者向右切换头像 .setupHandler('update', (self) => { const { faceIndex } = self.getData(); if (Input.isRepeated('left')) { self.setData({ faceIndex: (faceIndex + 7) % 8 }); } if (Input.isRepeated('right')) { self.setData({ faceIndex: (faceIndex + 1) % 8 }); } }) // 初始化的时候触发, 会等待所有异步操作完毕 .setupHandler('create', async (self) => { console.log('creating...'); await Promise.all([ new Promise((resolve) => { windowskin.addLoadListener(resolve); }), new Promise((resolve) => { face.addLoadListener(resolve); }), ]); console.log('loaded...'); await delay(1000); console.log('done!'); }) // 当更新绑定数据时候, initData不会触发change事件 // 判断faceIndex是否发生了改变 // 可以根据特定的值发生了变化来执行对应的操作 .setupHandler('change', (self, oldData) => { if (oldData.faceIndex !== self.getData().faceIndex) self.triggerEvent(self.getDrawHandler('face')); }) // 添加一个精灵 .addSprite('windowskin', windowBackSprite, (self) => { var w = self.width; var h = self.height; var bitmap = new Bitmap(w, h); windowBackSprite.bitmap = bitmap; windowBackSprite.setFrame(0, 0, w, h); if (w > 0 && h > 0 && windowskin) { var p = 96; bitmap.blt(windowskin, 0, 0, p, p, 0, 0, w, h); } }) // 添加另一个精灵 // 会从绑定数据中读取信息 .addSprite('face', windowContentsSprite, (self) => { windowContentsSprite.bitmap.clear(); var faceIndex = self.getData().faceIndex; var x = 0; var y = 0; var width = Window_Base._faceWidth; var height = Window_Base._faceHeight; var bitmap = ImageManager.loadFace('Actor1'); var pw = Window_Base._faceWidth; var ph = Window_Base._faceHeight; var sw = Math.min(width, pw); var sh = Math.min(height, ph); var dx = Math.floor(x + Math.max(width - pw, 0) / 2); var dy = Math.floor(y + Math.max(height - ph, 0) / 2); var sx = (faceIndex % 4) * pw + (pw - sw) / 2; var sy = Math.floor(faceIndex / 4) * ph + (ph - sh) / 2; windowContentsSprite.bitmap.blt( bitmap, sx, sy, sw, sh, dx, dy, width, height ); }); // 完成建造 return builder.build(); };
// 模拟异步行为的等待
const delay = (timeout) => {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
};
const buildTestObject = () => {
// 实例一个建造者
const builder = GameObject.builder();
// 读取Bitmap
const windowskin = ImageManager.loadSystem('Window');
const face = ImageManager.loadFace('Actor1');
// 随便弄俩精灵, 一个背景, 一个头像
windowBackSprite = new Sprite();
windowBackSprite.alpha = 192 / 255;
windowContentsSprite = new Sprite();
windowContentsSprite.bitmap = new Bitmap(500, 500);
// 开始建造
builder
// 当一切加载完毕以后执行
// 这里初始化了绑定的数据和窗口大小
.setupHandler('start', (self) => {
console.log('start');
self.initData({ faceIndex: 0 });
self.x = 50;
self.y = 50;
self.width = 200;
self.height = 200;
})
// 每次更新的时候执行
// 从data里获取faceIndex
// 判断用户输入选择向左或者向右切换头像
.setupHandler('update', (self) => {
const { faceIndex } = self.getData();
if (Input.isRepeated('left')) {
self.setData({ faceIndex: (faceIndex + 7) % 8 });
}
if (Input.isRepeated('right')) {
self.setData({ faceIndex: (faceIndex + 1) % 8 });
}
})
// 初始化的时候触发, 会等待所有异步操作完毕
.setupHandler('create', async (self) => {
console.log('creating...');
await Promise.all([
new Promise((resolve) => {
windowskin.addLoadListener(resolve);
}),
new Promise((resolve) => {
face.addLoadListener(resolve);
}),
]);
console.log('loaded...');
await delay(1000);
console.log('done!');
})
// 当更新绑定数据时候, initData不会触发change事件
// 判断faceIndex是否发生了改变
// 可以根据特定的值发生了变化来执行对应的操作
.setupHandler('change', (self, oldData) => {
if (oldData.faceIndex !== self.getData().faceIndex)
self.triggerEvent(self.getDrawHandler('face'));
})
// 添加一个精灵
.addSprite('windowskin', windowBackSprite, (self) => {
var w = self.width;
var h = self.height;
var bitmap = new Bitmap(w, h);
windowBackSprite.bitmap = bitmap;
windowBackSprite.setFrame(0, 0, w, h);
if (w > 0 && h > 0 && windowskin) {
var p = 96;
bitmap.blt(windowskin, 0, 0, p, p, 0, 0, w, h);
}
})
// 添加另一个精灵
// 会从绑定数据中读取信息
.addSprite('face', windowContentsSprite, (self) => {
windowContentsSprite.bitmap.clear();
var faceIndex = self.getData().faceIndex;
var x = 0;
var y = 0;
var width = Window_Base._faceWidth;
var height = Window_Base._faceHeight;
var bitmap = ImageManager.loadFace('Actor1');
var pw = Window_Base._faceWidth;
var ph = Window_Base._faceHeight;
var sw = Math.min(width, pw);
var sh = Math.min(height, ph);
var dx = Math.floor(x + Math.max(width - pw, 0) / 2);
var dy = Math.floor(y + Math.max(height - ph, 0) / 2);
var sx = (faceIndex % 4) * pw + (pw - sw) / 2;
var sy = Math.floor(faceIndex / 4) * ph + (ph - sh) / 2;
windowContentsSprite.bitmap.blt(
bitmap,
sx,
sy,
sw,
sh,
dx,
dy,
width,
height
);
});
// 完成建造
return builder.build();
};
在控制台输入
const a = buildTestObject()
SceneManager._scene.addChild(a)
就可以看到效果了:
以下是当文档来看也是极好的Typescript版本
declare type Maybe<T> = T | null;
/**
* 事件响应, 可以返回一个Promise
*/
type EventHandler = (self: GameObject, ...args: any[]) => void | Promise<any>;
/**
* 事件名
*/
type EventName =
| 'create'
| 'terminate'
| 'start'
| 'update'
| 'change'
| 'draw'
| string;
/**
* 处理全局消息通信
*/
class GlobalEventManager {
static listeners: Record<EventName, GameObject[]> = {};
private static getListeners(eventName: EventName) {
const listeners = this.listeners[eventName] || [];
if (!listeners.length) this.listeners[eventName] = listeners;
return listeners;
}
/**
* 订阅事件
*/
public static subscribe(item: GameObject, eventName: EventName) {
const listeners = this.getListeners(eventName);
if (listeners.find((listener) => listener === item)) return;
listeners.push(item);
}
/**
* 取消订阅
*/
public static unsubscribe(item: GameObject, eventName: EventName) {
const listeners = this.getListeners(eventName);
const index = listeners.indexOf(item);
if (index >= 0) listeners.splice(index, 1);
}
/**
* 取消全部订阅
*/
public static removeListener(item: GameObject) {
Object.keys(this.listeners).forEach((eventName) => {
this.unsubscribe(item, eventName);
});
}
/**
* 广播事件
*/
public static dispatch(eventName: EventName, ...args: []) {
const listeners = this.listeners[eventName] || [];
listeners.forEach((item) => {
item.triggerEvent(eventName, ...args);
});
}
}
class GameObjectBuilder<T = any> {
gameObject: GameObject<T>;
constructor() {
this.gameObject = new GameObject();
}
setupHandler(eventName: EventName, eventHandler: EventHandler) {
this.gameObject.setupHandler(eventName, eventHandler);
return this;
}
initData(data: Maybe<T>) {
this.gameObject.initData(data);
return this;
}
addSprite(name: string, sprite: PIXI.Sprite, handler: EventHandler) {
this.gameObject.addSprite(name, sprite, handler);
return this;
}
build() {
return this.gameObject;
}
}
class GameObject<T = any> extends PIXI.Container {
static builder() {
return new GameObjectBuilder();
}
private _width: number;
private _height: number;
children: GameObject[] = [];
willCreate: boolean = true;
willTerminate: boolean = false;
isCreated: boolean = false;
isTerminated: boolean = false;
isStarted: boolean = false;
eventHandlers: Record<EventName, EventHandler> = {};
data: Maybe<T> = null;
sprites: Record<string, PIXI.Sprite> = {};
/**
* 覆写PIXI默认的宽高, 防止图像拉伸
*/
constructor(width = 0, height = 0) {
super();
this._width = width;
this._height = height;
Object.defineProperties(this, {
width: {
get: () => this._width,
set: (w) => {
this._width = w;
this.refresh();
},
},
height: {
get: () => this._height,
set: (h) => {
this._height = h;
this.refresh();
},
},
});
}
/**
* 注册事件处理方法或异步方法
*/
setupHandler(eventName: EventName, eventHandler: EventHandler) {
this.eventHandlers[eventName] = eventHandler;
}
/**
* 移除已注册的方法
*/
removeHandler(eventName: EventName) {
delete this.eventHandlers[eventName];
}
/**
* 手动触发事件
*/
triggerEvent(eventName: EventName, ...args: any[]): void | Promise<any> {
const handler = this.eventHandlers[eventName];
if (handler) return handler(this, ...args);
}
/**
* 获取绘制事件名
*/
getDrawHandler(name: string) {
return `draw${name.replace(/^./, (str) => str.toUpperCase())}`;
}
/**
* 重绘全部精灵
*/
refresh() {
Object.keys(this.sprites).forEach((name) => {
this.triggerEvent(this.getDrawHandler(name));
});
}
/**
* 添加精灵
*/
addSprite(name: string, sprite: PIXI.Sprite, handler: EventHandler) {
this.sprites[name] = sprite;
this.setupHandler(this.getDrawHandler(name), handler);
this.addChild(sprite);
}
/**
* 初始化数据, 不会触发数据更新事件
*/
initData(data: Maybe<T>) {
this.data = data;
}
/**
* 获取数据
*/
getData() {
return this.data;
}
/**
* 数据绑定, 触发数据更新事件
*/
setData(data: Maybe<T>) {
const oldData = this.data;
this.data = data;
this.triggerEvent('change', oldData);
}
/**
* 第一次载入场景时触发, 用于处理异步行为
*/
async onCreate() {
this.willCreate = false;
await this.triggerEvent('create');
this.isCreated = true;
}
/**
* 完成初始化后触发, 用于初始化对象
*/
onStart() {
this.triggerEvent('start');
this.refresh();
this.isStarted = true;
}
/**
* 每一帧更新事件, 不要在这里重绘任何东西
*/
onUpdate() {
this.triggerEvent('update');
this.updateChildren();
}
/**
* 用来处理终止事件
*/
async onTerminate() {
this.willTerminate = false;
await this.triggerEvent('terminate');
this.isTerminated = true;
GlobalEventManager.removeListener(this);
}
/**
* 主循环
*/
update() {
if (this.isStarted) {
this.onUpdate();
} else if (this.willCreate) {
this.onCreate();
} else if (
this.isCreated &&
this.children.every((child) => child.isCreated !== false)
) {
this.onStart();
} else if (
this.willTerminate &&
this.children.every((child) => child.isTerminated !== false)
) {
this.onTerminate();
}
}
/**
* 更新子对象
*/
updateChildren() {
this.children.forEach((child) => {
child.update();
});
}
/**
* 终止对象
*/
terminate() {
this.willTerminate = true;
this.children.forEach((child) => {
child.terminate();
});
}
}
declare type Maybe<T> = T | null;
/**
* 事件响应, 可以返回一个Promise
*/
type EventHandler = (self: GameObject, ...args: any[]) => void | Promise<any>;
/**
* 事件名
*/
type EventName =
| 'create'
| 'terminate'
| 'start'
| 'update'
| 'change'
| 'draw'
| string;
/**
* 处理全局消息通信
*/
class GlobalEventManager {
static listeners: Record<EventName, GameObject[]> = {};
private static getListeners(eventName: EventName) {
const listeners = this.listeners[eventName] || [];
if (!listeners.length) this.listeners[eventName] = listeners;
return listeners;
}
/**
* 订阅事件
*/
public static subscribe(item: GameObject, eventName: EventName) {
const listeners = this.getListeners(eventName);
if (listeners.find((listener) => listener === item)) return;
listeners.push(item);
}
/**
* 取消订阅
*/
public static unsubscribe(item: GameObject, eventName: EventName) {
const listeners = this.getListeners(eventName);
const index = listeners.indexOf(item);
if (index >= 0) listeners.splice(index, 1);
}
/**
* 取消全部订阅
*/
public static removeListener(item: GameObject) {
Object.keys(this.listeners).forEach((eventName) => {
this.unsubscribe(item, eventName);
});
}
/**
* 广播事件
*/
public static dispatch(eventName: EventName, ...args: []) {
const listeners = this.listeners[eventName] || [];
listeners.forEach((item) => {
item.triggerEvent(eventName, ...args);
});
}
}
class GameObjectBuilder<T = any> {
gameObject: GameObject<T>;
constructor() {
this.gameObject = new GameObject();
}
setupHandler(eventName: EventName, eventHandler: EventHandler) {
this.gameObject.setupHandler(eventName, eventHandler);
return this;
}
initData(data: Maybe<T>) {
this.gameObject.initData(data);
return this;
}
addSprite(name: string, sprite: PIXI.Sprite, handler: EventHandler) {
this.gameObject.addSprite(name, sprite, handler);
return this;
}
build() {
return this.gameObject;
}
}
class GameObject<T = any> extends PIXI.Container {
static builder() {
return new GameObjectBuilder();
}
private _width: number;
private _height: number;
children: GameObject[] = [];
willCreate: boolean = true;
willTerminate: boolean = false;
isCreated: boolean = false;
isTerminated: boolean = false;
isStarted: boolean = false;
eventHandlers: Record<EventName, EventHandler> = {};
data: Maybe<T> = null;
sprites: Record<string, PIXI.Sprite> = {};
/**
* 覆写PIXI默认的宽高, 防止图像拉伸
*/
constructor(width = 0, height = 0) {
super();
this._width = width;
this._height = height;
Object.defineProperties(this, {
width: {
get: () => this._width,
set: (w) => {
this._width = w;
this.refresh();
},
},
height: {
get: () => this._height,
set: (h) => {
this._height = h;
this.refresh();
},
},
});
}
/**
* 注册事件处理方法或异步方法
*/
setupHandler(eventName: EventName, eventHandler: EventHandler) {
this.eventHandlers[eventName] = eventHandler;
}
/**
* 移除已注册的方法
*/
removeHandler(eventName: EventName) {
delete this.eventHandlers[eventName];
}
/**
* 手动触发事件
*/
triggerEvent(eventName: EventName, ...args: any[]): void | Promise<any> {
const handler = this.eventHandlers[eventName];
if (handler) return handler(this, ...args);
}
/**
* 获取绘制事件名
*/
getDrawHandler(name: string) {
return `draw${name.replace(/^./, (str) => str.toUpperCase())}`;
}
/**
* 重绘全部精灵
*/
refresh() {
Object.keys(this.sprites).forEach((name) => {
this.triggerEvent(this.getDrawHandler(name));
});
}
/**
* 添加精灵
*/
addSprite(name: string, sprite: PIXI.Sprite, handler: EventHandler) {
this.sprites[name] = sprite;
this.setupHandler(this.getDrawHandler(name), handler);
this.addChild(sprite);
}
/**
* 初始化数据, 不会触发数据更新事件
*/
initData(data: Maybe<T>) {
this.data = data;
}
/**
* 获取数据
*/
getData() {
return this.data;
}
/**
* 数据绑定, 触发数据更新事件
*/
setData(data: Maybe<T>) {
const oldData = this.data;
this.data = data;
this.triggerEvent('change', oldData);
}
/**
* 第一次载入场景时触发, 用于处理异步行为
*/
async onCreate() {
this.willCreate = false;
await this.triggerEvent('create');
this.isCreated = true;
}
/**
* 完成初始化后触发, 用于初始化对象
*/
onStart() {
this.triggerEvent('start');
this.refresh();
this.isStarted = true;
}
/**
* 每一帧更新事件, 不要在这里重绘任何东西
*/
onUpdate() {
this.triggerEvent('update');
this.updateChildren();
}
/**
* 用来处理终止事件
*/
async onTerminate() {
this.willTerminate = false;
await this.triggerEvent('terminate');
this.isTerminated = true;
GlobalEventManager.removeListener(this);
}
/**
* 主循环
*/
update() {
if (this.isStarted) {
this.onUpdate();
} else if (this.willCreate) {
this.onCreate();
} else if (
this.isCreated &&
this.children.every((child) => child.isCreated !== false)
) {
this.onStart();
} else if (
this.willTerminate &&
this.children.every((child) => child.isTerminated !== false)
) {
this.onTerminate();
}
}
/**
* 更新子对象
*/
updateChildren() {
this.children.forEach((child) => {
child.update();
});
}
/**
* 终止对象
*/
terminate() {
this.willTerminate = true;
this.children.forEach((child) => {
child.terminate();
});
}
}
讲人话版JS:
"use strict"; /** * 处理全局消息通信 */ class GlobalEventManager { static getListeners(eventName) { const listeners = this.listeners[eventName] || []; if (!listeners.length) this.listeners[eventName] = listeners; return listeners; } /** * 订阅事件 */ static subscribe(item, eventName) { const listeners = this.getListeners(eventName); if (listeners.find((listener) => listener === item)) return; listeners.push(item); } /** * 取消订阅 */ static unsubscribe(item, eventName) { const listeners = this.getListeners(eventName); const index = listeners.indexOf(item); if (index >= 0) listeners.splice(index, 1); } /** * 取消全部订阅 */ static removeListener(item) { Object.keys(this.listeners).forEach((eventName) => { this.unsubscribe(item, eventName); }); } /** * 广播事件 */ static dispatch(eventName, ...args) { const listeners = this.listeners[eventName] || []; listeners.forEach((item) => { item.triggerEvent(eventName, ...args); }); } } GlobalEventManager.listeners = {}; class GameObjectBuilder { constructor() { this.gameObject = new GameObject(); } setupHandler(eventName, eventHandler) { this.gameObject.setupHandler(eventName, eventHandler); return this; } initData(data) { this.gameObject.initData(data); return this; } addSprite(name, sprite, handler) { this.gameObject.addSprite(name, sprite, handler); return this; } build() { return this.gameObject; } } class GameObject extends PIXI.Container { /** * 覆写PIXI默认的宽高, 防止图像拉伸 */ constructor(width = 0, height = 0) { super(); this.children = []; this.willCreate = true; this.willTerminate = false; this.isCreated = false; this.isTerminated = false; this.isStarted = false; this.eventHandlers = {}; this.data = null; this.sprites = {}; this._width = width; this._height = height; Object.defineProperties(this, { width: { get: () => this._width, set: (w) => { this._width = w; this.refresh(); }, }, height: { get: () => this._height, set: (h) => { this._height = h; this.refresh(); }, }, }); } static builder() { return new GameObjectBuilder(); } /** * 注册事件处理方法或异步方法 */ setupHandler(eventName, eventHandler) { this.eventHandlers[eventName] = eventHandler; } /** * 移除已注册的方法 */ removeHandler(eventName) { delete this.eventHandlers[eventName]; } /** * 手动触发事件 */ triggerEvent(eventName, ...args) { const handler = this.eventHandlers[eventName]; if (handler) return handler(this, ...args); } /** * 获取绘制事件名 */ getDrawHandler(name) { return `draw${name.replace(/^./, (str) => str.toUpperCase())}`; } /** * 重绘全部精灵 */ refresh() { Object.keys(this.sprites).forEach((name) => { this.triggerEvent(this.getDrawHandler(name)); }); } /** * 添加精灵 */ addSprite(name, sprite, handler) { this.sprites[name] = sprite; this.setupHandler(this.getDrawHandler(name), handler); this.addChild(sprite); } /** * 初始化数据, 不会触发数据更新事件 */ initData(data) { this.data = data; } /** * 获取数据 */ getData() { return this.data; } /** * 数据绑定, 触发数据更新事件 */ setData(data) { const oldData = this.data; this.data = data; this.triggerEvent('change', oldData); } /** * 第一次载入场景时触发, 用于处理异步行为 */ async onCreate() { this.willCreate = false; await this.triggerEvent('create'); this.isCreated = true; } /** * 完成初始化后触发, 用于初始化对象 */ onStart() { this.triggerEvent('start'); this.refresh(); this.isStarted = true; } /** * 每一帧更新事件, 不要在这里重绘任何东西 */ onUpdate() { this.triggerEvent('update'); this.updateChildren(); } /** * 用来处理终止事件 */ async onTerminate() { this.willTerminate = false; await this.triggerEvent('terminate'); this.isTerminated = true; GlobalEventManager.removeListener(this); } /** * 主循环 */ update() { if (this.isStarted) { this.onUpdate(); } else if (this.willCreate) { this.onCreate(); } else if (this.isCreated && this.children.every((child) => child.isCreated !== false)) { this.onStart(); } else if (this.willTerminate && this.children.every((child) => child.isTerminated !== false)) { this.onTerminate(); } } /** * 更新子对象 */ updateChildren() { this.children.forEach((child) => { child.update(); }); } /** * 终止对象 */ terminate() { this.willTerminate = true; this.children.forEach((child) => { child.terminate(); }); } }
"use strict";
/**
* 处理全局消息通信
*/
class GlobalEventManager {
static getListeners(eventName) {
const listeners = this.listeners[eventName] || [];
if (!listeners.length)
this.listeners[eventName] = listeners;
return listeners;
}
/**
* 订阅事件
*/
static subscribe(item, eventName) {
const listeners = this.getListeners(eventName);
if (listeners.find((listener) => listener === item))
return;
listeners.push(item);
}
/**
* 取消订阅
*/
static unsubscribe(item, eventName) {
const listeners = this.getListeners(eventName);
const index = listeners.indexOf(item);
if (index >= 0)
listeners.splice(index, 1);
}
/**
* 取消全部订阅
*/
static removeListener(item) {
Object.keys(this.listeners).forEach((eventName) => {
this.unsubscribe(item, eventName);
});
}
/**
* 广播事件
*/
static dispatch(eventName, ...args) {
const listeners = this.listeners[eventName] || [];
listeners.forEach((item) => {
item.triggerEvent(eventName, ...args);
});
}
}
GlobalEventManager.listeners = {};
class GameObjectBuilder {
constructor() {
this.gameObject = new GameObject();
}
setupHandler(eventName, eventHandler) {
this.gameObject.setupHandler(eventName, eventHandler);
return this;
}
initData(data) {
this.gameObject.initData(data);
return this;
}
addSprite(name, sprite, handler) {
this.gameObject.addSprite(name, sprite, handler);
return this;
}
build() {
return this.gameObject;
}
}
class GameObject extends PIXI.Container {
/**
* 覆写PIXI默认的宽高, 防止图像拉伸
*/
constructor(width = 0, height = 0) {
super();
this.children = [];
this.willCreate = true;
this.willTerminate = false;
this.isCreated = false;
this.isTerminated = false;
this.isStarted = false;
this.eventHandlers = {};
this.data = null;
this.sprites = {};
this._width = width;
this._height = height;
Object.defineProperties(this, {
width: {
get: () => this._width,
set: (w) => {
this._width = w;
this.refresh();
},
},
height: {
get: () => this._height,
set: (h) => {
this._height = h;
this.refresh();
},
},
});
}
static builder() {
return new GameObjectBuilder();
}
/**
* 注册事件处理方法或异步方法
*/
setupHandler(eventName, eventHandler) {
this.eventHandlers[eventName] = eventHandler;
}
/**
* 移除已注册的方法
*/
removeHandler(eventName) {
delete this.eventHandlers[eventName];
}
/**
* 手动触发事件
*/
triggerEvent(eventName, ...args) {
const handler = this.eventHandlers[eventName];
if (handler)
return handler(this, ...args);
}
/**
* 获取绘制事件名
*/
getDrawHandler(name) {
return `draw${name.replace(/^./, (str) => str.toUpperCase())}`;
}
/**
* 重绘全部精灵
*/
refresh() {
Object.keys(this.sprites).forEach((name) => {
this.triggerEvent(this.getDrawHandler(name));
});
}
/**
* 添加精灵
*/
addSprite(name, sprite, handler) {
this.sprites[name] = sprite;
this.setupHandler(this.getDrawHandler(name), handler);
this.addChild(sprite);
}
/**
* 初始化数据, 不会触发数据更新事件
*/
initData(data) {
this.data = data;
}
/**
* 获取数据
*/
getData() {
return this.data;
}
/**
* 数据绑定, 触发数据更新事件
*/
setData(data) {
const oldData = this.data;
this.data = data;
this.triggerEvent('change', oldData);
}
/**
* 第一次载入场景时触发, 用于处理异步行为
*/
async onCreate() {
this.willCreate = false;
await this.triggerEvent('create');
this.isCreated = true;
}
/**
* 完成初始化后触发, 用于初始化对象
*/
onStart() {
this.triggerEvent('start');
this.refresh();
this.isStarted = true;
}
/**
* 每一帧更新事件, 不要在这里重绘任何东西
*/
onUpdate() {
this.triggerEvent('update');
this.updateChildren();
}
/**
* 用来处理终止事件
*/
async onTerminate() {
this.willTerminate = false;
await this.triggerEvent('terminate');
this.isTerminated = true;
GlobalEventManager.removeListener(this);
}
/**
* 主循环
*/
update() {
if (this.isStarted) {
this.onUpdate();
}
else if (this.willCreate) {
this.onCreate();
}
else if (this.isCreated &&
this.children.every((child) => child.isCreated !== false)) {
this.onStart();
}
else if (this.willTerminate &&
this.children.every((child) => child.isTerminated !== false)) {
this.onTerminate();
}
}
/**
* 更新子对象
*/
updateChildren() {
this.children.forEach((child) => {
child.update();
});
}
/**
* 终止对象
*/
terminate() {
this.willTerminate = true;
this.children.forEach((child) => {
child.terminate();
});
}
}
放弃治疗es5版本:
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; /** * 处理全局消息通信 */ var GlobalEventManager = /** @class */ (function () { function GlobalEventManager() { } GlobalEventManager.getListeners = function (eventName) { var listeners = this.listeners[eventName] || []; if (!listeners.length) this.listeners[eventName] = listeners; return listeners; }; /** * 订阅事件 */ GlobalEventManager.subscribe = function (item, eventName) { var listeners = this.getListeners(eventName); if (listeners.find(function (listener) { return listener === item; })) return; listeners.push(item); }; /** * 取消订阅 */ GlobalEventManager.unsubscribe = function (item, eventName) { var listeners = this.getListeners(eventName); var index = listeners.indexOf(item); if (index >= 0) listeners.splice(index, 1); }; /** * 取消全部订阅 */ GlobalEventManager.removeListener = function (item) { var _this = this; Object.keys(this.listeners).forEach(function (eventName) { _this.unsubscribe(item, eventName); }); }; /** * 广播事件 */ GlobalEventManager.dispatch = function (eventName) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } var listeners = this.listeners[eventName] || []; listeners.forEach(function (item) { item.triggerEvent.apply(item, __spreadArrays([eventName], args)); }); }; GlobalEventManager.listeners = {}; return GlobalEventManager; }()); var GameObjectBuilder = /** @class */ (function () { function GameObjectBuilder() { this.gameObject = new GameObject(); } GameObjectBuilder.prototype.setupHandler = function (eventName, eventHandler) { this.gameObject.setupHandler(eventName, eventHandler); return this; }; GameObjectBuilder.prototype.initData = function (data) { this.gameObject.initData(data); return this; }; GameObjectBuilder.prototype.addSprite = function (name, sprite, handler) { this.gameObject.addSprite(name, sprite, handler); return this; }; GameObjectBuilder.prototype.build = function () { return this.gameObject; }; return GameObjectBuilder; }()); var GameObject = /** @class */ (function (_super) { __extends(GameObject, _super); /** * 覆写PIXI默认的宽高, 防止图像拉伸 */ function GameObject(width, height) { if (width === void 0) { width = 0; } if (height === void 0) { height = 0; } var _this = _super.call(this) || this; _this.children = []; _this.willCreate = true; _this.willTerminate = false; _this.isCreated = false; _this.isTerminated = false; _this.isStarted = false; _this.eventHandlers = {}; _this.data = null; _this.sprites = {}; _this._width = width; _this._height = height; Object.defineProperties(_this, { width: { get: function () { return _this._width; }, set: function (w) { _this._width = w; _this.refresh(); }, }, height: { get: function () { return _this._height; }, set: function (h) { _this._height = h; _this.refresh(); }, }, }); return _this; } GameObject.builder = function () { return new GameObjectBuilder(); }; /** * 注册事件处理方法或异步方法 */ GameObject.prototype.setupHandler = function (eventName, eventHandler) { this.eventHandlers[eventName] = eventHandler; }; /** * 移除已注册的方法 */ GameObject.prototype.removeHandler = function (eventName) { delete this.eventHandlers[eventName]; }; /** * 手动触发事件 */ GameObject.prototype.triggerEvent = function (eventName) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } var handler = this.eventHandlers[eventName]; if (handler) return handler.apply(void 0, __spreadArrays([this], args)); }; /** * 获取绘制事件名 */ GameObject.prototype.getDrawHandler = function (name) { return "draw" + name.replace(/^./, function (str) { return str.toUpperCase(); }); }; /** * 重绘全部精灵 */ GameObject.prototype.refresh = function () { var _this = this; Object.keys(this.sprites).forEach(function (name) { _this.triggerEvent(_this.getDrawHandler(name)); }); }; /** * 添加精灵 */ GameObject.prototype.addSprite = function (name, sprite, handler) { this.sprites[name] = sprite; this.setupHandler(this.getDrawHandler(name), handler); this.addChild(sprite); }; /** * 初始化数据, 不会触发数据更新事件 */ GameObject.prototype.initData = function (data) { this.data = data; }; /** * 获取数据 */ GameObject.prototype.getData = function () { return this.data; }; /** * 数据绑定, 触发数据更新事件 */ GameObject.prototype.setData = function (data) { var oldData = this.data; this.data = data; this.triggerEvent('change', oldData); }; /** * 第一次载入场景时触发, 用于处理异步行为 */ GameObject.prototype.onCreate = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: this.willCreate = false; return [4 /*yield*/, this.triggerEvent('create')]; case 1: _a.sent(); this.isCreated = true; return [2 /*return*/]; } }); }); }; /** * 完成初始化后触发, 用于初始化对象 */ GameObject.prototype.onStart = function () { this.triggerEvent('start'); this.refresh(); this.isStarted = true; }; /** * 每一帧更新事件, 不要在这里重绘任何东西 */ GameObject.prototype.onUpdate = function () { this.triggerEvent('update'); this.updateChildren(); }; /** * 用来处理终止事件 */ GameObject.prototype.onTerminate = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: this.willTerminate = false; return [4 /*yield*/, this.triggerEvent('terminate')]; case 1: _a.sent(); this.isTerminated = true; GlobalEventManager.removeListener(this); return [2 /*return*/]; } }); }); }; /** * 主循环 */ GameObject.prototype.update = function () { if (this.isStarted) { this.onUpdate(); } else if (this.willCreate) { this.onCreate(); } else if (this.isCreated && this.children.every(function (child) { return child.isCreated !== false; })) { this.onStart(); } else if (this.willTerminate && this.children.every(function (child) { return child.isTerminated !== false; })) { this.onTerminate(); } }; /** * 更新子对象 */ GameObject.prototype.updateChildren = function () { this.children.forEach(function (child) { child.update(); }); }; /** * 终止对象 */ GameObject.prototype.terminate = function () { this.willTerminate = true; this.children.forEach(function (child) { child.terminate(); }); }; return GameObject; }(PIXI.Container));
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
/**
* 处理全局消息通信
*/
var GlobalEventManager = /** @class */ (function () {
function GlobalEventManager() {
}
GlobalEventManager.getListeners = function (eventName) {
var listeners = this.listeners[eventName] || [];
if (!listeners.length)
this.listeners[eventName] = listeners;
return listeners;
};
/**
* 订阅事件
*/
GlobalEventManager.subscribe = function (item, eventName) {
var listeners = this.getListeners(eventName);
if (listeners.find(function (listener) { return listener === item; }))
return;
listeners.push(item);
};
/**
* 取消订阅
*/
GlobalEventManager.unsubscribe = function (item, eventName) {
var listeners = this.getListeners(eventName);
var index = listeners.indexOf(item);
if (index >= 0)
listeners.splice(index, 1);
};
/**
* 取消全部订阅
*/
GlobalEventManager.removeListener = function (item) {
var _this = this;
Object.keys(this.listeners).forEach(function (eventName) {
_this.unsubscribe(item, eventName);
});
};
/**
* 广播事件
*/
GlobalEventManager.dispatch = function (eventName) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var listeners = this.listeners[eventName] || [];
listeners.forEach(function (item) {
item.triggerEvent.apply(item, __spreadArrays([eventName], args));
});
};
GlobalEventManager.listeners = {};
return GlobalEventManager;
}());
var GameObjectBuilder = /** @class */ (function () {
function GameObjectBuilder() {
this.gameObject = new GameObject();
}
GameObjectBuilder.prototype.setupHandler = function (eventName, eventHandler) {
this.gameObject.setupHandler(eventName, eventHandler);
return this;
};
GameObjectBuilder.prototype.initData = function (data) {
this.gameObject.initData(data);
return this;
};
GameObjectBuilder.prototype.addSprite = function (name, sprite, handler) {
this.gameObject.addSprite(name, sprite, handler);
return this;
};
GameObjectBuilder.prototype.build = function () {
return this.gameObject;
};
return GameObjectBuilder;
}());
var GameObject = /** @class */ (function (_super) {
__extends(GameObject, _super);
/**
* 覆写PIXI默认的宽高, 防止图像拉伸
*/
function GameObject(width, height) {
if (width === void 0) { width = 0; }
if (height === void 0) { height = 0; }
var _this = _super.call(this) || this;
_this.children = [];
_this.willCreate = true;
_this.willTerminate = false;
_this.isCreated = false;
_this.isTerminated = false;
_this.isStarted = false;
_this.eventHandlers = {};
_this.data = null;
_this.sprites = {};
_this._width = width;
_this._height = height;
Object.defineProperties(_this, {
width: {
get: function () { return _this._width; },
set: function (w) {
_this._width = w;
_this.refresh();
},
},
height: {
get: function () { return _this._height; },
set: function (h) {
_this._height = h;
_this.refresh();
},
},
});
return _this;
}
GameObject.builder = function () {
return new GameObjectBuilder();
};
/**
* 注册事件处理方法或异步方法
*/
GameObject.prototype.setupHandler = function (eventName, eventHandler) {
this.eventHandlers[eventName] = eventHandler;
};
/**
* 移除已注册的方法
*/
GameObject.prototype.removeHandler = function (eventName) {
delete this.eventHandlers[eventName];
};
/**
* 手动触发事件
*/
GameObject.prototype.triggerEvent = function (eventName) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var handler = this.eventHandlers[eventName];
if (handler)
return handler.apply(void 0, __spreadArrays([this], args));
};
/**
* 获取绘制事件名
*/
GameObject.prototype.getDrawHandler = function (name) {
return "draw" + name.replace(/^./, function (str) { return str.toUpperCase(); });
};
/**
* 重绘全部精灵
*/
GameObject.prototype.refresh = function () {
var _this = this;
Object.keys(this.sprites).forEach(function (name) {
_this.triggerEvent(_this.getDrawHandler(name));
});
};
/**
* 添加精灵
*/
GameObject.prototype.addSprite = function (name, sprite, handler) {
this.sprites[name] = sprite;
this.setupHandler(this.getDrawHandler(name), handler);
this.addChild(sprite);
};
/**
* 初始化数据, 不会触发数据更新事件
*/
GameObject.prototype.initData = function (data) {
this.data = data;
};
/**
* 获取数据
*/
GameObject.prototype.getData = function () {
return this.data;
};
/**
* 数据绑定, 触发数据更新事件
*/
GameObject.prototype.setData = function (data) {
var oldData = this.data;
this.data = data;
this.triggerEvent('change', oldData);
};
/**
* 第一次载入场景时触发, 用于处理异步行为
*/
GameObject.prototype.onCreate = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.willCreate = false;
return [4 /*yield*/, this.triggerEvent('create')];
case 1:
_a.sent();
this.isCreated = true;
return [2 /*return*/];
}
});
});
};
/**
* 完成初始化后触发, 用于初始化对象
*/
GameObject.prototype.onStart = function () {
this.triggerEvent('start');
this.refresh();
this.isStarted = true;
};
/**
* 每一帧更新事件, 不要在这里重绘任何东西
*/
GameObject.prototype.onUpdate = function () {
this.triggerEvent('update');
this.updateChildren();
};
/**
* 用来处理终止事件
*/
GameObject.prototype.onTerminate = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.willTerminate = false;
return [4 /*yield*/, this.triggerEvent('terminate')];
case 1:
_a.sent();
this.isTerminated = true;
GlobalEventManager.removeListener(this);
return [2 /*return*/];
}
});
});
};
/**
* 主循环
*/
GameObject.prototype.update = function () {
if (this.isStarted) {
this.onUpdate();
}
else if (this.willCreate) {
this.onCreate();
}
else if (this.isCreated &&
this.children.every(function (child) { return child.isCreated !== false; })) {
this.onStart();
}
else if (this.willTerminate &&
this.children.every(function (child) { return child.isTerminated !== false; })) {
this.onTerminate();
}
};
/**
* 更新子对象
*/
GameObject.prototype.updateChildren = function () {
this.children.forEach(function (child) {
child.update();
});
};
/**
* 终止对象
*/
GameObject.prototype.terminate = function () {
this.willTerminate = true;
this.children.forEach(function (child) {
child.terminate();
});
};
return GameObject;
}(PIXI.Container));
对了, 你问这个东西现在有啥实际价值么?
答案是暂无
不过也许把建造函数封装好了, 能很快得实现按需要载入部分窗体的功能, 而不是每次从一个类继承一个新的开始魔改? |
评分
-
查看全部评分
|