import { Component, HostListener, OnInit } from '@angular/core'; import { JumpService } from '../jump.service'; @Component({ selector: 'app-mario', standalone: true, imports: [], templateUrl: './mario.component.html', styleUrl: './mario.component.scss' }) export class MarioComponent implements OnInit { mario = { x: 50, y: 0, width: 40, height: 60, dx: 0, dy: 0, speed: 4, jumpStrength: 20, gravity: 0.5, onGround: false, color: 'orange' }; private canvas!: HTMLCanvasElement; private ctx!: CanvasRenderingContext2D; private canvasWidth = window.innerWidth * 5; private canvasHeight = window.innerHeight; private platforms = [ { x: 300, y: 500, width: 100, height: 10 }, { x: 600, y: 400, width: 150, height: 10 }, { x: 900, y: 350, width: 200, height: 10 }, { x: 1300, y: 450, width: 120, height: 10 }, { x: 1600, y: 380, width: 180, height: 10 }, { x: 1900, y: 320, width: 120, height: 10 }, { x: 2200, y: 300, width: 150, height: 10 }, { x: 2500, y: 350, width: 180, height: 10 }, { x: 2800, y: 400, width: 120, height: 10 }, { x: 3100, y: 450, width: 150, height: 10 }, { x: 3400, y: 390, width: 130, height: 10 }, { x: 3700, y: 350, width: 200, height: 10 }, { x: 4000, y: 300, width: 140, height: 10 }, { x: 4300, y: 330, width: 180, height: 10 }, { x: 4600, y: 380, width: 120, height: 10 }, { x: 4900, y: 350, width: 160, height: 10 }, { x: 5200, y: 420, width: 180, height: 10 }, { x: 5500, y: 460, width: 120, height: 10 }, { x: 5800, y: 500, width: 160, height: 10 }, { x: 6100, y: 400, width: 140, height: 10 } ]; ngOnInit(): void { this.canvas = document.getElementById('gameCanvas') as HTMLCanvasElement; this.ctx = this.canvas.getContext('2d')!; this.canvas.width = this.canvasWidth; this.canvas.height = this.canvasHeight; this.mario.y = this.canvasHeight - 100; this.loop(); } totalJumps = 0; constructor(private jumpService: JumpService) {} @HostListener('window:keydown', ['$event']) handleKeyDown(event: KeyboardEvent) { if (event.key === 'ArrowRight') this.mario.dx = this.mario.speed; if (event.key === 'ArrowLeft') this.mario.dx = -this.mario.speed; if (event.key === ' ' && this.mario.onGround) { this.mario.dy = -this.mario.jumpStrength; this.mario.onGround = false; this.jumpService.registerJump().subscribe({ next: (res) => this.totalJumps = res.totalJumps, error: (err) => console.error('Jump API error:', err) }); } } @HostListener('window:keyup', ['$event']) handleKeyUp(event: KeyboardEvent) { if (['ArrowRight', 'ArrowLeft'].includes(event.key)) this.mario.dx = 0; } private loop = () => { this.update(); this.draw(); this.scrollToMario(); requestAnimationFrame(this.loop); }; private update() { this.mario.x += this.mario.dx; this.mario.y += this.mario.dy; // Gravity this.mario.dy += this.mario.gravity; this.mario.onGround = false; const groundY = this.canvasHeight - 60; if (this.mario.y + this.mario.height >= groundY) { this.mario.y = groundY - this.mario.height; this.mario.dy = 0; this.mario.onGround = true; } for (const platform of this.platforms) { if ( this.mario.x + this.mario.width > platform.x && this.mario.x < platform.x + platform.width && this.mario.y + this.mario.height <= platform.y && this.mario.y + this.mario.height + this.mario.dy >= platform.y ) { this.mario.y = platform.y - this.mario.height; this.mario.dy = 0; this.mario.onGround = true; } } // Boundaries if (this.mario.x < 0) this.mario.x = 0; if (this.mario.x + this.mario.width > this.canvasWidth) this.mario.x = this.canvasWidth - this.mario.width; } private draw() { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); // Ground this.ctx.fillStyle = '#044d00'; this.ctx.fillRect(0, this.canvas.height - 60, this.canvas.width, 60); // Platforms this.ctx.fillStyle = '#888'; for (const p of this.platforms) { this.ctx.fillRect(p.x, p.y, p.width, p.height); } // Mario this.ctx.fillStyle = this.mario.color; this.ctx.fillRect(this.mario.x, this.mario.y, this.mario.width, this.mario.height); this.ctx.fillStyle = 'white'; this.ctx.fillRect(this.mario.x + 8, this.mario.y + 15, 8, 8); this.ctx.fillRect(this.mario.x + 24, this.mario.y + 15, 8, 8); this.ctx.fillStyle = 'black'; this.ctx.fillRect(this.mario.x + 10, this.mario.y + 17, 4, 4); this.ctx.fillRect(this.mario.x + 26, this.mario.y + 17, 4, 4); this.ctx.fillStyle = 'yellow'; this.ctx.fillRect(this.canvasWidth - 60, this.canvas.height - 160, 20, 100); this.ctx.fillStyle = 'black'; this.ctx.fillText('🏁', this.canvasWidth - 60, this.canvas.height - 170); // Counter this.ctx.fillStyle = 'black'; this.ctx.font = '20px Arial'; this.ctx.fillText(`Jumps: ${this.totalJumps}`, this.canvas.width - 150, 30); } private scrollToMario() { const scrollContainer = this.canvas.parentElement!; const centerOffset = scrollContainer.clientWidth / 2; scrollContainer.scrollLeft = this.mario.x - centerOffset; } }