TL; DR Попытка создать движок, подобный Unity, но в машинописном тексте и только для браузерных игр. Я делаю это правильно?
Итак, я создаю игровой движок. Это шаблон на основе сущностей / компонентов, который я использую, но мой вопрос в том, правильно ли я его строю? Дело в том, что у меня есть основная игра l oop, которая в первую очередь сама по себе Init, gameObjects и компоненты, связанные с gameObject через события. После этого он запускает игру, gameObjects и компоненты таким же образом. В конце метода Start он также запускает обновление l oop, которое также обновляет gameObject и т. Д.
Пользователь, который создает игру, управляет gameObject только через компоненты, которые он создает сам, наследуя базовый класс компонентов. Это намеренно похожая система, подобная движку Unity. Основная демография c - это люди, знакомые с Unity. Все gameObjects хранятся в классе сцены, который не имеет отношения к вопросу.
Actual Question : Я борюсь с отношением между gameObject и компонентом. Есть ли способ сделать это лучше? Любой шаблон проектирования, который я могу использовать?
note : функция уничтожения в данный момент не работает. все еще выясняю это.
Класс приложения:
class Application implements IStartable, IUpdatable {
private onAppInit: SignalDispatcher = new SignalDispatcher();
public get OnAppInit(): ISignal {
return this.onAppInit.asEvent();
}
private onAppStart: SignalDispatcher = new SignalDispatcher();
public get OnAppStart(): ISignal {
return this.onAppStart.asEvent();
}
private onAppUpdate: SignalDispatcher = new SignalDispatcher();
public get OnAppUpdate(): ISignal {
return this.onAppUpdate.asEvent();
}
private onAppClose: SignalDispatcher = new SignalDispatcher();
public get OnAppClose(): ISignal {
return this.onAppClose.asEvent();
}
private currentScene: Scene;
constructor() {
this.currentScene = new Scene(this);
}
public AddGameObject(object: GameObject) {
this.currentScene.AddGameObject(object);
}
public Start() {
this.onAppInit.dispatch();
this.onAppStart.dispatch();
this.Update();
}
public Close() {
this.onAppClose.dispatch();
}
public Update() {
this.onAppUpdate.dispatch();
window.requestAnimationFrame(() => {
this.Update();
});
}
}
Класс GameObject:
class GameObject extends EngineObject {
public name: string;
public transform: undefined;
private components: Component[] = [];
private onAwake: SignalDispatcher = new SignalDispatcher();
private onStart: SignalDispatcher = new SignalDispatcher();
private onUpdate: SignalDispatcher = new SignalDispatcher();
private onDestroy: SimpleEventDispatcher<
EngineObject
> = new SimpleEventDispatcher();
constructor(name: string, transform = undefined) {
super();
this.name = name;
this.transform = transform;
}
Awake() {
super.Awake();
this.onAwake.dispatch();
}
Start() {
super.Start();
this.onStart.dispatch();
}
Update() {
super.Update();
this.onUpdate.dispatch();
}
Destroy(object: EngineObject = this) {
this.onDestroy.dispatch(object);
super.Destroy(object);
}
public AddComponent<T extends Component>(component: T) {
component.GameObject = this;
component.UniqueId = this.components.length;
this.onAwake.asEvent().sub(component.Awake.bind(component));
this.onStart.asEvent().sub(component.Start.bind(component));
this.onUpdate.asEvent().sub(component.Update.bind(component));
this.onDestroy.asEvent().sub(component.Destroy.bind(component));
this.components.push(component);
}
public GetComponent<T extends Component>(instance: T): Component | undefined {
let found: boolean;
let returnComponent: Component | undefined;
this.components.forEach(component => {
if (found) return;
if (typeof component === typeof instance) {
found = true;
returnComponent = component;
return;
}
});
return returnComponent;
}
}
Класс компонента:
export class Component extends EngineObject {
private uniqueId = -1;
public get UniqueId(): number {
if (this.uniqueId < 0)
console.warn("Component has no gameobject reference");
return this.uniqueId;
}
public set UniqueId(amount: number) {
if (this.uniqueId >= 0) {
console.error("Id already set");
return;
}
this.uniqueId = amount;
}
protected gameObject!: GameObject;
public get GameObject(): GameObject {
return this.gameObject;
}
public set GameObject(gameObject: GameObject) {
if (this.gameObject) {
console.error("GameObject already set");
return;
}
this.gameObject = gameObject;
}
constructor() {
super();
}
public Destroy(object: EngineObject = this) {
super.Destroy(object);
}
}