@al8b/screen 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/base-screen.js +38 -16
- package/dist/core/base-screen.js.map +1 -1
- package/dist/core/base-screen.mjs +38 -18
- package/dist/core/base-screen.mjs.map +1 -1
- package/dist/core/index.js +61 -31
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +61 -31
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/screen.js +61 -31
- package/dist/core/screen.js.map +1 -1
- package/dist/core/screen.mjs +61 -31
- package/dist/core/screen.mjs.map +1 -1
- package/dist/drawing/primitives-screen.js +49 -22
- package/dist/drawing/primitives-screen.js.map +1 -1
- package/dist/drawing/primitives-screen.mjs +49 -24
- package/dist/drawing/primitives-screen.mjs.map +1 -1
- package/dist/drawing/sprite-screen.js +61 -29
- package/dist/drawing/sprite-screen.js.map +1 -1
- package/dist/drawing/sprite-screen.mjs +61 -31
- package/dist/drawing/sprite-screen.mjs.map +1 -1
- package/dist/drawing/text-screen.js +61 -31
- package/dist/drawing/text-screen.js.map +1 -1
- package/dist/drawing/text-screen.mjs +61 -31
- package/dist/drawing/text-screen.mjs.map +1 -1
- package/dist/index.js +61 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +61 -31
- package/dist/index.mjs.map +1 -1
- package/dist/tri/triangle-screen.js +61 -31
- package/dist/tri/triangle-screen.js.map +1 -1
- package/dist/tri/triangle-screen.mjs +61 -31
- package/dist/tri/triangle-screen.mjs.map +1 -1
- package/package.json +4 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/drawing/sprite-screen.ts","../../src/drawing/primitives-screen.ts","../../src/core/base-screen.ts","../../src/tri/ttri.ts"],"sourcesContent":["/**\n * Sprite rendering for Screen class\n */\n\nimport { APIErrorCode, reportRuntimeError } from \"@al8b/diagnostics\";\nimport type { TileMap as Map } from \"@al8b/map\";\nimport type { Sprite } from \"@al8b/sprites\";\n\nimport { PrimitiveScreen } from \"./primitives-screen\";\n\nexport class SpriteScreen extends PrimitiveScreen {\n\t// Cache imageSmoothingEnabled — only set when pixelated flag changes\n\tprivate _lastImageSmoothing = true;\n\n\t// Cache frame time once per draw frame instead of per-sprite\n\tprotected _frameTime = 0;\n\n\t/**\n\t * Initialize draw state (called before each draw frame)\n\t */\n\toverride initDraw(): void {\n\t\tsuper.initDraw();\n\t\tthis._frameTime = performance.now();\n\t}\n\n\t/**\n\t * Set imageSmoothingEnabled only when it actually changes\n\t */\n\tprotected setImageSmoothing(): void {\n\t\tconst smooth = !this.pixelated;\n\t\tif (smooth !== this._lastImageSmoothing) {\n\t\t\tthis.context.imageSmoothingEnabled = smooth;\n\t\t\tthis._lastImageSmoothing = smooth;\n\t\t}\n\t}\n\n\t/**\n\t * Get the canvas for the current sprite frame\n\t */\n\tprotected getSpriteFrame(sprite: Sprite | string | any): HTMLCanvasElement | null {\n\t\tlet frame: number | null = null;\n\n\t\t// Handle string sprite name\n\t\tif (typeof sprite === \"string\") {\n\t\t\tconst spriteName = sprite;\n\t\t\tlet spriteObj: Sprite | null = null;\n\n\t\t\tif (this.runtime && this.runtime.sprites) {\n\t\t\t\tspriteObj = this.runtime.sprites[sprite];\n\t\t\t}\n\n\t\t\t// Handle \"sprite.frame\" format (e.g., \"player.0\")\n\t\t\tif (!spriteObj) {\n\t\t\t\tconst parts = sprite.split(\".\");\n\t\t\t\tif (parts.length > 1 && this.runtime && this.runtime.sprites) {\n\t\t\t\t\tspriteObj = this.runtime.sprites[parts[0]];\n\t\t\t\t\tframe = Number.parseInt(parts[1]) || 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Report sprite not found error\n\t\t\tif (!spriteObj) {\n\t\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7004, { spriteName });\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tsprite = spriteObj;\n\t\t}\n\t\t// Handle Image instances - check for objects with canvas but no frames\n\t\telse if (sprite && typeof sprite === \"object\" && (sprite as any).canvas && !(sprite as any).frames) {\n\t\t\treturn (sprite as any).canvas || (sprite as any).image || null;\n\t\t}\n\n\t\t// Validate sprite object\n\t\tif (!sprite || !(sprite as Sprite).ready) {\n\t\t\tconst spriteName = typeof sprite === \"string\" ? sprite : \"unknown\";\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7005, { spriteName });\n\t\t\treturn null;\n\t\t}\n\n\t\tconst spriteObj = sprite as Sprite;\n\n\t\t// Handle multi-frame sprites — use cached _frameTime instead of Date.now() per call\n\t\tif (spriteObj.frames && spriteObj.frames.length > 1) {\n\t\t\tif (frame === null) {\n\t\t\t\tif (spriteObj.animation_start === 0) {\n\t\t\t\t\tspriteObj.animation_start = this._frameTime;\n\t\t\t\t}\n\t\t\t\tconst dt = 1000 / spriteObj.fps;\n\t\t\t\tframe = Math.floor((this._frameTime - spriteObj.animation_start) / dt) % spriteObj.frames.length;\n\t\t\t}\n\t\t\tif (frame >= 0 && frame < spriteObj.frames.length) {\n\t\t\t\treturn spriteObj.frames[frame].canvas;\n\t\t\t}\n\t\t\treturn spriteObj.frames[0].canvas;\n\t\t}\n\t\t// Handle single-frame sprites\n\t\telse if (spriteObj.frames && spriteObj.frames[0]) {\n\t\t\treturn spriteObj.frames[0].canvas;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Draw a sprite\n\t */\n\tdrawSprite(sprite: Sprite | string | any, x: number, y: number, w?: number, h?: number): void {\n\t\tconst canvas = this.getSpriteFrame(sprite);\n\t\tif (!canvas) return;\n\n\t\tif (w == null) {\n\t\t\tw = canvas.width;\n\t\t}\n\n\t\tif (!h) {\n\t\t\th = (w / canvas.width) * canvas.height;\n\t\t}\n\n\t\t// Viewport culling: skip sprites entirely outside visible area\n\t\t// Only when no screen/object transforms are active (simple AABB check)\n\t\tif (\n\t\t\t!this.screen_transform &&\n\t\t\tthis.object_rotation === 0 &&\n\t\t\tthis.object_scale_x === 1 &&\n\t\t\tthis.object_scale_y === 1\n\t\t) {\n\t\t\tconst drawX = x - w / 2 - (this.anchor_x * w) / 2;\n\t\t\tconst drawY = -y - h / 2 + (this.anchor_y * h) / 2;\n\t\t\tconst halfW = this.width / 2;\n\t\t\tconst halfH = this.height / 2;\n\t\t\tif (drawX > halfW || drawX + w < -halfW || drawY > halfH || drawY + h < -halfH) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.setImageSmoothing();\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.drawImage(canvas, -w / 2 - (this.anchor_x * w) / 2, -h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.drawImage(canvas, x - w / 2 - (this.anchor_x * w) / 2, -y - h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t}\n\t}\n\n\t/**\n\t * Draw a portion of a sprite\n\t */\n\tdrawSpritePart(\n\t\tsprite: Sprite | string | any,\n\t\tsx: number,\n\t\tsy: number,\n\t\tsw: number,\n\t\tsh: number,\n\t\tx: number,\n\t\ty: number,\n\t\tw?: number,\n\t\th?: number,\n\t): void {\n\t\tconst canvas = this.getSpriteFrame(sprite);\n\t\tif (!canvas) return;\n\n\t\tif (w == null) {\n\t\t\tw = sw;\n\t\t}\n\n\t\tif (!h) {\n\t\t\th = (w / sw) * sh;\n\t\t}\n\n\t\t// Viewport culling: skip sprites entirely outside visible area\n\t\tif (\n\t\t\t!this.screen_transform &&\n\t\t\tthis.object_rotation === 0 &&\n\t\t\tthis.object_scale_x === 1 &&\n\t\t\tthis.object_scale_y === 1\n\t\t) {\n\t\t\tconst drawX = x - w / 2 - (this.anchor_x * w) / 2;\n\t\t\tconst drawY = -y - h / 2 + (this.anchor_y * h) / 2;\n\t\t\tconst halfW = this.width / 2;\n\t\t\tconst halfH = this.height / 2;\n\t\t\tif (drawX > halfW || drawX + w < -halfW || drawY > halfH || drawY + h < -halfH) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.setImageSmoothing();\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.drawImage(\n\t\t\t\tcanvas,\n\t\t\t\tsx,\n\t\t\t\tsy,\n\t\t\t\tsw,\n\t\t\t\tsh,\n\t\t\t\t-w / 2 - (this.anchor_x * w) / 2,\n\t\t\t\t-h / 2 + (this.anchor_y * h) / 2,\n\t\t\t\tw,\n\t\t\t\th,\n\t\t\t);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.drawImage(\n\t\t\t\tcanvas,\n\t\t\t\tsx,\n\t\t\t\tsy,\n\t\t\t\tsw,\n\t\t\t\tsh,\n\t\t\t\tx - w / 2 - (this.anchor_x * w) / 2,\n\t\t\t\t-y - h / 2 + (this.anchor_y * h) / 2,\n\t\t\t\tw,\n\t\t\t\th,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Draw a map\n\t */\n\tdrawMap(map: Map | string, x: number, y: number, w: number, h: number): void {\n\t\tlet mapObj: Map | null = null;\n\n\t\tif (typeof map === \"string\") {\n\t\t\tif (this.runtime && this.runtime.maps) {\n\t\t\t\tmapObj = this.runtime.maps[map];\n\t\t\t}\n\t\t} else {\n\t\t\tmapObj = map;\n\t\t}\n\n\t\tif (!(mapObj && mapObj.ready)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.setImageSmoothing();\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tmapObj.draw(this.context, -w / 2 - (this.anchor_x * w) / 2, -h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tmapObj.draw(this.context, x - w / 2 - (this.anchor_x * w) / 2, -y - h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t}\n\t}\n}\n","import { APIErrorCode, reportRuntimeError } from \"@al8b/diagnostics\";\nimport { BaseScreen } from \"../core/base-screen\";\n\n/**\n * Adds primitive shape drawing APIs on top of BaseScreen.\n */\nexport class PrimitiveScreen extends BaseScreen {\n\tfillRect(x: number, y: number, w: number, h: number, color?: string | number): void {\n\t\t// Validate drawing context\n\t\tif (!this.context) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7092, {});\n\t\t\treturn;\n\t\t}\n\n\t\t// Validate drawing parameters\n\t\tif (!isFinite(x) || !isFinite(y) || !isFinite(w) || !isFinite(h) || w <= 0 || h <= 0) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7093, { error: `Invalid parameters: x=${x}, y=${y}, w=${w}, h=${h}` });\n\t\t\treturn;\n\t\t}\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.fillRect(-w / 2 - (this.anchor_x * w) / 2, -h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.fillRect(x - w / 2 - (this.anchor_x * w) / 2, -y - h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t}\n\t}\n\n\tfillRoundRect(x: number, y: number, w: number, h: number, round: number = 10, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tconst transform = this.initDrawOp(x, -y);\n\t\tconst rx = (transform ? -w / 2 : x - w / 2) - (this.anchor_x * w) / 2;\n\t\tconst ry = (transform ? -h / 2 : -y - h / 2) + (this.anchor_y * h) / 2;\n\n\t\tthis.context.beginPath();\n\t\tif (this.context.roundRect) {\n\t\t\tthis.context.roundRect(rx, ry, w, h, round);\n\t\t} else {\n\t\t\tconst r = Math.min(round, w / 2, h / 2);\n\t\t\tthis.context.moveTo(rx + r, ry);\n\t\t\tthis.context.lineTo(rx + w - r, ry);\n\t\t\tthis.context.quadraticCurveTo(rx + w, ry, rx + w, ry + r);\n\t\t\tthis.context.lineTo(rx + w, ry + h - r);\n\t\t\tthis.context.quadraticCurveTo(rx + w, ry + h, rx + w - r, ry + h);\n\t\t\tthis.context.lineTo(rx + r, ry + h);\n\t\t\tthis.context.quadraticCurveTo(rx, ry + h, rx, ry + h - r);\n\t\t\tthis.context.lineTo(rx, ry + r);\n\t\t\tthis.context.quadraticCurveTo(rx, ry, rx + r, ry);\n\t\t\tthis.context.closePath();\n\t\t}\n\t\tthis.context.fill();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tfillRound(x: number, y: number, w: number, h: number, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tw = Math.abs(w);\n\t\th = Math.abs(h);\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.ellipse((-this.anchor_x * w) / 2, (this.anchor_y * h) / 2, w / 2, h / 2, 0, 0, Math.PI * 2, false);\n\t\t\tthis.context.fill();\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.ellipse(\n\t\t\t\tx - (this.anchor_x * w) / 2,\n\t\t\t\t-y + (this.anchor_y * h) / 2,\n\t\t\t\tw / 2,\n\t\t\t\th / 2,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tMath.PI * 2,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t\tthis.context.fill();\n\t\t}\n\t}\n\n\tdrawRect(x: number, y: number, w: number, h: number, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.strokeRect(-w / 2 - (this.anchor_x * w) / 2, -h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.strokeRect(x - w / 2 - (this.anchor_x * w) / 2, -y - h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t}\n\t}\n\n\tdrawRoundRect(x: number, y: number, w: number, h: number, round: number = 10, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\t\tconst transform = this.initDrawOp(x, -y);\n\t\tconst rx = (transform ? -w / 2 : x - w / 2) - (this.anchor_x * w) / 2;\n\t\tconst ry = (transform ? -h / 2 : -y - h / 2) + (this.anchor_y * h) / 2;\n\n\t\tthis.context.beginPath();\n\t\tif (this.context.roundRect) {\n\t\t\tthis.context.roundRect(rx, ry, w, h, round);\n\t\t} else {\n\t\t\tconst r = Math.min(round, w / 2, h / 2);\n\t\t\tthis.context.moveTo(rx + r, ry);\n\t\t\tthis.context.lineTo(rx + w - r, ry);\n\t\t\tthis.context.quadraticCurveTo(rx + w, ry, rx + w, ry + r);\n\t\t\tthis.context.lineTo(rx + w, ry + h - r);\n\t\t\tthis.context.quadraticCurveTo(rx + w, ry + h, rx + w - r, ry + h);\n\t\t\tthis.context.lineTo(rx + r, ry + h);\n\t\t\tthis.context.quadraticCurveTo(rx, ry + h, rx, ry + h - r);\n\t\t\tthis.context.lineTo(rx, ry + r);\n\t\t\tthis.context.quadraticCurveTo(rx, ry, rx + r, ry);\n\t\t\tthis.context.closePath();\n\t\t}\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawRound(x: number, y: number, w: number, h: number, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\t\tw = Math.abs(w);\n\t\th = Math.abs(h);\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.ellipse((-this.anchor_x * w) / 2, (this.anchor_y * h) / 2, w / 2, h / 2, 0, 0, Math.PI * 2, false);\n\t\t\tthis.context.stroke();\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.ellipse(\n\t\t\t\tx - (this.anchor_x * w) / 2,\n\t\t\t\t-y + (this.anchor_y * h) / 2,\n\t\t\t\tw / 2,\n\t\t\t\th / 2,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tMath.PI * 2,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t\tthis.context.stroke();\n\t\t}\n\t}\n\n\tdrawLine(x1: number, y1: number, x2: number, y2: number, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(x1, -y1);\n\t\tthis.context.lineTo(x2, -y2);\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawPolygon(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tconst len = Math.floor(points.length / 2);\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tfor (let i = 1; i < len; i++) {\n\t\t\tthis.context.lineTo(points[i * 2], -points[i * 2 + 1]);\n\t\t}\n\t\tthis.context.closePath();\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawPolyline(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tconst len = Math.floor(points.length / 2);\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tfor (let i = 1; i < len; i++) {\n\t\t\tthis.context.lineTo(points[i * 2], -points[i * 2 + 1]);\n\t\t}\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tfillPolygon(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\n\t\tconst len = Math.floor(points.length / 2);\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tfor (let i = 1; i < len; i++) {\n\t\t\tthis.context.lineTo(points[i * 2], -points[i * 2 + 1]);\n\t\t}\n\t\tthis.context.fill();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawQuadCurve(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tlet index = 2;\n\t\twhile (index <= points.length - 4) {\n\t\t\tthis.context.quadraticCurveTo(points[index], -points[index + 1], points[index + 2], -points[index + 3]);\n\t\t\tindex += 4;\n\t\t}\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawBezierCurve(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tlet index = 2;\n\t\twhile (index <= points.length - 6) {\n\t\t\tthis.context.bezierCurveTo(\n\t\t\t\tpoints[index],\n\t\t\t\t-points[index + 1],\n\t\t\t\tpoints[index + 2],\n\t\t\t\t-points[index + 3],\n\t\t\t\tpoints[index + 4],\n\t\t\t\t-points[index + 5],\n\t\t\t);\n\t\t\tindex += 6;\n\t\t}\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawArc(\n\t\tx: number,\n\t\ty: number,\n\t\tradius: number,\n\t\tangle1: number,\n\t\tangle2: number,\n\t\tccw: boolean,\n\t\tcolor?: string | number,\n\t): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.arc(0, 0, radius, (-angle1 / 180) * Math.PI, (-angle2 / 180) * Math.PI, ccw);\n\t\t\tthis.context.stroke();\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.arc(x, -y, radius, (-angle1 / 180) * Math.PI, (-angle2 / 180) * Math.PI, ccw);\n\t\t\tthis.context.stroke();\n\t\t}\n\t}\n\n\tfillArc(\n\t\tx: number,\n\t\ty: number,\n\t\tradius: number,\n\t\tangle1: number,\n\t\tangle2: number,\n\t\tccw: boolean,\n\t\tcolor?: string | number,\n\t): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.arc(0, 0, radius, (-angle1 / 180) * Math.PI, (-angle2 / 180) * Math.PI, ccw);\n\t\t\tthis.context.fill();\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.arc(x, -y, radius, (-angle1 / 180) * Math.PI, (-angle2 / 180) * Math.PI, ccw);\n\t\t\tthis.context.fill();\n\t\t}\n\t}\n\n\tprivate extractPoints(args: any[]): {\n\t\tcolor?: string | number;\n\t\tpoints?: number[];\n\t} {\n\t\tlet color: string | number | undefined;\n\t\tlet points: number[] | undefined;\n\n\t\tif (args.length > 0 && args.length % 2 === 1 && typeof args[args.length - 1] === \"string\") {\n\t\t\tcolor = args[args.length - 1];\n\t\t\tpoints = args.slice(0, -1);\n\t\t} else if (Array.isArray(args[0])) {\n\t\t\tif (args[1] && typeof args[1] === \"string\") {\n\t\t\t\tcolor = args[1];\n\t\t\t}\n\t\t\tpoints = args[0];\n\t\t} else {\n\t\t\tpoints = args as number[];\n\t\t}\n\n\t\treturn {\n\t\t\tcolor,\n\t\t\tpoints,\n\t\t};\n\t}\n}\n","import { APIErrorCode, createDiagnostic, formatForBrowser, reportRuntimeError } from \"@al8b/diagnostics\";\nimport { ZBuffer } from \"../tri\";\nimport type { ScreenInterface, ScreenOptions } from \"../types\";\n\n/**\n * BaseScreen encapsulates canvas/context management plus shared drawing state.\n * Feature-specific behaviors (primitives, sprites, text, triangles) extend this class.\n */\nexport class BaseScreen {\n\tprotected canvas: HTMLCanvasElement;\n\tprotected context!: CanvasRenderingContext2D;\n\tprotected runtime: any;\n\n\tpublic width!: number;\n\tpublic height!: number;\n\n\t// Drawing state\n\tprotected alpha = 1;\n\tprotected pixelated = 1;\n\tprotected line_width = 1;\n\tprotected font = \"BitCell\";\n\n\t// Transformations\n\tprotected translation_x = 0;\n\tprotected translation_y = 0;\n\tprotected rotation = 0;\n\tprotected scale_x = 1;\n\tprotected scale_y = 1;\n\tprotected screen_transform = false;\n\n\t// Object transformations\n\tprotected object_rotation = 0;\n\tprotected object_scale_x = 1;\n\tprotected object_scale_y = 1;\n\tprotected anchor_x = 0;\n\tprotected anchor_y = 0;\n\n\t// Blending + font caches\n\tprotected blending: Record<string, string> = {};\n\tprotected font_load_requested: Record<string, boolean> = {};\n\tprotected font_loaded: Record<string, boolean> = {};\n\n\t// Interface cache\n\tprotected interfaceCache: ScreenInterface | null = null;\n\n\t// Cursor management\n\tprotected cursor: string = \"default\";\n\tprotected cursor_visibility: string = \"auto\";\n\tprotected last_mouse_move: number = Date.now();\n\n\t// 3D helper\n\tprotected zBuffer: ZBuffer;\n\n\tconstructor(options: ScreenOptions = {}) {\n\t\tthis.runtime = options.runtime;\n\n\t\tif (options.canvas) {\n\t\t\tthis.canvas = options.canvas;\n\t\t\tif (this.canvas.width === 0 || this.canvas.height === 0) {\n\t\t\t\tthis.canvas.width = options.width || 1080;\n\t\t\t\tthis.canvas.height = options.height || 1920;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.canvas = document.createElement(\"canvas\");\n\t\t\tthis.canvas.width = options.width || 1080;\n\t\t\tthis.canvas.height = options.height || 1920;\n\t\t}\n\n\t\tthis.initContext();\n\n\t\tthis.blending = {\n\t\t\tnormal: \"source-over\",\n\t\t\tadditive: \"lighter\",\n\t\t};\n\n\t\tconst blendModes = [\n\t\t\t\"source-over\",\n\t\t\t\"source-in\",\n\t\t\t\"source-out\",\n\t\t\t\"source-atop\",\n\t\t\t\"destination-over\",\n\t\t\t\"destination-in\",\n\t\t\t\"destination-out\",\n\t\t\t\"destination-atop\",\n\t\t\t\"lighter\",\n\t\t\t\"copy\",\n\t\t\t\"xor\",\n\t\t\t\"multiply\",\n\t\t\t\"screen\",\n\t\t\t\"overlay\",\n\t\t\t\"darken\",\n\t\t\t\"lighten\",\n\t\t\t\"color-dodge\",\n\t\t\t\"color-burn\",\n\t\t\t\"hard-light\",\n\t\t\t\"soft-light\",\n\t\t\t\"difference\",\n\t\t\t\"exclusion\",\n\t\t\t\"hue\",\n\t\t\t\"saturation\",\n\t\t\t\"color\",\n\t\t\t\"luminosity\",\n\t\t];\n\n\t\tfor (const mode of blendModes) {\n\t\t\tthis.blending[mode] = mode;\n\t\t}\n\n\t\tthis.loadFont(this.font);\n\t\tthis.zBuffer = new ZBuffer(this.canvas.width, this.canvas.height);\n\n\t\tthis.cursor = \"default\";\n\n\t\tthis.canvas.addEventListener(\"mousemove\", () => {\n\t\t\tthis.last_mouse_move = Date.now();\n\t\t\tif (this.cursor !== \"default\" && this.cursor_visibility === \"auto\") {\n\t\t\t\tthis.cursor = \"default\";\n\t\t\t\tthis.canvas.style.cursor = \"default\";\n\t\t\t}\n\t\t});\n\n\t\t// When the context is lost and then restored, base transform needs to be reinstated\n\t\tthis.canvas.addEventListener(\"contextrestored\", () => {\n\t\t\tthis.initContext();\n\t\t});\n\n\t\tsetInterval(() => this.checkMouseCursor(), 1000);\n\t\tthis.cursor_visibility = \"auto\";\n\t}\n\n\tprotected initContext(): void {\n\t\tconst ctx = this.canvas.getContext(\"2d\", {\n\t\t\talpha: false,\n\t\t});\n\t\tif (!ctx) {\n\t\t\tconst diagnostic = createDiagnostic(APIErrorCode.E7001);\n\t\t\tconst formatted = formatForBrowser(diagnostic);\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7001, {});\n\n\t\t\tthrow new Error(formatted);\n\t\t}\n\n\t\tif (ctx !== this.context) {\n\t\t\tthis.context = ctx;\n\t\t} else {\n\t\t\tthis.context.restore();\n\t\t}\n\n\t\tthis.context.save();\n\t\tthis.context.translate(this.canvas.width / 2, this.canvas.height / 2);\n\n\t\t// Calculate ratio: Math.min(canvas.width/200, canvas.height/200)\n\t\tconst ratio = Math.min(this.canvas.width / 200, this.canvas.height / 200);\n\t\tthis.context.scale(ratio, ratio);\n\n\t\t// Set logical width/height\n\t\tthis.width = this.canvas.width / ratio;\n\t\tthis.height = this.canvas.height / ratio;\n\t\tthis.context.lineCap = \"round\";\n\t}\n\n\t/**\n\t * Initialize draw state (called before each draw frame)\n\t */\n\tinitDraw(): void {\n\t\tthis.alpha = 1;\n\t\tthis.line_width = 1;\n\t\t// Note: Supersampling not implemented in l8b\n\t\t// If needed, add: if (this.supersampling != this.previous_supersampling) { this.resize(); this.previous_supersampling = this.supersampling; }\n\t}\n\n\t/**\n\t * Update interface dimensions (called before each draw frame)\n\t */\n\tupdateInterface(): void {\n\t\t// Update interface cache if it exists\n\t\tif (this.interfaceCache) {\n\t\t\tthis.interfaceCache.width = this.width;\n\t\t\tthis.interfaceCache.height = this.height;\n\t\t}\n\t}\n\n\tclear(color?: string): void {\n\t\tthis.context.globalAlpha = 1;\n\t\tthis.context.globalCompositeOperation = \"source-over\";\n\t\tthis.context.fillStyle = color || \"#000\";\n\t\tthis.context.strokeStyle = color || \"#000\";\n\t\tthis.context.fillRect(-this.width / 2, -this.height / 2, this.width, this.height);\n\t\tthis.zBuffer.clear();\n\t}\n\n\tsetColor(color: string | number): void {\n\t\tif (!color) return;\n\n\t\tif (!Number.isNaN(Number.parseInt(String(color)))) {\n\t\t\tconst num = Number.parseInt(String(color));\n\t\t\tconst r = ((Math.floor(num / 100) % 10) / 9) * 255;\n\t\t\tconst g = ((Math.floor(num / 10) % 10) / 9) * 255;\n\t\t\tconst b = ((num % 10) / 9) * 255;\n\t\t\tconst c = 0xff000000 + (r << 16) + (g << 8) + b;\n\t\t\tconst hex = \"#\" + c.toString(16).substring(2, 8);\n\t\t\tthis.context.fillStyle = hex;\n\t\t\tthis.context.strokeStyle = hex;\n\t\t} else if (typeof color === \"string\") {\n\t\t\t// Validate color format\n\t\t\tconst isValidColor =\n\t\t\t\t/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(color) ||\n\t\t\t\t/^rgb\\(|^rgba\\(|^hsl\\(|^hsla\\(/.test(color) ||\n\t\t\t\t/^(red|green|blue|yellow|cyan|magenta|black|white|gray|grey|orange|pink|purple|brown|transparent)$/i.test(color);\n\n\t\t\tif (!isValidColor) {\n\t\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7003, { color });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.context.fillStyle = color;\n\t\t\tthis.context.strokeStyle = color;\n\t\t}\n\t}\n\n\tsetAlpha(alpha: number): void {\n\t\tthis.alpha = alpha;\n\t}\n\n\tsetPixelated(pixelated: number): void {\n\t\tthis.pixelated = pixelated;\n\t}\n\n\tsetBlending(blending: string): void {\n\t\tconst blend = this.blending[blending || \"normal\"];\n\n\t\tif (!blend) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7007, { blendMode: blending });\n\t\t\t// Fallback to normal blend mode\n\t\t\tthis.context.globalCompositeOperation = \"source-over\";\n\t\t\treturn;\n\t\t}\n\n\t\tthis.context.globalCompositeOperation = blend as GlobalCompositeOperation;\n\t}\n\n\tsetLineWidth(width: number): void {\n\t\tthis.line_width = width;\n\t}\n\n\tsetLineDash(dash: number[] | null): void {\n\t\tif (!Array.isArray(dash)) {\n\t\t\tthis.context.setLineDash([]);\n\t\t} else {\n\t\t\tthis.context.setLineDash(dash);\n\t\t}\n\t}\n\n\tsetLinearGradient(x1: number, y1: number, x2: number, y2: number, c1: string, c2: string): void {\n\t\tconst grd = this.context.createLinearGradient(x1, -y1, x2, -y2);\n\t\tgrd.addColorStop(0, c1);\n\t\tgrd.addColorStop(1, c2);\n\t\tthis.context.fillStyle = grd;\n\t\tthis.context.strokeStyle = grd;\n\t}\n\n\tsetRadialGradient(x: number, y: number, radius: number, c1: string, c2: string): void {\n\t\tconst grd = this.context.createRadialGradient(x, -y, 0, x, -y, radius);\n\t\tgrd.addColorStop(0, c1);\n\t\tgrd.addColorStop(1, c2);\n\t\tthis.context.fillStyle = grd;\n\t\tthis.context.strokeStyle = grd;\n\t}\n\n\tsetFont(font: string): void {\n\t\tthis.font = font || \"Verdana\";\n\t\tthis.loadFont(this.font);\n\t}\n\n\tloadFont(font: string = \"BitCell\"): void {\n\t\tif (this.font_load_requested[font]) {\n\t\t\treturn;\n\t\t}\n\t\tthis.font_load_requested[font] = true;\n\t\ttry {\n\t\t\tdocument.fonts?.load?.(`16pt ${font}`).catch(() => {\n\t\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7006, { font });\n\t\t\t});\n\t\t} catch {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7006, { font });\n\t\t}\n\t}\n\n\tisFontReady(font: string = this.font): number {\n\t\tif (this.font_loaded[font]) {\n\t\t\treturn 1;\n\t\t}\n\n\t\ttry {\n\t\t\tconst ready = document.fonts?.check?.(`16pt ${font}`) ?? true;\n\t\t\tif (ready) {\n\t\t\t\tthis.font_loaded[font] = true;\n\t\t\t}\n\t\t\treturn ready ? 1 : 0;\n\t\t} catch {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\tsetTranslation(tx: number, ty: number): void {\n\t\tthis.translation_x = isFinite(tx) ? tx : 0;\n\t\tthis.translation_y = isFinite(ty) ? ty : 0;\n\t\tthis.updateScreenTransform();\n\t}\n\n\tsetScale(x: number, y: number): void {\n\t\tthis.scale_x = isFinite(x) && x !== 0 ? x : 1;\n\t\tthis.scale_y = isFinite(y) && y !== 0 ? y : 1;\n\t\tthis.updateScreenTransform();\n\t}\n\n\tsetRotation(rotation: number): void {\n\t\tthis.rotation = isFinite(rotation) ? rotation : 0;\n\t\tthis.updateScreenTransform();\n\t}\n\n\tprotected updateScreenTransform(): void {\n\t\tthis.screen_transform =\n\t\t\tthis.translation_x !== 0 ||\n\t\t\tthis.translation_y !== 0 ||\n\t\t\tthis.scale_x !== 1 ||\n\t\t\tthis.scale_y !== 1 ||\n\t\t\tthis.rotation !== 0;\n\t}\n\n\tsetDrawAnchor(ax: number, ay: number): void {\n\t\tthis.anchor_x = typeof ax === \"number\" ? ax : 0;\n\t\tthis.anchor_y = typeof ay === \"number\" ? ay : 0;\n\t}\n\n\tsetDrawRotation(rotation: number): void {\n\t\tthis.object_rotation = rotation;\n\t}\n\n\tsetDrawScale(x: number, y: number = x): void {\n\t\tthis.object_scale_x = x;\n\t\tthis.object_scale_y = y;\n\t}\n\n\tprotected initDrawOp(x: number, y: number, object_transform: boolean = true): boolean {\n\t\tlet res = false;\n\n\t\tif (this.screen_transform) {\n\t\t\tthis.context.save();\n\t\t\tres = true;\n\t\t\tthis.context.translate(this.translation_x, -this.translation_y);\n\t\t\tthis.context.scale(this.scale_x, this.scale_y);\n\t\t\tthis.context.rotate((-this.rotation / 180) * Math.PI);\n\t\t\tthis.context.translate(x, y);\n\t\t}\n\n\t\tif (object_transform && (this.object_rotation !== 0 || this.object_scale_x !== 1 || this.object_scale_y !== 1)) {\n\t\t\tif (!res) {\n\t\t\t\tthis.context.save();\n\t\t\t\tres = true;\n\t\t\t\tthis.context.translate(x, y);\n\t\t\t}\n\n\t\t\tif (this.object_rotation !== 0) {\n\t\t\t\tthis.context.rotate((-this.object_rotation / 180) * Math.PI);\n\t\t\t}\n\n\t\t\tif (this.object_scale_x !== 1 || this.object_scale_y !== 1) {\n\t\t\t\tthis.context.scale(this.object_scale_x, this.object_scale_y);\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tprotected closeDrawOp(): void {\n\t\tthis.context.restore();\n\t}\n\n\t/**\n\t * Check mouse cursor visibility\n\t * Auto-hides cursor after 4 seconds of inactivity\n\t */\n\tprotected checkMouseCursor(): void {\n\t\tif (Date.now() > this.last_mouse_move + 4000 && this.cursor_visibility === \"auto\") {\n\t\t\tif (this.cursor !== \"none\") {\n\t\t\t\tthis.cursor = \"none\";\n\t\t\t\tthis.canvas.style.cursor = \"none\";\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Set cursor visibility\n\t */\n\tsetCursorVisible(visible: boolean): void {\n\t\tthis.cursor_visibility = visible ? \"default\" : \"none\";\n\t\tif (visible) {\n\t\t\tthis.cursor = \"default\";\n\t\t\tthis.canvas.style.cursor = \"default\";\n\t\t} else {\n\t\t\tthis.cursor = \"none\";\n\t\t\tthis.canvas.style.cursor = \"none\";\n\t\t}\n\t}\n\n\tgetCanvas(): HTMLCanvasElement {\n\t\treturn this.canvas;\n\t}\n\n\tgetContext(): CanvasRenderingContext2D {\n\t\treturn this.context;\n\t}\n\n\tresize(width?: number, height?: number): void {\n\t\tif (width && height) {\n\t\t\t// Validate dimensions\n\t\t\tif (width <= 0 || height <= 0 || !isFinite(width) || !isFinite(height)) {\n\t\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7002, { width, height });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.canvas.width = width;\n\t\t\tthis.canvas.height = height;\n\t\t\tthis.initContext();\n\t\t\tthis.zBuffer.resize(width, height);\n\t\t\t// Update interface cache immediately after resize\n\t\t\tthis.updateInterface();\n\t\t}\n\t}\n}\n","/**\n * TTRI - Textured Triangle Rendering (Software Rasterization)\n *\n * Based on TIC-80's ttri implementation for 3D-style graphics.\n * This is NOT a 3D engine - it's pure 2D pixel manipulation using Canvas 2D API.\n *\n * How it works:\n * 1. Use getImageData() to get pixel buffer\n * 2. Rasterize triangle pixel-by-pixel (barycentric coordinates)\n * 3. Interpolate UV texture coordinates (perspective-correct with 1/z)\n * 4. Sample texture and write to pixel buffer\n * 5. Use putImageData() to update canvas\n *\n * This is software rendering like Doom, Quake software mode, and PlayStation 1.\n * No WebGL, no GPU - just CPU pixel manipulation.\n */\n\nimport type { TileMap as Map } from \"@al8b/map\";\nimport type { Sprite } from \"@al8b/sprites\";\n\nexport interface Vec2 {\n\tx: number;\n\ty: number;\n}\n\nexport interface Vec3 {\n\tx: number;\n\ty: number;\n\tz: number;\n}\n\nexport interface TexVert {\n\tx: number;\n\ty: number;\n\tu: number;\n\tv: number;\n\tz: number;\n}\n\nexport type TextureSource = \"tiles\" | \"map\" | \"screen\";\n\nexport interface TriangleData {\n\tcontext: CanvasRenderingContext2D;\n\twidth: number;\n\theight: number;\n\truntime?: any;\n\tpixelated: boolean;\n}\n\n/**\n * Z-Buffer for depth testing\n */\nexport class ZBuffer {\n\tprivate buffer: Float32Array;\n\tprivate width: number;\n\tprivate height: number;\n\n\tconstructor(width: number, height: number) {\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\tthis.buffer = new Float32Array(width * height);\n\t}\n\n\tclear(): void {\n\t\tthis.buffer.fill(0);\n\t}\n\n\tget(x: number, y: number): number {\n\t\treturn this.buffer[y * this.width + x] || 0;\n\t}\n\n\tset(x: number, y: number, z: number): void {\n\t\tthis.buffer[y * this.width + x] = z;\n\t}\n\n\tresize(width: number, height: number): void {\n\t\tif (this.width !== width || this.height !== height) {\n\t\t\tthis.width = width;\n\t\t\tthis.height = height;\n\t\t\tthis.buffer = new Float32Array(width * height);\n\t\t}\n\t}\n}\n\n/**\n * Edge function for triangle rasterization\n */\nfunction edgeFn(a: Vec2, b: Vec2, c: Vec2): number {\n\treturn (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n}\n\n/**\n * Get pixel from sprite/image\n */\nfunction getSpritePixel(\n\tsprite: Sprite | any,\n\tu: number,\n\tv: number,\n\truntime?: any,\n): {\n\tr: number;\n\tg: number;\n\tb: number;\n\ta: number;\n} | null {\n\t// Resolve sprite canvas from object or runtime registry\n\tlet canvas: HTMLCanvasElement | null = null;\n\n\tif (sprite && typeof sprite === \"object\" && sprite.canvas) {\n\t\tcanvas = sprite.canvas;\n\t} else if (typeof sprite === \"string\" && runtime?.sprites) {\n\t\tconst spriteObj = runtime.sprites[sprite];\n\t\tif (spriteObj?.frames?.[0]?.canvas) {\n\t\t\tcanvas = spriteObj.frames[0].canvas;\n\t\t}\n\t}\n\n\tif (!canvas) return null;\n\n\t// Apply texture coordinate wrapping (repeat mode)\n\tconst width = canvas.width;\n\tconst height = canvas.height;\n\tconst x = Math.floor(u) % width;\n\tconst y = Math.floor(v) % height;\n\tconst px = x < 0 ? x + width : x;\n\tconst py = y < 0 ? y + height : y;\n\n\t// Sample pixel color from sprite canvas\n\tconst ctx = canvas.getContext(\"2d\");\n\tif (!ctx) return null;\n\n\ttry {\n\t\tconst imageData = ctx.getImageData(px, py, 1, 1);\n\t\treturn {\n\t\t\tr: imageData.data[0],\n\t\t\tg: imageData.data[1],\n\t\t\tb: imageData.data[2],\n\t\t\ta: imageData.data[3],\n\t\t};\n\t} catch (e) {\n\t\treturn null;\n\t}\n}\n\n/**\n * Get pixel from map\n */\nfunction getMapPixel(\n\tmap: Map | any,\n\tu: number,\n\tv: number,\n\truntime?: any,\n): {\n\tr: number;\n\tg: number;\n\tb: number;\n\ta: number;\n} | null {\n\t// Get map object\n\tlet mapObj: any = null;\n\n\tif (map && typeof map === \"object\" && map.getCanvas) {\n\t\tmapObj = map;\n\t} else if (typeof map === \"string\" && runtime?.maps) {\n\t\tmapObj = runtime.maps[map];\n\t}\n\n\tif (!mapObj) return null;\n\n\t// Get canvas from map\n\tconst canvas = mapObj.getCanvas ? mapObj.getCanvas() : mapObj.canvas;\n\tif (!canvas) return null;\n\n\t// Wrap texture coordinates\n\tconst width = canvas.width;\n\tconst height = canvas.height;\n\tconst x = Math.floor(u) % width;\n\tconst y = Math.floor(v) % height;\n\tconst px = x < 0 ? x + width : x;\n\tconst py = y < 0 ? y + height : y;\n\n\t// Get pixel data\n\tconst ctx = canvas.getContext(\"2d\");\n\tif (!ctx) return null;\n\n\ttry {\n\t\tconst imageData = ctx.getImageData(px, py, 1, 1);\n\t\treturn {\n\t\t\tr: imageData.data[0],\n\t\t\tg: imageData.data[1],\n\t\t\tb: imageData.data[2],\n\t\t\ta: imageData.data[3],\n\t\t};\n\t} catch (e) {\n\t\treturn null;\n\t}\n}\n\n/**\n * Draw textured triangle with perspective correction\n */\nexport function drawTexturedTriangle(\n\tdata: TriangleData,\n\tv0: TexVert,\n\tv1: TexVert,\n\tv2: TexVert,\n\ttexture: Sprite | Map | string | any,\n\ttextureSource: TextureSource = \"tiles\",\n\tzBuffer?: ZBuffer,\n\tuseDepth: boolean = false,\n): void {\n\tconst { context, width, height, runtime, pixelated } = data;\n\n\t// Get bounding box\n\tconst minX = Math.max(0, Math.floor(Math.min(v0.x, v1.x, v2.x)));\n\tconst minY = Math.max(0, Math.floor(Math.min(v0.y, v1.y, v2.y)));\n\tconst maxX = Math.min(width, Math.ceil(Math.max(v0.x, v1.x, v2.x)));\n\tconst maxY = Math.min(height, Math.ceil(Math.max(v0.y, v1.y, v2.y)));\n\n\tif (minX >= maxX || minY >= maxY) return;\n\n\t// Calculate triangle area\n\tconst area = edgeFn(v0, v1, v2);\n\tif (Math.abs(area) < 0.001) return;\n\n\t// Backface culling\n\tif (area < 0) return;\n\n\t// Prepare perspective-correct interpolation\n\tconst useZ = useDepth && v0.z > 0 && v1.z > 0 && v2.z > 0;\n\n\tlet w0 = 1,\n\t\tw1 = 1,\n\t\tw2 = 1;\n\tlet u0 = v0.u,\n\t\tu1 = v1.u,\n\t\tu2 = v2.u;\n\tlet v0v = v0.v,\n\t\tv1v = v1.v,\n\t\tv2v = v2.v;\n\n\tif (useZ) {\n\t\tw0 = 1 / v0.z;\n\t\tw1 = 1 / v1.z;\n\t\tw2 = 1 / v2.z;\n\t\tu0 *= w0;\n\t\tu1 *= w1;\n\t\tu2 *= w2;\n\t\tv0v *= w0;\n\t\tv1v *= w1;\n\t\tv2v *= w2;\n\t}\n\n\t// Get image data for fast pixel manipulation\n\tconst imageData = context.getImageData(minX, minY, maxX - minX, maxY - minY);\n\tconst pixels = imageData.data;\n\n\t// Rasterize\n\tfor (let y = minY; y < maxY; y++) {\n\t\tfor (let x = minX; x < maxX; x++) {\n\t\t\tconst p = {\n\t\t\t\tx: x + 0.5,\n\t\t\t\ty: y + 0.5,\n\t\t\t};\n\n\t\t\t// Calculate barycentric coordinates\n\t\t\tconst w0b = edgeFn(v1, v2, p);\n\t\t\tconst w1b = edgeFn(v2, v0, p);\n\t\t\tconst w2b = edgeFn(v0, v1, p);\n\n\t\t\t// Check if point is inside triangle\n\t\t\tif (w0b >= 0 && w1b >= 0 && w2b >= 0) {\n\t\t\t\t// Normalize barycentric coordinates\n\t\t\t\tconst bary0 = w0b / area;\n\t\t\t\tconst bary1 = w1b / area;\n\t\t\t\tconst bary2 = w2b / area;\n\n\t\t\t\t// Depth test\n\t\t\t\tif (useZ && zBuffer) {\n\t\t\t\t\tconst z = bary0 * v0.z + bary1 * v1.z + bary2 * v2.z;\n\t\t\t\t\tconst currentZ = zBuffer.get(x, y);\n\t\t\t\t\tif (currentZ > 0 && currentZ >= z) continue;\n\t\t\t\t\tzBuffer.set(x, y, z);\n\t\t\t\t}\n\n\t\t\t\t// Interpolate texture coordinates\n\t\t\t\tlet u: number, v: number;\n\n\t\t\t\tif (useZ) {\n\t\t\t\t\tconst w = bary0 * w0 + bary1 * w1 + bary2 * w2;\n\t\t\t\t\tu = (bary0 * u0 + bary1 * u1 + bary2 * u2) / w;\n\t\t\t\t\tv = (bary0 * v0v + bary1 * v1v + bary2 * v2v) / w;\n\t\t\t\t} else {\n\t\t\t\t\tu = bary0 * v0.u + bary1 * v1.u + bary2 * v2.u;\n\t\t\t\t\tv = bary0 * v0.v + bary1 * v1.v + bary2 * v2.v;\n\t\t\t\t}\n\n\t\t\t\t// Sample texture\n\t\t\t\tlet pixel: {\n\t\t\t\t\tr: number;\n\t\t\t\t\tg: number;\n\t\t\t\t\tb: number;\n\t\t\t\t\ta: number;\n\t\t\t\t} | null = null;\n\n\t\t\t\tif (textureSource === \"map\") {\n\t\t\t\t\tpixel = getMapPixel(texture, u, v, runtime);\n\t\t\t\t} else {\n\t\t\t\t\tpixel = getSpritePixel(texture, u, v, runtime);\n\t\t\t\t}\n\n\t\t\t\t// Draw pixel\n\t\t\t\tif (pixel && pixel.a > 0) {\n\t\t\t\t\tconst idx = ((y - minY) * (maxX - minX) + (x - minX)) * 4;\n\t\t\t\t\tpixels[idx] = pixel.r;\n\t\t\t\t\tpixels[idx + 1] = pixel.g;\n\t\t\t\t\tpixels[idx + 2] = pixel.b;\n\t\t\t\t\tpixels[idx + 3] = pixel.a;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Put image data back\n\tcontext.imageSmoothingEnabled = !pixelated;\n\tcontext.putImageData(imageData, minX, minY);\n}\n\n/**\n * Draw solid color triangle\n */\nexport function drawTriangle(context: CanvasRenderingContext2D, v0: Vec2, v1: Vec2, v2: Vec2, color: string): void {\n\tcontext.fillStyle = color;\n\tcontext.beginPath();\n\tcontext.moveTo(v0.x, v0.y);\n\tcontext.lineTo(v1.x, v1.y);\n\tcontext.lineTo(v2.x, v2.y);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\n/**\n * Draw triangle outline\n */\nexport function drawTriangleOutline(\n\tcontext: CanvasRenderingContext2D,\n\tv0: Vec2,\n\tv1: Vec2,\n\tv2: Vec2,\n\tcolor: string,\n\tlineWidth: number = 1,\n): void {\n\tcontext.strokeStyle = color;\n\tcontext.lineWidth = lineWidth;\n\tcontext.beginPath();\n\tcontext.moveTo(v0.x, v0.y);\n\tcontext.lineTo(v1.x, v1.y);\n\tcontext.lineTo(v2.x, v2.y);\n\tcontext.closePath();\n\tcontext.stroke();\n}\n"],"mappings":"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","names":["APIErrorCode","reportRuntimeError","APIErrorCode","reportRuntimeError","APIErrorCode","createDiagnostic","formatForBrowser","reportRuntimeError","ZBuffer","buffer","width","height","Float32Array","clear","fill","get","x","y","set","z","resize","BaseScreen","canvas","context","runtime","width","height","alpha","pixelated","line_width","font","translation_x","translation_y","rotation","scale_x","scale_y","screen_transform","object_rotation","object_scale_x","object_scale_y","anchor_x","anchor_y","blending","font_load_requested","font_loaded","interfaceCache","cursor","cursor_visibility","last_mouse_move","Date","now","zBuffer","options","document","createElement","initContext","normal","additive","blendModes","mode","loadFont","ZBuffer","addEventListener","style","setInterval","checkMouseCursor","ctx","getContext","diagnostic","createDiagnostic","APIErrorCode","E7001","formatted","formatForBrowser","reportRuntimeError","listener","Error","restore","save","translate","ratio","Math","min","scale","lineCap","initDraw","updateInterface","clear","color","globalAlpha","globalCompositeOperation","fillStyle","strokeStyle","fillRect","setColor","Number","isNaN","parseInt","String","num","r","floor","g","b","c","hex","toString","substring","isValidColor","test","E7003","setAlpha","setPixelated","setBlending","blend","E7007","blendMode","setLineWidth","setLineDash","dash","Array","isArray","setLinearGradient","x1","y1","x2","y2","c1","c2","grd","createLinearGradient","addColorStop","setRadialGradient","x","y","radius","createRadialGradient","setFont","fonts","load","catch","E7006","isFontReady","ready","check","setTranslation","tx","ty","isFinite","updateScreenTransform","setScale","setRotation","setDrawAnchor","ax","ay","setDrawRotation","setDrawScale","initDrawOp","object_transform","res","rotate","PI","closeDrawOp","setCursorVisible","visible","getCanvas","resize","E7002","PrimitiveScreen","BaseScreen","fillRect","x","y","w","h","color","context","reportRuntimeError","runtime","listener","APIErrorCode","E7092","isFinite","E7093","error","setColor","globalAlpha","alpha","initDrawOp","anchor_x","anchor_y","closeDrawOp","fillRoundRect","round","transform","rx","ry","beginPath","roundRect","r","Math","min","moveTo","lineTo","quadraticCurveTo","closePath","fill","fillRound","abs","ellipse","PI","drawRect","lineWidth","line_width","strokeRect","drawRoundRect","stroke","drawRound","drawLine","x1","y1","x2","y2","drawPolygon","args","points","extractPoints","length","len","floor","i","drawPolyline","fillPolygon","drawQuadCurve","index","drawBezierCurve","bezierCurveTo","drawArc","radius","angle1","angle2","ccw","arc","fillArc","slice","Array","isArray","SpriteScreen","PrimitiveScreen","_lastImageSmoothing","_frameTime","initDraw","performance","now","setImageSmoothing","smooth","pixelated","context","imageSmoothingEnabled","getSpriteFrame","sprite","frame","spriteName","spriteObj","runtime","sprites","parts","split","length","Number","parseInt","reportRuntimeError","listener","APIErrorCode","E7004","canvas","frames","image","ready","E7005","animation_start","dt","fps","Math","floor","drawSprite","x","y","w","h","width","height","screen_transform","object_rotation","object_scale_x","object_scale_y","drawX","anchor_x","drawY","anchor_y","halfW","halfH","globalAlpha","alpha","initDrawOp","drawImage","closeDrawOp","drawSpritePart","sx","sy","sw","sh","drawMap","map","mapObj","maps","draw"]}
|
|
1
|
+
{"version":3,"sources":["../../src/tri/ttri.ts","../../src/core/base-screen.ts","../../src/drawing/primitives-screen.ts","../../src/drawing/sprite-screen.ts"],"sourcesContent":["/**\n * TTRI - Textured Triangle Rendering (Software Rasterization)\n *\n * Based on TIC-80's ttri implementation for 3D-style graphics.\n * This is NOT a 3D engine - it's pure 2D pixel manipulation using Canvas 2D API.\n *\n * How it works:\n * 1. Use getImageData() to get pixel buffer\n * 2. Rasterize triangle pixel-by-pixel (barycentric coordinates)\n * 3. Interpolate UV texture coordinates (perspective-correct with 1/z)\n * 4. Sample texture and write to pixel buffer\n * 5. Use putImageData() to update canvas\n *\n * This is software rendering like Doom, Quake software mode, and PlayStation 1.\n * No WebGL, no GPU - just CPU pixel manipulation.\n */\n\nimport type { TileMap as Map } from \"@al8b/map\";\nimport type { Sprite } from \"@al8b/sprites\";\n\nexport interface Vec2 {\n\tx: number;\n\ty: number;\n}\n\nexport interface Vec3 {\n\tx: number;\n\ty: number;\n\tz: number;\n}\n\nexport interface TexVert {\n\tx: number;\n\ty: number;\n\tu: number;\n\tv: number;\n\tz: number;\n}\n\nexport type TextureSource = \"tiles\" | \"map\" | \"screen\";\n\nexport interface TriangleData {\n\tcontext: CanvasRenderingContext2D;\n\twidth: number;\n\theight: number;\n\truntime?: any;\n\tpixelated: boolean;\n}\n\n/**\n * Z-Buffer for depth testing\n */\nexport class ZBuffer {\n\tprivate buffer: Float32Array;\n\tprivate width: number;\n\tprivate height: number;\n\n\tconstructor(width: number, height: number) {\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\tthis.buffer = new Float32Array(width * height);\n\t}\n\n\tclear(): void {\n\t\tthis.buffer.fill(0);\n\t}\n\n\tget(x: number, y: number): number {\n\t\treturn this.buffer[y * this.width + x] || 0;\n\t}\n\n\tset(x: number, y: number, z: number): void {\n\t\tthis.buffer[y * this.width + x] = z;\n\t}\n\n\tresize(width: number, height: number): void {\n\t\tif (this.width !== width || this.height !== height) {\n\t\t\tthis.width = width;\n\t\t\tthis.height = height;\n\t\t\tthis.buffer = new Float32Array(width * height);\n\t\t}\n\t}\n}\n\n/**\n * Edge function for triangle rasterization\n */\nfunction edgeFn(a: Vec2, b: Vec2, c: Vec2): number {\n\treturn (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n}\n\n/**\n * Get pixel from sprite/image\n */\nfunction getSpritePixel(\n\tsprite: Sprite | any,\n\tu: number,\n\tv: number,\n\truntime?: any,\n): {\n\tr: number;\n\tg: number;\n\tb: number;\n\ta: number;\n} | null {\n\t// Resolve sprite canvas from object or runtime registry\n\tlet canvas: HTMLCanvasElement | null = null;\n\n\tif (sprite && typeof sprite === \"object\" && sprite.canvas) {\n\t\tcanvas = sprite.canvas;\n\t} else if (typeof sprite === \"string\" && runtime?.sprites) {\n\t\tconst spriteObj = runtime.sprites[sprite];\n\t\tif (spriteObj?.frames?.[0]?.canvas) {\n\t\t\tcanvas = spriteObj.frames[0].canvas;\n\t\t}\n\t}\n\n\tif (!canvas) return null;\n\n\t// Apply texture coordinate wrapping (repeat mode)\n\tconst width = canvas.width;\n\tconst height = canvas.height;\n\tconst x = Math.floor(u) % width;\n\tconst y = Math.floor(v) % height;\n\tconst px = x < 0 ? x + width : x;\n\tconst py = y < 0 ? y + height : y;\n\n\t// Sample pixel color from sprite canvas\n\tconst ctx = canvas.getContext(\"2d\");\n\tif (!ctx) return null;\n\n\ttry {\n\t\tconst imageData = ctx.getImageData(px, py, 1, 1);\n\t\treturn {\n\t\t\tr: imageData.data[0],\n\t\t\tg: imageData.data[1],\n\t\t\tb: imageData.data[2],\n\t\t\ta: imageData.data[3],\n\t\t};\n\t} catch (e) {\n\t\treturn null;\n\t}\n}\n\n/**\n * Get pixel from map\n */\nfunction getMapPixel(\n\tmap: Map | any,\n\tu: number,\n\tv: number,\n\truntime?: any,\n): {\n\tr: number;\n\tg: number;\n\tb: number;\n\ta: number;\n} | null {\n\t// Get map object\n\tlet mapObj: any = null;\n\n\tif (map && typeof map === \"object\" && map.getCanvas) {\n\t\tmapObj = map;\n\t} else if (typeof map === \"string\" && runtime?.maps) {\n\t\tmapObj = runtime.maps[map];\n\t}\n\n\tif (!mapObj) return null;\n\n\t// Get canvas from map\n\tconst canvas = mapObj.getCanvas ? mapObj.getCanvas() : mapObj.canvas;\n\tif (!canvas) return null;\n\n\t// Wrap texture coordinates\n\tconst width = canvas.width;\n\tconst height = canvas.height;\n\tconst x = Math.floor(u) % width;\n\tconst y = Math.floor(v) % height;\n\tconst px = x < 0 ? x + width : x;\n\tconst py = y < 0 ? y + height : y;\n\n\t// Get pixel data\n\tconst ctx = canvas.getContext(\"2d\");\n\tif (!ctx) return null;\n\n\ttry {\n\t\tconst imageData = ctx.getImageData(px, py, 1, 1);\n\t\treturn {\n\t\t\tr: imageData.data[0],\n\t\t\tg: imageData.data[1],\n\t\t\tb: imageData.data[2],\n\t\t\ta: imageData.data[3],\n\t\t};\n\t} catch (e) {\n\t\treturn null;\n\t}\n}\n\n/**\n * Draw textured triangle with perspective correction\n */\nexport function drawTexturedTriangle(\n\tdata: TriangleData,\n\tv0: TexVert,\n\tv1: TexVert,\n\tv2: TexVert,\n\ttexture: Sprite | Map | string | any,\n\ttextureSource: TextureSource = \"tiles\",\n\tzBuffer?: ZBuffer,\n\tuseDepth: boolean = false,\n): void {\n\tconst { context, width, height, runtime, pixelated } = data;\n\n\t// Get bounding box\n\tconst minX = Math.max(0, Math.floor(Math.min(v0.x, v1.x, v2.x)));\n\tconst minY = Math.max(0, Math.floor(Math.min(v0.y, v1.y, v2.y)));\n\tconst maxX = Math.min(width, Math.ceil(Math.max(v0.x, v1.x, v2.x)));\n\tconst maxY = Math.min(height, Math.ceil(Math.max(v0.y, v1.y, v2.y)));\n\n\tif (minX >= maxX || minY >= maxY) return;\n\n\t// Calculate triangle area\n\tconst area = edgeFn(v0, v1, v2);\n\tif (Math.abs(area) < 0.001) return;\n\n\t// Backface culling\n\tif (area < 0) return;\n\n\t// Prepare perspective-correct interpolation\n\tconst useZ = useDepth && v0.z > 0 && v1.z > 0 && v2.z > 0;\n\n\tlet w0 = 1,\n\t\tw1 = 1,\n\t\tw2 = 1;\n\tlet u0 = v0.u,\n\t\tu1 = v1.u,\n\t\tu2 = v2.u;\n\tlet v0v = v0.v,\n\t\tv1v = v1.v,\n\t\tv2v = v2.v;\n\n\tif (useZ) {\n\t\tw0 = 1 / v0.z;\n\t\tw1 = 1 / v1.z;\n\t\tw2 = 1 / v2.z;\n\t\tu0 *= w0;\n\t\tu1 *= w1;\n\t\tu2 *= w2;\n\t\tv0v *= w0;\n\t\tv1v *= w1;\n\t\tv2v *= w2;\n\t}\n\n\t// Get image data for fast pixel manipulation\n\tconst imageData = context.getImageData(minX, minY, maxX - minX, maxY - minY);\n\tconst pixels = imageData.data;\n\n\t// Rasterize\n\tfor (let y = minY; y < maxY; y++) {\n\t\tfor (let x = minX; x < maxX; x++) {\n\t\t\tconst p = {\n\t\t\t\tx: x + 0.5,\n\t\t\t\ty: y + 0.5,\n\t\t\t};\n\n\t\t\t// Calculate barycentric coordinates\n\t\t\tconst w0b = edgeFn(v1, v2, p);\n\t\t\tconst w1b = edgeFn(v2, v0, p);\n\t\t\tconst w2b = edgeFn(v0, v1, p);\n\n\t\t\t// Check if point is inside triangle\n\t\t\tif (w0b >= 0 && w1b >= 0 && w2b >= 0) {\n\t\t\t\t// Normalize barycentric coordinates\n\t\t\t\tconst bary0 = w0b / area;\n\t\t\t\tconst bary1 = w1b / area;\n\t\t\t\tconst bary2 = w2b / area;\n\n\t\t\t\t// Depth test\n\t\t\t\tif (useZ && zBuffer) {\n\t\t\t\t\tconst z = bary0 * v0.z + bary1 * v1.z + bary2 * v2.z;\n\t\t\t\t\tconst currentZ = zBuffer.get(x, y);\n\t\t\t\t\tif (currentZ > 0 && currentZ >= z) continue;\n\t\t\t\t\tzBuffer.set(x, y, z);\n\t\t\t\t}\n\n\t\t\t\t// Interpolate texture coordinates\n\t\t\t\tlet u: number, v: number;\n\n\t\t\t\tif (useZ) {\n\t\t\t\t\tconst w = bary0 * w0 + bary1 * w1 + bary2 * w2;\n\t\t\t\t\tu = (bary0 * u0 + bary1 * u1 + bary2 * u2) / w;\n\t\t\t\t\tv = (bary0 * v0v + bary1 * v1v + bary2 * v2v) / w;\n\t\t\t\t} else {\n\t\t\t\t\tu = bary0 * v0.u + bary1 * v1.u + bary2 * v2.u;\n\t\t\t\t\tv = bary0 * v0.v + bary1 * v1.v + bary2 * v2.v;\n\t\t\t\t}\n\n\t\t\t\t// Sample texture\n\t\t\t\tlet pixel: {\n\t\t\t\t\tr: number;\n\t\t\t\t\tg: number;\n\t\t\t\t\tb: number;\n\t\t\t\t\ta: number;\n\t\t\t\t} | null = null;\n\n\t\t\t\tif (textureSource === \"map\") {\n\t\t\t\t\tpixel = getMapPixel(texture, u, v, runtime);\n\t\t\t\t} else {\n\t\t\t\t\tpixel = getSpritePixel(texture, u, v, runtime);\n\t\t\t\t}\n\n\t\t\t\t// Draw pixel\n\t\t\t\tif (pixel && pixel.a > 0) {\n\t\t\t\t\tconst idx = ((y - minY) * (maxX - minX) + (x - minX)) * 4;\n\t\t\t\t\tpixels[idx] = pixel.r;\n\t\t\t\t\tpixels[idx + 1] = pixel.g;\n\t\t\t\t\tpixels[idx + 2] = pixel.b;\n\t\t\t\t\tpixels[idx + 3] = pixel.a;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Put image data back\n\tcontext.imageSmoothingEnabled = !pixelated;\n\tcontext.putImageData(imageData, minX, minY);\n}\n\n/**\n * Draw solid color triangle\n */\nexport function drawTriangle(context: CanvasRenderingContext2D, v0: Vec2, v1: Vec2, v2: Vec2, color: string): void {\n\tcontext.fillStyle = color;\n\tcontext.beginPath();\n\tcontext.moveTo(v0.x, v0.y);\n\tcontext.lineTo(v1.x, v1.y);\n\tcontext.lineTo(v2.x, v2.y);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\n/**\n * Draw triangle outline\n */\nexport function drawTriangleOutline(\n\tcontext: CanvasRenderingContext2D,\n\tv0: Vec2,\n\tv1: Vec2,\n\tv2: Vec2,\n\tcolor: string,\n\tlineWidth: number = 1,\n): void {\n\tcontext.strokeStyle = color;\n\tcontext.lineWidth = lineWidth;\n\tcontext.beginPath();\n\tcontext.moveTo(v0.x, v0.y);\n\tcontext.lineTo(v1.x, v1.y);\n\tcontext.lineTo(v2.x, v2.y);\n\tcontext.closePath();\n\tcontext.stroke();\n}\n","import { ZBuffer } from \"../tri\";\nimport type { ScreenInterface, ScreenOptions } from \"../types\";\n\n/**\n * BaseScreen encapsulates canvas/context management plus shared drawing state.\n * Feature-specific behaviors (primitives, sprites, text, triangles) extend this class.\n */\nexport class BaseScreen {\n\tprotected canvas: HTMLCanvasElement;\n\tprotected context!: CanvasRenderingContext2D;\n\tprotected runtime: any;\n\n\tpublic width!: number;\n\tpublic height!: number;\n\n\t// Drawing state\n\tprotected alpha = 1;\n\tprotected pixelated = 1;\n\tprotected line_width = 1;\n\tprotected font = \"BitCell\";\n\n\t// Transformations\n\tprotected translation_x = 0;\n\tprotected translation_y = 0;\n\tprotected rotation = 0;\n\tprotected scale_x = 1;\n\tprotected scale_y = 1;\n\tprotected screen_transform = false;\n\n\t// Object transformations\n\tprotected object_rotation = 0;\n\tprotected object_scale_x = 1;\n\tprotected object_scale_y = 1;\n\tprotected anchor_x = 0;\n\tprotected anchor_y = 0;\n\n\t// Blending + font caches\n\tprotected blending: Record<string, string> = {};\n\tprotected font_load_requested: Record<string, boolean> = {};\n\tprotected font_loaded: Record<string, boolean> = {};\n\n\t// Interface cache\n\tprotected interfaceCache: ScreenInterface | null = null;\n\n\t// Cursor management\n\tprotected cursor: string = \"default\";\n\tprotected cursor_visibility: string = \"auto\";\n\tprotected last_mouse_move: number = Date.now();\n\n\t// 3D helper\n\tprotected zBuffer: ZBuffer;\n\n\tconstructor(options: ScreenOptions = {}) {\n\t\tthis.runtime = options.runtime;\n\n\t\tif (options.canvas) {\n\t\t\tthis.canvas = options.canvas;\n\t\t\tif (this.canvas.width === 0 || this.canvas.height === 0) {\n\t\t\t\tthis.canvas.width = options.width || 1080;\n\t\t\t\tthis.canvas.height = options.height || 1920;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.canvas = document.createElement(\"canvas\");\n\t\t\tthis.canvas.width = options.width || 1080;\n\t\t\tthis.canvas.height = options.height || 1920;\n\t\t}\n\n\t\tthis.initContext();\n\n\t\tthis.blending = {\n\t\t\tnormal: \"source-over\",\n\t\t\tadditive: \"lighter\",\n\t\t};\n\n\t\tconst blendModes = [\n\t\t\t\"source-over\",\n\t\t\t\"source-in\",\n\t\t\t\"source-out\",\n\t\t\t\"source-atop\",\n\t\t\t\"destination-over\",\n\t\t\t\"destination-in\",\n\t\t\t\"destination-out\",\n\t\t\t\"destination-atop\",\n\t\t\t\"lighter\",\n\t\t\t\"copy\",\n\t\t\t\"xor\",\n\t\t\t\"multiply\",\n\t\t\t\"screen\",\n\t\t\t\"overlay\",\n\t\t\t\"darken\",\n\t\t\t\"lighten\",\n\t\t\t\"color-dodge\",\n\t\t\t\"color-burn\",\n\t\t\t\"hard-light\",\n\t\t\t\"soft-light\",\n\t\t\t\"difference\",\n\t\t\t\"exclusion\",\n\t\t\t\"hue\",\n\t\t\t\"saturation\",\n\t\t\t\"color\",\n\t\t\t\"luminosity\",\n\t\t];\n\n\t\tfor (const mode of blendModes) {\n\t\t\tthis.blending[mode] = mode;\n\t\t}\n\n\t\tthis.loadFont(this.font);\n\t\tthis.zBuffer = new ZBuffer(this.canvas.width, this.canvas.height);\n\n\t\tthis.cursor = \"default\";\n\n\t\tthis.canvas.addEventListener(\"mousemove\", () => {\n\t\t\tthis.last_mouse_move = Date.now();\n\t\t\tif (this.cursor !== \"default\" && this.cursor_visibility === \"auto\") {\n\t\t\t\tthis.cursor = \"default\";\n\t\t\t\tthis.canvas.style.cursor = \"default\";\n\t\t\t}\n\t\t});\n\n\t\t// When the context is lost and then restored, base transform needs to be reinstated\n\t\tthis.canvas.addEventListener(\"contextrestored\", () => {\n\t\t\tthis.initContext();\n\t\t});\n\n\t\tsetInterval(() => this.checkMouseCursor(), 1000);\n\t\tthis.cursor_visibility = \"auto\";\n\t}\n\n\tprotected initContext(): void {\n\t\tconst ctx = this.canvas.getContext(\"2d\", {\n\t\t\talpha: false,\n\t\t});\n\t\tif (!ctx) {\n\t\t\tconst message = \"Failed to get 2D rendering context\";\n\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7001\", message, data: {} });\n\n\t\t\tthrow new Error(message);\n\t\t}\n\n\t\tif (ctx !== this.context) {\n\t\t\tthis.context = ctx;\n\t\t} else {\n\t\t\tthis.context.restore();\n\t\t}\n\n\t\tthis.context.save();\n\t\tthis.context.translate(this.canvas.width / 2, this.canvas.height / 2);\n\n\t\t// Calculate ratio: Math.min(canvas.width/200, canvas.height/200)\n\t\tconst ratio = Math.min(this.canvas.width / 200, this.canvas.height / 200);\n\t\tthis.context.scale(ratio, ratio);\n\n\t\t// Set logical width/height\n\t\tthis.width = this.canvas.width / ratio;\n\t\tthis.height = this.canvas.height / ratio;\n\t\tthis.context.lineCap = \"round\";\n\t}\n\n\t/**\n\t * Initialize draw state (called before each draw frame)\n\t */\n\tinitDraw(): void {\n\t\tthis.alpha = 1;\n\t\tthis.line_width = 1;\n\t\t// Note: Supersampling not implemented in l8b\n\t\t// If needed, add: if (this.supersampling != this.previous_supersampling) { this.resize(); this.previous_supersampling = this.supersampling; }\n\t}\n\n\t/**\n\t * Update interface dimensions (called before each draw frame)\n\t */\n\tupdateInterface(): void {\n\t\t// Update interface cache if it exists\n\t\tif (this.interfaceCache) {\n\t\t\tthis.interfaceCache.width = this.width;\n\t\t\tthis.interfaceCache.height = this.height;\n\t\t}\n\t}\n\n\tclear(color?: string): void {\n\t\tthis.context.globalAlpha = 1;\n\t\tthis.context.globalCompositeOperation = \"source-over\";\n\t\tthis.context.fillStyle = color || \"#000\";\n\t\tthis.context.strokeStyle = color || \"#000\";\n\t\tthis.context.fillRect(-this.width / 2, -this.height / 2, this.width, this.height);\n\t\tthis.zBuffer.clear();\n\t}\n\n\tsetColor(color: string | number): void {\n\t\tif (!color) return;\n\n\t\tif (!Number.isNaN(Number.parseInt(String(color)))) {\n\t\t\tconst num = Number.parseInt(String(color));\n\t\t\tconst r = ((Math.floor(num / 100) % 10) / 9) * 255;\n\t\t\tconst g = ((Math.floor(num / 10) % 10) / 9) * 255;\n\t\t\tconst b = ((num % 10) / 9) * 255;\n\t\t\tconst c = 0xff000000 + (r << 16) + (g << 8) + b;\n\t\t\tconst hex = \"#\" + c.toString(16).substring(2, 8);\n\t\t\tthis.context.fillStyle = hex;\n\t\t\tthis.context.strokeStyle = hex;\n\t\t} else if (typeof color === \"string\") {\n\t\t\t// Validate color format\n\t\t\tconst isValidColor =\n\t\t\t\t/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(color) ||\n\t\t\t\t/^rgb\\(|^rgba\\(|^hsl\\(|^hsla\\(/.test(color) ||\n\t\t\t\t/^(red|green|blue|yellow|cyan|magenta|black|white|gray|grey|orange|pink|purple|brown|transparent)$/i.test(color);\n\n\t\t\tif (!isValidColor) {\n\t\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7003\", message: \"Invalid color\", data: { color } });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.context.fillStyle = color;\n\t\t\tthis.context.strokeStyle = color;\n\t\t}\n\t}\n\n\tsetAlpha(alpha: number): void {\n\t\tthis.alpha = alpha;\n\t}\n\n\tsetPixelated(pixelated: number): void {\n\t\tthis.pixelated = pixelated;\n\t}\n\n\tsetBlending(blending: string): void {\n\t\tconst blend = this.blending[blending || \"normal\"];\n\n\t\tif (!blend) {\n\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7007\", message: \"Invalid blend mode\", data: { blendMode: blending } });\n\t\t\t// Fallback to normal blend mode\n\t\t\tthis.context.globalCompositeOperation = \"source-over\";\n\t\t\treturn;\n\t\t}\n\n\t\tthis.context.globalCompositeOperation = blend as GlobalCompositeOperation;\n\t}\n\n\tsetLineWidth(width: number): void {\n\t\tthis.line_width = width;\n\t}\n\n\tsetLineDash(dash: number[] | null): void {\n\t\tif (!Array.isArray(dash)) {\n\t\t\tthis.context.setLineDash([]);\n\t\t} else {\n\t\t\tthis.context.setLineDash(dash);\n\t\t}\n\t}\n\n\tsetLinearGradient(x1: number, y1: number, x2: number, y2: number, c1: string, c2: string): void {\n\t\tconst grd = this.context.createLinearGradient(x1, -y1, x2, -y2);\n\t\tgrd.addColorStop(0, c1);\n\t\tgrd.addColorStop(1, c2);\n\t\tthis.context.fillStyle = grd;\n\t\tthis.context.strokeStyle = grd;\n\t}\n\n\tsetRadialGradient(x: number, y: number, radius: number, c1: string, c2: string): void {\n\t\tconst grd = this.context.createRadialGradient(x, -y, 0, x, -y, radius);\n\t\tgrd.addColorStop(0, c1);\n\t\tgrd.addColorStop(1, c2);\n\t\tthis.context.fillStyle = grd;\n\t\tthis.context.strokeStyle = grd;\n\t}\n\n\tsetFont(font: string): void {\n\t\tthis.font = font || \"Verdana\";\n\t\tthis.loadFont(this.font);\n\t}\n\n\tloadFont(font: string = \"BitCell\"): void {\n\t\tif (this.font_load_requested[font]) {\n\t\t\treturn;\n\t\t}\n\t\tthis.font_load_requested[font] = true;\n\t\ttry {\n\t\t\tdocument.fonts?.load?.(`16pt ${font}`).catch(() => {\n\t\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7006\", message: \"Font loading failed\", data: { font } });\n\t\t\t});\n\t\t} catch {\n\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7006\", message: \"Font loading failed\", data: { font } });\n\t\t}\n\t}\n\n\tisFontReady(font: string = this.font): number {\n\t\tif (this.font_loaded[font]) {\n\t\t\treturn 1;\n\t\t}\n\n\t\ttry {\n\t\t\tconst ready = document.fonts?.check?.(`16pt ${font}`) ?? true;\n\t\t\tif (ready) {\n\t\t\t\tthis.font_loaded[font] = true;\n\t\t\t}\n\t\t\treturn ready ? 1 : 0;\n\t\t} catch {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\tsetTranslation(tx: number, ty: number): void {\n\t\tthis.translation_x = isFinite(tx) ? tx : 0;\n\t\tthis.translation_y = isFinite(ty) ? ty : 0;\n\t\tthis.updateScreenTransform();\n\t}\n\n\tsetScale(x: number, y: number): void {\n\t\tthis.scale_x = isFinite(x) && x !== 0 ? x : 1;\n\t\tthis.scale_y = isFinite(y) && y !== 0 ? y : 1;\n\t\tthis.updateScreenTransform();\n\t}\n\n\tsetRotation(rotation: number): void {\n\t\tthis.rotation = isFinite(rotation) ? rotation : 0;\n\t\tthis.updateScreenTransform();\n\t}\n\n\tprotected updateScreenTransform(): void {\n\t\tthis.screen_transform =\n\t\t\tthis.translation_x !== 0 ||\n\t\t\tthis.translation_y !== 0 ||\n\t\t\tthis.scale_x !== 1 ||\n\t\t\tthis.scale_y !== 1 ||\n\t\t\tthis.rotation !== 0;\n\t}\n\n\tsetDrawAnchor(ax: number, ay: number): void {\n\t\tthis.anchor_x = typeof ax === \"number\" ? ax : 0;\n\t\tthis.anchor_y = typeof ay === \"number\" ? ay : 0;\n\t}\n\n\tsetDrawRotation(rotation: number): void {\n\t\tthis.object_rotation = rotation;\n\t}\n\n\tsetDrawScale(x: number, y: number = x): void {\n\t\tthis.object_scale_x = x;\n\t\tthis.object_scale_y = y;\n\t}\n\n\tprotected initDrawOp(x: number, y: number, object_transform: boolean = true): boolean {\n\t\tlet res = false;\n\n\t\tif (this.screen_transform) {\n\t\t\tthis.context.save();\n\t\t\tres = true;\n\t\t\tthis.context.translate(this.translation_x, -this.translation_y);\n\t\t\tthis.context.scale(this.scale_x, this.scale_y);\n\t\t\tthis.context.rotate((-this.rotation / 180) * Math.PI);\n\t\t\tthis.context.translate(x, y);\n\t\t}\n\n\t\tif (object_transform && (this.object_rotation !== 0 || this.object_scale_x !== 1 || this.object_scale_y !== 1)) {\n\t\t\tif (!res) {\n\t\t\t\tthis.context.save();\n\t\t\t\tres = true;\n\t\t\t\tthis.context.translate(x, y);\n\t\t\t}\n\n\t\t\tif (this.object_rotation !== 0) {\n\t\t\t\tthis.context.rotate((-this.object_rotation / 180) * Math.PI);\n\t\t\t}\n\n\t\t\tif (this.object_scale_x !== 1 || this.object_scale_y !== 1) {\n\t\t\t\tthis.context.scale(this.object_scale_x, this.object_scale_y);\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tprotected closeDrawOp(): void {\n\t\tthis.context.restore();\n\t}\n\n\t/**\n\t * Check mouse cursor visibility\n\t * Auto-hides cursor after 4 seconds of inactivity\n\t */\n\tprotected checkMouseCursor(): void {\n\t\tif (Date.now() > this.last_mouse_move + 4000 && this.cursor_visibility === \"auto\") {\n\t\t\tif (this.cursor !== \"none\") {\n\t\t\t\tthis.cursor = \"none\";\n\t\t\t\tthis.canvas.style.cursor = \"none\";\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Set cursor visibility\n\t */\n\tsetCursorVisible(visible: boolean): void {\n\t\tthis.cursor_visibility = visible ? \"default\" : \"none\";\n\t\tif (visible) {\n\t\t\tthis.cursor = \"default\";\n\t\t\tthis.canvas.style.cursor = \"default\";\n\t\t} else {\n\t\t\tthis.cursor = \"none\";\n\t\t\tthis.canvas.style.cursor = \"none\";\n\t\t}\n\t}\n\n\tgetCanvas(): HTMLCanvasElement {\n\t\treturn this.canvas;\n\t}\n\n\tgetContext(): CanvasRenderingContext2D {\n\t\treturn this.context;\n\t}\n\n\tresize(width?: number, height?: number): void {\n\t\tif (width && height) {\n\t\t\t// Validate dimensions\n\t\t\tif (width <= 0 || height <= 0 || !isFinite(width) || !isFinite(height)) {\n\t\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7002\", message: \"Invalid resize dimensions\", data: { width, height } });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.canvas.width = width;\n\t\t\tthis.canvas.height = height;\n\t\t\tthis.initContext();\n\t\t\tthis.zBuffer.resize(width, height);\n\t\t\t// Update interface cache immediately after resize\n\t\t\tthis.updateInterface();\n\t\t}\n\t}\n}\n","import { BaseScreen } from \"../core/base-screen\";\n\n/**\n * Adds primitive shape drawing APIs on top of BaseScreen.\n */\nexport class PrimitiveScreen extends BaseScreen {\n\tfillRect(x: number, y: number, w: number, h: number, color?: string | number): void {\n\t\t// Validate drawing context\n\t\tif (!this.context) {\n\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7092\", message: \"Drawing context not available\", data: {} });\n\t\t\treturn;\n\t\t}\n\n\t\t// Validate drawing parameters\n\t\tif (!isFinite(x) || !isFinite(y) || !isFinite(w) || !isFinite(h) || w <= 0 || h <= 0) {\n\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7093\", message: \"Invalid draw parameters\", data: { error: `Invalid parameters: x=${x}, y=${y}, w=${w}, h=${h}` } });\n\t\t\treturn;\n\t\t}\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.fillRect(-w / 2 - (this.anchor_x * w) / 2, -h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.fillRect(x - w / 2 - (this.anchor_x * w) / 2, -y - h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t}\n\t}\n\n\tfillRoundRect(x: number, y: number, w: number, h: number, round: number = 10, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tconst transform = this.initDrawOp(x, -y);\n\t\tconst rx = (transform ? -w / 2 : x - w / 2) - (this.anchor_x * w) / 2;\n\t\tconst ry = (transform ? -h / 2 : -y - h / 2) + (this.anchor_y * h) / 2;\n\n\t\tthis.context.beginPath();\n\t\tif (this.context.roundRect) {\n\t\t\tthis.context.roundRect(rx, ry, w, h, round);\n\t\t} else {\n\t\t\tconst r = Math.min(round, w / 2, h / 2);\n\t\t\tthis.context.moveTo(rx + r, ry);\n\t\t\tthis.context.lineTo(rx + w - r, ry);\n\t\t\tthis.context.quadraticCurveTo(rx + w, ry, rx + w, ry + r);\n\t\t\tthis.context.lineTo(rx + w, ry + h - r);\n\t\t\tthis.context.quadraticCurveTo(rx + w, ry + h, rx + w - r, ry + h);\n\t\t\tthis.context.lineTo(rx + r, ry + h);\n\t\t\tthis.context.quadraticCurveTo(rx, ry + h, rx, ry + h - r);\n\t\t\tthis.context.lineTo(rx, ry + r);\n\t\t\tthis.context.quadraticCurveTo(rx, ry, rx + r, ry);\n\t\t\tthis.context.closePath();\n\t\t}\n\t\tthis.context.fill();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tfillRound(x: number, y: number, w: number, h: number, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tw = Math.abs(w);\n\t\th = Math.abs(h);\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.ellipse((-this.anchor_x * w) / 2, (this.anchor_y * h) / 2, w / 2, h / 2, 0, 0, Math.PI * 2, false);\n\t\t\tthis.context.fill();\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.ellipse(\n\t\t\t\tx - (this.anchor_x * w) / 2,\n\t\t\t\t-y + (this.anchor_y * h) / 2,\n\t\t\t\tw / 2,\n\t\t\t\th / 2,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tMath.PI * 2,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t\tthis.context.fill();\n\t\t}\n\t}\n\n\tdrawRect(x: number, y: number, w: number, h: number, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.strokeRect(-w / 2 - (this.anchor_x * w) / 2, -h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.strokeRect(x - w / 2 - (this.anchor_x * w) / 2, -y - h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t}\n\t}\n\n\tdrawRoundRect(x: number, y: number, w: number, h: number, round: number = 10, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\t\tconst transform = this.initDrawOp(x, -y);\n\t\tconst rx = (transform ? -w / 2 : x - w / 2) - (this.anchor_x * w) / 2;\n\t\tconst ry = (transform ? -h / 2 : -y - h / 2) + (this.anchor_y * h) / 2;\n\n\t\tthis.context.beginPath();\n\t\tif (this.context.roundRect) {\n\t\t\tthis.context.roundRect(rx, ry, w, h, round);\n\t\t} else {\n\t\t\tconst r = Math.min(round, w / 2, h / 2);\n\t\t\tthis.context.moveTo(rx + r, ry);\n\t\t\tthis.context.lineTo(rx + w - r, ry);\n\t\t\tthis.context.quadraticCurveTo(rx + w, ry, rx + w, ry + r);\n\t\t\tthis.context.lineTo(rx + w, ry + h - r);\n\t\t\tthis.context.quadraticCurveTo(rx + w, ry + h, rx + w - r, ry + h);\n\t\t\tthis.context.lineTo(rx + r, ry + h);\n\t\t\tthis.context.quadraticCurveTo(rx, ry + h, rx, ry + h - r);\n\t\t\tthis.context.lineTo(rx, ry + r);\n\t\t\tthis.context.quadraticCurveTo(rx, ry, rx + r, ry);\n\t\t\tthis.context.closePath();\n\t\t}\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawRound(x: number, y: number, w: number, h: number, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\t\tw = Math.abs(w);\n\t\th = Math.abs(h);\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.ellipse((-this.anchor_x * w) / 2, (this.anchor_y * h) / 2, w / 2, h / 2, 0, 0, Math.PI * 2, false);\n\t\t\tthis.context.stroke();\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.ellipse(\n\t\t\t\tx - (this.anchor_x * w) / 2,\n\t\t\t\t-y + (this.anchor_y * h) / 2,\n\t\t\t\tw / 2,\n\t\t\t\th / 2,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tMath.PI * 2,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t\tthis.context.stroke();\n\t\t}\n\t}\n\n\tdrawLine(x1: number, y1: number, x2: number, y2: number, color?: string | number): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(x1, -y1);\n\t\tthis.context.lineTo(x2, -y2);\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawPolygon(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tconst len = Math.floor(points.length / 2);\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tfor (let i = 1; i < len; i++) {\n\t\t\tthis.context.lineTo(points[i * 2], -points[i * 2 + 1]);\n\t\t}\n\t\tthis.context.closePath();\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawPolyline(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tconst len = Math.floor(points.length / 2);\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tfor (let i = 1; i < len; i++) {\n\t\t\tthis.context.lineTo(points[i * 2], -points[i * 2 + 1]);\n\t\t}\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tfillPolygon(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\n\t\tconst len = Math.floor(points.length / 2);\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tfor (let i = 1; i < len; i++) {\n\t\t\tthis.context.lineTo(points[i * 2], -points[i * 2 + 1]);\n\t\t}\n\t\tthis.context.fill();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawQuadCurve(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tlet index = 2;\n\t\twhile (index <= points.length - 4) {\n\t\t\tthis.context.quadraticCurveTo(points[index], -points[index + 1], points[index + 2], -points[index + 3]);\n\t\t\tindex += 4;\n\t\t}\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawBezierCurve(args: any[]): void {\n\t\tconst { color, points } = this.extractPoints(args);\n\t\tif (!points || points.length < 4) return;\n\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tconst transform = this.initDrawOp(0, 0, false);\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(points[0], -points[1]);\n\t\tlet index = 2;\n\t\twhile (index <= points.length - 6) {\n\t\t\tthis.context.bezierCurveTo(\n\t\t\t\tpoints[index],\n\t\t\t\t-points[index + 1],\n\t\t\t\tpoints[index + 2],\n\t\t\t\t-points[index + 3],\n\t\t\t\tpoints[index + 4],\n\t\t\t\t-points[index + 5],\n\t\t\t);\n\t\t\tindex += 6;\n\t\t}\n\t\tthis.context.stroke();\n\t\tif (transform) this.closeDrawOp();\n\t}\n\n\tdrawArc(\n\t\tx: number,\n\t\ty: number,\n\t\tradius: number,\n\t\tangle1: number,\n\t\tangle2: number,\n\t\tccw: boolean,\n\t\tcolor?: string | number,\n\t): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.context.lineWidth = this.line_width;\n\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.arc(0, 0, radius, (-angle1 / 180) * Math.PI, (-angle2 / 180) * Math.PI, ccw);\n\t\t\tthis.context.stroke();\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.arc(x, -y, radius, (-angle1 / 180) * Math.PI, (-angle2 / 180) * Math.PI, ccw);\n\t\t\tthis.context.stroke();\n\t\t}\n\t}\n\n\tfillArc(\n\t\tx: number,\n\t\ty: number,\n\t\tradius: number,\n\t\tangle1: number,\n\t\tangle2: number,\n\t\tccw: boolean,\n\t\tcolor?: string | number,\n\t): void {\n\t\tif (color) this.setColor(color);\n\t\tthis.context.globalAlpha = this.alpha;\n\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.arc(0, 0, radius, (-angle1 / 180) * Math.PI, (-angle2 / 180) * Math.PI, ccw);\n\t\t\tthis.context.fill();\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.arc(x, -y, radius, (-angle1 / 180) * Math.PI, (-angle2 / 180) * Math.PI, ccw);\n\t\t\tthis.context.fill();\n\t\t}\n\t}\n\n\tprivate extractPoints(args: any[]): {\n\t\tcolor?: string | number;\n\t\tpoints?: number[];\n\t} {\n\t\tlet color: string | number | undefined;\n\t\tlet points: number[] | undefined;\n\n\t\tif (args.length > 0 && args.length % 2 === 1 && typeof args[args.length - 1] === \"string\") {\n\t\t\tcolor = args[args.length - 1];\n\t\t\tpoints = args.slice(0, -1);\n\t\t} else if (Array.isArray(args[0])) {\n\t\t\tif (args[1] && typeof args[1] === \"string\") {\n\t\t\t\tcolor = args[1];\n\t\t\t}\n\t\t\tpoints = args[0];\n\t\t} else {\n\t\t\tpoints = args as number[];\n\t\t}\n\n\t\treturn {\n\t\t\tcolor,\n\t\t\tpoints,\n\t\t};\n\t}\n}\n","/**\n * Sprite rendering for Screen class\n */\n\nimport type { TileMap as Map } from \"@al8b/map\";\nimport type { Sprite } from \"@al8b/sprites\";\n\nimport { PrimitiveScreen } from \"./primitives-screen\";\n\nexport class SpriteScreen extends PrimitiveScreen {\n\t// Cache imageSmoothingEnabled — only set when pixelated flag changes\n\tprivate _lastImageSmoothing = true;\n\n\t// Cache frame time once per draw frame instead of per-sprite\n\tprotected _frameTime = 0;\n\n\t/**\n\t * Initialize draw state (called before each draw frame)\n\t */\n\toverride initDraw(): void {\n\t\tsuper.initDraw();\n\t\tthis._frameTime = performance.now();\n\t}\n\n\t/**\n\t * Set imageSmoothingEnabled only when it actually changes\n\t */\n\tprotected setImageSmoothing(): void {\n\t\tconst smooth = !this.pixelated;\n\t\tif (smooth !== this._lastImageSmoothing) {\n\t\t\tthis.context.imageSmoothingEnabled = smooth;\n\t\t\tthis._lastImageSmoothing = smooth;\n\t\t}\n\t}\n\n\t/**\n\t * Get the canvas for the current sprite frame\n\t */\n\tprotected getSpriteFrame(sprite: Sprite | string | any): HTMLCanvasElement | null {\n\t\tlet frame: number | null = null;\n\n\t\t// Handle string sprite name\n\t\tif (typeof sprite === \"string\") {\n\t\t\tconst spriteName = sprite;\n\t\t\tlet spriteObj: Sprite | null = null;\n\n\t\t\tif (this.runtime && this.runtime.sprites) {\n\t\t\t\tspriteObj = this.runtime.sprites[sprite];\n\t\t\t}\n\n\t\t\t// Handle \"sprite.frame\" format (e.g., \"player.0\")\n\t\t\tif (!spriteObj) {\n\t\t\t\tconst parts = sprite.split(\".\");\n\t\t\t\tif (parts.length > 1 && this.runtime && this.runtime.sprites) {\n\t\t\t\t\tspriteObj = this.runtime.sprites[parts[0]];\n\t\t\t\t\tframe = Number.parseInt(parts[1]) || 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Report sprite not found error\n\t\t\tif (!spriteObj) {\n\t\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7004\", message: \"Sprite not found\", data: { spriteName } });\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tsprite = spriteObj;\n\t\t}\n\t\t// Handle Image instances - check for objects with canvas but no frames\n\t\telse if (sprite && typeof sprite === \"object\" && (sprite as any).canvas && !(sprite as any).frames) {\n\t\t\treturn (sprite as any).canvas || (sprite as any).image || null;\n\t\t}\n\n\t\t// Validate sprite object\n\t\tif (!sprite || !(sprite as Sprite).ready) {\n\t\t\tconst spriteName = typeof sprite === \"string\" ? sprite : \"unknown\";\n\t\t\tthis.runtime?.listener?.reportError?.({ code: \"E7005\", message: \"Sprite not ready\", data: { spriteName } });\n\t\t\treturn null;\n\t\t}\n\n\t\tconst spriteObj = sprite as Sprite;\n\n\t\t// Handle multi-frame sprites — use cached _frameTime instead of Date.now() per call\n\t\tif (spriteObj.frames && spriteObj.frames.length > 1) {\n\t\t\tif (frame === null) {\n\t\t\t\tif (spriteObj.animation_start === 0) {\n\t\t\t\t\tspriteObj.animation_start = this._frameTime;\n\t\t\t\t}\n\t\t\t\tconst dt = 1000 / spriteObj.fps;\n\t\t\t\tframe = Math.floor((this._frameTime - spriteObj.animation_start) / dt) % spriteObj.frames.length;\n\t\t\t}\n\t\t\tif (frame >= 0 && frame < spriteObj.frames.length) {\n\t\t\t\treturn spriteObj.frames[frame].canvas;\n\t\t\t}\n\t\t\treturn spriteObj.frames[0].canvas;\n\t\t}\n\t\t// Handle single-frame sprites\n\t\telse if (spriteObj.frames && spriteObj.frames[0]) {\n\t\t\treturn spriteObj.frames[0].canvas;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Draw a sprite\n\t */\n\tdrawSprite(sprite: Sprite | string | any, x: number, y: number, w?: number, h?: number): void {\n\t\tconst canvas = this.getSpriteFrame(sprite);\n\t\tif (!canvas) return;\n\n\t\tif (w == null) {\n\t\t\tw = canvas.width;\n\t\t}\n\n\t\tif (!h) {\n\t\t\th = (w / canvas.width) * canvas.height;\n\t\t}\n\n\t\t// Viewport culling: skip sprites entirely outside visible area\n\t\t// Only when no screen/object transforms are active (simple AABB check)\n\t\tif (\n\t\t\t!this.screen_transform &&\n\t\t\tthis.object_rotation === 0 &&\n\t\t\tthis.object_scale_x === 1 &&\n\t\t\tthis.object_scale_y === 1\n\t\t) {\n\t\t\tconst drawX = x - w / 2 - (this.anchor_x * w) / 2;\n\t\t\tconst drawY = -y - h / 2 + (this.anchor_y * h) / 2;\n\t\t\tconst halfW = this.width / 2;\n\t\t\tconst halfH = this.height / 2;\n\t\t\tif (drawX > halfW || drawX + w < -halfW || drawY > halfH || drawY + h < -halfH) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.setImageSmoothing();\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.drawImage(canvas, -w / 2 - (this.anchor_x * w) / 2, -h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.drawImage(canvas, x - w / 2 - (this.anchor_x * w) / 2, -y - h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t}\n\t}\n\n\t/**\n\t * Draw a portion of a sprite\n\t */\n\tdrawSpritePart(\n\t\tsprite: Sprite | string | any,\n\t\tsx: number,\n\t\tsy: number,\n\t\tsw: number,\n\t\tsh: number,\n\t\tx: number,\n\t\ty: number,\n\t\tw?: number,\n\t\th?: number,\n\t): void {\n\t\tconst canvas = this.getSpriteFrame(sprite);\n\t\tif (!canvas) return;\n\n\t\tif (w == null) {\n\t\t\tw = sw;\n\t\t}\n\n\t\tif (!h) {\n\t\t\th = (w / sw) * sh;\n\t\t}\n\n\t\t// Viewport culling: skip sprites entirely outside visible area\n\t\tif (\n\t\t\t!this.screen_transform &&\n\t\t\tthis.object_rotation === 0 &&\n\t\t\tthis.object_scale_x === 1 &&\n\t\t\tthis.object_scale_y === 1\n\t\t) {\n\t\t\tconst drawX = x - w / 2 - (this.anchor_x * w) / 2;\n\t\t\tconst drawY = -y - h / 2 + (this.anchor_y * h) / 2;\n\t\t\tconst halfW = this.width / 2;\n\t\t\tconst halfH = this.height / 2;\n\t\t\tif (drawX > halfW || drawX + w < -halfW || drawY > halfH || drawY + h < -halfH) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.setImageSmoothing();\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tthis.context.drawImage(\n\t\t\t\tcanvas,\n\t\t\t\tsx,\n\t\t\t\tsy,\n\t\t\t\tsw,\n\t\t\t\tsh,\n\t\t\t\t-w / 2 - (this.anchor_x * w) / 2,\n\t\t\t\t-h / 2 + (this.anchor_y * h) / 2,\n\t\t\t\tw,\n\t\t\t\th,\n\t\t\t);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tthis.context.drawImage(\n\t\t\t\tcanvas,\n\t\t\t\tsx,\n\t\t\t\tsy,\n\t\t\t\tsw,\n\t\t\t\tsh,\n\t\t\t\tx - w / 2 - (this.anchor_x * w) / 2,\n\t\t\t\t-y - h / 2 + (this.anchor_y * h) / 2,\n\t\t\t\tw,\n\t\t\t\th,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Draw a map\n\t */\n\tdrawMap(map: Map | string, x: number, y: number, w: number, h: number): void {\n\t\tlet mapObj: Map | null = null;\n\n\t\tif (typeof map === \"string\") {\n\t\t\tif (this.runtime && this.runtime.maps) {\n\t\t\t\tmapObj = this.runtime.maps[map];\n\t\t\t}\n\t\t} else {\n\t\t\tmapObj = map;\n\t\t}\n\n\t\tif (!(mapObj && mapObj.ready)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.context.globalAlpha = this.alpha;\n\t\tthis.setImageSmoothing();\n\t\tif (this.initDrawOp(x, -y)) {\n\t\t\tmapObj.draw(this.context, -w / 2 - (this.anchor_x * w) / 2, -h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t\tthis.closeDrawOp();\n\t\t} else {\n\t\t\tmapObj.draw(this.context, x - w / 2 - (this.anchor_x * w) / 2, -y - h / 2 + (this.anchor_y * h) / 2, w, h);\n\t\t}\n\t}\n}\n"],"mappings":"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","names":["ZBuffer","buffer","width","height","Float32Array","clear","fill","get","x","y","set","z","resize","BaseScreen","canvas","context","runtime","width","height","alpha","pixelated","line_width","font","translation_x","translation_y","rotation","scale_x","scale_y","screen_transform","object_rotation","object_scale_x","object_scale_y","anchor_x","anchor_y","blending","font_load_requested","font_loaded","interfaceCache","cursor","cursor_visibility","last_mouse_move","Date","now","zBuffer","options","document","createElement","initContext","normal","additive","blendModes","mode","loadFont","ZBuffer","addEventListener","style","setInterval","checkMouseCursor","ctx","getContext","message","listener","reportError","code","data","Error","restore","save","translate","ratio","Math","min","scale","lineCap","initDraw","updateInterface","clear","color","globalAlpha","globalCompositeOperation","fillStyle","strokeStyle","fillRect","setColor","Number","isNaN","parseInt","String","num","r","floor","g","b","c","hex","toString","substring","isValidColor","test","setAlpha","setPixelated","setBlending","blend","blendMode","setLineWidth","setLineDash","dash","Array","isArray","setLinearGradient","x1","y1","x2","y2","c1","c2","grd","createLinearGradient","addColorStop","setRadialGradient","x","y","radius","createRadialGradient","setFont","fonts","load","catch","isFontReady","ready","check","setTranslation","tx","ty","isFinite","updateScreenTransform","setScale","setRotation","setDrawAnchor","ax","ay","setDrawRotation","setDrawScale","initDrawOp","object_transform","res","rotate","PI","closeDrawOp","setCursorVisible","visible","getCanvas","resize","PrimitiveScreen","BaseScreen","fillRect","x","y","w","h","color","context","runtime","listener","reportError","code","message","data","isFinite","error","setColor","globalAlpha","alpha","initDrawOp","anchor_x","anchor_y","closeDrawOp","fillRoundRect","round","transform","rx","ry","beginPath","roundRect","r","Math","min","moveTo","lineTo","quadraticCurveTo","closePath","fill","fillRound","abs","ellipse","PI","drawRect","lineWidth","line_width","strokeRect","drawRoundRect","stroke","drawRound","drawLine","x1","y1","x2","y2","drawPolygon","args","points","extractPoints","length","len","floor","i","drawPolyline","fillPolygon","drawQuadCurve","index","drawBezierCurve","bezierCurveTo","drawArc","radius","angle1","angle2","ccw","arc","fillArc","slice","Array","isArray","SpriteScreen","PrimitiveScreen","_lastImageSmoothing","_frameTime","initDraw","performance","now","setImageSmoothing","smooth","pixelated","context","imageSmoothingEnabled","getSpriteFrame","sprite","frame","spriteName","spriteObj","runtime","sprites","parts","split","length","Number","parseInt","listener","reportError","code","message","data","canvas","frames","image","ready","animation_start","dt","fps","Math","floor","drawSprite","x","y","w","h","width","height","screen_transform","object_rotation","object_scale_x","object_scale_y","drawX","anchor_x","drawY","anchor_y","halfW","halfH","globalAlpha","alpha","initDrawOp","drawImage","closeDrawOp","drawSpritePart","sx","sy","sw","sh","drawMap","map","mapObj","maps","draw"]}
|
|
@@ -25,15 +25,6 @@ __export(text_screen_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(text_screen_exports);
|
|
27
27
|
|
|
28
|
-
// src/drawing/sprite-screen.ts
|
|
29
|
-
var import_diagnostics3 = require("@al8b/diagnostics");
|
|
30
|
-
|
|
31
|
-
// src/drawing/primitives-screen.ts
|
|
32
|
-
var import_diagnostics2 = require("@al8b/diagnostics");
|
|
33
|
-
|
|
34
|
-
// src/core/base-screen.ts
|
|
35
|
-
var import_diagnostics = require("@al8b/diagnostics");
|
|
36
|
-
|
|
37
28
|
// src/tri/ttri.ts
|
|
38
29
|
var ZBuffer = class {
|
|
39
30
|
static {
|
|
@@ -175,10 +166,13 @@ var BaseScreen = class {
|
|
|
175
166
|
alpha: false
|
|
176
167
|
});
|
|
177
168
|
if (!ctx) {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
169
|
+
const message = "Failed to get 2D rendering context";
|
|
170
|
+
this.runtime?.listener?.reportError?.({
|
|
171
|
+
code: "E7001",
|
|
172
|
+
message,
|
|
173
|
+
data: {}
|
|
174
|
+
});
|
|
175
|
+
throw new Error(message);
|
|
182
176
|
}
|
|
183
177
|
if (ctx !== this.context) {
|
|
184
178
|
this.context = ctx;
|
|
@@ -231,8 +225,12 @@ var BaseScreen = class {
|
|
|
231
225
|
} else if (typeof color === "string") {
|
|
232
226
|
const isValidColor = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(color) || /^rgb\(|^rgba\(|^hsl\(|^hsla\(/.test(color) || /^(red|green|blue|yellow|cyan|magenta|black|white|gray|grey|orange|pink|purple|brown|transparent)$/i.test(color);
|
|
233
227
|
if (!isValidColor) {
|
|
234
|
-
|
|
235
|
-
|
|
228
|
+
this.runtime?.listener?.reportError?.({
|
|
229
|
+
code: "E7003",
|
|
230
|
+
message: "Invalid color",
|
|
231
|
+
data: {
|
|
232
|
+
color
|
|
233
|
+
}
|
|
236
234
|
});
|
|
237
235
|
return;
|
|
238
236
|
}
|
|
@@ -249,8 +247,12 @@ var BaseScreen = class {
|
|
|
249
247
|
setBlending(blending) {
|
|
250
248
|
const blend = this.blending[blending || "normal"];
|
|
251
249
|
if (!blend) {
|
|
252
|
-
|
|
253
|
-
|
|
250
|
+
this.runtime?.listener?.reportError?.({
|
|
251
|
+
code: "E7007",
|
|
252
|
+
message: "Invalid blend mode",
|
|
253
|
+
data: {
|
|
254
|
+
blendMode: blending
|
|
255
|
+
}
|
|
254
256
|
});
|
|
255
257
|
this.context.globalCompositeOperation = "source-over";
|
|
256
258
|
return;
|
|
@@ -292,13 +294,21 @@ var BaseScreen = class {
|
|
|
292
294
|
this.font_load_requested[font] = true;
|
|
293
295
|
try {
|
|
294
296
|
document.fonts?.load?.(`16pt ${font}`).catch(() => {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
+
this.runtime?.listener?.reportError?.({
|
|
298
|
+
code: "E7006",
|
|
299
|
+
message: "Font loading failed",
|
|
300
|
+
data: {
|
|
301
|
+
font
|
|
302
|
+
}
|
|
297
303
|
});
|
|
298
304
|
});
|
|
299
305
|
} catch {
|
|
300
|
-
|
|
301
|
-
|
|
306
|
+
this.runtime?.listener?.reportError?.({
|
|
307
|
+
code: "E7006",
|
|
308
|
+
message: "Font loading failed",
|
|
309
|
+
data: {
|
|
310
|
+
font
|
|
311
|
+
}
|
|
302
312
|
});
|
|
303
313
|
}
|
|
304
314
|
}
|
|
@@ -406,9 +416,13 @@ var BaseScreen = class {
|
|
|
406
416
|
resize(width, height) {
|
|
407
417
|
if (width && height) {
|
|
408
418
|
if (width <= 0 || height <= 0 || !isFinite(width) || !isFinite(height)) {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
419
|
+
this.runtime?.listener?.reportError?.({
|
|
420
|
+
code: "E7002",
|
|
421
|
+
message: "Invalid resize dimensions",
|
|
422
|
+
data: {
|
|
423
|
+
width,
|
|
424
|
+
height
|
|
425
|
+
}
|
|
412
426
|
});
|
|
413
427
|
return;
|
|
414
428
|
}
|
|
@@ -428,12 +442,20 @@ var PrimitiveScreen = class extends BaseScreen {
|
|
|
428
442
|
}
|
|
429
443
|
fillRect(x, y, w, h, color) {
|
|
430
444
|
if (!this.context) {
|
|
431
|
-
|
|
445
|
+
this.runtime?.listener?.reportError?.({
|
|
446
|
+
code: "E7092",
|
|
447
|
+
message: "Drawing context not available",
|
|
448
|
+
data: {}
|
|
449
|
+
});
|
|
432
450
|
return;
|
|
433
451
|
}
|
|
434
452
|
if (!isFinite(x) || !isFinite(y) || !isFinite(w) || !isFinite(h) || w <= 0 || h <= 0) {
|
|
435
|
-
|
|
436
|
-
|
|
453
|
+
this.runtime?.listener?.reportError?.({
|
|
454
|
+
code: "E7093",
|
|
455
|
+
message: "Invalid draw parameters",
|
|
456
|
+
data: {
|
|
457
|
+
error: `Invalid parameters: x=${x}, y=${y}, w=${w}, h=${h}`
|
|
458
|
+
}
|
|
437
459
|
});
|
|
438
460
|
return;
|
|
439
461
|
}
|
|
@@ -729,8 +751,12 @@ var SpriteScreen = class extends PrimitiveScreen {
|
|
|
729
751
|
}
|
|
730
752
|
}
|
|
731
753
|
if (!spriteObj2) {
|
|
732
|
-
|
|
733
|
-
|
|
754
|
+
this.runtime?.listener?.reportError?.({
|
|
755
|
+
code: "E7004",
|
|
756
|
+
message: "Sprite not found",
|
|
757
|
+
data: {
|
|
758
|
+
spriteName
|
|
759
|
+
}
|
|
734
760
|
});
|
|
735
761
|
return null;
|
|
736
762
|
}
|
|
@@ -740,8 +766,12 @@ var SpriteScreen = class extends PrimitiveScreen {
|
|
|
740
766
|
}
|
|
741
767
|
if (!sprite || !sprite.ready) {
|
|
742
768
|
const spriteName = typeof sprite === "string" ? sprite : "unknown";
|
|
743
|
-
|
|
744
|
-
|
|
769
|
+
this.runtime?.listener?.reportError?.({
|
|
770
|
+
code: "E7005",
|
|
771
|
+
message: "Sprite not ready",
|
|
772
|
+
data: {
|
|
773
|
+
spriteName
|
|
774
|
+
}
|
|
745
775
|
});
|
|
746
776
|
return null;
|
|
747
777
|
}
|