@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/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
+ });