bp-space-invaders
Version:
The BP Space Invaders Game
1 lines • 373 kB
Source Map (JSON)
{"version":3,"file":"bp-space-invaders.mjs","sources":["../../../projects/space-invaders/src/lib/service/game-cookie.service.ts","../../../projects/space-invaders/src/lib/asset/enum/asset-align.enum.ts","../../../projects/space-invaders/src/lib/asset/enum/asset-align-vertical.enum.ts","../../../projects/space-invaders/src/lib/gameboard/gameboard-constants.ts","../../../projects/space-invaders/src/lib/service/game.service.ts","../../../projects/space-invaders/src/lib/aliens/alien-boss-1/alien-boss-1-constants.ts","../../../projects/space-invaders/src/lib/aliens/alien/alien-constants.ts","../../../projects/space-invaders/src/lib/enum/observable-type.enum.ts","../../../projects/space-invaders/src/lib/asset/asset.class.ts","../../../projects/space-invaders/src/lib/aliens/alien/alien.class.ts","../../../projects/space-invaders/src/lib/aliens/alien-boss/alien-boss.class.ts","../../../projects/space-invaders/src/lib/aliens/alien-boss-1/alien-boss-1.class.ts","../../../projects/space-invaders/src/lib/aliens/alien-boss-2/alien-boss-2-constants.ts","../../../projects/space-invaders/src/lib/aliens/alien-boss-2/alien-boss-2.class.ts","../../../projects/space-invaders/src/lib/aliens/alien-boss/test-component/alien-boss.component.ts","../../../projects/space-invaders/src/lib/aliens/alien-boss/test-component/alien-boss.component.html","../../../projects/space-invaders/src/lib/aliens/alien-1/alien-1-constants.ts","../../../projects/space-invaders/src/lib/aliens/alien-1/alien-1.class.ts","../../../projects/space-invaders/src/lib/aliens/alien-2/alien-2-constants.ts","../../../projects/space-invaders/src/lib/aliens/alien-2/alien-2.class.ts","../../../projects/space-invaders/src/lib/aliens/alien-3/alien-3-constants.ts","../../../projects/space-invaders/src/lib/aliens/alien-3/alien-3.class.ts","../../../projects/space-invaders/src/lib/aliens/alien-4/alien-4-constants.ts","../../../projects/space-invaders/src/lib/aliens/alien-4/alien-4.class.ts","../../../projects/space-invaders/src/lib/aliens/alien-5/alien-5-constants.ts","../../../projects/space-invaders/src/lib/aliens/alien-5/alien-5.class.ts","../../../projects/space-invaders/src/lib/aliens/alien-6/alien-6-constants.ts","../../../projects/space-invaders/src/lib/aliens/alien-6/alien-6.class.ts","../../../projects/space-invaders/src/lib/aliens/alien/test-component/alien.component.ts","../../../projects/space-invaders/src/lib/aliens/alien/test-component/alien.component.html","../../../projects/space-invaders/src/lib/bomb/bomb-constants.ts","../../../projects/space-invaders/src/lib/bomb/bomb.class.ts","../../../projects/space-invaders/src/lib/bomb/test-component/bomb.component.ts","../../../projects/space-invaders/src/lib/bomb/test-component/bomb.component.html","../../../projects/space-invaders/src/lib/number/number-constants.ts","../../../projects/space-invaders/src/lib/number/number.class.ts","../../../projects/space-invaders/src/lib/service/text.service.ts","../../../projects/space-invaders/src/lib/service/invasion.service.ts","../../../projects/space-invaders/src/lib/service/moon.service.ts","../../../projects/space-invaders/src/lib/moon-defense/moon-defense-constants.ts","../../../projects/space-invaders/src/lib/moon-defense/moon-defense.class.ts","../../../projects/space-invaders/src/lib/service/moon-defense.service.ts","../../../projects/space-invaders/src/lib/spaceships/spaceship-2/spaceship-2-constants.ts","../../../projects/space-invaders/src/lib/spaceships/spaceship/spaceship-constants.ts","../../../projects/space-invaders/src/lib/spaceships/spaceship/spaceship.class.ts","../../../projects/space-invaders/src/lib/spaceships/spaceship-2/spaceship-2.class.ts","../../../projects/space-invaders/src/lib/service/spaceship.service.ts","../../../projects/space-invaders/src/lib/missile/missile-2/missile-2-constants.ts","../../../projects/space-invaders/src/lib/missile/missile/missile-constants.ts","../../../projects/space-invaders/src/lib/missile/missile/missile.class.ts","../../../projects/space-invaders/src/lib/missile/missile-2/missile-2.class.ts","../../../projects/space-invaders/src/lib/service/projectile.service.ts","../../../projects/space-invaders/src/lib/gameboard/gameboard.component.ts","../../../projects/space-invaders/src/lib/gameboard/gameboard.component.html","../../../projects/space-invaders/src/lib/missile/missile-1/missile-1-constants.ts","../../../projects/space-invaders/src/lib/missile/missile-1/missile-1.class.ts","../../../projects/space-invaders/src/lib/missile/missile/test-component/missile.component.ts","../../../projects/space-invaders/src/lib/missile/missile/test-component/missile.component.html","../../../projects/space-invaders/src/lib/moon-defense/test-component/moon-defense.component.ts","../../../projects/space-invaders/src/lib/moon-defense/test-component/moon-defense.component.html","../../../projects/space-invaders/src/lib/number/test-component/number.component.ts","../../../projects/space-invaders/src/lib/number/test-component/number.component.html","../../../projects/space-invaders/src/lib/spaceships/spaceship-1/spaceship-1-constants.ts","../../../projects/space-invaders/src/lib/spaceships/spaceship-1/spaceship-1.class.ts","../../../projects/space-invaders/src/lib/spaceships/spaceship/test-component/spaceship.component.ts","../../../projects/space-invaders/src/lib/spaceships/spaceship/test-component/spaceship.component.html","../../../projects/space-invaders/src/lib/space-invaders/space-invaders.component.ts","../../../projects/space-invaders/src/lib/space-invaders/space-invaders.component.html","../../../projects/space-invaders/src/lib/space-invaders.module.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { CookieService } from 'ngx-cookie-service';\nimport { GameDataModel } from '../model/game-data.model';\nimport { DebugDataModel } from '../model/debug-data.model';\n\n/**\n * The Cookie service\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class GameCookieService {\n /**\n * The constructor\n * @param cookieService The cookieService from DI\n */\n constructor(private cookieService: CookieService) {}\n\n /**\n * Get the cookie\n */\n private getCookie(cookieName: string): string {\n return this.cookieService.get(cookieName);\n }\n\n /**\n * Get the High Score\n */\n public getGameData(): GameDataModel {\n const cookie = this.getCookie('bp-space-invaders');\n return cookie ? (JSON.parse(cookie) as GameDataModel) : ({ highScore: 0 } as GameDataModel);\n }\n\n /**\n * Set the cookie\n */\n public setGameData(data: GameDataModel): void {\n this.cookieService.set('bp-space-invaders', JSON.stringify(data));\n }\n\n /**\n * Get the Debug information\n */\n public getDebugData(): string {\n const cookie = this.getCookie('bp-space-invaders-debug');\n /* eslint-disable-next-line */\n return cookie ? (JSON.parse(cookie)['assetName'] as string) : '';\n }\n\n /**\n * Get the Secondary Debug information\n */\n public getSecondaryDebugData(): string {\n const cookie = this.getCookie('bp-space-invaders-debug');\n /* eslint-disable-next-line */\n return cookie ? (JSON.parse(cookie)['secondaryAssetName'] as string) : '';\n }\n\n /**\n * Set the debug cookie data\n *\n * @param assetName The asset name\n */\n public setDebugData(debugData: DebugDataModel): void {\n const cookie = this.getCookie('bp-space-invaders-debug');\n const existingCookie = (cookie ? JSON.parse(cookie) : {}) as DebugDataModel;\n existingCookie.assetName = debugData.assetName ? debugData.assetName : existingCookie.assetName;\n existingCookie.secondaryAssetName = debugData.secondaryAssetName\n ? debugData.secondaryAssetName\n : existingCookie.secondaryAssetName;\n this.cookieService.set('bp-space-invaders-debug', JSON.stringify(existingCookie));\n }\n}\n","/**\n * The Asset Align Enum\n */\nexport enum AssetAlignEnum {\n /**\n * Left\n */\n left = 'left',\n /**\n * Left Third\n */\n leftThird = 'leftThird',\n /**\n * Left Fourth\n */\n leftFourth = 'leftFourth',\n /**\n * right\n */\n right = 'right',\n /**\n * right Third\n */\n rightThird = 'rightThird',\n /**\n * right Fourth\n */\n rightFourth = 'rightFourth',\n /**\n * Center\n */\n center = 'center'\n}\n","/**\n * The Asset Align Vertical Enum\n */\nexport enum AssetAlignVerticalEnum {\n /**\n * Top\n */\n top = 'top',\n /**\n * Bottom\n */\n bottom = 'bottom',\n /**\n * Middle\n */\n middle = 'middle'\n}\n","/**\n * Block Size\n */\nexport const BLOCK_SIZE = 3;\n/**\n * Columns\n */\nexport const COLS = 260;\n/**\n * Rows\n */\nexport const ROWS = 240;\n/**\n * Alien Rows\n */\nexport const ALIEN_ROWS = 6;\n/**\n * Alien Columns\n */\nexport const ALIEN_COLUMNS = 6;\n/**\n * Moon Height\n */\nexport const MOON_HEIGHT = 10;\n\n/**\n * Colors Darker\n */\nexport const COLORS = [\n 'rgba(34, 65, 4)', // MOON GREEN\n 'rgba(200, 95, 36)', // Light Orange\n 'rgba(8, 136, 23)' // Green\n];\n\n/**\n * The Level Height\n */\nexport class LEVELHEIGHT {\n /**\n * Level 0 Height\n */\n static readonly 0 = 20;\n /**\n * Level 1 Height\n */\n static readonly 1 = 30;\n /**\n * Level 2 Height\n */\n static readonly 2 = 40;\n /**\n * Level 3 Height\n */\n static readonly 3 = 50;\n /**\n * Level 4 Height\n */\n static readonly 4 = 60;\n /**\n * Level 5 Height\n */\n static readonly 5 = 70;\n /**\n * Level 6 Height\n */\n static readonly 6 = 80;\n /**\n * Level 7 Height\n */\n static readonly 7 = 90;\n}\n\n/**\n * The Level Speed\n */\nexport class LEVELSPEED {\n /**\n * Level 0 Time\n */\n static readonly 0 = 700;\n /**\n * Level 1 Time\n */\n static readonly 1 = 500;\n /**\n * Level 2 Time\n */\n static readonly 2 = 350;\n /**\n * Level 3 Time\n */\n static readonly 3 = 250;\n /**\n * Level 4 Time\n */\n static readonly 4 = 150;\n /**\n * Level 5 Time\n */\n static readonly 5 = 100;\n // 29+ is 20ms\n}\n","import { Injectable, ElementRef } from '@angular/core';\nimport { IAsset } from '../interface/asset.interface';\nimport { Observable, Subject } from 'rxjs';\nimport { ObservableModel } from '../model/observable.model';\nimport { BoundaryModel } from '../model/boundary.model';\nimport { BoundarySetupModel } from '../model/boundary-set.model';\nimport { BoardModel } from '../model/board.model';\nimport { AssetAlignEnum } from '../asset/enum/asset-align.enum';\nimport { AssetAlignVerticalEnum } from '../asset/enum/asset-align-vertical.enum';\nimport { AssetClass } from '../asset/asset.class';\nimport { BLOCK_SIZE } from '../gameboard/gameboard-constants';\n\n/**\n * The game service\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class GameService {\n /**\n * Master Observable Subject$\n */\n private masterSubject$ = new Subject<ObservableModel>();\n\n /**\n * The board\n */\n private board: BoardModel;\n\n /**\n * Valid the Asset\n * @param asset The asset\n * @param boundary The board dimensions\n */\n valid(asset: IAsset, boundary: BoundaryModel): boolean {\n return asset.shape.every((row, dy) => {\n return row.every((value, dx) => {\n const x = asset.x + dx;\n const y = asset.y + dy;\n return (\n this.isEmpty(value) ||\n (this.insideWalls(x, boundary) &&\n this.aboveFloor(y, boundary.floor) &&\n this.belowCeiling(y, boundary.ceiling))\n );\n });\n });\n }\n\n /**\n * If the shape has value\n * @param value value of the shape\n */\n isEmpty(value: number): boolean {\n return value === 0;\n }\n\n /**\n * Is the piece within the gameboard walls\n * @param x The x position\n * @param boundary The boundary object\n */\n private insideWalls(x: number, boundary: BoundaryModel): boolean {\n return x >= boundary.left && x <= boundary.right;\n }\n\n /**\n * Is the piece within the gameboard floor\n * @param y The y position\n * @param boundaryTop The boundary top number\n */\n private belowCeiling(y: number, boundaryTop: number): boolean {\n return y >= boundaryTop;\n }\n\n /**\n * Is the piece within the gameboard floor\n * @param y The y position\n * @param boundaryBottom The boundary bottom number\n */\n private aboveFloor(y: number, boundaryBottom: number): boolean {\n return y <= boundaryBottom;\n }\n\n /**\n * Build the boundary\n * @param boundarySetup The y position\n */\n public getBoundary(boundarySetup: BoundarySetupModel): BoundaryModel {\n return {\n left: boundarySetup.x,\n right: boundarySetup.width,\n ceiling: boundarySetup.y,\n floor: boundarySetup.height\n } as BoundaryModel;\n }\n\n /**\n * Determine if an asset has collided with another asset\n * @param asset The asset receiving the damage\n * @param damageAsset The asset giving the damage\n */\n public isHit(asset: IAsset, damageAsset: IAsset): boolean {\n if (\n asset.x <= damageAsset.x &&\n damageAsset.x <= asset.x + asset.shape[0].length &&\n asset.y <= damageAsset.y &&\n damageAsset.y <= asset.y + asset.shape.length\n ) {\n const startY = damageAsset.y;\n let maxY = startY + damageAsset.shape.length;\n if (maxY > asset.y + asset.shape.length) {\n maxY = asset.y + asset.shape.length;\n }\n\n for (let y = startY; y < maxY; y++) {\n for (let x = damageAsset.x; x < damageAsset.x + damageAsset.shape[y - damageAsset.y].length; x++) {\n const assetY = Math.round(Math.abs(y - asset.y));\n const assetX = Math.round(Math.abs(x - asset.x));\n const damageAssetY = Math.round(Math.abs(y - damageAsset.y));\n const damageAssetX = Math.round(Math.abs(x - damageAsset.x));\n if (asset.shape[assetY][assetX] > 0 && damageAsset.shape[damageAssetY][damageAssetX] > 0) {\n return true;\n }\n }\n }\n }\n\n return false;\n }\n\n /**\n * Provide the outline\n *\n * @param ctx The Canvas Rendering Context 2D\n * @param columns The number of Columns\n * @param rows The number of rows\n * @param offset The offset for the grid\n */\n public addOutlines(ctx: CanvasRenderingContext2D, offset: number, width: number): void {\n ctx.fillStyle = 'grey';\n\n let lastIndex = 0;\n // vertical lines\n for (let index = 0; index < ctx.canvas.width; index += offset) {\n ctx.fillRect(index, 0, width, ctx.canvas.height);\n lastIndex = index;\n }\n\n ctx.fillRect(lastIndex + 1, 0, width, ctx.canvas.height);\n\n // horizontal lines\n for (let index = 0; index < ctx.canvas.height; index += offset) {\n ctx.fillRect(0, index, ctx.canvas.width, width);\n lastIndex = index;\n }\n\n ctx.fillRect(0, lastIndex + 1, ctx.canvas.width, width);\n\n ctx.fillStyle = 'red';\n ctx.fillRect(ctx.canvas.width / (BLOCK_SIZE * 2), 0, width, ctx.canvas.height);\n ctx.fillRect(0, ctx.canvas.height / (BLOCK_SIZE * 2), ctx.canvas.width, width);\n }\n\n /**\n * Initialize the board\n *\n * @param ctx The Canvas Rendering Context 2D\n * @param canvas The canvas element\n * @param columns The number of Columns\n * @param rows The number of rows\n * @param blockSize The block size\n */\n public initBoard(\n canvas: ElementRef<HTMLCanvasElement>,\n columns: number,\n rows: number,\n blockSize: number\n ): CanvasRenderingContext2D {\n const ctx = canvas.nativeElement.getContext('2d');\n\n this.board = {\n x: 0,\n y: 0,\n height: rows,\n width: columns\n } as BoardModel;\n\n // Calculate size of canvas from constants.\n ctx.canvas.width = columns * blockSize + 1;\n ctx.canvas.height = rows * blockSize + 1;\n\n // Scale so we don't need to give size on every draw.\n ctx.scale(blockSize, blockSize);\n\n return ctx;\n }\n\n /**\n * Get the game board\n */\n public getGameboard(): BoardModel {\n return this.board;\n }\n\n /**\n * Get the master observable\n */\n public getMasterObservable(): Observable<ObservableModel> {\n return this.masterSubject$;\n }\n\n /**\n * Get the master observable\n */\n public emitMasterObservableEvent(data: ObservableModel): void {\n this.masterSubject$.next(data);\n }\n\n /**\n * Position the Asset\n */\n public positionAsset(\n asset: AssetClass,\n alignPosition: AssetAlignEnum,\n justifyPosition: AssetAlignVerticalEnum\n ): IAsset {\n let x = 0;\n let y = 0;\n\n if (alignPosition === AssetAlignEnum.center) {\n x = (this.board.width - asset.getAssetWidth()) / 2;\n } else if (alignPosition === AssetAlignEnum.leftThird) {\n x = this.board.width / 3 - asset.getAssetWidth() / 2;\n } else if (alignPosition === AssetAlignEnum.leftFourth) {\n x = this.board.width / 4 - asset.getAssetWidth() / 2;\n } else if (alignPosition === AssetAlignEnum.rightThird) {\n x = (this.board.width * 2) / 3 - asset.getAssetWidth() / 2;\n } else if (alignPosition === AssetAlignEnum.rightFourth) {\n x = (this.board.width * 3) / 4 - asset.getAssetWidth() / 2;\n } else if (alignPosition === AssetAlignEnum.right) {\n x = this.board.width - asset.getAssetWidth();\n }\n\n if (justifyPosition === AssetAlignVerticalEnum.bottom) {\n y = this.board.height - asset.getAssetHeight();\n } else if (justifyPosition === AssetAlignVerticalEnum.middle) {\n y = (this.board.height - asset.getAssetHeight()) / 2;\n }\n\n return {\n x: Math.round(x),\n y: Math.round(y)\n } as IAsset;\n }\n}\n","/**\n * The first asset animation\n */\nconst ASSET_ANIMATION_1 = [\n [0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0],\n [0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],\n [0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0],\n [0, 2, 2, 0, 0, 2, 0, 0, 2, 2, 0, 0, 2, 0, 0, 2, 2, 0],\n [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],\n [0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0],\n [0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]\n];\n\n/**\n * The asset animation array\n */\nexport const ASSET_ANIMATION = [ASSET_ANIMATION_1];\n","/**\n * Columns\n */\nexport const COLS = 31;\n/**\n * Rows\n */\nexport const ROWS = 31;\n/**\n * Block Size\n */\nexport const BLOCK_SIZE = 25;\n\n/**\n * The colors\n */\nexport const COLORS = [\n 'none',\n 'rgba(200, 95, 36)', // Light Orange\n 'rgba(255, 0, 0)', // Red\n 'rgba(122, 122, 122)', // Grey\n 'rgba(163, 46, 132)' // Purple\n];\n\n/**\n * The keys\n */\nexport class KEY {\n /**\n * Down\n */\n static readonly DOWN = 'ArrowDown';\n /**\n * LEFT\n */\n static readonly LEFT = 'ArrowLeft';\n /**\n * RIGHT\n */\n static readonly RIGHT = 'ArrowRight';\n}\n\n/**\n * The first destruction animation\n */\nconst DESTRUCTION_ANIMATION_1 = [\n [2, 0, 0, 0, 0, 0, 0, 0, 0, 2],\n [0, 2, 0, 0, 0, 0, 0, 0, 2, 0],\n [0, 0, 2, 3, 2, 0, 2, 0, 0, 0],\n [0, 0, 2, 0, 2, 2, 3, 2, 0, 0],\n [0, 0, 0, 2, 3, 2, 2, 0, 0, 0],\n [0, 0, 2, 3, 2, 2, 0, 2, 0, 0],\n [0, 0, 2, 0, 2, 3, 2, 2, 0, 0],\n [0, 2, 0, 0, 0, 0, 0, 0, 2, 0],\n [2, 0, 0, 0, 0, 0, 0, 0, 0, 2]\n];\n\n/**\n * The second destruction animation\n */\nconst DESTRUCTION_ANIMATION_2 = [\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 2, 0, 0, 0, 0, 2, 0, 0],\n [0, 0, 0, 3, 0, 2, 3, 0, 0, 0],\n [0, 0, 0, 0, 3, 0, 0, 0, 0, 0],\n [0, 0, 0, 3, 0, 2, 2, 0, 0, 0],\n [0, 0, 2, 0, 0, 0, 0, 2, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n];\n\n/**\n * The third destruction animation\n */\nconst DESTRUCTION_ANIMATION_3 = [\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 3, 0, 2, 0, 0, 0, 0],\n [0, 0, 0, 0, 3, 0, 0, 0, 0, 0],\n [0, 0, 0, 2, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n];\n\n/**\n * The destruction animations\n */\nexport const DESTRUCTION_ANIMATION = [DESTRUCTION_ANIMATION_1, DESTRUCTION_ANIMATION_2, DESTRUCTION_ANIMATION_3];\n","/**\n * The Observable Enum\n */\nexport enum ObservableTypeEnum {\n /**\n * Alien Boss Destroyed\n */\n alienBossDestroyed = 'alienBossDestroyed',\n /**\n * Alien Creep Left Boundary\n */\n alienCreepLeftBoundary = 'alienCreepLeftBoundary',\n /**\n * Alien Creep Right Boundary\n */\n alienCreepRightBoundary = 'alienCreepRightBoundary',\n /**\n * Alien Destroyed\n */\n alienDestroyed = 'alienDestroyed',\n /**\n * Alien Drop\n */\n alienDrop = 'alienDrop',\n /**\n * Bomb Dropped Event\n */\n bombDropped = 'bombDropped',\n /**\n * Display Score Event\n */\n displayScore = 'displayScore',\n /**\n * Game Over\n */\n gameOver = 'gameOver',\n /**\n * Game Paused\n */\n gamePaused = 'gamePaused',\n /**\n * Game Started\n */\n gameStarted = 'gameStarted',\n /**\n * Key Down Event\n */\n keyDownEvent = 'keyDownEvent',\n /**\n * Key Up Event\n */\n keyUpEvent = 'keyUpEvent',\n /**\n * Missile Shot Event\n */\n missileShot = 'missileShot',\n /**\n * Moon Defense Destroyed\n */\n moonDefenseDestroyed = 'moonDefenseDestroyed',\n /**\n * Spaceship Hit\n */\n spaceshipDestroyed = 'spaceshipDestroyed'\n}\n","import { IAsset } from '../interface/asset.interface';\nimport { GameService } from '../service/game.service';\nimport { AssetAlignEnum } from './enum/asset-align.enum';\nimport { AssetAlignVerticalEnum } from './enum/asset-align-vertical.enum';\nimport { ObservableModel } from '../model/observable.model';\nimport { ObservableTypeEnum } from '../enum/observable-type.enum';\nimport { TimerModel } from '../model/timer.model';\nimport { BoundaryModel } from '../model/boundary.model';\nimport { BoundarySetupModel } from '../model/boundary-set.model';\n\n/**\n * The Asset Class\n */\nexport abstract class AssetClass implements IAsset {\n /**\n * The shape for determining the boundaries\n */\n public shape: number[][];\n /**\n * The x coordinate\n */\n public x: number;\n /**\n * The y coordinate\n */\n public y: number;\n /**\n * The animate once\n */\n public isAnimateOnce: boolean;\n /**\n * The asset to animate\n */\n protected assetAnimation: number[][];\n /**\n * The destruction to animate\n */\n protected destructionAnimation: number[][];\n /**\n * The engine animation\n */\n protected engineAnimation: number[][];\n /**\n * The request id from the animation\n */\n protected requestId: number;\n /**\n * The destroy request id from the animation\n */\n protected destructionRequestId: number;\n /**\n * The Asset Timmer\n */\n protected assetTimer: TimerModel;\n /**\n * The Destruction Timmer\n */\n protected destructionTimer: TimerModel;\n /**\n * engine Timer\n */\n protected engineTimer: TimerModel;\n /**\n * The engine X offset\n */\n protected engineXOffset: number;\n /**\n * The engine Y offset\n */\n protected engineYOffset: number;\n /**\n * Animation Counter\n */\n protected animationCounter: number;\n /**\n * Destruction Counter\n */\n protected destructionAnimationCounter: number;\n /**\n * Engine Animation Counter\n */\n protected engineAnimationCounter: number;\n /**\n * the boardary model\n */\n protected boundary: BoundaryModel;\n /**\n * Is the asset is destroyed\n */\n public isDestroyed: boolean;\n /**\n * If the asset knowns the game is over\n */\n protected isGameOver: boolean;\n /**\n * If the asset knowns the game is paused\n */\n protected isGamePaused: boolean;\n /**\n * Asset Animations\n */\n protected assetAnimations: number[][][];\n /**\n * Engine Animations\n */\n protected engineAnimations: number[][][];\n /**\n * Destruction Animations\n */\n protected destructionAnimations: number[][][];\n\n /**\n * Constructor\n * @param ctx The ctx\n * @param x initial x parameter\n * @param y initial y parameter\n */\n constructor(\n protected gameService: GameService,\n protected ctx: CanvasRenderingContext2D,\n protected boundarySetup: BoundarySetupModel,\n protected uid: number\n ) {\n this.x = 0;\n this.y = 0;\n this.isAnimateOnce = false;\n\n this.isDestroyed = false;\n this.isGameOver = false;\n this.isGamePaused = false;\n\n this.spawn();\n\n this.boundary = this.gameService.getBoundary(boundarySetup);\n\n this.init();\n }\n\n /**\n * Init the asset\n */\n init(): void {\n this.gameService.getMasterObservable().subscribe((result: ObservableModel) => {\n if (result.type === ObservableTypeEnum.keyDownEvent || result.type === ObservableTypeEnum.keyUpEvent) {\n this.processKeyStroke(result);\n } else if (result.type === ObservableTypeEnum.gameOver) {\n this.isGameOver = result.booleanData;\n } else if (result.type === ObservableTypeEnum.gamePaused) {\n this.isGamePaused = result.booleanData;\n }\n });\n }\n\n /**\n * Get the Asset height\n */\n getAssetHeight(): number {\n return this.shape.length;\n }\n\n /**\n * Get the Asset Width\n */\n getAssetWidth(): number {\n return this.shape[0].length;\n }\n\n /**\n * Position the Asset\n */\n positionAsset(alignPosition: AssetAlignEnum, justifyPosition: AssetAlignVerticalEnum): IAsset {\n let x = 0;\n let y = 0;\n\n if (alignPosition === AssetAlignEnum.center) {\n x = (this.boundary.right - this.getAssetWidth()) / 2;\n } else if (alignPosition === AssetAlignEnum.leftThird) {\n x = this.boundary.right / 3 - this.getAssetWidth() / 2;\n } else if (alignPosition === AssetAlignEnum.leftFourth) {\n x = this.boundary.right / 4 - this.getAssetWidth() / 2;\n } else if (alignPosition === AssetAlignEnum.rightThird) {\n x = (this.boundary.right * 2) / 3 - this.getAssetWidth() / 2;\n } else if (alignPosition === AssetAlignEnum.rightFourth) {\n x = (this.boundary.right * 3) / 4 - this.getAssetWidth() / 2;\n } else if (alignPosition === AssetAlignEnum.right) {\n x = this.boundary.right - this.getAssetWidth();\n }\n\n if (justifyPosition === AssetAlignVerticalEnum.bottom) {\n y = this.boundary.floor - this.getAssetHeight();\n } else if (justifyPosition === AssetAlignVerticalEnum.middle) {\n y = (this.boundary.floor - this.getAssetHeight()) / 2;\n }\n\n return {\n x: Math.round(x),\n y: Math.round(y)\n } as IAsset;\n }\n\n /**\n * Process the key stroke\n * @param eventCode the key event code\n */\n /* eslint-disable-next-line */\n protected processKeyStroke(event: ObservableModel): void {}\n\n /**\n * Spawn the asset\n */\n protected spawn(): void {\n if (!(this.assetAnimation && this.assetAnimation.length > 0)) {\n throw new Error('You must have an asset array.');\n }\n\n if (!this.engineAnimation) {\n throw new Error('You must have an engine array.');\n }\n\n this.engineXOffset = 0;\n this.engineYOffset = this.assetAnimation.length;\n this.assetTimer = { start: 0, elapsed: 0 };\n this.destructionTimer = { start: 0, elapsed: 0 };\n this.engineTimer = { start: 0, elapsed: 0 };\n this.animationCounter = 0;\n this.engineAnimationCounter = 0;\n this.destructionAnimationCounter = 0;\n\n this.assetTimer.start = performance.now();\n this.destructionTimer.start = performance.now();\n this.engineTimer.start = performance.now();\n\n this.restore();\n }\n\n /**\n * Restore the\n */\n restore(): void {\n /* eslint-disable-next-line */\n this.shape = JSON.parse(\n /* eslint-disable-next-line */\n JSON.stringify(this.assetAnimation.concat(JSON.parse(JSON.stringify(this.engineAnimation))))\n );\n }\n\n /**\n * Move the asset\n * @param asset The asset input\n */\n move(asset: IAsset): void {\n this.x = Math.round(asset.x);\n this.y = Math.round(asset.y);\n }\n\n /**\n * Determine if we should stop the animation\n */\n protected stopAnimation(): boolean {\n if (this.isDestroyed || this.isGameOver || this.isGamePaused || this.isAnimateOnce) {\n cancelAnimationFrame(this.requestId);\n return true;\n }\n\n return false;\n }\n}\n","import { COLORS, DESTRUCTION_ANIMATION } from './alien-constants';\nimport { IAsset } from '../../interface/asset.interface';\nimport { GameService } from '../../service/game.service';\nimport { ObservableModel } from '../../model/observable.model';\nimport { ObservableTypeEnum } from '../../enum/observable-type.enum';\nimport { AssetClass } from '../../asset/asset.class';\nimport { TimerModel } from '../../model/timer.model';\nimport { BoundarySetupModel } from '../../model/boundary-set.model';\n\n/**\n * The Alien Class\n */\nexport abstract class AlienClass extends AssetClass {\n /**\n * The Missile Timer\n */\n protected bombTimer: TimerModel;\n /**\n * The can fire weapon\n */\n public canFireWeapon: boolean;\n /**\n * The alienType\n */\n protected isAlienAsset: boolean;\n\n /**\n * Constructor\n * @param gameService The GameService\n * @param ctx The ctx\n * @param boundarySetup The BoundarySetupModel\n * @param guid The guid of the alien\n */\n constructor(\n gameService: GameService,\n ctx: CanvasRenderingContext2D,\n boundarySetup: BoundarySetupModel,\n guid: number,\n private assetPoints: number\n ) {\n super(gameService, ctx, boundarySetup, guid);\n\n this.bombTimer = {\n start: performance.now(),\n elapsed: 0\n } as TimerModel;\n }\n\n /**\n * Spawn the alien\n */\n protected override spawn(): void {\n this.assetAnimation = this.assetAnimations[0];\n this.engineAnimation = [];\n this.destructionAnimations = DESTRUCTION_ANIMATION;\n this.destructionAnimation = this.destructionAnimations[0];\n super.spawn();\n }\n\n /**\n * Draw everything necessary\n */\n protected draw(): void {\n this.ctx.save();\n this.ctx.translate(this.x, this.y);\n this.drawAlien();\n this.ctx.restore();\n }\n\n /**\n * Draw the alien\n */\n private drawAlien(): void {\n this.assetAnimation.forEach((row, y) => {\n row.forEach((value, x) => {\n if (value > 0) {\n this.ctx.fillStyle = COLORS[value];\n this.ctx.fillRect(x, y, 1, 1);\n }\n });\n });\n }\n\n /**\n * Is the alien hit\n * @param missileAsset The Missile Asset\n */\n isHit(missileAsset: IAsset): void {\n if (!this.isDestroyed) {\n this.isDestroyed = this.gameService.isHit(\n {\n x: this.x,\n y: this.y,\n shape: this.shape\n } as IAsset,\n missileAsset\n );\n\n const alienType = this.isAlienAsset ? ObservableTypeEnum.alienDestroyed : ObservableTypeEnum.alienBossDestroyed;\n\n if (this.isDestroyed) {\n this.gameService.emitMasterObservableEvent({\n type: alienType,\n numberData: this.uid,\n pointData: this.points\n } as ObservableModel);\n missileAsset.isDestroyed = true;\n }\n }\n }\n\n /**\n * Allow the alien to creep\n * @param asset The Asset\n */\n creep(asset: IAsset): boolean {\n asset.shape = this.shape;\n return this.gameService.valid(asset, this.boundary);\n }\n\n /**\n * Randomize when an alien can drop a bomb\n */\n private randomizeDropBomb(): boolean {\n if (this.canFireWeapon) {\n const randomBombNumber = Math.floor(Math.random() * 10 + 1);\n return randomBombNumber >= 4 && randomBombNumber <= 6;\n }\n\n return false;\n }\n\n /**\n * Draw the alien\n */\n private drawAlienDestruction(): void {\n this.destructionAnimation.forEach((row, y) => {\n row.forEach((value, x) => {\n if (value > 0) {\n this.ctx.fillStyle = COLORS[value];\n this.ctx.fillRect(this.x + x, this.y + y, 1, 1);\n }\n });\n });\n }\n\n /**\n * Animate the alien\n * @param now the current time\n */\n protected destructionAnimate(now = 0): void {\n this.destructionTimer.elapsed = now - this.destructionTimer.start;\n\n if (this.destructionAnimationCounter === this.destructionAnimations.length) {\n cancelAnimationFrame(this.destructionRequestId);\n return;\n }\n\n if (this.destructionTimer.elapsed > 50) {\n this.destructionTimer.start = now;\n this.destructionAnimation =\n this.destructionAnimations[this.destructionAnimationCounter++ % this.destructionAnimations.length];\n }\n\n this.drawAlienDestruction();\n this.destructionRequestId = requestAnimationFrame(this.destructionAnimate.bind(this) as FrameRequestCallback);\n }\n\n /**\n * Animate the alien\n * @param now the current time\n */\n public animate(now = 0): void {\n this.assetTimer.elapsed = now - this.assetTimer.start;\n this.bombTimer.elapsed = now - this.bombTimer.start;\n\n if (this.isDestroyed) {\n this.destructionAnimate();\n return;\n }\n\n this.destructionAnimationCounter = 0;\n\n if (this.assetTimer.elapsed > 900) {\n this.assetTimer.start = now;\n this.assetAnimation = this.assetAnimations[this.animationCounter++ % this.assetAnimations.length];\n }\n\n if (this.bombTimer.elapsed > 1000) {\n this.bombTimer.start = now;\n if (this.randomizeDropBomb()) {\n this.gameService.emitMasterObservableEvent({\n type: ObservableTypeEnum.bombDropped,\n assetCoordinateData: {\n x: this.x + this.getAssetWidth() / 2 - 1,\n y: this.y + this.getAssetHeight() - 5\n } as IAsset\n } as ObservableModel);\n }\n }\n\n this.draw();\n }\n\n /**\n * Set the asset points\n * @param points The number of points\n */\n get points() {\n return this.assetPoints;\n }\n\n /**\n * If the asset is an alien or alien boss\n */\n public isAlien(): boolean {\n return this.isAlienAsset;\n }\n}\n","import { GameService } from '../../service/game.service';\nimport { AlienClass } from '../alien/alien.class';\nimport { KEY } from '../alien/alien-constants';\nimport { IAsset } from '../../interface/asset.interface';\nimport { ObservableModel } from '../../model/observable.model';\nimport { ObservableTypeEnum } from '../../enum/observable-type.enum';\nimport { BoundarySetupModel } from '../../model/boundary-set.model';\nimport { AssetAlignEnum } from '../../asset/enum/asset-align.enum';\nimport { AssetAlignVerticalEnum } from '../../asset/enum/asset-align-vertical.enum';\n\n/**\n * The Alien Boss Class\n */\nexport abstract class AlienBossClass extends AlienClass {\n /**\n * the direction of the ship\n */\n private directionLeft: boolean;\n /**\n * The moves\n */\n private moves = {\n [KEY.LEFT]: (asset: IAsset): IAsset => ({ ...asset, x: asset.x - 5 }),\n [KEY.RIGHT]: (asset: IAsset): IAsset => ({ ...asset, x: asset.x + 5 })\n };\n\n /**\n * Constructor\n * @param gameService The GameService\n * @param ctx The ctx\n * @param boundarySetup The BoundarySetupModel\n * @param guid The guid of the alien\n */\n constructor(\n gameService: GameService,\n ctx: CanvasRenderingContext2D,\n boundarySetup: BoundarySetupModel,\n guid: number,\n points: number\n ) {\n super(gameService, ctx, boundarySetup, guid, points);\n this.directionLeft = true;\n this.isAlienAsset = false;\n }\n\n /**\n * Determine the direction of the boss\n */\n private determineBossDirection(): void {\n this.directionLeft = Math.floor(Math.random() * 10) + 1 > 5;\n }\n\n /**\n * positiong the alien boss for another flight\n */\n public positionAlienBoss(): void {\n this.determineBossDirection();\n const direction = this.directionLeft ? AssetAlignEnum.right : AssetAlignEnum.left;\n const asset = this.positionAsset(direction, AssetAlignVerticalEnum.top);\n asset.y = this.y;\n this.move(asset);\n this.isDestroyed = false;\n }\n\n /**\n * Animate the alien\n * @param now the current time\n */\n public override animate(now = 0): void {\n this.assetTimer.elapsed = now - this.assetTimer.start;\n\n if (this.isDestroyed) {\n this.destructionAnimate();\n return;\n }\n if (this.isGameOver) {\n this.isDestroyed = true;\n return;\n }\n\n this.destructionAnimationCounter = 0;\n\n if (this.assetTimer.elapsed > 200) {\n this.assetTimer.start = now;\n this.assetAnimation = this.assetAnimations[this.animationCounter++ % this.assetAnimations.length];\n const asset = this.directionLeft ? this.moves['ArrowLeft'](this) : this.moves['ArrowRight'](this);\n if (this.gameService.valid(asset, this.boundary)) {\n this.move(asset);\n } else {\n this.isDestroyed = true;\n this.gameService.emitMasterObservableEvent({\n type: ObservableTypeEnum.alienBossDestroyed,\n booleanData: true,\n pointData: 0\n } as ObservableModel);\n }\n }\n\n this.draw();\n }\n}\n","import { ASSET_ANIMATION } from './alien-boss-1-constants';\nimport { GameService } from '../../service/game.service';\nimport { BoundarySetupModel } from '../../model/boundary-set.model';\nimport { AlienBossClass } from '../alien-boss/alien-boss.class';\n\n/**\n * The Alien Boss 1 Class\n */\nexport class AlienBoss1Class extends AlienBossClass {\n /**\n * Constructor\n * @param gameService The GameService\n * @param ctx The ctx\n * @param boundarySetup The BoundarySetupModel\n * @param guid The guid of the alien\n */\n constructor(\n gameService: GameService,\n ctx: CanvasRenderingContext2D,\n boundarySetup: BoundarySetupModel,\n guid: number\n ) {\n super(gameService, ctx, boundarySetup, guid, 120);\n }\n\n /**\n * Spawn the alien\n */\n protected override spawn(): void {\n this.assetAnimations = ASSET_ANIMATION;\n super.spawn();\n }\n}\n","/**\n * The first asset animation\n */\nconst ASSET_ANIMATION_1 = [\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0],\n [0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0],\n [0, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 0],\n [0, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 0],\n [0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0],\n [0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0],\n [0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n];\n\n/**\n * The asset animation array\n */\nexport const ASSET_ANIMATION = [ASSET_ANIMATION_1];\n","import { ASSET_ANIMATION } from './alien-boss-2-constants';\nimport { GameService } from '../../service/game.service';\nimport { BoundarySetupModel } from '../../model/boundary-set.model';\nimport { AlienBossClass } from '../alien-boss/alien-boss.class';\n\n/**\n * The Alien Boss 2 Class\n */\nexport class AlienBoss2Class extends AlienBossClass {\n /**\n * Constructor\n * @param gameService The GameService\n * @param ctx The ctx\n * @param boundarySetup The BoundarySetupModel\n * @param guid The guid of the alien\n */\n constructor(\n gameService: GameService,\n ctx: CanvasRenderingContext2D,\n boundarySetup: BoundarySetupModel,\n guid: number\n ) {\n super(gameService, ctx, boundarySetup, guid, 120);\n }\n\n /**\n * Spawn the alien\n */\n protected override spawn(): void {\n this.assetAnimations = ASSET_ANIMATION;\n super.spawn();\n }\n}\n","import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';\n\nimport { GameService } from '../../../service/game.service';\nimport { AssetAlignVerticalEnum } from '../../../asset/enum/asset-align-vertical.enum';\nimport { AssetAlignEnum } from '../../../asset/enum/asset-align.enum';\nimport { AssetConfigurationModel } from '../../../model/asset-configuration.model';\nimport { BoundarySetupModel } from '../../../model/boundary-set.model';\nimport { AlienBoss1Class } from '../../alien-boss-1/alien-boss-1.class';\nimport { AlienBossClass } from '../alien-boss.class';\nimport { AlienBoss2Class } from '../../alien-boss-2/alien-boss-2.class';\nimport { DebugDataModel } from '../../../model/debug-data.model';\nimport { GameCookieService } from '../../../service/game-cookie.service';\n\n/**\n * The Alien Component\n */\n@Component({\n selector: 'bp-alien-boss',\n templateUrl: './alien-boss.component.html',\n styleUrls: ['./alien-boss.component.scss']\n})\nexport class AlienBossComponent implements OnInit {\n /**\n * The canvas\n */\n @ViewChild('board', { static: true })\n canvas: ElementRef<HTMLCanvasElement>;\n\n /**\n * CTS\n */\n private ctx: CanvasRenderingContext2D;\n\n /**\n * request Id\n */\n private requestId: number;\n\n /**\n * request\n */\n private isAnimateOnce: boolean;\n\n /**\n * aliens\n */\n private alienBosses: AlienBossClass[];\n\n /**\n * The alien\n */\n private alienBoss: AlienBossClass;\n\n /**\n * Debug Assets\n */\n public assets: AssetConfigurationModel[];\n\n /**\n * The Constructor\n * @param gameService The GameService from DI\n * @param gameCookie The Game Cookie Service\n */\n constructor(private gameService: GameService, private gameCookieService: GameCookieService) {\n this.isAnimateOnce = true;\n this.assets = [\n {\n key: 'alienBoss',\n name: 'Boss'\n } as AssetConfigurationModel,\n {\n key: 'alienBoss2',\n name: 'Boss 2'\n } as AssetConfigurationModel\n ];\n }\n\n /**\n * On Init\n */\n ngOnInit() {\n const columns = 20;\n const rows = 20;\n this.ctx = this.gameService.initBoard(this.canvas, rows, columns, 25);\n this.addAlienBosses({\n x: 0,\n y: 0,\n height: rows,\n width: columns\n } as BoundarySetupModel);\n\n this.toggleAssets(this.gameCookieService.getSecondaryDebugData());\n\n this.animate();\n }\n\n /**\n * Add the aliens\n */\n private addAlienBosses(boundary: BoundarySetupModel): void {\n this.alienBosses = [];\n\n const boss = new AlienBoss1Class(this.gameService, this.ctx, boundary, 1);\n boss.move(boss.positionAsset(AssetAlignEnum.center, AssetAlignVerticalEnum.middle));\n boss.isAnimateOnce = true;\n this.alienBosses.push(boss);\n\n const boss2 = new AlienBoss2Class(this.gameService, this.ctx, boundary, 1);\n boss2.move(boss2.positionAsset(AssetAlignEnum.center, AssetAlignVerticalEnum.middle));\n boss2.isAnimateOnce = true;\n this.alienBosses.push(boss2);\n\n this.alienBoss = this.alienBosses[1];\n this.alienBoss.isAnimateOnce = true;\n this.alienBoss.isDestroyed = false;\n }\n\n /**\n * Animate the object once\n */\n animateAsset(): void {\n this.isAnimateOnce = !this.isAnimateOnce;\n this.alienBoss.isDestroyed = false;\n this.alienBoss.move(this.alienBoss.positionAsset(AssetAlignEnum.center, AssetAlignVerticalEnum.middle));\n cancelAnimationFrame(this.requestId);\n this.animate();\n }\n\n /**\n * Draw the board\n */\n private draw() {\n this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);\n this.gameService.addOutlines(this.ctx, 1, 0.025);\n }\n\n /**\n * Animate\n */\n public animate(): void {\n this.draw();\n this.alienBoss.animate();\n if (!this.isAnimateOnce) {\n this.requestId = requestAnimationFrame(this.animate.bind(this) as FrameRequestCallback);\n }\n }\n\n /**\n * toggleAssets\n *\n * @param key The asset to display\n */\n toggleAssets(key: string): void {\n this.alienBoss.isDestroyed = true;\n this.draw();\n let index = 0;\n this.alienBosses.map((alienBoss: AlienBossClass) => {\n alienBoss.isDestroyed = true;\n });\n this.assets.map((asset: AssetConfigurationModel, $index: number) => {\n if (key === asset.key) {\n index = $index;\n this.gameCookieService.setDebugData({\n secondaryAssetName: key\n } as DebugDataModel);\n }\n });\n\n this.alienBoss = this.alienBosses[index];\n this.animateAsset();\n }\n}\n","<div class=\"game-container\">\n <div class=\"asset-title\">Alien</div>\n <div class=\"game-board-container\">\n <canvas #board class=\"game-board\"></canvas>\n </div>\n <div class=\"button-container\">\n <button (click)=\"animateAsset()\" class=\"animation-button button\">Animate</button>\n <div *ngFor=\"let asset of assets\">\n <button (click)=\"toggleAssets(asset.key)\" class=\"animation-button button\">\n {{ asset.name }}\n </button>\n </div>\n </div>\n</div>\n","/**\n * The First asset animation\n */\nconst ASSET_ANIMATION_1 = [\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0],\n [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],\n [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n];\n\n/**\n * The Second Asset Animation\n */\nconst ASSET_ANIMATE_2 = [\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],\n [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],\n [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],\n [0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0],\n [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],\n [0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n];\n\n/**\n * The asset animation array\n */\nexport const ASSET_ANIMATION = [ASSET_ANIMATION_1, ASSET_ANIMATE_2];\n","import { ASSET_ANIMATION } from './alien-1-constants';\nimport { GameService } from '../../service/game.service';\nimport { AlienClass } from '../alien/alien.class';\nimport { BoundarySetupModel } from '../../model/boundary-set.model';\n\n/**\n * The Alien 1 Class\n */\nexport class Alien1Class extends AlienClass {\n /**\n * Constructor\n * @param gameService The GameService\n * @param ctx The ctx\n * @param boundarySetup The BoundarySetupModel\n * @param guid The guid of the alien\n */\n constructor(\n gameService: GameService,\n ctx: CanvasRenderingContext2D,\n boundarySetup: BoundarySetupModel,\n guid: number\n ) {\n super(gameService, ctx, boundarySetup, guid, 30);\n this.isAlienAsset = true;\n }\n\n /**\n * Spawn the alien\n */\n protected override spawn(): void {\n this.assetAnimations = ASSET_ANIMATION;\n super.spawn();\n }\n}\n","/**\n * The first asset animation\n */\nconst ASSET_ANIMATION_1 = [\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],\n [0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0],\n [0,