UNPKG

bp-prism-game

Version:
1,667 lines (1,646 loc) 377 kB
import * as i0 from '@angular/core'; import { Component, Inject, Injectable, ViewChild, HostListener, NgModule } from '@angular/core'; import * as i1 from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; import * as i2 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i1$1 from 'ngx-cookie-service'; import { CookieService } from 'ngx-cookie-service'; import { Subject as Subject$1 } from 'rxjs/internal/Subject'; import { Subject } from 'rxjs'; /** * Display Dialog component for display */ class DisplayDialogComponent { /** * The GenericDialogComponent constructor * * @param dialogRef MatDialogRef of this from DI * @param data MAT_DIALOG_DATA from DI of the caller */ constructor(dialogRef, data) { this.dialogRef = dialogRef; this.data = data; this.title = this.data.title; this.messageText = this.data.messageText; this.displayMessage = this.messageText !== undefined; this.isRedFont = data.isFontRed; } } DisplayDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: DisplayDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); DisplayDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.2", type: DisplayDialogComponent, selector: "bp-prism-display-dialog", ngImport: i0, template: "<div class=\"dialog-container\">\n <h1 mat-dialog-title name=\"title\" [innerHtml]=\"title\" [class.game-over-font]=\"isRedFont\"></h1>\n <div mat-dialog-content name=\"messageText\" [innerHtml]=\"messageText\" *ngIf=\"displayMessage\"></div>\n</div>\n", styles: ["::ng-deep .display-dialog-container .mat-dialog-container{width:500px;height:250px;background-color:#000;border:1px solid white}::ng-deep .display-dialog-container .dialog-container{display:flex;height:100%;flex-direction:column;justify-content:center;width:100%}::ng-deep .display-dialog-container .dialog-container .mat-dialog-title{text-align:center;font-weight:500;font-size:45px;line-height:20px;font-family:\"Press Start 2P\";color:#fff}::ng-deep .display-dialog-container .dialog-container .game-over-font{color:red}::ng-deep .display-dialog-container .dialog-container .mat-dialog-content{margin-top:20px;text-align:center;font-weight:500;font-size:20px;line-height:30px;font-family:\"Press Start 2P\";color:#fff}\n"], directives: [{ type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: DisplayDialogComponent, decorators: [{ type: Component, args: [{ selector: 'bp-prism-display-dialog', template: "<div class=\"dialog-container\">\n <h1 mat-dialog-title name=\"title\" [innerHtml]=\"title\" [class.game-over-font]=\"isRedFont\"></h1>\n <div mat-dialog-content name=\"messageText\" [innerHtml]=\"messageText\" *ngIf=\"displayMessage\"></div>\n</div>\n", styles: ["::ng-deep .display-dialog-container .mat-dialog-container{width:500px;height:250px;background-color:#000;border:1px solid white}::ng-deep .display-dialog-container .dialog-container{display:flex;height:100%;flex-direction:column;justify-content:center;width:100%}::ng-deep .display-dialog-container .dialog-container .mat-dialog-title{text-align:center;font-weight:500;font-size:45px;line-height:20px;font-family:\"Press Start 2P\";color:#fff}::ng-deep .display-dialog-container .dialog-container .game-over-font{color:red}::ng-deep .display-dialog-container .dialog-container .mat-dialog-content{margin-top:20px;text-align:center;font-weight:500;font-size:20px;line-height:30px;font-family:\"Press Start 2P\";color:#fff}\n"] }] }], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{ type: Inject, args: [MAT_DIALOG_DATA] }] }]; } }); /** * The display dialog service */ class DisplayDialogService { /** * The constructor * * @param dialog The MatDialog from DI */ constructor(dialog) { this.dialog = dialog; } /** * Get the Dialog Position */ getDialogPosition() { return { top: '350px' }; } /** * Display the game over text */ displayGameOver(data) { return this.dialog.open(DisplayDialogComponent, { panelClass: 'display-dialog-container', position: this.getDialogPosition(), data: { title: `GAME OVER`, messageText: `High Score: ${data.highScore}<br>Level: ${data.level}`, isFontRed: true } }); } /** * Display the next level text */ displayNextLevel(data) { return this.dialog.open(DisplayDialogComponent, { panelClass: 'display-dialog-container', position: this.getDialogPosition(), data: { title: `NEXT LEVEL`, messageText: `Level: ${data.level}`, isFontRed: false } }); } /** * Display the game paused text */ displayGamePaused() { return this.dialog.open(DisplayDialogComponent, { panelClass: 'display-dialog-container', position: this.getDialogPosition(), data: { title: `PAUSED`, isFontRed: false } }); } } DisplayDialogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: DisplayDialogService, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Injectable }); DisplayDialogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: DisplayDialogService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: DisplayDialogService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: function () { return [{ type: i1.MatDialog }]; } }); /** * The Cookie service */ class GameCookieService { /** * The constructor * @param cookieService The cookieService from DI */ constructor(cookieService) { this.cookieService = cookieService; } /** * Get the cookie */ getCookie(cookieName) { return this.cookieService.get(cookieName); } /** * Get the High Score */ getGameData() { const cookie = this.getCookie('bp-prism'); return cookie ? JSON.parse(cookie) : { highScore: 0, level: 1 }; } /** * Set the cookie */ setGameData(data) { this.cookieService.set('bp-prism', JSON.stringify(data)); } /** * Get the Debug information */ getDebugData() { const cookie = this.getCookie('bp-prism-debug'); /* eslint-disable-next-line */ return cookie ? JSON.parse(cookie)['assetName'] : ''; } /** * Set the debug cookie data * * @param assetName The asset name */ setDebugData(assetName) { this.cookieService.set('bp-prism-debug', JSON.stringify(Object({ assetName }))); } } GameCookieService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: GameCookieService, deps: [{ token: i1$1.CookieService }], target: i0.ɵɵFactoryTarget.Injectable }); GameCookieService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: GameCookieService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: GameCookieService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: function () { return [{ type: i1$1.CookieService }]; } }); /** * The Game board * 1 - Blank * 2 - Trees * 3 - Rocks * 4 - Water * 5 - Grass * 6 - Slime * 7 - Lava * 8 - Main Gunner * 9 - Alien Base * 10 - Prism Base * 11 - Score * 12 - High Score * 13 - Level * 14 - Prism Blast icon * 15 - Bridge * 16 - Path */ // prettier-ignore const GAMEBOARD = [ [1, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2], [2, 0, 0, 0, 2, 2, 2, 3, 3, 3, 3, 3, 2, 0, 2, 0, 2, 2, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 9, 0], [2, 0, 2, 0, 0, 2, 2, 3, 3, 3, 2, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 2, 2], [2, 9, 0, 2, 0, 2, 5, 2, 2, 2, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2], [2, 2, 2, 2, 0, 2, 5, 5, 5, 2, 9, 0, 2, 2, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2], [2, 2, 2, 0, 0, 2, 5, 2, 0, 0, 0, 2, 2, 3, 2, 2, 0, 2, 0, 0, 2, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0], [2, 2, 2, 0, 2, 3, 3, 3, 0, 0, 0, 2, 3, 4, 2, 2, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 5, 2, 0, 2, 0, 0, 3, 0, 0, 2, 3, 4, 4, 4, 2, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 0, 2, 0, 3, 3, 0, 2, 3, 3, 4, 4, 4, 0, 0, 9, 0, 2, 0, 0, 0, 0, 3, 3, 2, 2, 0, 0, 0], [5, 2, 0, 0, 2, 0, 3, 2, 0, 0, 2, 3, 3, 4, 0, 0, 2, 2, 2, 2, 0, 0, 0, 3, 4, 4, 4, 2, 0, 0, 0], [2, 5, 0, 2, 2, 0, 3, 3, 0, 0, 0, 2, 3, 0, 0, 2, 0, 0, 2, 2, 0, 0, 2, 4, 4, 4, 4, 2, 0, 0, 0], [2, 2, 0, 3, 2, 0, 2, 3, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 2, 4, 4, 4, 4, 4, 2, 0, 0], [2, 5, 0, 3, 2, 0, 3, 3, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 4, 4, 2, 2, 2, 0, 0], [2, 0, 0, 2, 2, 0, 3, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 2, 4, 2, 2, 2, 0, 0, 0, 0], [2, 0, 2, 2, 2, 0, 3, 3, 0, 0, 0, 2, 0, 0, 1, 1, 1, 0, 0, 3, 3, 3, 4, 4, 3, 3, 2, 2, 2, 2, 0], [2, 0, 0, 0, 2, 0, 3, 3, 0, 0, 0, 0, 2, 3, 1, 1, 1, 0, 0, 3, 3, 2, 4, 2, 3, 3, 3, 2, 2, 2, 0], [2, 2, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 3, 1, 8, 1, 0, 0, 3, 3, 4, 4, 3, 3, 0, 0, 2, 0, 0, 0], [0, 0, 2, 2, 0, 2, 2, 5, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 3, 4, 4, 3, 3, 0, 0, 2, 2, 0, 3, 3], [0, 2, 2, 2, 0, 2, 2, 5, 0, 2, 0, 0, 0, 0, 2, 3, 0, 0, 3, 3, 2, 5, 5, 2, 0, 2, 0, 0, 0, 3, 3], [0, 2, 2, 0, 0, 2, 4, 2, 0, 2, 0, 2, 2, 3, 5, 2, 2, 0, 2, 2, 5, 5, 5, 2, 0, 2, 0, 2, 2, 3, 7], [0, 2, 0, 0, 2, 4, 4, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 7, 7, 7], [0, 0, 0, 2, 4, 4, 2, 2, 2, 2, 0, 0, 2, 5, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 7, 7, 7], [0, 2, 2, 4, 4, 4, 4, 4, 3, 3, 5, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 7, 7, 7], [0, 2, 4, 4, 4, 2, 2, 4, 4, 2, 5, 2, 0, 4, 4, 4, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 2, 7, 7, 7, 7], [0, 2, 2, 2, 2, 2, 2, 2, 4, 4, 2, 4, 15, 4, 4, 4, 5, 3, 3, 0, 0, 0, 0, 2, 0, 2, 7, 7, 7, 7, 7], [0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 4, 4, 0, 3, 2, 3, 5, 3, 3, 0, 0, 2, 2, 0, 0, 2, 7, 7, 7, 7, 7], [2, 2, 2, 2, 2, 2, 0, 0, 2, 4, 4, 4, 0, 3, 2, 3, 5, 5, 2, 2, 0, 2, 2, 0, 2, 7, 7, 7, 7, 7, 7], [2, 6, 6, 2, 2, 6, 2, 0, 2, 2, 2, 2, 0, 3, 2, 3, 5, 5, 5, 5, 0, 2, 2, 0, 0, 2, 7, 7, 7, 7, 7], [2, 6, 6, 2, 6, 6, 2, 0, 2, 0, 0, 0, 0, 2, 3, 5, 5, 2, 2, 2, 0, 0, 0, 2, 0, 0, 2, 7, 7, 7, 7], [2, 6, 6, 6, 6, 6, 2, 0, 2, 0, 3, 2, 3, 3, 3, 2, 5, 5, 5, 2, 2, 2, 0, 2, 2, 0, 0, 2, 2, 7, 7], [2, 2, 2, 2, 6, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 2, 7, 7], [2, 2, 2, 6, 6, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 2, 5, 2, 0, 0, 2, 0, 2, 7, 7], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2], [1, 1, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ]; /** * GAMEBOARD TWO */ const GAMEBOARDTWO = JSON.parse(JSON.stringify(GAMEBOARD)); GAMEBOARDTWO[6][1] = 0; GAMEBOARDTWO[18][2] = 9; GAMEBOARDTWO[4][29] = 0; GAMEBOARDTWO[16][26] = 9; GAMEBOARDTWO[7][10] = 0; GAMEBOARDTWO[8][18] = 9; GAMEBOARDTWO[11][17] = 0; GAMEBOARDTWO[21][15] = 9; /** * GAMEBOARD THREE */ const GAMEBOARDTHREE = JSON.parse(JSON.stringify(GAMEBOARD)); GAMEBOARDTHREE[6][1] = 0; GAMEBOARDTHREE[10][5] = 9; GAMEBOARDTHREE[4][29] = 0; GAMEBOARDTHREE[20][24] = 9; GAMEBOARDTHREE[7][10] = 0; GAMEBOARDTHREE[13][20] = 9; GAMEBOARDTHREE[11][17] = 0; GAMEBOARDTHREE[3][15] = 9; /** * GAMEBOARD FOUR */ const GAMEBOARDFOUR = JSON.parse(JSON.stringify(GAMEBOARD)); GAMEBOARDFOUR[6][1] = 0; GAMEBOARDFOUR[20][0] = 9; GAMEBOARDFOUR[4][29] = 0; GAMEBOARDFOUR[4][28] = 9; GAMEBOARDFOUR[7][10] = 0; GAMEBOARDFOUR[16][18] = 9; GAMEBOARDFOUR[11][17] = 0; GAMEBOARDFOUR[8][7] = 9; /** * The Game Boards */ const GAMEBOARDS = [ GAMEBOARD, GAMEBOARDTWO, GAMEBOARDTHREE, GAMEBOARDFOUR, GAMEBOARD, GAMEBOARDTWO, GAMEBOARDTHREE, GAMEBOARDFOUR, GAMEBOARD ]; /** * Block Size */ const BLOCK_SIZE = 5; /** * Columns */ const COLS$2 = GAMEBOARD[0].length * BLOCK_SIZE; /** * Rows */ const ROWS$2 = GAMEBOARD.length * BLOCK_SIZE; /** * The Level Waves */ class LEVELWAVES { } /** * Level 0 Wave */ LEVELWAVES[0] = 1; /** * Level 1 Wave */ LEVELWAVES[1] = 1; /** * Level 2 Wave */ LEVELWAVES[2] = 2; /** * Level 3 Wave */ LEVELWAVES[3] = 3; /** * Level 4 Wave */ LEVELWAVES[4] = 4; /** * Level 5 Wave */ LEVELWAVES[5] = 5; /** * Level 6 Wave */ LEVELWAVES[6] = 6; /** * Level 7 Wave */ LEVELWAVES[7] = 7; /** * The Level Speed */ class LEVELSPEED { } /** * Level 0 Speed */ LEVELSPEED[0] = 500; /** * Level 1 Speed */ LEVELSPEED[1] = 450; /** * Level 2 Speed */ LEVELSPEED[2] = 400; /** * Level 3 Speed */ LEVELSPEED[3] = 375; /** * Level 4 Speed */ LEVELSPEED[4] = 350; /** * Level 5 Speed */ LEVELSPEED[5] = 325; /** * Level 6 Speed */ LEVELSPEED[6] = 300; /** * Level 7 Speed */ LEVELSPEED[7] = 275; /** * The Level Creep */ class LEVELCREEP { } /** * Level 0 Creep */ LEVELCREEP[0] = 5; /** * Level 1 Creep */ LEVELCREEP[1] = 10; /** * Level 2 Creep */ LEVELCREEP[2] = 15; /** * Level 3 Creep */ LEVELCREEP[3] = 20; /** * Level 4 Creep */ LEVELCREEP[4] = 25; /** * Level 5 Creep */ LEVELCREEP[5] = 30; /** * Level 6 Creep */ LEVELCREEP[6] = 40; /** * Level 7 Creep */ LEVELCREEP[7] = 50; /** * The keys */ class KEY { } /** * Space */ KEY.SPACE = 'Space'; /** * Left */ KEY.LEFT = 'ArrowLeft'; /** * Right */ KEY.RIGHT = 'ArrowRight'; /** * KeyP */ KEY.P = 'KeyP'; /** * Down */ KEY.DOWN = 'ArrowDown'; /** * up */ KEY.UP = 'ArrowUp'; /** * The Observable Enum */ var ObservableTypeEnum; (function (ObservableTypeEnum) { /** * Alien Hit */ ObservableTypeEnum["alienDestroyed"] = "alienDestroyed"; /** * Game Over */ ObservableTypeEnum["gameOver"] = "gameOver"; /** * Game Paused */ ObservableTypeEnum["gamePaused"] = "gamePaused"; /** * Images Loaded */ ObservableTypeEnum["imagesLoaded"] = "imagesLoaded"; /** * Key Down Event */ ObservableTypeEnum["keyDownEvent"] = "keyDownEvent"; /** * Key Up Event */ ObservableTypeEnum["keyUpEvent"] = "keyUpEvent"; /** * Level Completed */ ObservableTypeEnum["levelCompleted"] = "levelCompleted"; /** * Missile Destroyed Event */ ObservableTypeEnum["missileDestroyed"] = "missileDestroyed"; /** * Missile Launched Event */ ObservableTypeEnum["missileLaunched"] = "missileLaunched"; /** * Prism Base Destroyed */ ObservableTypeEnum["prismBaseDestroyed"] = "prismBaseDestroyed"; /** * Prism Blast Defused Event */ ObservableTypeEnum["prismBlastDefused"] = "prismBlastDefused"; /** * Prism Blast Fire Event */ ObservableTypeEnum["prismBlastFire"] = "prismBlastFire"; /** * Prism Blast Launched Event */ ObservableTypeEnum["prismBlastLaunched"] = "prismBlastLaunched"; })(ObservableTypeEnum || (ObservableTypeEnum = {})); /** * The Asset Align Enum */ var AssetAlignEnum; (function (AssetAlignEnum) { /** * Left */ AssetAlignEnum["left"] = "left"; /** * Left Third */ AssetAlignEnum["leftThird"] = "leftThird"; /** * Left Fourth */ AssetAlignEnum["leftFourth"] = "leftFourth"; /** * right */ AssetAlignEnum["right"] = "right"; /** * right Third */ AssetAlignEnum["rightThird"] = "rightThird"; /** * right Fourth */ AssetAlignEnum["rightFourth"] = "rightFourth"; /** * Center */ AssetAlignEnum["center"] = "center"; })(AssetAlignEnum || (AssetAlignEnum = {})); /** * The Asset Align Vertical Enum */ var AssetAlignVerticalEnum; (function (AssetAlignVerticalEnum) { /** * Top */ AssetAlignVerticalEnum["top"] = "top"; /** * Bottom */ AssetAlignVerticalEnum["bottom"] = "bottom"; /** * Middle */ AssetAlignVerticalEnum["middle"] = "middle"; })(AssetAlignVerticalEnum || (AssetAlignVerticalEnum = {})); /** * The Asset Class */ class AssetClass { /** * Constructor * @param gameService The game service * @param ctx The ctx * @param assetUid the uid of the asset * @param imageType The optional animation number */ constructor(gameService, ctx, assetUid, imageType) { this.gameService = gameService; this.ctx = ctx; this.assetUid = assetUid; this.imageType = imageType; this.assetScale = { x: 1, y: 1 }; this.x = 0; this.y = 0; this.images = []; this.assetHeight = 0; this.assetWidth = 0; this.isAnimated = false; this.isDestroyed = false; this.isGameOver = false; this.isGamePaused = false; this.isImageLoaded = false; this.assetTimer = { start: performance.now(), elapsed: 0 }; this.animationCounter = 0; this.boundary = this.gameService.getBoundary(); this.init(); } /** * Init the asset */ init() { this.gameService.getMasterObservable().subscribe((result) => { if (result.type === ObservableTypeEnum.keyDownEvent || result.type === ObservableTypeEnum.keyUpEvent) { this.processKeyStroke(result); } else if (result.type === ObservableTypeEnum.gameOver) { this.isGameOver = result.booleanData; } else if (result.type === ObservableTypeEnum.gamePaused) { this.isGamePaused = result.booleanData; } }); } /** * The extended animate class */ /* eslint-disable-next-line */ animate() { } /** * Get the Asset height */ getAssetHeight() { return this.assetHeight * this.assetScale.y; } /** * Get the Asset Width */ getAssetWidth() { return this.assetWidth * this.assetScale.x; } /** * set The Asset Dimensions * @param height The asset height * @param width The asset width */ setAssetDimensions(height, width) { this.assetHeight = height; this.assetWidth = width; } /** * Get the asset uid */ get uid() { return this.assetUid; } /** * Process the key stroke * @param eventCode the key event code */ /* eslint-disable-next-line */ processKeyStroke(event) { } /** * Move the asset * @param asset The asset input */ move(asset) { this.x = asset.x; this.y = asset.y; } /** * Determine if we should stop the animation */ stopAnimation() { return this.isDestroyed || this.isGameOver || this.isGamePaused; } /** * Position the Asset */ positionAsset(alignPosition, justifyPosition) { let x = 0; let y = 0; if (alignPosition === AssetAlignEnum.center) { x = (this.boundary.right - this.getAssetWidth()) / 2; } else if (alignPosition === AssetAlignEnum.leftThird) { x = this.boundary.right / 3 - this.getAssetWidth() / 2; } else if (alignPosition === AssetAlignEnum.leftFourth) { x = this.boundary.right / 4 - this.getAssetWidth() / 2; } else if (alignPosition === AssetAlignEnum.rightThird) { x = (this.boundary.right * 2) / 3 - this.getAssetWidth() / 2; } else if (alignPosition === AssetAlignEnum.rightFourth) { x = (this.boundary.right * 3) / 4 - this.getAssetWidth() / 2; } else if (alignPosition === AssetAlignEnum.right) { x = this.boundary.right - this.getAssetWidth(); } if (justifyPosition === AssetAlignVerticalEnum.bottom) { y = this.boundary.floor - this.getAssetHeight(); } else if (justifyPosition === AssetAlignVerticalEnum.middle) { y = (this.boundary.floor - this.getAssetHeight()) / 2; } return { x: Math.round(x), y: Math.round(y) }; } } /** * The Prism Base Class */ class BaseClass extends AssetClass { /** * Constructor * @param gameService The GameService * @param ctx The ctx * @param guid The guid of the alien */ constructor(gameService, ctx, guid) { super(gameService, ctx, guid); } /** * Draw the base */ draw() { if (this.isImageLoaded) { this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.scale(this.assetScale.x, this.assetScale.y); this.ctx.drawImage(this.currentBase.imageSource, this.currentBase.x, this.currentBase.y); this.ctx.restore(); } } /** * Animate the base */ animate() { this.draw(); } } /** * The Image Loaded Enum */ var ImageLoadedEnum; (function (ImageLoadedEnum) { /** * Unknown */ ImageLoadedEnum["unknown"] = "unknown"; /** * Alien Base */ ImageLoadedEnum["alienBase"] = "alienBase"; /** * Alien Dropship 1 */ ImageLoadedEnum["alienDropship1"] = "alienDropship1"; /** * Alien Dropship 2 */ ImageLoadedEnum["alienDropship2"] = "alienDropship2"; /** * Alien One Right */ ImageLoadedEnum["alienOneRight"] = "alienOneRight"; /** * Alien One Left */ ImageLoadedEnum["alienOneLeft"] = "alienOneLeft"; /** * Alien 2 Animation East 1 */ ImageLoadedEnum["alien2AnimationEast1"] = "alien2AnimationEast1"; /** * Alien 2 Animation East 2 */ ImageLoadedEnum["alien2AnimationEast2"] = "alien2AnimationEast2"; /** * Alien 2 Animation North 1 */ ImageLoadedEnum["alien2AnimationNorth1"] = "alien2AnimationNorth1"; /** * Alien 2 Animation North 2 */ ImageLoadedEnum["alien2AnimationNorth2"] = "alien2AnimationNorth2"; /** * Alien 2 Animation West 1 */ ImageLoadedEnum["alien2AnimationWest1"] = "alien2AnimationWest1"; /** * Alien 2 Animation West 2 */ ImageLoadedEnum["alien2AnimationWest2"] = "alien2AnimationWest2"; /** * Scenery Bridge */ ImageLoadedEnum["bridge"] = "bridge"; /** * grass */ ImageLoadedEnum["grass"] = "grass"; /** * Scenery Lava */ ImageLoadedEnum["lava"] = "lava"; /** * letter l */ ImageLoadedEnum["letterl"] = "letterl"; /** * letter p */ ImageLoadedEnum["letterp"] = "letterp"; /** * level one */ ImageLoadedEnum["levelOneMap"] = "levelOneMap"; /** * Main Gunner */ ImageLoadedEnum["mainGunner"] = "mainGunner"; /** * Main Gunner Support */ ImageLoadedEnum["mainGunnerSupport"] = "mainGunnerSupport"; /** * Blue missile */ ImageLoadedEnum["missileBlue"] = "missileBlue"; /** * missile green */ ImageLoadedEnum["missileGreen"] = "missileGreen"; /** * missile indigo */ ImageLoadedEnum["missileIndigo"] = "missileIndigo"; /** * missile orange */ ImageLoadedEnum["missileOrange"] = "missileOrange"; /** * missile red */ ImageLoadedEnum["missileRed"] = "missileRed"; /** * missile violet */ ImageLoadedEnum["missileViolet"] = "missileViolet"; /** * missile white */ ImageLoadedEnum["missileWhite"] = "missileWhite"; /** * missile yellow */ ImageLoadedEnum["missileYellow"] = "missileYellow"; /** * number 0 */ ImageLoadedEnum["number0"] = "number0"; /** * number 1 */ ImageLoadedEnum["number1"] = "number1"; /** * number 2 */ ImageLoadedEnum["number2"] = "number2"; /** * number 3 */ ImageLoadedEnum["number3"] = "number3"; /** * number 4 */ ImageLoadedEnum["number4"] = "number4"; /** * number 5 */ ImageLoadedEnum["number5"] = "number5"; /** * number 6 */ ImageLoadedEnum["number6"] = "number6"; /** * number 7 */ ImageLoadedEnum["number7"] = "number7"; /** * number 8 */ ImageLoadedEnum["number8"] = "number8"; /** * number 9 */ ImageLoadedEnum["number9"] = "number9"; /** * path */ ImageLoadedEnum["path"] = "path"; /** * path direction */ ImageLoadedEnum["pathDirection"] = "pathDirection"; /** * prism base */ ImageLoadedEnum["prismBase"] = "prismBase"; /** * prism blast icon */ ImageLoadedEnum["prismBlastIcon"] = "prismBlastIcon"; /** * rock */ ImageLoadedEnum["rock"] = "rock"; /** * rock land */ ImageLoadedEnum["rockGround"] = "rockGround"; /** * slime */ ImageLoadedEnum["slime"] = "slime"; /** * slime 2 */ ImageLoadedEnum["slime2"] = "slime2"; /** * slime ground */ ImageLoadedEnum["slimeGround"] = "slimeGround"; /** * Tractor Beam 1 */ ImageLoadedEnum["tractorBeam1"] = "tractorBeam1"; /** * Tractor Beam 2 */ ImageLoadedEnum["tractorBeam2"] = "tractorBeam2"; /** * Tractor Beam 3 */ ImageLoadedEnum["tractorBeam3"] = "tractorBeam3"; /** * Scenery Tree */ ImageLoadedEnum["tree"] = "tree"; /** * Scenery Tree Land */ ImageLoadedEnum["treeGround"] = "treeGround"; /** * Scenery Water 0 */ ImageLoadedEnum["water0"] = "water0"; /** * Scenery Water 1 */ ImageLoadedEnum["water1"] = "water1"; /** * Scenery Water 2 */ ImageLoadedEnum["water2"] = "water2"; /** * Scenery Water 3 */ ImageLoadedEnum["water3"] = "water3"; /** * Scenery Water 4 */ ImageLoadedEnum["water4"] = "water4"; /** * Scenery Water 5 */ ImageLoadedEnum["water5"] = "water5"; /** * Scenery Water 6 */ ImageLoadedEnum["water6"] = "water6"; /** * Scenery Water 7 */ ImageLoadedEnum["water7"] = "water7"; /** * Scenery Water 8 */ ImageLoadedEnum["water8"] = "water8"; /** * Scenery Water 9 */ ImageLoadedEnum["water9"] = "water9"; /** * Scenery Water 10 */ ImageLoadedEnum["water10"] = "water10"; /** * Scenery Water 11 */ ImageLoadedEnum["water11"] = "water11"; /** * Scenery Water 12 */ ImageLoadedEnum["water12"] = "water12"; /** * Scenery Water 13 */ ImageLoadedEnum["water13"] = "water13"; /** * Scenery Water 14 */ ImageLoadedEnum["water14"] = "water14"; /** * Scenery Water 15 */ ImageLoadedEnum["water15"] = "water15"; /** * Scenery Water Waves */ ImageLoadedEnum["waterWaves"] = "waterWaves"; })(ImageLoadedEnum || (ImageLoadedEnum = {})); /** * The Prism Base Class */ class PrismBaseClass extends BaseClass { /** * Constructor * @param gameService The GameService * @param ctx The ctx * @param guid The guid of the alien */ constructor(gameService, ctx, guid) { super(gameService, ctx, guid); /** * moves */ this.moves = { [KEY.P]: true }; this.loadPrismBaseImages(); this.assetScale = { x: 0.2, y: 0.2 }; } /** * Load the alien Images */ loadPrismBaseImages() { const imagesToLoad = [ImageLoadedEnum.prismBase]; imagesToLoad.map((key) => { this.images.push(this.gameService.getImage(key)); this.isImageLoaded = true; }); this.currentBase = this.images[0]; } /** * Press Key Stroke * @param event The Key event */ processKeyStroke(event) { const eventCode = event.stringData; const keyDown = event.type === ObservableTypeEnum.keyDownEvent; if (this.moves[eventCode] && keyDown) { this.gameService.emitMasterObservableEvent({ type: ObservableTypeEnum.prismBlastLaunched, assetCoordinateData: { x: this.x, y: this.y - BLOCK_SIZE }, booleanData: true }); } } } /** * The Alien Base Class */ class AlienBaseClass extends BaseClass { /** * Constructor * @param gameService The GameService * @param ctx The ctx * @param guid The guid of the alien */ constructor(gameService, ctx, guid) { super(gameService, ctx, guid); this.loadAlienBaseImages(); this.assetScale = { x: 0.2, y: 0.2 }; } /** * Load the alien Images */ loadAlienBaseImages() { const imagesToLoad = [ImageLoadedEnum.alienBase]; imagesToLoad.map((key) => { this.images.push(this.gameService.getImage(key)); this.isImageLoaded = true; }); this.currentBase = this.images[0]; } } /** * The Asset Direction Enum */ var AssetDirectionEnum; (function (AssetDirectionEnum) { /** * East */ AssetDirectionEnum[AssetDirectionEnum["east"] = 90] = "east"; /** * West */ AssetDirectionEnum[AssetDirectionEnum["west"] = -90] = "west"; /** * North */ AssetDirectionEnum[AssetDirectionEnum["north"] = 0] = "north"; /** * South */ AssetDirectionEnum[AssetDirectionEnum["south"] = 180] = "south"; })(AssetDirectionEnum || (AssetDirectionEnum = {})); /** * The Alien Class */ class AlienClass extends AssetClass { /** * Constructor * @param gameService The GameService * @param ctx The ctx * @param guid The guid of the alien */ constructor(gameService, ctx, guid) { super(gameService, ctx, guid); this.alienAssetTimer = { start: performance.now(), elapsed: 0 }; this.alienSpeed = 500; this.originamAlienSpeed = this.alienSpeed; this.currentAlienDirection = AssetDirectionEnum.west; this.eastAlienImages = []; this.westAlienImages = []; this.northAlienImages = []; this.gameService.getMasterObservable().subscribe((event) => { if (event.type === ObservableTypeEnum.prismBlastLaunched && event.booleanData) { this.alienSpeed = 2000; } else if (event.type === ObservableTypeEnum.prismBlastDefused && event.booleanData) { this.alienSpeed = this.originamAlienSpeed; } }); } /** * Determine the path of the creep * * @param moves All the moves of the creep */ setCreepPath(moves) { this.allMoves = moves; this.nextMove = this.allMoves[0]; this.move(this.allMoves[0]); } /** * Set the creep speed * @param speed The speed to set */ setCreepSpeed(speed) { this.alienSpeed = speed; } /** * Draw the alien */ draw() { if (this.isImageLoaded) { this.ctx.save(); this.ctx.translate(this.x + BLOCK_SIZE / 2, this.y + BLOCK_SIZE / 2); this.ctx.scale(this.assetScale.x, this.assetScale.y); this.ctx.drawImage(this.currentAlien.imageSource, this.currentAlien.x, this.currentAlien.y); this.ctx.restore(); } } /** * Animate the alien * @param now the current time */ animate(now = 0) { this.assetTimer.elapsed = now - this.assetTimer.start; this.alienAssetTimer.elapsed = now - this.alienAssetTimer.start; if (this.stopAnimation()) { return; } if (this.assetTimer.elapsed > Math.floor(this.alienSpeed / 2)) { this.assetTimer.start = now; this.nextMove = this.allMoves.shift(); this.move(this.nextMove); if (this.nextMove.rotate === 90 && this.currentAlienDirection !== AssetDirectionEnum.east) { this.currentAlienDirection = AssetDirectionEnum.east; this.images = this.eastAlienImages; } else if (this.nextMove.rotate === -90 && this.currentAlienDirection !== AssetDirectionEnum.west) { this.currentAlienDirection = AssetDirectionEnum.west; this.images = this.westAlienImages; } else if (this.nextMove.rotate === 0 && this.currentAlienDirection !== AssetDirectionEnum.north) { this.currentAlienDirection = AssetDirectionEnum.north; this.images = this.northAlienImages; } if (this.gameService.isBaseDestroy(this)) { this.isDestroyed = true; return; } } if (this.alienAssetTimer.elapsed > Math.floor(this.alienSpeed / 4)) { this.alienAssetTimer.start = now; this.currentAlien = this.images[this.animationCounter++ % this.images.length]; } this.draw(); } } /** * The Alien 1 Class */ class Alien1Class extends AlienClass { /** * Constructor * @param gameService The GameService * @param ctx The ctx * @param guid The guid of the alien * @param spawnLocation The guid of the alien */ constructor(gameService, ctx, guid) { super(gameService, ctx, guid); this.loadAlienImages(); this.assetScale = { x: 0.2, y: 0.2 }; } /** * Load the alien Images */ loadAlienImages() { const imagesToLoad = [ImageLoadedEnum.alienOneRight, ImageLoadedEnum.alienOneLeft]; imagesToLoad.map((key) => { this.images.push(this.gameService.getImage(key)); this.isImageLoaded = true; }); this.currentAlien = this.images[0]; this.eastAlienImages = this.images; this.northAlienImages = this.images; this.westAlienImages = this.images; } } /** * The Alien 2 Class */ class Alien2Class extends AlienClass { /** * Constructor * @param gameService The GameService * @param ctx The ctx * @param guid The guid of the alien * @param spawnLocation The guid of the alien */ constructor(gameService, ctx, guid) { super(gameService, ctx, guid); this.loadAlienImages(); this.assetScale = { x: 0.2, y: 0.2 }; } /** * Load the alien Images */ loadAlienImages() { const imagesToLoad = [ ImageLoadedEnum.alien2AnimationEast1, ImageLoadedEnum.alien2AnimationEast2, ImageLoadedEnum.alien2AnimationNorth1, ImageLoadedEnum.alien2AnimationNorth2, ImageLoadedEnum.alien2AnimationWest1, ImageLoadedEnum.alien2AnimationWest2 ]; imagesToLoad.map((key) => { this.images.push(this.gameService.getImage(key)); this.isImageLoaded = true; }); this.eastAlienImages = [this.images[0], this.images[1]]; this.northAlienImages = [this.images[2], this.images[3]]; this.westAlienImages = [this.images[4], this.images[5]]; this.images = this.westAlienImages; this.currentAlien = this.images[0]; } } /** * The Alien Path Enum */ var AlienPathEnum; (function (AlienPathEnum) { /** * Empty */ AlienPathEnum["empty"] = "empty"; /** * Start */ AlienPathEnum["start"] = "start"; /** * Invalid */ AlienPathEnum["invalid"] = "invalid"; /** * Valid */ AlienPathEnum["valid"] = "valid"; /** * Goal */ AlienPathEnum["goal"] = "goal"; /** * Main Gunner */ AlienPathEnum["gunner"] = "gunner"; /** * Alien Base */ AlienPathEnum["alientBase"] = "alienBase"; /** * Blocked */ AlienPathEnum["blocked"] = "blocked"; /** * Unknown */ AlienPathEnum["unknown"] = "unknown"; /** * Visited */ AlienPathEnum["visited"] = "visited"; /** * Obstacle */ AlienPathEnum["obstacle"] = "obstacle"; })(AlienPathEnum || (AlienPathEnum = {})); /** * The Alien Path Direction Enum */ var AlienPathDirectionEnum; (function (AlienPathDirectionEnum) { /** * North */ AlienPathDirectionEnum["north"] = "north"; /** * East */ AlienPathDirectionEnum["east"] = "east"; /** * West */ AlienPathDirectionEnum["west"] = "west"; /** * South */ AlienPathDirectionEnum["south"] = "south"; })(AlienPathDirectionEnum || (AlienPathDirectionEnum = {})); /** * The path service */ class PathService { // http://gregtrowbridge.com/a-basic-pathfinding-algorithm/ /** * Finds the shortest path for an alien from the spawn location * To the base * * @param startCoordinates the Starting Coordinating */ findShortestPath(startCoordinates, gameboard) { const pathBoard = JSON.parse(JSON.stringify(gameboard)); const distanceFromLeft = startCoordinates.x; const distanceFromTop = startCoordinates.y; // Each "location" will store its coordinates // and the shortest path required to arrive there const location = { distanceFromTop, distanceFromLeft, path: [ { x: distanceFromLeft * BLOCK_SIZE, y: distanceFromTop * BLOCK_SIZE } ], status: AlienPathEnum.start }; // Initialize the queue with the start location already inside const queue = [location]; // Loop through the grid searching for the goal while (queue.length > 0) { // Take the first location off the queue const currentLocation = queue.shift(); // Explore South let newLocation = this.exploreInDirection(currentLocation, AlienPathDirectionEnum.south, pathBoard); if (newLocation.status === AlienPathEnum.goal) { return newLocation.path; } else if (newLocation.status === AlienPathEnum.valid) { queue.push(newLocation); } // Explore East newLocation = this.exploreInDirection(currentLocation, AlienPathDirectionEnum.east, pathBoard); if (newLocation.status === AlienPathEnum.goal) { return newLocation.path; } else if (newLocation.status === AlienPathEnum.valid) { queue.push(newLocation); } // Explore West newLocation = this.exploreInDirection(currentLocation, AlienPathDirectionEnum.west, pathBoard); if (newLocation.status === AlienPathEnum.goal) { return newLocation.path; } else if (newLocation.status === AlienPathEnum.valid) { queue.push(newLocation); } // Explore North newLocation = this.exploreInDirection(currentLocation, AlienPathDirectionEnum.north, pathBoard); if (newLocation.status === AlienPathEnum.goal) { return newLocation.path; } else if (newLocation.status === AlienPathEnum.valid) { queue.push(newLocation); } } // No valid path found return []; // Emergency map fix /* return [ { x: 0, y: 0, rotate: 0 } as IAsset ]; */ } /** * Checks the location status */ locationStatus(location, localPathboard) { const yGridSize = localPathboard.length; const xGridSize = localPathboard[0].length; const distanceFromTop = location.distanceFromTop; const distanceFromLeft = location.distanceFromLeft; if (location.distanceFromLeft < 0 || location.distanceFromLeft >= xGridSize || location.distanceFromTop < 0 || location.distanceFromTop >= yGridSize) { // location is not on the grid--return false return AlienPathEnum.invalid; } else if (localPathboard[distanceFromTop][distanceFromLeft] === AlienPathEnum.goal) { return AlienPathEnum.goal; } else if (localPathboard[distanceFromTop][distanceFromLeft] !== AlienPathEnum.empty) { // location is either an obstacle or has been visited return AlienPathEnum.blocked; } else { return AlienPathEnum.valid; } } /** * Explore around the current location * @param currentLocation The current location * @param direction the direction to explore */ exploreInDirection(currentLocation, direction, localPathboard) { const newPath = currentLocation.path.slice(); let rotation = 0; let distanceFromTop = currentLocation.distanceFromTop; let distanceFromLeft = currentLocation.distanceFromLeft; if (direction === AlienPathDirectionEnum.north) { distanceFromTop -= 1; rotation = AssetDirectionEnum.north; } else if (direction === AlienPathDirectionEnum.east) { rotation = AssetDirectionEnum.east; distanceFromLeft += 1; } else if (direction === AlienPathDirectionEnum.south) { rotation = AssetDirectionEnum.south; distanceFromTop += 1; } else { rotation = AssetDirectionEnum.west; distanceFromLeft -= 1; } let xOffset = 0; let yOffset = 0; const offset = BLOCK_SIZE / 2; if (rotation === AssetDirectionEnum.north) { yOffset = offset; } else if (rotation === AssetDirectionEnum.south) { yOffset = -offset; } else if (rotation === AssetDirectionEnum.east) { xOffset = -offset; } else { xOffset = offset; } newPath.push({ x: distanceFromLeft * BLOCK_SIZE + xOffset, y: distanceFromTop * BLOCK_SIZE + yOffset, rotate: rotation }); newPath.push({ x: distanceFromLeft * BLOCK_SIZE, y: distanceFromTop * BLOCK_SIZE, rotate: rotation }); const newLocation = { distanceFromTop, distanceFromLeft, path: newPath, status: AlienPathEnum.unknown }; newLocation.status = this.locationStatus(newLocation, localPathboard); // If this new location is valid, mark it as 'Visited' if (newLocation.status === AlienPathEnum.valid) { localPathboard[newLocation.distanceFromTop][newLocation.distanceFromLeft] = AlienPathEnum.visited; } return newLocation; } /** * Get the Alien Drop Ship Path * @param startPosition The starting position * @param endPosition The ending position */ getAlienDropShipPath(startPosition, endPosition) { const path = []; const yPosition = endPosition.y > 0 ? endPosition.y - BLOCK_SIZE : endPosition.y; for (let index = startPosition.x; index <= endPosition.x; index += BLOCK_SIZE / 2) { path.push({ x: index, y: yPosition, rotate: AssetDirectionEnum.north }); } return path; } } PathService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: PathService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); PathService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: PathService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: PathService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); /** * The Alien Dropship Class */ class AlienDropshipClass extends AlienClass { /** * Constructor * @param gameService The GameService * @param ctx The ctx * @param guid The guid of the alien * @param spawnLocation The guid of the alien */ constructor(gameService, ctx, guid) { super(gameService, ctx, guid); this.tractorBeamTimer = { start: performance.now(), elapsed: 0 }; this.pathService = new PathService(); this.tractorBeamImages = []; this.tractorBeamAnimationCounter = 0; this.tractorBeamScale = 0; this.setAlienDropshipToDeploy(); this.loadAlienDropshipImages(); this.assetScale = { x: 0.2, y: 0.2 }; } /** * Load the alien Images */ loadAlienDropshipImages() { let imagesToLoad = [ImageLoadedEnum.alienDropship1, ImageLoadedEnum.alienDropship2]; imagesToLoad.map((key) => { this.images.push(this.gameService.getImage(key)); }); imagesToLoad = [ImageLoadedEnum.tractorBeam1, ImageLoadedEnum.tractorBeam2, ImageLoadedEnum.tractorBeam3]; imagesToLoad.map((key) => { this.tractorBeamImages.push(this.gameService.getImage(key)); }); this.isImageLoaded = true; this.currentAlien = this.images[0]; this.tractorBeamImage = this.tractorBeamImages[0]; } /** * If the aliens can land */ canLandAliens() { return this.atLandingBase; } /** * Reset the ship to deploy aliens */ setAlienDropshipToDeploy() { this.atLandingBase = false; this.isLeavingBase = false; this.tractorBeamScale = 0.05; } /** * If the aliens have landed */ setAliensLanded() { const gameboard = this.gameService.getBoardSize(); const endingPosition = { x: gameboard.width + BLOCK_SIZE, y: this.nextMove.y + BLOCK_SIZE }; this.allMoves = this.pathService.getAlienDropShipPath(this.nextMove, endingPosition); this.isLeavingBase = true; this.atLandingBase = false; } /** * Draw the alien tractor beam */ drawTractorBeam() { this.ctx.save(); this.ctx.translate(this.x + BLOCK_SIZE / 2, this.y + BLOCK_SIZE / 2); this.ctx.scale(this.assetScale.x * this.tractorBeamScale, this.assetScale.y * this.tractorBeamScale); this.ctx.drawImage(this.tractorBeamImage.imageSource, this.tractorBeamImage.x, this.tractorBeamImage.y); this.ctx.restore(); if (this.tractorBeamScale < 1) { this.tractorBeamScale += 0.05; } } /** * Animate the alien * @param now the current time */ animate(now = 0) { this.assetTimer.elapsed = now - this.assetTimer.start; this.tractorBeamTimer.elapsed = now - this.tractorBeamTimer.start; if (this.stopAnimation()) { this.setAlienDropshipToDeploy(); return; } if (this.assetTimer.elapsed > 75) { this.currentAlien = this.images[this.animationCounter++ % this.images.length]; this.assetTimer.start = now; if (this.allMoves.length > 0 && !this.canLandAliens()) { this.nextMove = this.allMoves.shift(); this.move(this.nextMove); } else if (this.allMoves.length === 0 && !this.canLandAliens()) { this.atLandingBase = true; } else if (this.isLeavingBase && !this.gameService.valid(this.nextMove)) { this.isDestroyed = true; } } if (this.allMoves.length === 0 && this.canLandAliens() && this.tractorBeamTimer.elapsed > 15) { this.tractorBeamImage = this.tractorBeamImages[this.tractorBeamAnimationCounter++ % this.tractorBeamImages.length]; this.tractorBeamTimer.start = now; this.drawTractorBeam(); }