@al8b/screen 0.1.0

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.
Files changed (68) hide show
  1. package/README.md +23 -0
  2. package/dist/core/base-screen.d.mts +84 -0
  3. package/dist/core/base-screen.d.ts +84 -0
  4. package/dist/core/base-screen.js +419 -0
  5. package/dist/core/base-screen.js.map +1 -0
  6. package/dist/core/base-screen.mjs +396 -0
  7. package/dist/core/base-screen.mjs.map +1 -0
  8. package/dist/core/index.d.mts +10 -0
  9. package/dist/core/index.d.ts +10 -0
  10. package/dist/core/index.js +1208 -0
  11. package/dist/core/index.js.map +1 -0
  12. package/dist/core/index.mjs +1183 -0
  13. package/dist/core/index.mjs.map +1 -0
  14. package/dist/core/screen.d.mts +15 -0
  15. package/dist/core/screen.d.ts +15 -0
  16. package/dist/core/screen.js +1209 -0
  17. package/dist/core/screen.js.map +1 -0
  18. package/dist/core/screen.mjs +1184 -0
  19. package/dist/core/screen.mjs.map +1 -0
  20. package/dist/drawing/primitives-screen.d.mts +28 -0
  21. package/dist/drawing/primitives-screen.d.ts +28 -0
  22. package/dist/drawing/primitives-screen.js +685 -0
  23. package/dist/drawing/primitives-screen.js.map +1 -0
  24. package/dist/drawing/primitives-screen.mjs +662 -0
  25. package/dist/drawing/primitives-screen.mjs.map +1 -0
  26. package/dist/drawing/sprite-screen.d.mts +41 -0
  27. package/dist/drawing/sprite-screen.d.ts +41 -0
  28. package/dist/drawing/sprite-screen.js +853 -0
  29. package/dist/drawing/sprite-screen.js.map +1 -0
  30. package/dist/drawing/sprite-screen.mjs +830 -0
  31. package/dist/drawing/sprite-screen.mjs.map +1 -0
  32. package/dist/drawing/text-screen.d.mts +19 -0
  33. package/dist/drawing/text-screen.d.ts +19 -0
  34. package/dist/drawing/text-screen.js +909 -0
  35. package/dist/drawing/text-screen.js.map +1 -0
  36. package/dist/drawing/text-screen.mjs +884 -0
  37. package/dist/drawing/text-screen.mjs.map +1 -0
  38. package/dist/index.d.mts +10 -0
  39. package/dist/index.d.ts +10 -0
  40. package/dist/index.js +1210 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/index.mjs +1184 -0
  43. package/dist/index.mjs.map +1 -0
  44. package/dist/tri/index.d.mts +3 -0
  45. package/dist/tri/index.d.ts +3 -0
  46. package/dist/tri/index.js +231 -0
  47. package/dist/tri/index.js.map +1 -0
  48. package/dist/tri/index.mjs +203 -0
  49. package/dist/tri/index.mjs.map +1 -0
  50. package/dist/tri/triangle-screen.d.mts +16 -0
  51. package/dist/tri/triangle-screen.d.ts +16 -0
  52. package/dist/tri/triangle-screen.js +1147 -0
  53. package/dist/tri/triangle-screen.js.map +1 -0
  54. package/dist/tri/triangle-screen.mjs +1122 -0
  55. package/dist/tri/triangle-screen.mjs.map +1 -0
  56. package/dist/tri/ttri.d.mts +71 -0
  57. package/dist/tri/ttri.d.ts +71 -0
  58. package/dist/tri/ttri.js +229 -0
  59. package/dist/tri/ttri.js.map +1 -0
  60. package/dist/tri/ttri.mjs +203 -0
  61. package/dist/tri/ttri.mjs.map +1 -0
  62. package/dist/types/index.d.mts +64 -0
  63. package/dist/types/index.d.ts +64 -0
  64. package/dist/types/index.js +19 -0
  65. package/dist/types/index.js.map +1 -0
  66. package/dist/types/index.mjs +1 -0
  67. package/dist/types/index.mjs.map +1 -0
  68. package/package.json +37 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,1184 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/drawing/sprite-screen.ts
