generated from projects/testosmaximus
157 lines
3.8 KiB
TypeScript
157 lines
3.8 KiB
TypeScript
export class RickGamePanel {
|
||
private canvas!: HTMLCanvasElement
|
||
private ctx!: CanvasRenderingContext2D
|
||
private player = { x: 20, y: 180, vy: 0, width: 10, height: 10, onGround: false }
|
||
private gravity = 0.7
|
||
private jumpPower = -12
|
||
private isGameOver = false
|
||
|
||
private enemies: { x: number, y: number, width: number, height: number, speed: number }[] = []
|
||
private spawnTimer = 0
|
||
|
||
constructor(private container: HTMLElement) {
|
||
this.createUI()
|
||
this.ctx = this.canvas.getContext('2d')!
|
||
this.attachListeners()
|
||
this.frame()
|
||
}
|
||
|
||
private createUI() {
|
||
const panel = document.createElement('div')
|
||
panel.style.cssText = `
|
||
background: #1a1a1a;
|
||
color: #eee;
|
||
font-family: monospace;
|
||
padding: 16px;
|
||
border-radius: 12px;
|
||
width: fit-content;
|
||
box-shadow: 0 0 20px rgba(255,255,255,0.1);
|
||
`
|
||
|
||
const title = document.createElement('div')
|
||
title.innerHTML = `<strong>🌀 Rickjump 2: Invasion</strong>`
|
||
title.style.marginBottom = '10px'
|
||
panel.appendChild(title)
|
||
|
||
this.canvas = document.createElement('canvas')
|
||
this.canvas.width = 300
|
||
this.canvas.height = 200
|
||
this.canvas.style.cssText = `
|
||
border: 2px solid #444;
|
||
background: #000;
|
||
image-rendering: pixelated;
|
||
`
|
||
panel.appendChild(this.canvas)
|
||
|
||
const footer = document.createElement('div')
|
||
footer.textContent = '↳ try not to get rick’d'
|
||
footer.style.cssText = `
|
||
margin-top: 10px;
|
||
font-size: 0.7em;
|
||
color: #aaa;
|
||
`
|
||
panel.appendChild(footer)
|
||
|
||
this.container.appendChild(panel)
|
||
}
|
||
|
||
private attachListeners() {
|
||
this.canvas.addEventListener('click', () => {
|
||
if (this.player.onGround) {
|
||
this.player.vy = this.jumpPower
|
||
this.player.onGround = false
|
||
}
|
||
})
|
||
}
|
||
|
||
private frame = () => {
|
||
if (this.isGameOver) return
|
||
|
||
// physics
|
||
this.player.vy += this.gravity
|
||
this.player.y += this.player.vy
|
||
|
||
if (this.player.y >= 180) {
|
||
this.player.y = 180
|
||
this.player.vy = 0
|
||
this.player.onGround = true
|
||
}
|
||
|
||
// enemies
|
||
for (const enemy of this.enemies) {
|
||
enemy.x -= enemy.speed
|
||
}
|
||
|
||
// cleanup
|
||
this.enemies = this.enemies.filter(e => e.x + e.width > 0)
|
||
|
||
// collisions
|
||
for (const enemy of this.enemies) {
|
||
const p = this.player
|
||
const collide =
|
||
p.x < enemy.x + enemy.width &&
|
||
p.x + p.width > enemy.x &&
|
||
p.y < enemy.y + enemy.height &&
|
||
p.y + p.height > enemy.y
|
||
|
||
if (collide) {
|
||
this.isGameOver = true
|
||
setTimeout(() => {
|
||
window.open('https://www.youtube.com/watch?v=dQw4w9WgXcQ', '_blank')
|
||
}, 200)
|
||
return
|
||
}
|
||
}
|
||
|
||
// spawn enemy
|
||
this.spawnTimer--
|
||
if (this.spawnTimer <= 0) {
|
||
this.spawnEnemy()
|
||
this.spawnTimer = 30 + Math.floor(Math.random() * 60)
|
||
}
|
||
|
||
this.draw()
|
||
requestAnimationFrame(this.frame)
|
||
}
|
||
|
||
private spawnEnemy() {
|
||
const h = 10 + Math.floor(Math.random() * 20)
|
||
const y = 190 - h
|
||
const speed = 1.5 + Math.random() * 1.5
|
||
this.enemies.push({ x: 300, y, width: 10, height: h, speed })
|
||
}
|
||
|
||
private draw() {
|
||
const ctx = this.ctx
|
||
ctx.clearRect(0, 0, 300, 200)
|
||
|
||
// background
|
||
ctx.fillStyle = '#111'
|
||
ctx.fillRect(0, 0, 300, 200)
|
||
|
||
// ground
|
||
ctx.fillStyle = '#444'
|
||
ctx.fillRect(0, 190, 300, 10)
|
||
|
||
// enemies
|
||
for (const e of this.enemies) {
|
||
ctx.fillStyle = '#f00'
|
||
ctx.fillRect(e.x, e.y, e.width, e.height)
|
||
}
|
||
|
||
// player
|
||
ctx.fillStyle = '#0af'
|
||
ctx.fillRect(this.player.x, this.player.y, this.player.width, this.player.height)
|
||
}
|
||
}
|
||
|
||
export function insertRickPanel(target: HTMLElement | string = document.body): void {
|
||
const container = typeof target === 'string'
|
||
? document.querySelector(target)
|
||
: target
|
||
|
||
if (container instanceof HTMLElement) {
|
||
new RickGamePanel(container)
|
||
}
|
||
}
|