在Angular中开发2D游戏时遇到了一个奇怪的问题。
我组件中的函数调用异步函数来加载精灵,然后在回调GameComponent.ts中执行游戏循环:
constructor(private loader: AppService, private game: GameService, private
score: ScoreService) {}
ngAfterViewInit(): void {
this.loader.createGameEnvironment(this.canvas.nativeElement);
this.subscribed = this.loader.getAssetsLoadedEmitter().subscribe(() => {
this.game.startGame();
this.lastScore = this.game.score;
console.log(this.userScore._id);
});
console.log(this.userScore._id);
if (this.userScore._id !== undefined) {
this.userScore.score = this.lastScore;
this.score.updateScore(this.userScore).subscribe( () => {
console.log('score updated successfully: ' + this.userScore.score);
});
} else {
this.showModal = true;
}
}
游戏服务类中定义游戏循环GameService.ts的函数:
startGame(): void {
this.score = 0;
/* launch the loop every 10 miliseconds */
this.gameLoop = setInterval(() => {
this.suffleProperties();
this.cleanCanvas();
this.renderBackground();
this.createObstacles();
this.moveObstacles();
this.createPlayer();
this.updateScore();
console.log(this.score);
}, 10);
// window.location.reload();
}
调用clearInterval GameService.ts的函数:
checkCollision(obstacle: Obstacles): void {
if (((this.player.x + CONFIG.playerCar.width > obstacle.x) && (this.player.y < obstacle.y + obstacle.height)) &&
((this.player.x < obstacle.x + obstacle.width) && (this.player.y < obstacle.y + obstacle.height)) &&
((this.player.x + CONFIG.playerCar.width > obstacle.x) && (this.player.y + CONFIG.playerCar.height > obstacle.y)) &&
((this.player.x < obstacle.x + obstacle.width) && (this.player.y + CONFIG.playerCar.height > obstacle.y))) {
clearInterval(this.gameLoop);
alert('Game Over');
}
}
调用checkCollision函数GameService.ts的入口点:
moveObstacles(): void {
this.obstacles.forEach((element: Obstacles, index: number) => {
element.y += 3;
element.update();
this.checkCollision(element);
if (element.y > this.height) {
this.obstacles.splice(index, 1);
}
});
}
EventEmitter的定义,我们在组件的回调中加载游戏:
export class AppService {
isAssetsLoaded: EventEmitter<number> = new EventEmitter();
constructor(private game: GameService) { }
createGameEnvironment(canvasElement): void {
this.game.loadSpritesAssets(canvasElement).then( () => {
this.isAssetsLoaded.emit();
});
}
getAssetsLoadedEmitter(): EventEmitter<number> {
return this.isAssetsLoaded;
}
问题是,当达到clearInterval且循环完成时,代码执行不会超出startGame方法,并且无法在组件内部的AfterViewInit中到达预订之外的代码部分。
答案 0 :(得分:1)
这是我为您解决的问题的解决方案:updated stackblitz example
我创建了一个EventEmitter,您可以订阅该事件以获取最终分数。
在game.service.ts中:
export interface IGameEndData{
message: string;
score: number;
}
@Injectable()
export class GameService {
gameEndEvent = new EventEmitter<IGameEndData>();
checkCount(): void {
if (this.count === 10) {
clearInterval(this.gameLoop);
console.log('Game Over');
this.gameEndEvent.emit({
message: "You can put any kind of information in here",
score: this.score
})
...
以及在app.component.ts中:
ngAfterViewInit(): void {
this.loader.createGameEnvironment(this.canvas.nativeElement);
this.subscribed = this.loader.getAssetsLoadedEmitter().subscribe(() => {
this.game.startGame();
this.game.gameEndEvent.subscribe((endData:IGameEndData)=>{
console.log("endData: ", endData);
console.log("setting the current score as last score:");
this.lastScore.score = endData.score;
console.log("last score object:", this.lastScore);
})
希望这是您想要的。