import type { DrawContext } from '../types'; export function drawCityBuildings(dc: DrawContext): void { const { ctx, width, height, state } = dc; const parallax = state.mouseX * 0.35; const drawBuilding = (x: number, bWidth: number, bHeight: number, color: string, hasSpire: boolean = false) => { const baseY = height * 0.8; ctx.fillStyle = color; ctx.fillRect(x + parallax, baseY - bHeight, bWidth, bHeight); const gradient = ctx.createLinearGradient(x + parallax, 0, x + parallax + bWidth, 0); gradient.addColorStop(0, 'rgba(255, 255, 255, 0.1)'); gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.2)'); gradient.addColorStop(1, 'rgba(255, 255, 255, 0.05)'); ctx.fillStyle = gradient; ctx.fillRect(x + parallax, baseY - bHeight, bWidth, bHeight); ctx.fillStyle = 'rgba(255, 255, 200, 0.8)'; const windowCols = Math.floor(bWidth / 18); const windowRows = Math.floor(bHeight / 25); for (let row = 0; row < windowRows; row++) { for (let col = 0; col < windowCols; col++) { if (Math.random() > 0.15) { ctx.fillStyle = Math.random() > 0.7 ? 'rgba(255, 255, 200, 0.9)' : 'rgba(200, 220, 255, 0.6)'; ctx.fillRect( x + parallax + col * 18 + 5, baseY - bHeight + row * 25 + 8, 10, 12 ); } } } if (hasSpire) { ctx.fillStyle = '#90A4AE'; ctx.beginPath(); ctx.moveTo(x + parallax + bWidth / 2, baseY - bHeight - 40); ctx.lineTo(x + parallax + bWidth / 2 - 8, baseY - bHeight); ctx.lineTo(x + parallax + bWidth / 2 + 8, baseY - bHeight); ctx.closePath(); ctx.fill(); } }; drawBuilding(width * 0.02, 55, height * 0.28, '#607D8B'); drawBuilding(width * 0.08, 70, height * 0.42, '#78909C', true); drawBuilding(width * 0.18, 50, height * 0.32, '#546E7A'); drawBuilding(width * 0.25, 85, height * 0.55, '#455A64', true); drawBuilding(width * 0.38, 60, height * 0.38, '#607D8B'); drawBuilding(width * 0.48, 75, height * 0.48, '#78909C', true); drawBuilding(width * 0.58, 55, height * 0.35, '#546E7A'); drawBuilding(width * 0.68, 90, height * 0.52, '#455A64', true); drawBuilding(width * 0.8, 65, height * 0.4, '#607D8B'); drawBuilding(width * 0.9, 50, height * 0.3, '#78909C'); } export function drawStreet(dc: DrawContext): void { const { ctx, width, height } = dc; const time = Date.now() * 0.001; ctx.fillStyle = '#424242'; ctx.fillRect(0, height * 0.82, width, height * 0.08); ctx.strokeStyle = '#FFEB3B'; ctx.lineWidth = 3; ctx.setLineDash([30, 20]); ctx.beginPath(); ctx.moveTo(0, height * 0.86); ctx.lineTo(width, height * 0.86); ctx.stroke(); ctx.setLineDash([]); const drawCar = (baseX: number, y: number, color: string, direction: number) => { const x = ((baseX + time * 50 * direction) % (width + 100)) - 50; ctx.fillStyle = color; ctx.beginPath(); ctx.roundRect(x, y, 40, 15, 3); ctx.fill(); ctx.fillStyle = color; ctx.beginPath(); ctx.roundRect(x + 8, y - 10, 24, 12, 3); ctx.fill(); ctx.fillStyle = '#81D4FA'; ctx.fillRect(x + 10, y - 8, 9, 8); ctx.fillRect(x + 21, y - 8, 9, 8); ctx.fillStyle = '#212121'; ctx.beginPath(); ctx.arc(x + 10, y + 15, 5, 0, Math.PI * 2); ctx.arc(x + 30, y + 15, 5, 0, Math.PI * 2); ctx.fill(); }; drawCar(width * 0.1, height * 0.83, '#E53935', 1); drawCar(width * 0.5, height * 0.83, '#1E88E5', 1); drawCar(width * 0.3, height * 0.87, '#43A047', -1); drawCar(width * 0.8, height * 0.87, '#FDD835', -1); } export function drawAirplane(dc: DrawContext): void { const { ctx, width, height, state } = dc; const time = Date.now() * 0.0003; const parallax = state.mouseX * 0.1; const x = (time * width) % (width + 200) - 100; const y = height * 0.15 + Math.sin(time * 5) * 10; ctx.save(); ctx.translate(x + parallax, y); ctx.fillStyle = '#ECEFF1'; ctx.beginPath(); ctx.ellipse(0, 0, 40, 8, 0, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.ellipse(45, 0, 12, 6, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#B0BEC5'; ctx.beginPath(); ctx.moveTo(-10, 0); ctx.lineTo(-30, -35); ctx.lineTo(10, -35); ctx.lineTo(15, 0); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.moveTo(-10, 0); ctx.lineTo(-30, 35); ctx.lineTo(10, 35); ctx.lineTo(15, 0); ctx.closePath(); ctx.fill(); ctx.fillStyle = '#E53935'; ctx.beginPath(); ctx.moveTo(-35, 0); ctx.lineTo(-50, -20); ctx.lineTo(-30, 0); ctx.closePath(); ctx.fill(); ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)'; ctx.lineWidth = 3; ctx.beginPath(); ctx.moveTo(-50, 0); ctx.lineTo(-150, 3); ctx.stroke(); ctx.restore(); } export function drawParks(dc: DrawContext): void { const { ctx, width, height } = dc; ctx.fillStyle = '#81C784'; const parks = [ { x: width * 0.05, y: height * 0.81, rx: 25, ry: 8 }, { x: width * 0.35, y: height * 0.81, rx: 30, ry: 10 }, { x: width * 0.75, y: height * 0.81, rx: 35, ry: 9 }, ]; parks.forEach(p => { ctx.beginPath(); ctx.ellipse(p.x, p.y, p.rx, p.ry, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#4CAF50'; ctx.beginPath(); ctx.arc(p.x - 10, p.y - 5, 8, 0, Math.PI * 2); ctx.arc(p.x + 10, p.y - 3, 6, 0, Math.PI * 2); ctx.fill(); }); } export function drawCityScene(dc: DrawContext): void { drawAirplane(dc); drawCityBuildings(dc); drawParks(dc); drawStreet(dc); }