@jiant/canvable 0.0.1-fix
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/README.md +85 -0
- package/dist/main.d.mts +239 -0
- package/dist/main.d.ts +239 -0
- package/dist/main.js +497 -0
- package/dist/main.mjs +464 -0
- package/package.json +33 -0
package/dist/main.js
ADDED
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/main.ts
|
|
21
|
+
var main_exports = {};
|
|
22
|
+
__export(main_exports, {
|
|
23
|
+
Camera: () => Camera,
|
|
24
|
+
Circle: () => Circle,
|
|
25
|
+
Node: () => Node,
|
|
26
|
+
Scene: () => Scene,
|
|
27
|
+
TWO_PI: () => TWO_PI,
|
|
28
|
+
Vector2D: () => Vector2D,
|
|
29
|
+
getCanvas: () => getCanvas
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(main_exports);
|
|
32
|
+
|
|
33
|
+
// src/constants.ts
|
|
34
|
+
var TWO_PI = Math.PI * 2;
|
|
35
|
+
|
|
36
|
+
// src/classes/Vector2D.ts
|
|
37
|
+
var Vector2D = class _Vector2D {
|
|
38
|
+
/**
|
|
39
|
+
* Creates a new Vector2D instance
|
|
40
|
+
* @param x - The x component of the vector
|
|
41
|
+
* @param y - The y component of the vector
|
|
42
|
+
*/
|
|
43
|
+
constructor(x = 0, y = 0) {
|
|
44
|
+
this.x = x;
|
|
45
|
+
this.y = y;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Adds another vector to this vector
|
|
49
|
+
* @param vector - The vector to add
|
|
50
|
+
* @param self - If true, modifies the current vector in place, otherwise returns a new vector
|
|
51
|
+
* @returns A new Vector2D representing the sum
|
|
52
|
+
*/
|
|
53
|
+
add(vector, self = false) {
|
|
54
|
+
if (self) {
|
|
55
|
+
this.x += vector.x;
|
|
56
|
+
this.y += vector.y;
|
|
57
|
+
return this;
|
|
58
|
+
} else {
|
|
59
|
+
return new _Vector2D(this.x + vector.x, this.y + vector.y);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Subtracts another vector from this vector
|
|
64
|
+
* @param vector - The vector to subtract
|
|
65
|
+
* @param self - If true, modifies the current vector in place, otherwise returns a new vector
|
|
66
|
+
* @returns A new Vector2D representing the difference
|
|
67
|
+
*/
|
|
68
|
+
subtract(vector, self = false) {
|
|
69
|
+
if (self) {
|
|
70
|
+
this.x -= vector.x;
|
|
71
|
+
this.y -= vector.y;
|
|
72
|
+
return this;
|
|
73
|
+
} else {
|
|
74
|
+
return new _Vector2D(this.x - vector.x, this.y - vector.y);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Multiplies this vector by a scalar value
|
|
79
|
+
* @param scalar - The scalar value to multiply by
|
|
80
|
+
* @returns A new Vector2D scaled by the input value
|
|
81
|
+
*/
|
|
82
|
+
multiply(scalar) {
|
|
83
|
+
return new _Vector2D(this.x * scalar, this.y * scalar);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Divides this vector by a scalar value
|
|
87
|
+
* @param scalar - The scalar value to divide by
|
|
88
|
+
* @throws {Error} If scalar is zero
|
|
89
|
+
* @returns A new Vector2D divided by the scalar value
|
|
90
|
+
*/
|
|
91
|
+
divide(scalar) {
|
|
92
|
+
if (scalar === 0) throw new Error("Cannot divide by zero");
|
|
93
|
+
return new _Vector2D(this.x / scalar, this.y / scalar);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Calculates the magnitude (length) of this vector
|
|
97
|
+
* @returns The magnitude of the vector
|
|
98
|
+
*/
|
|
99
|
+
magnitude() {
|
|
100
|
+
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Creates a normalized (unit) vector pointing in the same direction
|
|
104
|
+
* @returns A new Vector2D with magnitude 1 (or 0 if this vector is 0)
|
|
105
|
+
*/
|
|
106
|
+
normalize() {
|
|
107
|
+
const mag = this.magnitude();
|
|
108
|
+
if (mag === 0) return new _Vector2D(0, 0);
|
|
109
|
+
return this.divide(mag);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Calculates the dot product with another vector
|
|
113
|
+
* @param vector - The vector to calculate the dot product with
|
|
114
|
+
* @returns The dot product of the two vectors
|
|
115
|
+
*/
|
|
116
|
+
dot(vector) {
|
|
117
|
+
return this.x * vector.x + this.y * vector.y;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Calculates the 2D cross product with another vector
|
|
121
|
+
* @param vector - The vector to calculate the cross product with
|
|
122
|
+
* @returns The magnitude of the cross product
|
|
123
|
+
*/
|
|
124
|
+
cross(vector) {
|
|
125
|
+
return this.x * vector.y - this.y * vector.x;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Calculates the angle between this vector and another vector
|
|
129
|
+
* @param vector - The vector to calculate the angle with
|
|
130
|
+
* @returns The angle in radians between the two vectors
|
|
131
|
+
*/
|
|
132
|
+
angle(vector) {
|
|
133
|
+
const dot = this.dot(vector);
|
|
134
|
+
const mags = this.magnitude() * vector.magnitude();
|
|
135
|
+
return Math.acos(dot / mags);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Rotates the vector by a given angle
|
|
139
|
+
* @param angle - The angle to rotate by (in radians)
|
|
140
|
+
* @returns A new Vector2D rotated by the specified angle
|
|
141
|
+
*/
|
|
142
|
+
rotate(angle) {
|
|
143
|
+
const cos = Math.cos(angle);
|
|
144
|
+
const sin = Math.sin(angle);
|
|
145
|
+
return new _Vector2D(this.x * cos - this.y * sin, this.x * sin + this.y * cos);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Calculates the distance to another vector
|
|
149
|
+
* @param vector - The vector to calculate the distance to
|
|
150
|
+
* @returns The distance between the two vectors
|
|
151
|
+
*/
|
|
152
|
+
distance(vector) {
|
|
153
|
+
return this.subtract(vector).magnitude();
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Projects this vector onto another vector
|
|
157
|
+
* @param vector - The vector to project onto
|
|
158
|
+
* @returns A new Vector2D representing the projection
|
|
159
|
+
*/
|
|
160
|
+
project(vector) {
|
|
161
|
+
const normalized = vector.normalize();
|
|
162
|
+
const scalar = this.dot(normalized);
|
|
163
|
+
return normalized.multiply(scalar);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Reflects this vector across a normal
|
|
167
|
+
* @param normal - The normal vector to reflect across
|
|
168
|
+
* @returns A new Vector2D representing the reflection
|
|
169
|
+
*/
|
|
170
|
+
reflect(normal) {
|
|
171
|
+
const normalized = normal.normalize();
|
|
172
|
+
return this.subtract(normalized.multiply(2 * this.dot(normalized)));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Linearly interpolates between this vector and another vector
|
|
176
|
+
* @param vector - The vector to interpolate towards
|
|
177
|
+
* @param t - The interpolation parameter (0-1)
|
|
178
|
+
* @returns A new Vector2D representing the interpolated vector
|
|
179
|
+
*/
|
|
180
|
+
lerp(vector, t) {
|
|
181
|
+
return new _Vector2D(this.x + (vector.x - this.x) * t, this.y + (vector.y - this.y) * t);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Limits the magnitude of this vector to a maximum value
|
|
185
|
+
* @param max - The maximum magnitude
|
|
186
|
+
* @returns A new Vector2D with limited magnitude
|
|
187
|
+
*/
|
|
188
|
+
limit(max) {
|
|
189
|
+
const mag = this.magnitude();
|
|
190
|
+
if (mag > max) {
|
|
191
|
+
return this.normalize().multiply(max);
|
|
192
|
+
}
|
|
193
|
+
return new _Vector2D(this.x, this.y);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Checks if this vector is equal to another vector within a tolerance
|
|
197
|
+
* @param vector - The vector to compare with
|
|
198
|
+
* @param tolerance - The maximum difference allowed (default: 0.000001)
|
|
199
|
+
* @returns True if the vectors are equal within the tolerance
|
|
200
|
+
*/
|
|
201
|
+
equals(vector, tolerance = 1e-6) {
|
|
202
|
+
return Math.abs(this.x - vector.x) < tolerance && Math.abs(this.y - vector.y) < tolerance;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Creates a copy of this vector
|
|
206
|
+
* @returns A new Vector2D with the same components
|
|
207
|
+
*/
|
|
208
|
+
clone() {
|
|
209
|
+
return new _Vector2D(this.x, this.y);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Converts the vector to a string representation
|
|
213
|
+
* @returns A string representation of the vector
|
|
214
|
+
*/
|
|
215
|
+
toString() {
|
|
216
|
+
return `Vector2D(${this.x}, ${this.y})`;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Creates a vector pointing in a specific direction
|
|
220
|
+
* @param angle - The angle in radians
|
|
221
|
+
* @param magnitude - The length of the vector (default: 1)
|
|
222
|
+
* @returns A new Vector2D with the specified angle and magnitude
|
|
223
|
+
*/
|
|
224
|
+
static fromAngle(angle, magnitude = 1) {
|
|
225
|
+
return new _Vector2D(magnitude * Math.cos(angle), magnitude * Math.sin(angle));
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Creates a random vector with the specified magnitude
|
|
229
|
+
* @param magnitude - The length of the vector (default: 1)
|
|
230
|
+
* @returns A new Vector2D with random direction and specified magnitude
|
|
231
|
+
*/
|
|
232
|
+
static random(magnitude = 1) {
|
|
233
|
+
const angle = Math.random() * TWO_PI;
|
|
234
|
+
return _Vector2D.fromAngle(angle, magnitude);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Adds two vectors together
|
|
238
|
+
* @param v1 - The first vector
|
|
239
|
+
* @param v2 - The second vector
|
|
240
|
+
* @returns A new Vector2D representing the sum
|
|
241
|
+
*/
|
|
242
|
+
static add(v1, v2) {
|
|
243
|
+
return v1.add(v2);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Subtracts one vector from another
|
|
247
|
+
* @param v1 - The vector to subtract from
|
|
248
|
+
* @param v2 - The vector to subtract
|
|
249
|
+
* @returns A new Vector2D representing the difference
|
|
250
|
+
*/
|
|
251
|
+
static subtract(v1, v2) {
|
|
252
|
+
return v1.subtract(v2);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Calculates the distance between two vectors
|
|
256
|
+
* @param v1 - The first vector
|
|
257
|
+
* @param v2 - The second vector
|
|
258
|
+
* @returns The distance between the vectors
|
|
259
|
+
*/
|
|
260
|
+
static distance(v1, v2) {
|
|
261
|
+
return v1.distance(v2);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// src/nodes/Node.ts
|
|
266
|
+
var import_uuid = require("uuid");
|
|
267
|
+
var Node = class {
|
|
268
|
+
id;
|
|
269
|
+
pos;
|
|
270
|
+
children = [];
|
|
271
|
+
scene;
|
|
272
|
+
constructor(config) {
|
|
273
|
+
const { id, pos } = config || {};
|
|
274
|
+
this.id = id || this.generateID();
|
|
275
|
+
this.pos = pos || new Vector2D();
|
|
276
|
+
}
|
|
277
|
+
addObject(object) {
|
|
278
|
+
this.children.push(object);
|
|
279
|
+
}
|
|
280
|
+
removeObject(object) {
|
|
281
|
+
const index = this.children.indexOf(object);
|
|
282
|
+
if (index !== -1) {
|
|
283
|
+
this.children.splice(index, 1);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
generateID() {
|
|
287
|
+
return (0, import_uuid.v4)();
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// src/nodes/Circle.ts
|
|
292
|
+
var Circle = class extends Node {
|
|
293
|
+
vel = new Vector2D();
|
|
294
|
+
size = 10;
|
|
295
|
+
friction = 0.1;
|
|
296
|
+
constructor(config) {
|
|
297
|
+
super();
|
|
298
|
+
this.vel = config?.vel || new Vector2D();
|
|
299
|
+
this.size = config?.size || 10;
|
|
300
|
+
this.friction = config?.friction || 0.1;
|
|
301
|
+
}
|
|
302
|
+
draw(ctx, selected) {
|
|
303
|
+
const radius = 10;
|
|
304
|
+
const cameraPos = this.scene?.camera.pos || new Vector2D();
|
|
305
|
+
const cameraScale = this.scene?.camera.zoom || 1;
|
|
306
|
+
const relativePos = new Vector2D((this.pos.x - cameraPos.x) * cameraScale, (this.pos.y - cameraPos.y) * cameraScale);
|
|
307
|
+
if (selected) {
|
|
308
|
+
ctx.beginPath();
|
|
309
|
+
ctx.arc(relativePos.x, relativePos.y, radius + 5, 0, Math.PI * 2);
|
|
310
|
+
ctx.fillStyle = "transparent";
|
|
311
|
+
ctx.lineWidth = 3;
|
|
312
|
+
ctx.strokeStyle = "white";
|
|
313
|
+
ctx.stroke();
|
|
314
|
+
ctx.closePath();
|
|
315
|
+
}
|
|
316
|
+
ctx.beginPath();
|
|
317
|
+
ctx.arc(relativePos.x, relativePos.y, radius, 0, Math.PI * 2);
|
|
318
|
+
ctx.fillStyle = "blue";
|
|
319
|
+
ctx.fill();
|
|
320
|
+
ctx.closePath();
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
// src/nodes/Camera.ts
|
|
325
|
+
var Camera = class extends Node {
|
|
326
|
+
zoom;
|
|
327
|
+
constructor(x = 0, y = 0, zoom = 1) {
|
|
328
|
+
super();
|
|
329
|
+
this.zoom = zoom;
|
|
330
|
+
}
|
|
331
|
+
update(deltaTime) {
|
|
332
|
+
}
|
|
333
|
+
transformCoordinates(position) {
|
|
334
|
+
return new Vector2D((position.x - this.pos.x) * this.zoom, (position.y - this.pos.y) * this.zoom);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// src/nodes/InputManager.ts
|
|
339
|
+
var InputManager = class extends Node {
|
|
340
|
+
keyState = /* @__PURE__ */ new Map();
|
|
341
|
+
keyJustPressed = /* @__PURE__ */ new Set();
|
|
342
|
+
mouseState = /* @__PURE__ */ new Map();
|
|
343
|
+
mouseJustPressed = /* @__PURE__ */ new Set();
|
|
344
|
+
constructor() {
|
|
345
|
+
super();
|
|
346
|
+
this.setupListeners();
|
|
347
|
+
}
|
|
348
|
+
setupListeners() {
|
|
349
|
+
window.addEventListener("keydown", this.handleKeyDown.bind(this));
|
|
350
|
+
window.addEventListener("keyup", this.handleKeyUp.bind(this));
|
|
351
|
+
window.addEventListener("mousedown", this.handleMouseDown.bind(this));
|
|
352
|
+
window.addEventListener("mouseup", this.handleMouseUp.bind(this));
|
|
353
|
+
}
|
|
354
|
+
handleKeyDown(event) {
|
|
355
|
+
const key = event.key;
|
|
356
|
+
if (!this.keyState.get(key)) {
|
|
357
|
+
this.keyState.set(key, true);
|
|
358
|
+
this.keyJustPressed.add(key);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
handleKeyUp(event) {
|
|
362
|
+
const key = event.key;
|
|
363
|
+
this.keyState.set(key, false);
|
|
364
|
+
this.keyJustPressed.delete(key);
|
|
365
|
+
}
|
|
366
|
+
handleMouseDown(event) {
|
|
367
|
+
const button = event.button;
|
|
368
|
+
if (!this.mouseState.get(button)) {
|
|
369
|
+
this.mouseState.set(button, true);
|
|
370
|
+
this.mouseJustPressed.add(button);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
handleMouseUp(event) {
|
|
374
|
+
const button = event.button;
|
|
375
|
+
this.mouseState.set(button, false);
|
|
376
|
+
this.mouseJustPressed.delete(button);
|
|
377
|
+
}
|
|
378
|
+
justPressed(keyOrButton) {
|
|
379
|
+
if (typeof keyOrButton === "string") {
|
|
380
|
+
return this.keyJustPressed.has(keyOrButton);
|
|
381
|
+
} else if (typeof keyOrButton === "number") {
|
|
382
|
+
return this.mouseJustPressed.has(keyOrButton);
|
|
383
|
+
}
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
isPressed(keyOrButton) {
|
|
387
|
+
if (typeof keyOrButton === "string") {
|
|
388
|
+
return !!this.keyState.get(keyOrButton);
|
|
389
|
+
} else if (typeof keyOrButton === "number") {
|
|
390
|
+
return !!this.mouseState.get(keyOrButton);
|
|
391
|
+
}
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
postUpdate() {
|
|
395
|
+
this.keyJustPressed.clear();
|
|
396
|
+
this.mouseJustPressed.clear();
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
// src/nodes/Scene.ts
|
|
401
|
+
var Scene = class extends Node {
|
|
402
|
+
camera;
|
|
403
|
+
inputManager;
|
|
404
|
+
ctx;
|
|
405
|
+
lastTime = 0;
|
|
406
|
+
totalTime = 0;
|
|
407
|
+
constructor(ctx, opts) {
|
|
408
|
+
super();
|
|
409
|
+
this.ctx = ctx;
|
|
410
|
+
this.camera = opts?.camera || new Camera();
|
|
411
|
+
this.inputManager = opts?.inputManager || new InputManager();
|
|
412
|
+
this.setup();
|
|
413
|
+
}
|
|
414
|
+
addObject(object) {
|
|
415
|
+
super.addObject(object);
|
|
416
|
+
object.scene = this;
|
|
417
|
+
}
|
|
418
|
+
setup() {
|
|
419
|
+
this.resizeCanvas();
|
|
420
|
+
}
|
|
421
|
+
resizeCanvas() {
|
|
422
|
+
const canvas = this.ctx.canvas;
|
|
423
|
+
const style = getComputedStyle(canvas);
|
|
424
|
+
const width = parseInt(style.width);
|
|
425
|
+
const height = parseInt(style.height);
|
|
426
|
+
canvas.width = width;
|
|
427
|
+
canvas.height = height;
|
|
428
|
+
}
|
|
429
|
+
update(deltaTime) {
|
|
430
|
+
this.camera.update(deltaTime);
|
|
431
|
+
this.children.forEach((child) => {
|
|
432
|
+
if (isUpdatable(child)) {
|
|
433
|
+
child.update(deltaTime);
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
draw(ctx) {
|
|
438
|
+
ctx.fillStyle = ctx.canvas.style.backgroundColor;
|
|
439
|
+
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
440
|
+
this.children.forEach((child) => {
|
|
441
|
+
if (isDrawable(child)) {
|
|
442
|
+
child.draw(ctx);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
gameLoop(callback, targetFPS = 60) {
|
|
447
|
+
const frameInterval = 1e3 / targetFPS;
|
|
448
|
+
let lastFrameTime = 0;
|
|
449
|
+
const loop = (currentTime) => {
|
|
450
|
+
try {
|
|
451
|
+
const elapsed = currentTime - lastFrameTime;
|
|
452
|
+
if (elapsed > frameInterval) {
|
|
453
|
+
const deltaTime = (currentTime - this.lastTime) / 1e3;
|
|
454
|
+
this.lastTime = currentTime;
|
|
455
|
+
this.totalTime += deltaTime;
|
|
456
|
+
lastFrameTime = currentTime - elapsed % frameInterval;
|
|
457
|
+
this.update(deltaTime);
|
|
458
|
+
this.draw(this.ctx);
|
|
459
|
+
if (callback) {
|
|
460
|
+
callback(deltaTime, this.totalTime);
|
|
461
|
+
}
|
|
462
|
+
this.inputManager.postUpdate();
|
|
463
|
+
}
|
|
464
|
+
} catch (error) {
|
|
465
|
+
console.error("Error in game loop:", error);
|
|
466
|
+
}
|
|
467
|
+
requestAnimationFrame(loop);
|
|
468
|
+
};
|
|
469
|
+
this.lastTime = performance.now();
|
|
470
|
+
requestAnimationFrame(loop);
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
function isUpdatable(obj) {
|
|
474
|
+
return "update" in obj;
|
|
475
|
+
}
|
|
476
|
+
function isDrawable(obj) {
|
|
477
|
+
return "draw" in obj;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// src/main.ts
|
|
481
|
+
function getCanvas(id) {
|
|
482
|
+
const canvas = document.getElementById(id);
|
|
483
|
+
if (!canvas) {
|
|
484
|
+
throw new Error(`Canvas with id "${id}" not found`);
|
|
485
|
+
}
|
|
486
|
+
return canvas;
|
|
487
|
+
}
|
|
488
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
489
|
+
0 && (module.exports = {
|
|
490
|
+
Camera,
|
|
491
|
+
Circle,
|
|
492
|
+
Node,
|
|
493
|
+
Scene,
|
|
494
|
+
TWO_PI,
|
|
495
|
+
Vector2D,
|
|
496
|
+
getCanvas
|
|
497
|
+
});
|