| 4 | import { Ball } from "./Ball"; |
| 5 | |
| 6 | export class BallManager { |
| 7 | private balls: Ball[]; |
| 8 | private canvasRef: HTMLCanvasElement; |
| 9 | private ctx: CanvasRenderingContext2D; |
| 10 | private obstacles: Obstacle[] |
| 11 | private sinks: Sink[] |
| 12 | private requestId?: number; |
| 13 | private onFinish?: (index: number,startX?: number) => void; |
| 14 | |
| 15 | constructor(canvasRef: HTMLCanvasElement, onFinish?: (index: number,startX?: number) => void) { |
| 16 | this.balls = []; |
| 17 | this.canvasRef = canvasRef; |
| 18 | this.ctx = this.canvasRef.getContext("2d")!; |
| 19 | this.obstacles = createObstacles(); |
| 20 | this.sinks = createSinks(); |
| 21 | this.update(); |
| 22 | this.onFinish = onFinish; |
| 23 | } |
| 24 | |
| 25 | addBall(startX?: number) { |
| 26 | const newBall = new Ball(startX || pad(WIDTH / 2 + 13), pad(50), ballRadius, 'red', this.ctx, this.obstacles, this.sinks, (index) => { |
| 27 | this.balls = this.balls.filter(ball => ball !== newBall); |
| 28 | this.onFinish?.(index, startX) |
| 29 | }); |
| 30 | this.balls.push(newBall); |
| 31 | } |
| 32 | |
| 33 | drawObstacles() { |
| 34 | this.ctx.fillStyle = 'white'; |
| 35 | this.obstacles.forEach((obstacle) => { |
| 36 | this.ctx.beginPath(); |
| 37 | this.ctx.arc(unpad(obstacle.x), unpad(obstacle.y), obstacle.radius, 0, Math.PI * 2); |
| 38 | this.ctx.fill(); |
| 39 | this.ctx.closePath(); |
| 40 | }); |
| 41 | } |
| 42 | |
| 43 | getColor(index: number) { |
| 44 | if (index <3 || index > this.sinks.length - 3) { |
| 45 | return {background: '#ff003f', color: 'white'}; |
| 46 | } |
| 47 | if (index < 6 || index > this.sinks.length - 6) { |
| 48 | return {background: '#ff7f00', color: 'white'}; |
| 49 | } |
| 50 | if (index < 9 || index > this.sinks.length - 9) { |
| 51 | return {background: '#ffbf00', color: 'black'}; |
| 52 | } |
| 53 | if (index < 12 || index > this.sinks.length - 12) { |
| 54 | return {background: '#ffff00', color: 'black'}; |
| 55 | } |
| 56 | if (index < 15 || index > this.sinks.length - 15) { |
| 57 | return {background: '#bfff00', color: 'black'}; |
| 58 | } |
| 59 | return {background: '#7fff00', color: 'black'}; |
| 60 | } |
| 61 | drawSinks() { |
| 62 | this.ctx.fillStyle = 'green'; |
| 63 | const SPACING = obstacleRadius * 2; |
nothing calls this directly
no outgoing calls
no test coverage detected