5
+ import { APIErrorCode as APIErrorCode3, reportRuntimeError as reportRuntimeError3 } from "@al8b/diagnostics";
6
+
7
+ // src/drawing/primitives-screen.ts
8
+ import { APIErrorCode as APIErrorCode2, reportRuntimeError as reportRuntimeError2 } from "@al8b/diagnostics";
9
+
10
+ // src/core/base-screen.ts
11
+ import { APIErrorCode, createDiagnostic, formatForBrowser, reportRuntimeError } from "@al8b/diagnostics";
12
+
13
+ // src/tri/ttri.ts
14
+ var ZBuffer = class {
15
+ static {
16
+ __name(this, "ZBuffer");
17
+ }
18
+ buffer;
19
+ width;
20
+ height;
21
+ constructor(width, height) {
22
+ this.width = width;
23
+ this.height = height;
24
+ this.buffer = new Float32Array(width * height);
25
+ }
26
+ clear() {
27
+ this.buffer.fill(0);
28
+ }
29
+ get(x, y) {
30
+ return this.buffer[y * this.width + x] || 0;
31
+ }
32
+ set(x, y, z) {
33
+ this.buffer[y * this.width + x] = z;
34
+ }
35
+ resize(width, height) {
36
+ if (this.width !== width || this.height !== height) {
37
+ this.width = width;
38
+ this.height = height;
39
+ this.buffer = new Float32Array(width * height);
40
+ }
41
+ }
42
+ };
43
+ function edgeFn(a, b, c) {
44
+ return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
45
+ }
46
+ __name(edgeFn, "edgeFn");
47
+ function getSpritePixel(sprite, u, v, runtime) {
48
+ let canvas = null;
49
+ if (sprite && typeof sprite === "object" && sprite.canvas) {
50
+ canvas = sprite.canvas;
51
+ } else if (typeof sprite === "string" && runtime?.sprites) {
52
+ const spriteObj = runtime.sprites[sprite];
53
+ if (spriteObj?.frames?.[0]?.canvas) {
54
+ canvas = spriteObj.frames[0].canvas;
55
+ }
56
+ }
57
+ if (!canvas) return null;
58
+ const width = canvas.width;
59
+ const height = canvas.height;
60
+ const x = Math.floor(u) % width;
61
+ const y = Math.floor(v) % height;
62
+ const px = x < 0 ? x + width : x;
63
+ const py = y < 0 ? y + height : y;
64
+ const ctx = canvas.getContext("2d");
65
+ if (!ctx) return null;
66
+ try {
67
+ const imageData = ctx.getImageData(px, py, 1, 1);
68
+ return {
69
+ r: imageData.data[0],
70
+ g: imageData.data[1],
71
+ b: imageData.data[2],
72
+ a: imageData.data[3]
73
+ };
74
+ } catch (e) {
75
+ return null;
76
+ }
77
+ }
78
+ __name(getSpritePixel, "getSpritePixel");
79
+ function getMapPixel(map, u, v, runtime) {
80
+ let mapObj = null;
81
+ if (map && typeof map === "object" && map.getCanvas) {
82
+ mapObj = map;
83
+ } else if (typeof map === "string" && runtime?.maps) {
84
+ mapObj = runtime.maps[map];
85
+ }
86
+ if (!mapObj) return null;
87
+ const canvas = mapObj.getCanvas ? mapObj.getCanvas() : mapObj.canvas;
88
+ if (!canvas) return null;
89
+ const width = canvas.width;
90
+ const height = canvas.height;
91
+ const x = Math.floor(u) % width;
92
+ const y = Math.floor(v) % height;
93
+ const px = x < 0 ? x + width : x;
94
+ const py = y < 0 ? y + height : y;
95
+ const ctx = canvas.getContext("2d");
96
+ if (!ctx) return null;
97
+ try {
98
+ const imageData = ctx.getImageData(px, py, 1, 1);
99
+ return {
100
+ r: imageData.data[0],
101
+ g: imageData.data[1],
102
+ b: imageData.data[2],
103
+ a: imageData.data[3]
104
+ };
105
+ } catch (e) {
106
+ return null;
107
+ }
108
+ }
109
+ __name(getMapPixel, "getMapPixel");
110
+ function drawTexturedTriangle(data, v0, v1, v2, texture, textureSource = "tiles", zBuffer, useDepth = false) {
111
+ const { context, width, height, runtime, pixelated } = data;
112
+ const minX = Math.max(0, Math.floor(Math.min(v0.x, v1.x, v2.x)));
113
+ const minY = Math.max(0, Math.floor(Math.min(v0.y, v1.y, v2.y)));
114
+ const maxX = Math.min(width, Math.ceil(Math.max(v0.x, v1.x, v2.x)));
115
+ const maxY = Math.min(height, Math.ceil(Math.max(v0.y, v1.y, v2.y)));
116
+ if (minX >= maxX || minY >= maxY) return;
117
+ const area = edgeFn(v0, v1, v2);
118
+ if (Math.abs(area) < 1e-3) return;
119
+ if (area < 0) return;
120
+ const useZ = useDepth && v0.z > 0 && v1.z > 0 && v2.z > 0;
121
+ let w0 = 1, w1 = 1, w2 = 1;
122
+ let u0 = v0.u, u1 = v1.u, u2 = v2.u;
123
+ let v0v = v0.v, v1v = v1.v, v2v = v2.v;
124
+ if (useZ) {
125
+ w0 = 1 / v0.z;
126
+ w1 = 1 / v1.z;
127
+ w2 = 1 / v2.z;
128
+ u0 *= w0;
129
+ u1 *= w1;
130
+ u2 *= w2;
131
+ v0v *= w0;
132
+ v1v *= w1;
133
+ v2v *= w2;
134
+ }
135
+ const imageData = context.getImageData(minX, minY, maxX - minX, maxY - minY);
136
+ const pixels = imageData.data;
137
+ for (let y = minY; y < maxY; y++) {
138
+ for (let x = minX; x < maxX; x++) {
139
+ const p = {
140
+ x: x + 0.5,
141
+ y: y + 0.5
142
+ };
143
+ const w0b = edgeFn(v1, v2, p);
144
+ const w1b = edgeFn(v2, v0, p);
145
+ const w2b = edgeFn(v0, v1, p);
146
+ if (w0b >= 0 && w1b >= 0 && w2b >= 0) {
147
+ const bary0 = w0b / area;
148
+ const bary1 = w1b / area;
149
+ const bary2 = w2b / area;
150
+ if (useZ && zBuffer) {
151
+ const z = bary0 * v0.z + bary1 * v1.z + bary2 * v2.z;
152
+ const currentZ = zBuffer.get(x, y);
153
+ if (currentZ > 0 && currentZ >= z) continue;
154
+ zBuffer.set(x, y, z);
155
+ }
156
+ let u, v;
157
+ if (useZ) {
158
+ const w = bary0 * w0 + bary1 * w1 + bary2 * w2;
159
+ u = (bary0 * u0 + bary1 * u1 + bary2 * u2) / w;
160
+ v = (bary0 * v0v + bary1 * v1v + bary2 * v2v) / w;
161
+ } else {
162
+ u = bary0 * v0.u + bary1 * v1.u + bary2 * v2.u;
163
+ v = bary0 * v0.v + bary1 * v1.v + bary2 * v2.v;
164
+ }
165
+ let pixel = null;
166
+ if (textureSource === "map") {
167
+ pixel = getMapPixel(texture, u, v, runtime);
168
+ } else {
169
+ pixel = getSpritePixel(texture, u, v, runtime);
170
+ }
171
+ if (pixel && pixel.a > 0) {
172
+ const idx = ((y - minY) * (maxX - minX) + (x - minX)) * 4;
173
+ pixels[idx] = pixel.r;
174
+ pixels[idx + 1] = pixel.g;
175
+ pixels[idx + 2] = pixel.b;
176
+ pixels[idx + 3] = pixel.a;
177
+ }
178
+ }
179
+ }
180
+ }
181
+ context.imageSmoothingEnabled = !pixelated;
182
+ context.putImageData(imageData, minX, minY);
183
+ }
184
+ __name(drawTexturedTriangle, "drawTexturedTriangle");
185
+ function drawTriangle(context, v0, v1, v2, color) {
186
+ context.fillStyle = color;
187
+ context.beginPath();
188
+ context.moveTo(v0.x, v0.y);
189
+ context.lineTo(v1.x, v1.y);
190
+ context.lineTo(v2.x, v2.y);
191
+ context.closePath();
192
+ context.fill();
193
+ }
194
+ __name(drawTriangle, "drawTriangle");
195
+ function drawTriangleOutline(context, v0, v1, v2, color, lineWidth = 1) {
196
+ context.strokeStyle = color;
197
+ context.lineWidth = lineWidth;
198
+ context.beginPath();
199
+ context.moveTo(v0.x, v0.y);
200
+ context.lineTo(v1.x, v1.y);
201
+ context.lineTo(v2.x, v2.y);
202
+ context.closePath();
203
+ context.stroke();
204
+ }
205
+ __name(drawTriangleOutline, "drawTriangleOutline");
206
+
207
+ // src/core/base-screen.ts
208
+ var BaseScreen = class {
209
+ static {
210
+ __name(this, "BaseScreen");
211
+ }
212
+ canvas;
213
+ context;
214
+ runtime;
215
+ width;
216
+ height;
217
+ // Drawing state
218
+ alpha = 1;
219
+ pixelated = 1;
220
+ line_width = 1;
221
+ font = "BitCell";
222
+ // Transformations
223
+ translation_x = 0;
224
+ translation_y = 0;
225
+ rotation = 0;
226
+ scale_x = 1;
227
+ scale_y = 1;
228
+ screen_transform = false;
229
+ // Object transformations
230
+ object_rotation = 0;
231
+ object_scale_x = 1;
232
+ object_scale_y = 1;
233
+ anchor_x = 0;
234
+ anchor_y = 0;
235
+ // Blending + font caches
236
+ blending = {};
237
+ font_load_requested = {};
238
+ font_loaded = {};
239
+ // Interface cache
240
+ interfaceCache = null;
241
+ // Cursor management
242
+ cursor = "default";
243
+ cursor_visibility = "auto";
244
+ last_mouse_move = Date.now();
245
+ // 3D helper
246
+ zBuffer;
247
+ constructor(options = {}) {
248
+ this.runtime = options.runtime;
249
+ if (options.canvas) {
250
+ this.canvas = options.canvas;
251
+ if (this.canvas.width === 0 || this.canvas.height === 0) {
252
+ this.canvas.width = options.width || 1080;
253
+ this.canvas.height = options.height || 1920;
254
+ }
255
+ } else {
256
+ this.canvas = document.createElement("canvas");
257
+ this.canvas.width = options.width || 1080;
258
+ this.canvas.height = options.height || 1920;
259
+ }
260
+ this.initContext();
261
+ this.blending = {
262
+ normal: "source-over",
263
+ additive: "lighter"
264
+ };
265
+ const blendModes = [
266
+ "source-over",
267
+ "source-in",
268
+ "source-out",
269
+ "source-atop",
270
+ "destination-over",
271
+ "destination-in",
272
+ "destination-out",
273
+ "destination-atop",
274
+ "lighter",
275
+ "copy",
276
+ "xor",
277
+ "multiply",
278
+ "screen",
279
+ "overlay",
280
+ "darken",
281
+ "lighten",
282
+ "color-dodge",
283
+ "color-burn",
284
+ "hard-light",
285
+ "soft-light",
286
+ "difference",
287
+ "exclusion",
288
+ "hue",
289
+ "saturation",
290
+ "color",
291
+ "luminosity"
292
+ ];
293
+ for (const mode of blendModes) {
294
+ this.blending[mode] = mode;
295
+ }
296
+ this.loadFont(this.font);
297
+ this.zBuffer = new ZBuffer(this.canvas.width, this.canvas.height);
298
+ this.cursor = "default";
299
+ this.canvas.addEventListener("mousemove", () => {
300
+ this.last_mouse_move = Date.now();
301
+ if (this.cursor !== "default" && this.cursor_visibility === "auto") {
302
+ this.cursor = "default";
303
+ this.canvas.style.cursor = "default";
304
+ }
305
+ });
306
+ this.canvas.addEventListener("contextrestored", () => {
307
+ this.initContext();
308
+ });
309
+ setInterval(() => this.checkMouseCursor(), 1e3);
310
+ this.cursor_visibility = "auto";
311
+ }
312
+ initContext() {
313
+ const ctx = this.canvas.getContext("2d", {
314
+ alpha: false
315
+ });
316
+ if (!ctx) {
317
+ const diagnostic = createDiagnostic(APIErrorCode.E7001);
318
+ const formatted = formatForBrowser(diagnostic);
319
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7001, {});
320
+ throw new Error(formatted);
321
+ }
322
+ if (ctx !== this.context) {
323
+ this.context = ctx;
324
+ } else {
325
+ this.context.restore();
326
+ }
327
+ this.context.save();
328
+ this.context.translate(this.canvas.width / 2, this.canvas.height / 2);
329
+ const ratio = Math.min(this.canvas.width / 200, this.canvas.height / 200);
330
+ this.context.scale(ratio, ratio);
331
+ this.width = this.canvas.width / ratio;
332
+ this.height = this.canvas.height / ratio;
333
+ this.context.lineCap = "round";
334
+ }
335
+ /**
336
+ * Initialize draw state (called before each draw frame)
337
+ */
338
+ initDraw() {
339
+ this.alpha = 1;
340
+ this.line_width = 1;
341
+ }
342
+ /**
343
+ * Update interface dimensions (called before each draw frame)
344
+ */
345
+ updateInterface() {
346
+ if (this.interfaceCache) {
347
+ this.interfaceCache.width = this.width;
348
+ this.interfaceCache.height = this.height;
349
+ }
350
+ }
351
+ clear(color) {
352
+ this.context.globalAlpha = 1;
353
+ this.context.globalCompositeOperation = "source-over";
354
+ this.context.fillStyle = color || "#000";
355
+ this.context.strokeStyle = color || "#000";
356
+ this.context.fillRect(-this.width / 2, -this.height / 2, this.width, this.height);
357
+ this.zBuffer.clear();
358
+ }
359
+ setColor(color) {
360
+ if (!color) return;
361
+ if (!Number.isNaN(Number.parseInt(String(color)))) {
362
+ const num = Number.parseInt(String(color));
363
+ const r = Math.floor(num / 100) % 10 / 9 * 255;
364
+ const g = Math.floor(num / 10) % 10 / 9 * 255;
365
+ const b = num % 10 / 9 * 255;
366
+ const c = 4278190080 + (r << 16) + (g << 8) + b;
367
+ const hex = "#" + c.toString(16).substring(2, 8);
368
+ this.context.fillStyle = hex;
369
+ this.context.strokeStyle = hex;
370
+ } else if (typeof color === "string") {
371
+ 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);
372
+ if (!isValidColor) {
373
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7003, {
374
+ color
375
+ });
376
+ return;
377
+ }
378
+ this.context.fillStyle = color;
379
+ this.context.strokeStyle = color;
380
+ }
381
+ }
382
+ setAlpha(alpha) {
383
+ this.alpha = alpha;
384
+ }
385
+ setPixelated(pixelated) {
386
+ this.pixelated = pixelated;
387
+ }
388
+ setBlending(blending) {
389
+ const blend = this.blending[blending || "normal"];
390
+ if (!blend) {
391
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7007, {
392
+ blendMode: blending
393
+ });
394
+ this.context.globalCompositeOperation = "source-over";
395
+ return;
396
+ }
397
+ this.context.globalCompositeOperation = blend;
398
+ }
399
+ setLineWidth(width) {
400
+ this.line_width = width;
401
+ }
402
+ setLineDash(dash) {
403
+ if (!Array.isArray(dash)) {
404
+ this.context.setLineDash([]);
405
+ } else {
406
+ this.context.setLineDash(dash);
407
+ }
408
+ }
409
+ setLinearGradient(x1, y1, x2, y2, c1, c2) {
410
+ const grd = this.context.createLinearGradient(x1, -y1, x2, -y2);
411
+ grd.addColorStop(0, c1);
412
+ grd.addColorStop(1, c2);
413
+ this.context.fillStyle = grd;
414
+ this.context.strokeStyle = grd;
415
+ }
416
+ setRadialGradient(x, y, radius, c1, c2) {
417
+ const grd = this.context.createRadialGradient(x, -y, 0, x, -y, radius);
418
+ grd.addColorStop(0, c1);
419
+ grd.addColorStop(1, c2);
420
+ this.context.fillStyle = grd;
421
+ this.context.strokeStyle = grd;
422
+ }
423
+ setFont(font) {
424
+ this.font = font || "Verdana";
425
+ this.loadFont(this.font);
426
+ }
427
+ loadFont(font = "BitCell") {
428
+ if (this.font_load_requested[font]) {
429
+ return;
430
+ }
431
+ this.font_load_requested[font] = true;
432
+ try {
433
+ document.fonts?.load?.(`16pt ${font}`).catch(() => {
434
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7006, {
435
+ font
436
+ });
437
+ });
438
+ } catch {
439
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7006, {
440
+ font
441
+ });
442
+ }
443
+ }
444
+ isFontReady(font = this.font) {
445
+ if (this.font_loaded[font]) {
446
+ return 1;
447
+ }
448
+ try {
449
+ const ready = document.fonts?.check?.(`16pt ${font}`) ?? true;
450
+ if (ready) {
451
+ this.font_loaded[font] = true;
452
+ }
453
+ return ready ? 1 : 0;
454
+ } catch {
455
+ return 1;
456
+ }
457
+ }
458
+ setTranslation(tx, ty) {
459
+ this.translation_x = isFinite(tx) ? tx : 0;
460
+ this.translation_y = isFinite(ty) ? ty : 0;
461
+ this.updateScreenTransform();
462
+ }
463
+ setScale(x, y) {
464
+ this.scale_x = isFinite(x) && x !== 0 ? x : 1;
465
+ this.scale_y = isFinite(y) && y !== 0 ? y : 1;
466
+ this.updateScreenTransform();
467
+ }
468
+ setRotation(rotation) {
469
+ this.rotation = isFinite(rotation) ? rotation : 0;
470
+ this.updateScreenTransform();
471
+ }
472
+ updateScreenTransform() {
473
+ this.screen_transform = this.translation_x !== 0 || this.translation_y !== 0 || this.scale_x !== 1 || this.scale_y !== 1 || this.rotation !== 0;
474
+ }
475
+ setDrawAnchor(ax, ay) {
476
+ this.anchor_x = typeof ax === "number" ? ax : 0;
477
+ this.anchor_y = typeof ay === "number" ? ay : 0;
478
+ }
479
+ setDrawRotation(rotation) {
480
+ this.object_rotation = rotation;
481
+ }
482
+ setDrawScale(x, y = x) {
483
+ this.object_scale_x = x;
484
+ this.object_scale_y = y;
485
+ }
486
+ initDrawOp(x, y, object_transform = true) {
487
+ let res = false;
488
+ if (this.screen_transform) {
489
+ this.context.save();
490
+ res = true;
491
+ this.context.translate(this.translation_x, -this.translation_y);
492
+ this.context.scale(this.scale_x, this.scale_y);
493
+ this.context.rotate(-this.rotation / 180 * Math.PI);
494
+ this.context.translate(x, y);
495
+ }
496
+ if (object_transform && (this.object_rotation !== 0 || this.object_scale_x !== 1 || this.object_scale_y !== 1)) {
497
+ if (!res) {
498
+ this.context.save();
499
+ res = true;
500
+ this.context.translate(x, y);
501
+ }
502
+ if (this.object_rotation !== 0) {
503
+ this.context.rotate(-this.object_rotation / 180 * Math.PI);
504
+ }
505
+ if (this.object_scale_x !== 1 || this.object_scale_y !== 1) {
506
+ this.context.scale(this.object_scale_x, this.object_scale_y);
507
+ }
508
+ }
509
+ return res;
510
+ }
511
+ closeDrawOp() {
512
+ this.context.restore();
513
+ }
514
+ /**
515
+ * Check mouse cursor visibility
516
+ * Auto-hides cursor after 4 seconds of inactivity
517
+ */
518
+ checkMouseCursor() {
519
+ if (Date.now() > this.last_mouse_move + 4e3 && this.cursor_visibility === "auto") {
520
+ if (this.cursor !== "none") {
521
+ this.cursor = "none";
522
+ this.canvas.style.cursor = "none";
523
+ }
524
+ }
525
+ }
526
+ /**
527
+ * Set cursor visibility
528
+ */
529
+ setCursorVisible(visible) {
530
+ this.cursor_visibility = visible ? "default" : "none";
531
+ if (visible) {
532
+ this.cursor = "default";
533
+ this.canvas.style.cursor = "default";
534
+ } else {
535
+ this.cursor = "none";
536
+ this.canvas.style.cursor = "none";
537
+ }
538
+ }
539
+ getCanvas() {
540
+ return this.canvas;
541
+ }
542
+ getContext() {
543
+ return this.context;
544
+ }
545
+ resize(width, height) {
546
+ if (width && height) {
547
+ if (width <= 0 || height <= 0 || !isFinite(width) || !isFinite(height)) {
548
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7002, {
549
+ width,
550
+ height
551
+ });
552
+ return;
553
+ }
554
+ this.canvas.width = width;
555
+ this.canvas.height = height;
556
+ this.initContext();
557
+ this.zBuffer.resize(width, height);
558
+ this.updateInterface();
559
+ }
560
+ }
561
+ };
562
+
563
+ // src/drawing/primitives-screen.ts
564
+ var PrimitiveScreen = class extends BaseScreen {
565
+ static {
566
+ __name(this, "PrimitiveScreen");
567
+ }
568
+ fillRect(x, y, w, h, color) {
569
+ if (!this.context) {
570
+ reportRuntimeError2(this.runtime?.listener, APIErrorCode2.E7092, {});
571
+ return;
572
+ }
573
+ if (!isFinite(x) || !isFinite(y) || !isFinite(w) || !isFinite(h) || w <= 0 || h <= 0) {
574
+ reportRuntimeError2(this.runtime?.listener, APIErrorCode2.E7093, {
575
+ error: `Invalid parameters: x=${x}, y=${y}, w=${w}, h=${h}`
576
+ });
577
+ return;
578
+ }
579
+ if (color) this.setColor(color);
580
+ this.context.globalAlpha = this.alpha;
581
+ if (this.initDrawOp(x, -y)) {
582
+ this.context.fillRect(-w / 2 - this.anchor_x * w / 2, -h / 2 + this.anchor_y * h / 2, w, h);
583
+ this.closeDrawOp();
584
+ } else {
585
+ this.context.fillRect(x - w / 2 - this.anchor_x * w / 2, -y - h / 2 + this.anchor_y * h / 2, w, h);
586
+ }
587
+ }
588
+ fillRoundRect(x, y, w, h, round = 10, color) {
589
+ if (color) this.setColor(color);
590
+ this.context.globalAlpha = this.alpha;
591
+ const transform = this.initDrawOp(x, -y);
592
+ const rx = (transform ? -w / 2 : x - w / 2) - this.anchor_x * w / 2;
593
+ const ry = (transform ? -h / 2 : -y - h / 2) + this.anchor_y * h / 2;
594
+ this.context.beginPath();
595
+ if (this.context.roundRect) {
596
+ this.context.roundRect(rx, ry, w, h, round);
597
+ } else {
598
+ const r = Math.min(round, w / 2, h / 2);
599
+ this.context.moveTo(rx + r, ry);
600
+ this.context.lineTo(rx + w - r, ry);
601
+ this.context.quadraticCurveTo(rx + w, ry, rx + w, ry + r);
602
+ this.context.lineTo(rx + w, ry + h - r);
603
+ this.context.quadraticCurveTo(rx + w, ry + h, rx + w - r, ry + h);
604
+ this.context.lineTo(rx + r, ry + h);
605
+ this.context.quadraticCurveTo(rx, ry + h, rx, ry + h - r);
606
+ this.context.lineTo(rx, ry + r);
607
+ this.context.quadraticCurveTo(rx, ry, rx + r, ry);
608
+ this.context.closePath();
609
+ }
610
+ this.context.fill();
611
+ if (transform) this.closeDrawOp();
612
+ }
613
+ fillRound(x, y, w, h, color) {
614
+ if (color) this.setColor(color);
615
+ this.context.globalAlpha = this.alpha;
616
+ w = Math.abs(w);
617
+ h = Math.abs(h);
618
+ if (this.initDrawOp(x, -y)) {
619
+ this.context.beginPath();
620
+ this.context.ellipse(-this.anchor_x * w / 2, this.anchor_y * h / 2, w / 2, h / 2, 0, 0, Math.PI * 2, false);
621
+ this.context.fill();
622
+ this.closeDrawOp();
623
+ } else {
624
+ this.context.beginPath();
625
+ this.context.ellipse(x - this.anchor_x * w / 2, -y + this.anchor_y * h / 2, w / 2, h / 2, 0, 0, Math.PI * 2, false);
626
+ this.context.fill();
627
+ }
628
+ }
629
+ drawRect(x, y, w, h, color) {
630
+ if (color) this.setColor(color);
631
+ this.context.globalAlpha = this.alpha;
632
+ this.context.lineWidth = this.line_width;
633
+ if (this.initDrawOp(x, -y)) {
634
+ this.context.strokeRect(-w / 2 - this.anchor_x * w / 2, -h / 2 + this.anchor_y * h / 2, w, h);
635
+ this.closeDrawOp();
636
+ } else {
637
+ this.context.strokeRect(x - w / 2 - this.anchor_x * w / 2, -y - h / 2 + this.anchor_y * h / 2, w, h);
638
+ }
639
+ }
640
+ drawRoundRect(x, y, w, h, round = 10, color) {
641
+ if (color) this.setColor(color);
642
+ this.context.globalAlpha = this.alpha;
643
+ this.context.lineWidth = this.line_width;
644
+ const transform = this.initDrawOp(x, -y);
645
+ const rx = (transform ? -w / 2 : x - w / 2) - this.anchor_x * w / 2;
646
+ const ry = (transform ? -h / 2 : -y - h / 2) + this.anchor_y * h / 2;
647
+ this.context.beginPath();
648
+ if (this.context.roundRect) {
649
+ this.context.roundRect(rx, ry, w, h, round);
650
+ } else {
651
+ const r = Math.min(round, w / 2, h / 2);
652
+ this.context.moveTo(rx + r, ry);
653
+ this.context.lineTo(rx + w - r, ry);
654
+ this.context.quadraticCurveTo(rx + w, ry, rx + w, ry + r);
655
+ this.context.lineTo(rx + w, ry + h - r);
656
+ this.context.quadraticCurveTo(rx + w, ry + h, rx + w - r, ry + h);
657
+ this.context.lineTo(rx + r, ry + h);
658
+ this.context.quadraticCurveTo(rx, ry + h, rx, ry + h - r);
659
+ this.context.lineTo(rx, ry + r);
660
+ this.context.quadraticCurveTo(rx, ry, rx + r, ry);
661
+ this.context.closePath();
662
+ }
663
+ this.context.stroke();
664
+ if (transform) this.closeDrawOp();
665
+ }
666
+ drawRound(x, y, w, h, color) {
667
+ if (color) this.setColor(color);
668
+ this.context.globalAlpha = this.alpha;
669
+ this.context.lineWidth = this.line_width;
670
+ w = Math.abs(w);
671
+ h = Math.abs(h);
672
+ if (this.initDrawOp(x, -y)) {
673
+ this.context.beginPath();
674
+ this.context.ellipse(-this.anchor_x * w / 2, this.anchor_y * h / 2, w / 2, h / 2, 0, 0, Math.PI * 2, false);
675
+ this.context.stroke();
676
+ this.closeDrawOp();
677
+ } else {
678
+ this.context.beginPath();
679
+ this.context.ellipse(x - this.anchor_x * w / 2, -y + this.anchor_y * h / 2, w / 2, h / 2, 0, 0, Math.PI * 2, false);
680
+ this.context.stroke();
681
+ }
682
+ }
683
+ drawLine(x1, y1, x2, y2, color) {
684
+ if (color) this.setColor(color);
685
+ this.context.globalAlpha = this.alpha;
686
+ this.context.lineWidth = this.line_width;
687
+ const transform = this.initDrawOp(0, 0, false);
688
+ this.context.beginPath();
689
+ this.context.moveTo(x1, -y1);
690
+ this.context.lineTo(x2, -y2);
691
+ this.context.stroke();
692
+ if (transform) this.closeDrawOp();
693
+ }
694
+ drawPolygon(args) {
695
+ const { color, points } = this.extractPoints(args);
696
+ if (!points || points.length < 4) return;
697
+ if (color) this.setColor(color);
698
+ this.context.globalAlpha = this.alpha;
699
+ this.context.lineWidth = this.line_width;
700
+ const len = Math.floor(points.length / 2);
701
+ const transform = this.initDrawOp(0, 0, false);
702
+ this.context.beginPath();
703
+ this.context.moveTo(points[0], -points[1]);
704
+ for (let i = 1; i < len; i++) {
705
+ this.context.lineTo(points[i * 2], -points[i * 2 + 1]);
706
+ }
707
+ this.context.closePath();
708
+ this.context.stroke();
709
+ if (transform) this.closeDrawOp();
710
+ }
711
+ drawPolyline(args) {
712
+ const { color, points } = this.extractPoints(args);
713
+ if (!points || points.length < 4) return;
714
+ if (color) this.setColor(color);
715
+ this.context.globalAlpha = this.alpha;
716
+ this.context.lineWidth = this.line_width;
717
+ const len = Math.floor(points.length / 2);
718
+ const transform = this.initDrawOp(0, 0, false);
719
+ this.context.beginPath();
720
+ this.context.moveTo(points[0], -points[1]);
721
+ for (let i = 1; i < len; i++) {
722
+ this.context.lineTo(points[i * 2], -points[i * 2 + 1]);
723
+ }
724
+ this.context.stroke();
725
+ if (transform) this.closeDrawOp();
726
+ }
727
+ fillPolygon(args) {
728
+ const { color, points } = this.extractPoints(args);
729
+ if (!points || points.length < 4) return;
730
+ if (color) this.setColor(color);
731
+ this.context.globalAlpha = this.alpha;
732
+ const len = Math.floor(points.length / 2);
733
+ const transform = this.initDrawOp(0, 0, false);
734
+ this.context.beginPath();
735
+ this.context.moveTo(points[0], -points[1]);
736
+ for (let i = 1; i < len; i++) {
737
+ this.context.lineTo(points[i * 2], -points[i * 2 + 1]);
738
+ }
739
+ this.context.fill();
740
+ if (transform) this.closeDrawOp();
741
+ }
742
+ drawQuadCurve(args) {
743
+ const { color, points } = this.extractPoints(args);
744
+ if (!points || points.length < 4) return;
745
+ if (color) this.setColor(color);
746
+ this.context.globalAlpha = this.alpha;
747
+ this.context.lineWidth = this.line_width;
748
+ const transform = this.initDrawOp(0, 0, false);
749
+ this.context.beginPath();
750
+ this.context.moveTo(points[0], -points[1]);
751
+ let index = 2;
752
+ while (index <= points.length - 4) {
753
+ this.context.quadraticCurveTo(points[index], -points[index + 1], points[index + 2], -points[index + 3]);
754
+ index += 4;
755
+ }
756
+ this.context.stroke();
757
+ if (transform) this.closeDrawOp();
758
+ }
759
+ drawBezierCurve(args) {
760
+ const { color, points } = this.extractPoints(args);
761
+ if (!points || points.length < 4) return;
762
+ if (color) this.setColor(color);
763
+ this.context.globalAlpha = this.alpha;
764
+ this.context.lineWidth = this.line_width;
765
+ const transform = this.initDrawOp(0, 0, false);
766
+ this.context.beginPath();
767
+ this.context.moveTo(points[0], -points[1]);
768
+ let index = 2;
769
+ while (index <= points.length - 6) {
770
+ this.context.bezierCurveTo(points[index], -points[index + 1], points[index + 2], -points[index + 3], points[index + 4], -points[index + 5]);
771
+ index += 6;
772
+ }
773
+ this.context.stroke();
774
+ if (transform) this.closeDrawOp();
775
+ }
776
+ drawArc(x, y, radius, angle1, angle2, ccw, color) {
777
+ if (color) this.setColor(color);
778
+ this.context.globalAlpha = this.alpha;
779
+ this.context.lineWidth = this.line_width;
780
+ if (this.initDrawOp(x, -y)) {
781
+ this.context.beginPath();
782
+ this.context.arc(0, 0, radius, -angle1 / 180 * Math.PI, -angle2 / 180 * Math.PI, ccw);
783
+ this.context.stroke();
784
+ this.closeDrawOp();
785
+ } else {
786
+ this.context.beginPath();
787
+ this.context.arc(x, -y, radius, -angle1 / 180 * Math.PI, -angle2 / 180 * Math.PI, ccw);
788
+ this.context.stroke();
789
+ }
790
+ }
791
+ fillArc(x, y, radius, angle1, angle2, ccw, color) {
792
+ if (color) this.setColor(color);
793
+ this.context.globalAlpha = this.alpha;
794
+ if (this.initDrawOp(x, -y)) {
795
+ this.context.beginPath();
796
+ this.context.arc(0, 0, radius, -angle1 / 180 * Math.PI, -angle2 / 180 * Math.PI, ccw);
797
+ this.context.fill();
798
+ this.closeDrawOp();
799
+ } else {
800
+ this.context.beginPath();
801
+ this.context.arc(x, -y, radius, -angle1 / 180 * Math.PI, -angle2 / 180 * Math.PI, ccw);
802
+ this.context.fill();
803
+ }
804
+ }
805
+ extractPoints(args) {
806
+ let color;
807
+ let points;
808
+ if (args.length > 0 && args.length % 2 === 1 && typeof args[args.length - 1] === "string") {
809
+ color = args[args.length - 1];
810
+ points = args.slice(0, -1);
811
+ } else if (Array.isArray(args[0])) {
812
+ if (args[1] && typeof args[1] === "string") {
813
+ color = args[1];
814
+ }
815
+ points = args[0];
816
+ } else {
817
+ points = args;
818
+ }
819
+ return {
820
+ color,
821
+ points
822
+ };
823
+ }
824
+ };
825
+
826
+ // src/drawing/sprite-screen.ts
827
+ var SpriteScreen = class extends PrimitiveScreen {
828
+ static {
829
+ __name(this, "SpriteScreen");
830
+ }
831
+ // Cache imageSmoothingEnabled — only set when pixelated flag changes
832
+ _lastImageSmoothing = true;
833
+ // Cache frame time once per draw frame instead of per-sprite
834
+ _frameTime = 0;
835
+ /**
836
+ * Initialize draw state (called before each draw frame)
837
+ */
838
+ initDraw() {
839
+ super.initDraw();
840
+ this._frameTime = performance.now();
841
+ }
842
+ /**
843
+ * Set imageSmoothingEnabled only when it actually changes
844
+ */
845
+ setImageSmoothing() {
846
+ const smooth = !this.pixelated;
847
+ if (smooth !== this._lastImageSmoothing) {
848
+ this.context.imageSmoothingEnabled = smooth;
849
+ this._lastImageSmoothing = smooth;
850
+ }
851
+ }
852
+ /**
853
+ * Get the canvas for the current sprite frame
854
+ */
855
+ getSpriteFrame(sprite) {
856
+ let frame = null;
857
+ if (typeof sprite === "string") {
858
+ const spriteName = sprite;
859
+ let spriteObj2 = null;
860
+ if (this.runtime && this.runtime.sprites) {
861
+ spriteObj2 = this.runtime.sprites[sprite];
862
+ }
863
+ if (!spriteObj2) {
864
+ const parts = sprite.split(".");
865
+ if (parts.length > 1 && this.runtime && this.runtime.sprites) {
866
+ spriteObj2 = this.runtime.sprites[parts[0]];
867
+ frame = Number.parseInt(parts[1]) || 0;
868
+ }
869
+ }
870
+ if (!spriteObj2) {
871
+ reportRuntimeError3(this.runtime?.listener, APIErrorCode3.E7004, {
872
+ spriteName
873
+ });
874
+ return null;
875
+ }
876
+ sprite = spriteObj2;
877
+ } else if (sprite && typeof sprite === "object" && sprite.canvas && !sprite.frames) {
878
+ return sprite.canvas || sprite.image || null;
879
+ }
880
+ if (!sprite || !sprite.ready) {
881
+ const spriteName = typeof sprite === "string" ? sprite : "unknown";
882
+ reportRuntimeError3(this.runtime?.listener, APIErrorCode3.E7005, {
883
+ spriteName
884
+ });
885
+ return null;
886
+ }
887
+ const spriteObj = sprite;
888
+ if (spriteObj.frames && spriteObj.frames.length > 1) {
889
+ if (frame === null) {
890
+ if (spriteObj.animation_start === 0) {
891
+ spriteObj.animation_start = this._frameTime;
892
+ }
893
+ const dt = 1e3 / spriteObj.fps;
894
+ frame = Math.floor((this._frameTime - spriteObj.animation_start) / dt) % spriteObj.frames.length;
895
+ }
896
+ if (frame >= 0 && frame < spriteObj.frames.length) {
897
+ return spriteObj.frames[frame].canvas;
898
+ }
899
+ return spriteObj.frames[0].canvas;
900
+ } else if (spriteObj.frames && spriteObj.frames[0]) {
901
+ return spriteObj.frames[0].canvas;
902
+ }
903
+ return null;
904
+ }
905
+ /**
906
+ * Draw a sprite
907
+ */
908
+ drawSprite(sprite, x, y, w, h) {
909
+ const canvas = this.getSpriteFrame(sprite);
910
+ if (!canvas) return;
911
+ if (w == null) {
912
+ w = canvas.width;
913
+ }
914
+ if (!h) {
915
+ h = w / canvas.width * canvas.height;
916
+ }
917
+ if (!this.screen_transform && this.object_rotation === 0 && this.object_scale_x === 1 && this.object_scale_y === 1) {
918
+ const drawX = x - w / 2 - this.anchor_x * w / 2;
919
+ const drawY = -y - h / 2 + this.anchor_y * h / 2;
920
+ const halfW = this.width / 2;
921
+ const halfH = this.height / 2;
922
+ if (drawX > halfW || drawX + w < -halfW || drawY > halfH || drawY + h < -halfH) {
923
+ return;
924
+ }
925
+ }
926
+ this.context.globalAlpha = this.alpha;
927
+ this.setImageSmoothing();
928
+ if (this.initDrawOp(x, -y)) {
929
+ this.context.drawImage(canvas, -w / 2 - this.anchor_x * w / 2, -h / 2 + this.anchor_y * h / 2, w, h);
930
+ this.closeDrawOp();
931
+ } else {
932
+ this.context.drawImage(canvas, x - w / 2 - this.anchor_x * w / 2, -y - h / 2 + this.anchor_y * h / 2, w, h);
933
+ }
934
+ }
935
+ /**
936
+ * Draw a portion of a sprite
937
+ */
938
+ drawSpritePart(sprite, sx, sy, sw, sh, x, y, w, h) {
939
+ const canvas = this.getSpriteFrame(sprite);
940
+ if (!canvas) return;
941
+ if (w == null) {
942
+ w = sw;
943
+ }
944
+ if (!h) {
945
+ h = w / sw * sh;
946
+ }
947
+ if (!this.screen_transform && this.object_rotation === 0 && this.object_scale_x === 1 && this.object_scale_y === 1) {
948
+ const drawX = x - w / 2 - this.anchor_x * w / 2;
949
+ const drawY = -y - h / 2 + this.anchor_y * h / 2;
950
+ const halfW = this.width / 2;
951
+ const halfH = this.height / 2;
952
+ if (drawX > halfW || drawX + w < -halfW || drawY > halfH || drawY + h < -halfH) {
953
+ return;
954
+ }
955
+ }
956
+ this.context.globalAlpha = this.alpha;
957
+ this.setImageSmoothing();
958
+ if (this.initDrawOp(x, -y)) {
959
+ this.context.drawImage(canvas, sx, sy, sw, sh, -w / 2 - this.anchor_x * w / 2, -h / 2 + this.anchor_y * h / 2, w, h);
960
+ this.closeDrawOp();
961
+ } else {
962
+ this.context.drawImage(canvas, sx, sy, sw, sh, x - w / 2 - this.anchor_x * w / 2, -y - h / 2 + this.anchor_y * h / 2, w, h);
963
+ }
964
+ }
965
+ /**
966
+ * Draw a map
967
+ */
968
+ drawMap(map, x, y, w, h) {
969
+ let mapObj = null;
970
+ if (typeof map === "string") {
971
+ if (this.runtime && this.runtime.maps) {
972
+ mapObj = this.runtime.maps[map];
973
+ }
974
+ } else {
975
+ mapObj = map;
976
+ }
977
+ if (!(mapObj && mapObj.ready)) {
978
+ return;
979
+ }
980
+ this.context.globalAlpha = this.alpha;
981
+ this.setImageSmoothing();
982
+ if (this.initDrawOp(x, -y)) {
983
+ mapObj.draw(this.context, -w / 2 - this.anchor_x * w / 2, -h / 2 + this.anchor_y * h / 2, w, h);
984
+ this.closeDrawOp();
985
+ } else {
986
+ mapObj.draw(this.context, x - w / 2 - this.anchor_x * w / 2, -y - h / 2 + this.anchor_y * h / 2, w, h);
987
+ }
988
+ }
989
+ };
990
+
991
+ // src/drawing/text-screen.ts
992
+ var TextScreen = class extends SpriteScreen {
993
+ static {
994
+ __name(this, "TextScreen");
995
+ }
996
+ // Font string cache — avoid rebuilding template string every draw call
997
+ _cachedFontSize = -1;
998
+ _cachedFontName = "";
999
+ _cachedFontString = "";
1000
+ getFontString(size) {
1001
+ if (size !== this._cachedFontSize || this.font !== this._cachedFontName) {
1002
+ this._cachedFontSize = size;
1003
+ this._cachedFontName = this.font;
1004
+ this._cachedFontString = `${size}pt ${this.font}`;
1005
+ }
1006
+ return this._cachedFontString;
1007
+ }
1008
+ textWidth(text, size) {
1009
+ this.context.font = this.getFontString(size);
1010
+ return this.context.measureText(text).width;
1011
+ }
1012
+ drawText(text, x, y, size, color) {
1013
+ if (color) this.setColor(color);
1014
+ this.context.globalAlpha = this.alpha;
1015
+ this.context.font = this.getFontString(size);
1016
+ this.context.textAlign = "center";
1017
+ this.context.textBaseline = "middle";
1018
+ const w = this.context.measureText(text).width;
1019
+ const h = size;
1020
+ if (this.initDrawOp(x, -y)) {
1021
+ this.context.fillText(text, 0 - this.anchor_x * w / 2, 0 + this.anchor_y * h / 2);
1022
+ this.closeDrawOp();
1023
+ } else {
1024
+ this.context.fillText(text, x - this.anchor_x * w / 2, -y + this.anchor_y * h / 2);
1025
+ }
1026
+ }
1027
+ drawTextOutline(text, x, y, size, color) {
1028
+ if (color) this.setColor(color);
1029
+ this.context.globalAlpha = this.alpha;
1030
+ this.context.font = this.getFontString(size);
1031
+ this.context.lineWidth = this.line_width;
1032
+ this.context.textAlign = "center";
1033
+ this.context.textBaseline = "middle";
1034
+ const w = this.context.measureText(text).width;
1035
+ const h = size;
1036
+ if (this.initDrawOp(x, -y)) {
1037
+ this.context.strokeText(text, 0 - this.anchor_x * w / 2, 0 + this.anchor_y * h / 2);
1038
+ this.closeDrawOp();
1039
+ } else {
1040
+ this.context.strokeText(text, x - this.anchor_x * w / 2, -y + this.anchor_y * h / 2);
1041
+ }
1042
+ }
1043
+ };
1044
+
1045
+ // src/tri/triangle-screen.ts
1046
+ var TriangleScreen = class extends TextScreen {
1047
+ static {
1048
+ __name(this, "TriangleScreen");
1049
+ }
1050
+ tri(x1, y1, x2, y2, x3, y3, color) {
1051
+ if (color) this.setColor(color);
1052
+ this.context.globalAlpha = this.alpha;
1053
+ const v0 = {
1054
+ x: x1,
1055
+ y: -y1
1056
+ };
1057
+ const v1 = {
1058
+ x: x2,
1059
+ y: -y2
1060
+ };
1061
+ const v2 = {
1062
+ x: x3,
1063
+ y: -y3
1064
+ };
1065
+ drawTriangle(this.context, v0, v1, v2, this.context.fillStyle);
1066
+ }
1067
+ trib(x1, y1, x2, y2, x3, y3, color) {
1068
+ if (color) this.setColor(color);
1069
+ this.context.globalAlpha = this.alpha;
1070
+ const v0 = {
1071
+ x: x1,
1072
+ y: -y1
1073
+ };
1074
+ const v1 = {
1075
+ x: x2,
1076
+ y: -y2
1077
+ };
1078
+ const v2 = {
1079
+ x: x3,
1080
+ y: -y3
1081
+ };
1082
+ drawTriangleOutline(this.context, v0, v1, v2, this.context.strokeStyle, this.line_width);
1083
+ }
1084
+ ttri(x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3, texture, textureSource = "tiles", z1 = 1, z2 = 1, z3 = 1, useDepth = false) {
1085
+ this.context.globalAlpha = this.alpha;
1086
+ const canvasWidth = this.canvas.width;
1087
+ const canvasHeight = this.canvas.height;
1088
+ const ratio = Math.min(canvasWidth / 200, canvasHeight / 200);
1089
+ const toCanvasX = /* @__PURE__ */ __name((x) => canvasWidth / 2 + x * ratio, "toCanvasX");
1090
+ const toCanvasY = /* @__PURE__ */ __name((y) => canvasHeight / 2 - y * ratio, "toCanvasY");
1091
+ const data = {
1092
+ context: this.context,
1093
+ width: canvasWidth,
1094
+ height: canvasHeight,
1095
+ runtime: this.runtime,
1096
+ pixelated: this.pixelated === 1
1097
+ };
1098
+ drawTexturedTriangle(data, {
1099
+ x: toCanvasX(x1),
1100
+ y: toCanvasY(y1),
1101
+ u: u1,
1102
+ v: v1,
1103
+ z: z1
1104
+ }, {
1105
+ x: toCanvasX(x2),
1106
+ y: toCanvasY(y2),
1107
+ u: u2,
1108
+ v: v2,
1109
+ z: z2
1110
+ }, {
1111
+ x: toCanvasX(x3),
1112
+ y: toCanvasY(y3),
1113
+ u: u3,
1114
+ v: v3,
1115
+ z: z3
1116
+ }, texture, textureSource, this.zBuffer, useDepth);
1117
+ }
1118
+ };
1119
+
1120
+ // src/core/screen.ts
1121
+ var Screen = class extends TriangleScreen {
1122
+ static {
1123
+ __name(this, "Screen");
1124
+ }
1125
+ getInterface() {
1126
+ if (this.interfaceCache) {
1127
+ return this.interfaceCache;
1128
+ }
1129
+ const screen = this;
1130
+ this.interfaceCache = {
1131
+ width: screen.width,
1132
+ height: screen.height,
1133
+ clear: /* @__PURE__ */ __name((color) => screen.clear(color), "clear"),
1134
+ setColor: /* @__PURE__ */ __name((color) => screen.setColor(color), "setColor"),
1135
+ setAlpha: /* @__PURE__ */ __name((alpha) => screen.setAlpha(alpha), "setAlpha"),
1136
+ setPixelated: /* @__PURE__ */ __name((pixelated) => screen.setPixelated(pixelated), "setPixelated"),
1137
+ setBlending: /* @__PURE__ */ __name((blending) => screen.setBlending(blending), "setBlending"),
1138
+ setLinearGradient: /* @__PURE__ */ __name((x1, y1, x2, y2, c1, c2) => screen.setLinearGradient(x1, y1, x2, y2, c1, c2), "setLinearGradient"),
1139
+ setRadialGradient: /* @__PURE__ */ __name((x, y, radius, c1, c2) => screen.setRadialGradient(x, y, radius, c1, c2), "setRadialGradient"),
1140
+ setFont: /* @__PURE__ */ __name((font) => screen.setFont(font), "setFont"),
1141
+ setTranslation: /* @__PURE__ */ __name((tx, ty) => screen.setTranslation(tx, ty), "setTranslation"),
1142
+ setScale: /* @__PURE__ */ __name((x, y) => screen.setScale(x, y), "setScale"),
1143
+ setRotation: /* @__PURE__ */ __name((rotation) => screen.setRotation(rotation), "setRotation"),
1144
+ setDrawAnchor: /* @__PURE__ */ __name((ax, ay) => screen.setDrawAnchor(ax, ay), "setDrawAnchor"),
1145
+ setDrawRotation: /* @__PURE__ */ __name((rotation) => screen.setDrawRotation(rotation), "setDrawRotation"),
1146
+ setDrawScale: /* @__PURE__ */ __name((x, y) => screen.setDrawScale(x, y), "setDrawScale"),
1147
+ fillRect: /* @__PURE__ */ __name((x, y, w, h, c) => screen.fillRect(x, y, w, h, c), "fillRect"),
1148
+ fillRoundRect: /* @__PURE__ */ __name((x, y, w, h, r, c) => screen.fillRoundRect(x, y, w, h, r, c), "fillRoundRect"),
1149
+ fillRound: /* @__PURE__ */ __name((x, y, w, h, c) => screen.fillRound(x, y, w, h, c), "fillRound"),
1150
+ drawRect: /* @__PURE__ */ __name((x, y, w, h, c) => screen.drawRect(x, y, w, h, c), "drawRect"),
1151
+ drawRoundRect: /* @__PURE__ */ __name((x, y, w, h, r, c) => screen.drawRoundRect(x, y, w, h, r, c), "drawRoundRect"),
1152
+ drawRound: /* @__PURE__ */ __name((x, y, w, h, c) => screen.drawRound(x, y, w, h, c), "drawRound"),
1153
+ drawSprite: /* @__PURE__ */ __name((sprite, x, y, w, h) => screen.drawSprite(sprite, x, y, w, h), "drawSprite"),
1154
+ drawSpritePart: /* @__PURE__ */ __name((sprite, sx, sy, sw, sh, x, y, w, h) => screen.drawSpritePart(sprite, sx, sy, sw, sh, x, y, w, h), "drawSpritePart"),
1155
+ drawMap: /* @__PURE__ */ __name((map, x, y, w, h) => screen.drawMap(map, x, y, w, h), "drawMap"),
1156
+ drawText: /* @__PURE__ */ __name((text, x, y, size, color) => screen.drawText(text, x, y, size, color), "drawText"),
1157
+ drawTextOutline: /* @__PURE__ */ __name((text, x, y, size, color) => screen.drawTextOutline(text, x, y, size, color), "drawTextOutline"),
1158
+ textWidth: /* @__PURE__ */ __name((text, size) => screen.textWidth(text, size), "textWidth"),
1159
+ setLineWidth: /* @__PURE__ */ __name((width) => screen.setLineWidth(width), "setLineWidth"),
1160
+ setLineDash: /* @__PURE__ */ __name((dash) => screen.setLineDash(dash), "setLineDash"),
1161
+ drawLine: /* @__PURE__ */ __name((x1, y1, x2, y2, color) => screen.drawLine(x1, y1, x2, y2, color), "drawLine"),
1162
+ drawPolygon: /* @__PURE__ */ __name((...args) => screen.drawPolygon(args), "drawPolygon"),
1163
+ drawPolyline: /* @__PURE__ */ __name((...args) => screen.drawPolyline(args), "drawPolyline"),
1164
+ fillPolygon: /* @__PURE__ */ __name((...args) => screen.fillPolygon(args), "fillPolygon"),
1165
+ drawQuadCurve: /* @__PURE__ */ __name((...args) => screen.drawQuadCurve(args), "drawQuadCurve"),
1166
+ drawBezierCurve: /* @__PURE__ */ __name((...args) => screen.drawBezierCurve(args), "drawBezierCurve"),
1167
+ drawArc: /* @__PURE__ */ __name((x, y, radius, angle1, angle2, ccw, color) => screen.drawArc(x, y, radius, angle1, angle2, ccw, color), "drawArc"),
1168
+ fillArc: /* @__PURE__ */ __name((x, y, radius, angle1, angle2, ccw, color) => screen.fillArc(x, y, radius, angle1, angle2, ccw, color), "fillArc"),
1169
+ setCursorVisible: /* @__PURE__ */ __name((visible) => screen.setCursorVisible(visible), "setCursorVisible"),
1170
+ loadFont: /* @__PURE__ */ __name((font) => screen.loadFont(font), "loadFont"),
1171
+ isFontReady: /* @__PURE__ */ __name((font) => screen.isFontReady(font), "isFontReady"),
1172
+ tri: /* @__PURE__ */ __name((x1, y1, x2, y2, x3, y3, color) => screen.tri(x1, y1, x2, y2, x3, y3, color), "tri"),
1173
+ trib: /* @__PURE__ */ __name((x1, y1, x2, y2, x3, y3, color) => screen.trib(x1, y1, x2, y2, x3, y3, color), "trib"),
1174
+ ttri: /* @__PURE__ */ __name((x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3, texture, textureSource, z1, z2, z3, useDepth) => screen.ttri(x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3, texture, textureSource, z1, z2, z3, useDepth), "ttri")
1175
+ };
1176
+ return this.interfaceCache;
1177
+ }
1178
+ };
1179
+ export {
1180
+ Screen,
1181
+ ZBuffer,
1182
+ Screen as default
1183
+ };
1184
+ //# sourceMappingURL=index.mjs.map