【发布时间】:2019-02-03 04:53:42
【问题描述】:
任务:
我正在将一个现有的 HTML5 项目(基于 Phaser 的科学软件)集成到 Angular 中,以便更好地构建不断扩展的 UI。
该软件位于其自己的组件中并且正在运行。软件的所有功能都从 controller 类公开。我在 Phaser 项目的状态中有一个控制器类的实例。
想象一个新的组件(比如,顶部菜单)我想说:
<div (click)="this.controller.makeAction()"></div>
,其中“this.controller”是一个实例,保存在顶部菜单组件中。
相关研究:
我在很多地方读到,推荐的在不相关组件之间进行通信的方式是通过服务并使用 rxjs BehaviorSubject。好的...问题来了:
问题:
当我创建服务时,我必须设置 BehaviorSubject 的实例。问题是我不知道游戏何时准备好,以便访问状态,从而将控制器提供给服务。所以.. BehaviorSubject 保持为空,我得到一个错误。
我真的很想避免将 Angular 代码放在 Phaser 项目中,因为它们应该尽可能地分离(目前没有任何耦合)。
问题:
我的方法正确吗?控制器将提供给任何 UI 元素,因此也提供给任何组件。如何解决这个问题?
相关代码:
1.服务
// Omitting imports and decorators
export class UserActionControllerService {
private _userActionController = new BehaviorSubject<UserActionController>(null);
userActionController = this._userActionController.asObservable();
constructor() { }
setUAC(userActionController: UserActionController){
this._userActionController.next(userActionController);
}
}
2。使用顶部菜单中的服务
//Omitting imports and decorator
export class TopMenuComponent implements OnInit {
userActionController: UserActionController;
constructor(private uac: UserActionControllerService) { }
ngOnInit() {
this.uac.userActionController.subscribe((value) => {
this.userActionController = value;
});
}
和 html...
<p>{{this.userActionController | async | json}}</p>
3.在服务中设置控制器的值
//Ommitting imports and decorator
export class GteCoreComponent implements OnInit {
game: Phaser.Game;
constructor(private userActionControllerService: UserActionControllerService) {}
ngOnInit() {
this.game = new GTE(width, height);
this.userActionControllerService.setUAC(this.game.state.states.MainScene.userActionController);
}
}
最后一行产生错误,因为游戏尚未创建。我尝试使用setTimeout(),仍然无济于事。
提前感谢您的帮助!
编辑:
我设法让它与 setTimeout 一起工作,这似乎是一个 hack。还有其他建议吗?
EDIT2:
根据要求,这里是 GTE 类:
export class GTE extends Phaser.Game {
game: Phaser.Game;
constructor(width?: number, height?: number) {
super(width, height, Phaser.CANVAS, 'phaser-div', null, false, true);
this.game = this;
this.game.state.add('Boot', Boot, false);
this.game.state.add('MainScene', MainScene, false);
this.game.state.start('Boot');
}
}
【问题讨论】:
-
我认为您应该从 Game Component 发出一个事件,该事件将在 TopMenuComponent 中被监听。类似于
init的东西。然后,您可以通过使用适当的数据在服务的 BehaviorSubject 上调用next来执行必要的操作。 -
Phaser.Game 是否有某种事件来指示它何时准备就绪?还是您需要显式调用某些东西以使其准备就绪?
-
@MarkHughes 感谢您的建议。我尝试将最后一行替换为:
this.game.load.onLoadComplete(()=>doSomething()),但问题是一样的。游戏尚未在this.game = new GTE(width, height);行中创建,因此我无法访问它的任何属性。 -
那
new GTE(...)做了什么? Phaser.Game 是否有一些文档来说明您应该如何实例化它? -
...其实可以把GTE类的代码放在问题里吗?
标签: angular rxjs communication phaser-framework angular-components