I encountered a peculiar issue while developing a 2D game in Angular.
The function in my component calls an async function to load the sprites, then executes the game loop in the callback 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;
}
}
The function in my game service class defines the game loop GameService.ts:
startGame(): void {
this.score = 0;
/* Launch the loop every 10 milliseconds */
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();
}
The function that calls the clearInterval is in 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');
}
}
The entry point where we call the checkCollision function in 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);
}
});
}
Definition of the EventEmitter where we load the game in the callback in the component:
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;
}
The issue arises when the clearInterval is reached and the loop finishes, the code execution does not exit the startGame method, and I cannot reach the code part outside the subscription in the AfterViewInit inside the component.