From 6c86146e948a19c7b870d6b9bc70c33e3254a517 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Thu, 26 Feb 2026 14:53:08 -0700 Subject: [PATCH] update snake --- .../shared/assets/img/icons/saas/adobe.svg | 1 + .../shared/assets/img/icons/saas/amazon.svg | 1 + .../assets/img/icons/saas/anthropic.svg | 1 + .../shared/assets/img/icons/saas/apple.svg | 1 + .../assets/img/icons/saas/atlassian.svg | 1 + .../shared/assets/img/icons/saas/box.svg | 1 + .../assets/img/icons/saas/cloudflare.svg | 1 + .../shared/assets/img/icons/saas/datadog.svg | 1 + .../shared/assets/img/icons/saas/discord.svg | 1 + .../shared/assets/img/icons/saas/dropbox.svg | 1 + .../shared/assets/img/icons/saas/github.svg | 1 + .../shared/assets/img/icons/saas/gitlab.svg | 1 + .../shared/assets/img/icons/saas/godaddy.svg | 1 + .../shared/assets/img/icons/saas/google.svg | 1 + .../shared/assets/img/icons/saas/hubspot.svg | 1 + .../shared/assets/img/icons/saas/icloud.svg | 1 + .../shared/assets/img/icons/saas/lastpass.svg | 1 + .../shared/assets/img/icons/saas/meta.svg | 1 + .../assets/img/icons/saas/microsoft.svg | 1 + .../shared/assets/img/icons/saas/mongodb.svg | 1 + .../shared/assets/img/icons/saas/netflix.svg | 1 + .../shared/assets/img/icons/saas/notion.svg | 1 + .../assets/img/icons/saas/onepassword.svg | 1 + .../shared/assets/img/icons/saas/openai.svg | 1 + .../shared/assets/img/icons/saas/paypal.svg | 1 + .../assets/img/icons/saas/salesforce.svg | 1 + .../shared/assets/img/icons/saas/shopify.svg | 1 + .../shared/assets/img/icons/saas/slack.svg | 1 + .../shared/assets/img/icons/saas/spotify.svg | 1 + .../shared/assets/img/icons/saas/square.svg | 1 + .../assets/img/icons/saas/squarespace.svg | 1 + .../shared/assets/img/icons/saas/stripe.svg | 1 + .../shared/assets/img/icons/saas/twilio.svg | 1 + .../shared/assets/img/icons/saas/wix.svg | 1 + .../shared/assets/img/icons/saas/zoom.svg | 1 + .../assets/img/icons/{snek.png => snake.png} | Bin .../routes/general/general.component.ts | 12 +- .../{snek.component.ts => snake.component.ts} | 117 +++++++++++++----- .../{snek.directive.ts => snake.directive.ts} | 14 +-- 39 files changed, 133 insertions(+), 45 deletions(-) create mode 100644 web/projects/shared/assets/img/icons/saas/adobe.svg create mode 100644 web/projects/shared/assets/img/icons/saas/amazon.svg create mode 100644 web/projects/shared/assets/img/icons/saas/anthropic.svg create mode 100644 web/projects/shared/assets/img/icons/saas/apple.svg create mode 100644 web/projects/shared/assets/img/icons/saas/atlassian.svg create mode 100644 web/projects/shared/assets/img/icons/saas/box.svg create mode 100644 web/projects/shared/assets/img/icons/saas/cloudflare.svg create mode 100644 web/projects/shared/assets/img/icons/saas/datadog.svg create mode 100644 web/projects/shared/assets/img/icons/saas/discord.svg create mode 100644 web/projects/shared/assets/img/icons/saas/dropbox.svg create mode 100644 web/projects/shared/assets/img/icons/saas/github.svg create mode 100644 web/projects/shared/assets/img/icons/saas/gitlab.svg create mode 100644 web/projects/shared/assets/img/icons/saas/godaddy.svg create mode 100644 web/projects/shared/assets/img/icons/saas/google.svg create mode 100644 web/projects/shared/assets/img/icons/saas/hubspot.svg create mode 100644 web/projects/shared/assets/img/icons/saas/icloud.svg create mode 100644 web/projects/shared/assets/img/icons/saas/lastpass.svg create mode 100644 web/projects/shared/assets/img/icons/saas/meta.svg create mode 100644 web/projects/shared/assets/img/icons/saas/microsoft.svg create mode 100644 web/projects/shared/assets/img/icons/saas/mongodb.svg create mode 100644 web/projects/shared/assets/img/icons/saas/netflix.svg create mode 100644 web/projects/shared/assets/img/icons/saas/notion.svg create mode 100644 web/projects/shared/assets/img/icons/saas/onepassword.svg create mode 100644 web/projects/shared/assets/img/icons/saas/openai.svg create mode 100644 web/projects/shared/assets/img/icons/saas/paypal.svg create mode 100644 web/projects/shared/assets/img/icons/saas/salesforce.svg create mode 100644 web/projects/shared/assets/img/icons/saas/shopify.svg create mode 100644 web/projects/shared/assets/img/icons/saas/slack.svg create mode 100644 web/projects/shared/assets/img/icons/saas/spotify.svg create mode 100644 web/projects/shared/assets/img/icons/saas/square.svg create mode 100644 web/projects/shared/assets/img/icons/saas/squarespace.svg create mode 100644 web/projects/shared/assets/img/icons/saas/stripe.svg create mode 100644 web/projects/shared/assets/img/icons/saas/twilio.svg create mode 100644 web/projects/shared/assets/img/icons/saas/wix.svg create mode 100644 web/projects/shared/assets/img/icons/saas/zoom.svg rename web/projects/shared/assets/img/icons/{snek.png => snake.png} (100%) rename web/projects/ui/src/app/routes/portal/routes/system/routes/general/{snek.component.ts => snake.component.ts} (83%) rename web/projects/ui/src/app/routes/portal/routes/system/routes/general/{snek.directive.ts => snake.directive.ts} (80%) diff --git a/web/projects/shared/assets/img/icons/saas/adobe.svg b/web/projects/shared/assets/img/icons/saas/adobe.svg new file mode 100644 index 000000000..2f4374c8a --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/adobe.svg @@ -0,0 +1 @@ +Adobe \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/amazon.svg b/web/projects/shared/assets/img/icons/saas/amazon.svg new file mode 100644 index 000000000..878e92e68 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/amazon.svg @@ -0,0 +1 @@ +Amazon \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/anthropic.svg b/web/projects/shared/assets/img/icons/saas/anthropic.svg new file mode 100644 index 000000000..d7e3b44f1 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/anthropic.svg @@ -0,0 +1 @@ +Anthropic \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/apple.svg b/web/projects/shared/assets/img/icons/saas/apple.svg new file mode 100644 index 000000000..cab0d6c61 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/apple.svg @@ -0,0 +1 @@ +Apple \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/atlassian.svg b/web/projects/shared/assets/img/icons/saas/atlassian.svg new file mode 100644 index 000000000..6eaac6cf8 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/atlassian.svg @@ -0,0 +1 @@ +Atlassian \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/box.svg b/web/projects/shared/assets/img/icons/saas/box.svg new file mode 100644 index 000000000..f0c83f2c6 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/box.svg @@ -0,0 +1 @@ +Box \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/cloudflare.svg b/web/projects/shared/assets/img/icons/saas/cloudflare.svg new file mode 100644 index 000000000..66cc02086 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/cloudflare.svg @@ -0,0 +1 @@ +Cloudflare \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/datadog.svg b/web/projects/shared/assets/img/icons/saas/datadog.svg new file mode 100644 index 000000000..ab4373190 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/datadog.svg @@ -0,0 +1 @@ +Datadog \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/discord.svg b/web/projects/shared/assets/img/icons/saas/discord.svg new file mode 100644 index 000000000..ef25142a3 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/discord.svg @@ -0,0 +1 @@ +Discord \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/dropbox.svg b/web/projects/shared/assets/img/icons/saas/dropbox.svg new file mode 100644 index 000000000..2fc268685 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/dropbox.svg @@ -0,0 +1 @@ +Dropbox \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/github.svg b/web/projects/shared/assets/img/icons/saas/github.svg new file mode 100644 index 000000000..4532de0e8 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/github.svg @@ -0,0 +1 @@ +GitHub \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/gitlab.svg b/web/projects/shared/assets/img/icons/saas/gitlab.svg new file mode 100644 index 000000000..2910f4aa4 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/gitlab.svg @@ -0,0 +1 @@ +GitLab diff --git a/web/projects/shared/assets/img/icons/saas/godaddy.svg b/web/projects/shared/assets/img/icons/saas/godaddy.svg new file mode 100644 index 000000000..2c95d1642 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/godaddy.svg @@ -0,0 +1 @@ +GoDaddy \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/google.svg b/web/projects/shared/assets/img/icons/saas/google.svg new file mode 100644 index 000000000..354fb4abc --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/google.svg @@ -0,0 +1 @@ +Google diff --git a/web/projects/shared/assets/img/icons/saas/hubspot.svg b/web/projects/shared/assets/img/icons/saas/hubspot.svg new file mode 100644 index 000000000..1b9ddd2be --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/hubspot.svg @@ -0,0 +1 @@ +HubSpot \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/icloud.svg b/web/projects/shared/assets/img/icons/saas/icloud.svg new file mode 100644 index 000000000..bf54590c0 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/icloud.svg @@ -0,0 +1 @@ +iCloud \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/lastpass.svg b/web/projects/shared/assets/img/icons/saas/lastpass.svg new file mode 100644 index 000000000..50ccd7bf5 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/lastpass.svg @@ -0,0 +1 @@ +LastPass \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/meta.svg b/web/projects/shared/assets/img/icons/saas/meta.svg new file mode 100644 index 000000000..af72710b2 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/meta.svg @@ -0,0 +1 @@ +Meta \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/microsoft.svg b/web/projects/shared/assets/img/icons/saas/microsoft.svg new file mode 100644 index 000000000..c7b53ae83 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/microsoft.svg @@ -0,0 +1 @@ +Microsoft diff --git a/web/projects/shared/assets/img/icons/saas/mongodb.svg b/web/projects/shared/assets/img/icons/saas/mongodb.svg new file mode 100644 index 000000000..13d7d00a6 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/mongodb.svg @@ -0,0 +1 @@ +MongoDB \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/netflix.svg b/web/projects/shared/assets/img/icons/saas/netflix.svg new file mode 100644 index 000000000..385426608 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/netflix.svg @@ -0,0 +1 @@ +Netflix \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/notion.svg b/web/projects/shared/assets/img/icons/saas/notion.svg new file mode 100644 index 000000000..e50096a05 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/notion.svg @@ -0,0 +1 @@ +Notion \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/onepassword.svg b/web/projects/shared/assets/img/icons/saas/onepassword.svg new file mode 100644 index 000000000..602256d72 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/onepassword.svg @@ -0,0 +1 @@ +1Password \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/openai.svg b/web/projects/shared/assets/img/icons/saas/openai.svg new file mode 100644 index 000000000..cb1897b63 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/openai.svg @@ -0,0 +1 @@ +OpenAI \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/paypal.svg b/web/projects/shared/assets/img/icons/saas/paypal.svg new file mode 100644 index 000000000..840b18910 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/paypal.svg @@ -0,0 +1 @@ +PayPal diff --git a/web/projects/shared/assets/img/icons/saas/salesforce.svg b/web/projects/shared/assets/img/icons/saas/salesforce.svg new file mode 100644 index 000000000..a5b6cc7ac --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/salesforce.svg @@ -0,0 +1 @@ +Salesforce \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/shopify.svg b/web/projects/shared/assets/img/icons/saas/shopify.svg new file mode 100644 index 000000000..525bd2b93 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/shopify.svg @@ -0,0 +1 @@ +Shopify \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/slack.svg b/web/projects/shared/assets/img/icons/saas/slack.svg new file mode 100644 index 000000000..a41e53bab --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/slack.svg @@ -0,0 +1 @@ +Slack diff --git a/web/projects/shared/assets/img/icons/saas/spotify.svg b/web/projects/shared/assets/img/icons/saas/spotify.svg new file mode 100644 index 000000000..c3ad6562a --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/spotify.svg @@ -0,0 +1 @@ +Spotify \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/square.svg b/web/projects/shared/assets/img/icons/saas/square.svg new file mode 100644 index 000000000..96a69d079 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/square.svg @@ -0,0 +1 @@ +Square \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/squarespace.svg b/web/projects/shared/assets/img/icons/saas/squarespace.svg new file mode 100644 index 000000000..23946ab1c --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/squarespace.svg @@ -0,0 +1 @@ +Squarespace \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/stripe.svg b/web/projects/shared/assets/img/icons/saas/stripe.svg new file mode 100644 index 000000000..48272a2c5 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/stripe.svg @@ -0,0 +1 @@ +Stripe \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/twilio.svg b/web/projects/shared/assets/img/icons/saas/twilio.svg new file mode 100644 index 000000000..2392f4bd9 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/twilio.svg @@ -0,0 +1 @@ +Twilio \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/wix.svg b/web/projects/shared/assets/img/icons/saas/wix.svg new file mode 100644 index 000000000..cd1480dd9 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/wix.svg @@ -0,0 +1 @@ +Wix \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/saas/zoom.svg b/web/projects/shared/assets/img/icons/saas/zoom.svg new file mode 100644 index 000000000..28828a365 --- /dev/null +++ b/web/projects/shared/assets/img/icons/saas/zoom.svg @@ -0,0 +1 @@ +Zoom \ No newline at end of file diff --git a/web/projects/shared/assets/img/icons/snek.png b/web/projects/shared/assets/img/icons/snake.png similarity index 100% rename from web/projects/shared/assets/img/icons/snek.png rename to web/projects/shared/assets/img/icons/snake.png diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/general/general.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/general/general.component.ts index e9509a2fc..dc0a79110 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/general/general.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/general/general.component.ts @@ -49,7 +49,7 @@ import { OSService } from 'src/app/services/os.service' import { DataModel } from 'src/app/services/patch-db/data-model' import { TitleDirective } from 'src/app/services/title.service' import { ABOUT } from 'src/app/routes/portal/components/header/about.component' -import { SnekDirective } from './snek.directive' +import { SnakeDirective } from './snake.directive' import { UPDATE } from './update.component' import { KeyboardSelectComponent } from './keyboard-select.component' import { ServerNameDialog } from './server-name.dialog' @@ -203,10 +203,10 @@ import { ServerNameDialog } from './server-name.dialog' } Play Snake } `, @@ -215,7 +215,7 @@ import { ServerNameDialog } from './server-name.dialog' max-inline-size: 40rem; } - .snek { + .snake { width: 1rem; opacity: 0.2; cursor: pointer; @@ -270,7 +270,7 @@ import { ServerNameDialog } from './server-name.dialog' TuiDataListWrapper, TuiTextfield, FormsModule, - SnekDirective, + SnakeDirective, TuiBadge, TuiBadgeNotification, TuiAnimated, diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/general/snek.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/general/snake.component.ts similarity index 83% rename from web/projects/ui/src/app/routes/portal/routes/system/routes/general/snek.component.ts rename to web/projects/ui/src/app/routes/portal/routes/system/routes/general/snake.component.ts index ebc947a67..f820911c5 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/general/snek.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/general/snake.component.ts @@ -36,6 +36,44 @@ const GRID_H = 26 const SPEED = 45 const STARTING_LENGTH = 4 +const SAAS_ICONS = [ + 'adobe', + 'amazon', + 'anthropic', + 'apple', + 'atlassian', + 'box', + 'cloudflare', + 'datadog', + 'discord', + 'dropbox', + 'github', + 'gitlab', + 'godaddy', + 'google', + 'hubspot', + 'icloud', + 'lastpass', + 'meta', + 'microsoft', + 'mongodb', + 'netflix', + 'notion', + 'onepassword', + 'openai', + 'paypal', + 'salesforce', + 'shopify', + 'slack', + 'spotify', + 'squarespace', + 'square', + 'stripe', + 'twilio', + 'wix', + 'zoom', +].map(name => `assets/img/icons/saas/${name}.svg`) + function lerpColor(from: RGB, to: RGB, t: number): string { const r = Math.round(from[0] + (to[0] - from[0]) * t) const g = Math.round(from[1] + (to[1] - from[1]) * t) @@ -128,7 +166,7 @@ function lerpColor(from: RGB, to: RGB, t: number): string { changeDetection: ChangeDetectionStrategy.OnPush, imports: [TuiButton, i18nPipe], }) -export class SnekComponent { +export class SnakeComponent { private readonly destroyRef = inject(DestroyRef) private readonly dialog = injectContext>() private readonly canvasRef = viewChild>('game') @@ -139,27 +177,30 @@ export class SnekComponent { score = 0 private grid = NaN + private canvasW = 0 + private canvasH = 0 private ctx!: CanvasRenderingContext2D - private image = new Image() - private imageLoaded = false + private images: HTMLImageElement[] = [] + private currentImage: HTMLImageElement | null = null private animationId = 0 private lastTime = 0 private dead = false private snake!: Snake - private bitcoin: Point = { x: NaN, y: NaN } + private food: Point = { x: NaN, y: NaN } private moveQueue: string[] = [] constructor() { - this.image.onload = () => { - this.imageLoaded = true + for (const src of SAAS_ICONS) { + const img = new Image() + img.src = src + this.images.push(img) } - this.image.src = 'assets/img/icons/bitcoin.svg' afterNextRender(() => { this.initCanvas() this.snake = this.createSnake() - this.spawnBitcoin() + this.spawnFood() this.drawFrame() this.animationId = requestAnimationFrame(t => this.loop(t)) }) @@ -259,6 +300,7 @@ export class SnekComponent { this.ctx = canvas.getContext('2d')! const container = canvas.parentElement! + const dpr = window.devicePixelRatio || 1 // Size grid based on available width, cap so canvas height stays reasonable const maxHeight = window.innerHeight * 0.55 @@ -267,8 +309,14 @@ export class SnekComponent { Math.floor(maxHeight / GRID_H), ) - canvas.width = this.grid * GRID_W - canvas.height = this.grid * GRID_H + this.canvasW = this.grid * GRID_W + this.canvasH = this.grid * GRID_H + + canvas.width = this.canvasW * dpr + canvas.height = this.canvasH * dpr + canvas.style.width = `${this.canvasW}px` + canvas.style.height = `${this.canvasH}px` + this.ctx.scale(dpr, dpr) } private createSnake(): Snake { @@ -288,18 +336,28 @@ export class SnekComponent { return this.grid * Math.floor(GRID_H / 2) } - private spawnBitcoin() { - this.bitcoin = { + private spawnFood() { + this.food = { x: this.randomInt(0, GRID_W) * this.grid, y: this.randomInt(0, GRID_H) * this.grid, } + + const img = this.images[this.randomInt(0, this.images.length)]! + this.currentImage = img.complete && img.naturalWidth ? img : null + + if (!this.currentImage) { + img.onload = () => { + this.currentImage = img + this.drawFrame() + } + } } private restart() { this.score = 0 this.snake = this.createSnake() this.moveQueue = [] - this.spawnBitcoin() + this.spawnFood() this.lastTime = 0 this.state.set('playing') } @@ -351,15 +409,12 @@ export class SnekComponent { this.snake.cells.pop() } - const canvas = this.canvasRef()?.nativeElement - if (!canvas) return - // Wall collision if ( newHead.x < 0 || newHead.y < 0 || - newHead.x >= canvas.width || - newHead.y >= canvas.height + newHead.x >= this.canvasW || + newHead.y >= this.canvasH ) { this.onDeath() return @@ -374,12 +429,12 @@ export class SnekComponent { } } - // Eat bitcoin - if (newHead.x === this.bitcoin.x && newHead.y === this.bitcoin.y) { + // Eat food + if (newHead.x === this.food.x && newHead.y === this.food.y) { this.score++ this.highScore = Math.max(this.score, this.highScore) this.snake.maxCells++ - this.spawnBitcoin() + this.spawnFood() } } @@ -393,20 +448,19 @@ export class SnekComponent { } private drawFrame() { - const canvas = this.canvasRef()?.nativeElement - if (!canvas || !this.ctx) return + if (!this.ctx) return - this.ctx.clearRect(0, 0, canvas.width, canvas.height) - this.drawBitcoin() + this.ctx.clearRect(0, 0, this.canvasW, this.canvasH) + this.drawFood() this.drawSnake() } - private drawBitcoin() { - if (!this.imageLoaded) return + private drawFood() { + if (!this.currentImage) return this.ctx.drawImage( - this.image, - this.bitcoin.x, - this.bitcoin.y, + this.currentImage, + this.food.x, + this.food.y, this.grid, this.grid, ) @@ -417,8 +471,7 @@ export class SnekComponent { if (cells.length === 0) { // Draw initial position in bottom-left corner (out of overlay text) const x = STARTING_LENGTH * this.grid - const canvas = this.canvasRef()?.nativeElement - const y = canvas ? canvas.height - this.grid * 2 : this.getStartY() + const y = this.canvasH ? this.canvasH - this.grid * 2 : this.getStartY() for (let i = 0; i < STARTING_LENGTH; i++) { const t = STARTING_LENGTH > 1 ? i / (STARTING_LENGTH - 1) : 0 this.ctx.fillStyle = lerpColor(HEAD_COLOR, TAIL_COLOR, t) diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/general/snek.directive.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/general/snake.directive.ts similarity index 80% rename from web/projects/ui/src/app/routes/portal/routes/system/routes/general/snek.directive.ts rename to web/projects/ui/src/app/routes/portal/routes/system/routes/general/snake.directive.ts index eff791c83..470dcd4da 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/general/snek.directive.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/general/snake.directive.ts @@ -8,31 +8,31 @@ import { import { PolymorpheusComponent } from '@taiga-ui/polymorpheus' import { filter } from 'rxjs' import { ApiService } from 'src/app/services/api/embassy-api.service' -import { SnekComponent } from './snek.component' +import { SnakeComponent } from './snake.component' @Directive({ - selector: 'img[snek]', + selector: 'img[snake]', }) -export class SnekDirective { +export class SnakeDirective { private readonly loader = inject(LoadingService) private readonly errorService = inject(ErrorService) private readonly api = inject(ApiService) private readonly dialog = inject(DialogService) @Input() - snek = 0 + snake = 0 @HostListener('click') async onClick() { this.dialog - .openComponent(new PolymorpheusComponent(SnekComponent), { + .openComponent(new PolymorpheusComponent(SnakeComponent), { label: 'Snake!' as i18nKey, size: 'l', closeable: false, dismissible: false, - data: this.snek, + data: this.snake, }) - .pipe(filter(score => score > this.snek)) + .pipe(filter(score => score > this.snake)) .subscribe(async score => { const loader = this.loader.open('Saving high score').subscribe()