@jiant/canvable 0.0.3 → 0.0.5
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 -85
- package/dist/main.d.mts +89 -11
- package/dist/main.d.ts +89 -11
- package/dist/main.js +300 -60
- package/dist/main.mjs +296 -60
- package/package.json +7 -4
package/dist/main.js
CHANGED
|
@@ -24,8 +24,12 @@ __export(main_exports, {
|
|
|
24
24
|
Camera: () => Camera,
|
|
25
25
|
Circle: () => Circle,
|
|
26
26
|
CircleBoundingBox: () => CircleBoundingBox,
|
|
27
|
+
KinematicBody: () => KinematicBody,
|
|
27
28
|
Node: () => Node,
|
|
28
|
-
Scene: () =>
|
|
29
|
+
Scene: () => Scene,
|
|
30
|
+
Square: () => Square,
|
|
31
|
+
SquareBoundingBox: () => SquareBoundingBox,
|
|
32
|
+
StaticBody: () => StaticBody,
|
|
29
33
|
TWO_PI: () => TWO_PI,
|
|
30
34
|
Vector2D: () => Vector2D,
|
|
31
35
|
getCanvas: () => getCanvas
|
|
@@ -289,13 +293,14 @@ var Vector2D = class _Vector2D {
|
|
|
289
293
|
}
|
|
290
294
|
};
|
|
291
295
|
|
|
292
|
-
// src/nodes/Node.ts
|
|
296
|
+
// src/nodes/shapes/Node.ts
|
|
293
297
|
var import_uuid = require("uuid");
|
|
294
298
|
var Node = class {
|
|
295
299
|
pos;
|
|
296
300
|
id;
|
|
297
301
|
children = [];
|
|
298
302
|
scene;
|
|
303
|
+
boundingBox;
|
|
299
304
|
constructor(scene, config) {
|
|
300
305
|
this.scene = scene;
|
|
301
306
|
const { id, pos } = config || {};
|
|
@@ -322,25 +327,54 @@ var Node = class {
|
|
|
322
327
|
}
|
|
323
328
|
};
|
|
324
329
|
|
|
325
|
-
// src/nodes/BoundingBox.ts
|
|
330
|
+
// src/nodes/boundingBox/BoundingBox.ts
|
|
326
331
|
var BoundingBox = class extends Node {
|
|
327
332
|
};
|
|
328
333
|
|
|
329
|
-
// src/nodes/
|
|
330
|
-
var
|
|
331
|
-
|
|
332
|
-
constructor(
|
|
333
|
-
super();
|
|
334
|
-
this.
|
|
334
|
+
// src/nodes/boundingBox/SquareBoundingBox.ts
|
|
335
|
+
var SquareBoundingBox = class _SquareBoundingBox extends BoundingBox {
|
|
336
|
+
size;
|
|
337
|
+
constructor(scene, size) {
|
|
338
|
+
super(scene);
|
|
339
|
+
this.size = size || new Vector2D(10, 10);
|
|
335
340
|
}
|
|
336
|
-
|
|
341
|
+
checkCollision(other) {
|
|
342
|
+
if (other instanceof _SquareBoundingBox) {
|
|
343
|
+
const thisPoint = this.scene?.camera.transformCoordinates(new Vector2D(this.pos.x, this.pos.y));
|
|
344
|
+
const otherPoint = this.scene?.camera.transformCoordinates(new Vector2D(other.pos.x, other.pos.y));
|
|
345
|
+
if (!thisPoint || !otherPoint) return { isColliding: false };
|
|
346
|
+
const dx = Math.abs(thisPoint.x - otherPoint.x);
|
|
347
|
+
const dy = Math.abs(thisPoint.y - otherPoint.y);
|
|
348
|
+
const halfWidths = (this.size.x + other.size.x) / 2;
|
|
349
|
+
const halfHeights = (this.size.y + other.size.y) / 2;
|
|
350
|
+
if (dx < halfWidths && dy < halfHeights) {
|
|
351
|
+
const overlapX = halfWidths - dx;
|
|
352
|
+
const overlapY = halfHeights - dy;
|
|
353
|
+
if (overlapX < overlapY) {
|
|
354
|
+
const mtvX = thisPoint.x < otherPoint.x ? -overlapX : overlapX;
|
|
355
|
+
return { isColliding: true, mtv: new Vector2D(mtvX, 0) };
|
|
356
|
+
} else {
|
|
357
|
+
const mtvY = thisPoint.y < otherPoint.y ? -overlapY : overlapY;
|
|
358
|
+
return { isColliding: true, mtv: new Vector2D(0, mtvY) };
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (other instanceof CircleBoundingBox) {
|
|
363
|
+
const result = other.checkCollision(this);
|
|
364
|
+
if (result.isColliding && result.mtv) {
|
|
365
|
+
return { isColliding: true, mtv: new Vector2D(-result.mtv.x, -result.mtv.y) };
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return { isColliding: false };
|
|
337
369
|
}
|
|
338
|
-
|
|
339
|
-
|
|
370
|
+
isPointInside(_point) {
|
|
371
|
+
const x_inside = _point.x >= this.pos.x - this.size.x && _point.x <= this.pos.x + this.size.x;
|
|
372
|
+
const y_inside = _point.y >= this.pos.y - this.size.y && _point.y <= this.pos.y + this.size.y;
|
|
373
|
+
return x_inside && y_inside;
|
|
340
374
|
}
|
|
341
375
|
};
|
|
342
376
|
|
|
343
|
-
// src/nodes/CircleBoundingBox.ts
|
|
377
|
+
// src/nodes/boundingBox/CircleBoundingBox.ts
|
|
344
378
|
var CircleBoundingBox = class _CircleBoundingBox extends BoundingBox {
|
|
345
379
|
radius;
|
|
346
380
|
constructor(scene, radius) {
|
|
@@ -349,15 +383,28 @@ var CircleBoundingBox = class _CircleBoundingBox extends BoundingBox {
|
|
|
349
383
|
}
|
|
350
384
|
checkCollision(other) {
|
|
351
385
|
if (other instanceof _CircleBoundingBox) {
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
if (!thisPoint || !otherPoint) return false;
|
|
355
|
-
const dx = thisPoint.x - otherPoint.x;
|
|
356
|
-
const dy = thisPoint.y - otherPoint.y;
|
|
386
|
+
const dx = this.pos.x - other.pos.x;
|
|
387
|
+
const dy = this.pos.y - other.pos.y;
|
|
357
388
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
358
|
-
|
|
389
|
+
if (distance < this.radius + other.radius) {
|
|
390
|
+
const overlap = this.radius + other.radius - distance;
|
|
391
|
+
const mtv = distance === 0 ? new Vector2D(overlap, 0) : new Vector2D(dx / distance * overlap, dy / distance * overlap);
|
|
392
|
+
return { isColliding: true, mtv };
|
|
393
|
+
}
|
|
359
394
|
}
|
|
360
|
-
|
|
395
|
+
if (other instanceof SquareBoundingBox) {
|
|
396
|
+
const closestX = Math.max(other.pos.x - other.size.x / 2, Math.min(this.pos.x, other.pos.x + other.size.x / 2));
|
|
397
|
+
const closestY = Math.max(other.pos.y - other.size.y / 2, Math.min(this.pos.y, other.pos.y + other.size.y / 2));
|
|
398
|
+
const dx = this.pos.x - closestX;
|
|
399
|
+
const dy = this.pos.y - closestY;
|
|
400
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
401
|
+
if (distance < this.radius) {
|
|
402
|
+
const overlap = this.radius - distance;
|
|
403
|
+
const mtv = distance === 0 ? new Vector2D(overlap, 0) : new Vector2D(dx / distance * overlap, dy / distance * overlap);
|
|
404
|
+
return { isColliding: true, mtv };
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return { isColliding: false };
|
|
361
408
|
}
|
|
362
409
|
isPointInside(_point) {
|
|
363
410
|
const point = this.scene?.camera.transformCoordinates(_point);
|
|
@@ -369,40 +416,104 @@ var CircleBoundingBox = class _CircleBoundingBox extends BoundingBox {
|
|
|
369
416
|
}
|
|
370
417
|
};
|
|
371
418
|
|
|
372
|
-
// src/nodes/
|
|
373
|
-
var
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
this.
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
419
|
+
// src/nodes/Camera.ts
|
|
420
|
+
var Camera = class extends Node {
|
|
421
|
+
zoom;
|
|
422
|
+
constructor(zoom = 1) {
|
|
423
|
+
super();
|
|
424
|
+
this.zoom = zoom;
|
|
425
|
+
}
|
|
426
|
+
update(deltaTime) {
|
|
427
|
+
}
|
|
428
|
+
transformCoordinates(position) {
|
|
429
|
+
return new Vector2D((position.x - this.pos.x) * this.zoom, (position.y - this.pos.y) * this.zoom);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
// src/nodes/physics/StaticBody.ts
|
|
434
|
+
var StaticBody = class extends Node {
|
|
435
|
+
shape;
|
|
436
|
+
constructor(scene, shape) {
|
|
437
|
+
super(scene, { pos: shape.pos });
|
|
438
|
+
this.shape = shape;
|
|
439
|
+
this.pos = shape.pos;
|
|
440
|
+
}
|
|
441
|
+
update(_dt) {
|
|
442
|
+
if (this.shape.update && typeof this.shape.update === "function") {
|
|
443
|
+
this.shape.update(_dt);
|
|
386
444
|
}
|
|
387
445
|
}
|
|
388
446
|
draw(ctx, selected) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
447
|
+
if (this.shape.draw) this.shape.draw(ctx, selected);
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
// src/nodes/physics/KinematicBody.ts
|
|
452
|
+
var KinematicBody = class _KinematicBody extends Node {
|
|
453
|
+
shape;
|
|
454
|
+
velocity = new Vector2D();
|
|
455
|
+
speed = 1500;
|
|
456
|
+
friction = 0.92;
|
|
457
|
+
maxSpeed = 800;
|
|
458
|
+
isColliding = false;
|
|
459
|
+
constructor(scene, shape, config) {
|
|
460
|
+
super(scene, { pos: shape.pos });
|
|
461
|
+
this.shape = shape;
|
|
462
|
+
if (config?.speed) this.speed = config.speed;
|
|
463
|
+
if (config?.friction) this.friction = config.friction;
|
|
464
|
+
if (config?.maxSpeed) this.maxSpeed = config.maxSpeed;
|
|
465
|
+
}
|
|
466
|
+
applyForce(x, y, dt) {
|
|
467
|
+
const len = Math.sqrt(x * x + y * y);
|
|
468
|
+
if (len > 0) {
|
|
469
|
+
const scale = this.speed * dt / len;
|
|
470
|
+
this.velocity.x += x * scale;
|
|
471
|
+
this.velocity.y += y * scale;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
update(dt) {
|
|
475
|
+
this.velocity.x *= this.friction;
|
|
476
|
+
this.velocity.y *= this.friction;
|
|
477
|
+
const currentSpeed = Math.sqrt(this.velocity.x * this.velocity.x + this.velocity.y * this.velocity.y);
|
|
478
|
+
if (currentSpeed > this.maxSpeed) {
|
|
479
|
+
const scale = this.maxSpeed / currentSpeed;
|
|
480
|
+
this.velocity.x *= scale;
|
|
481
|
+
this.velocity.y *= scale;
|
|
482
|
+
}
|
|
483
|
+
if (Math.abs(this.velocity.x) < 0.1) this.velocity.x = 0;
|
|
484
|
+
if (Math.abs(this.velocity.y) < 0.1) this.velocity.y = 0;
|
|
485
|
+
this.pos.x += this.velocity.x * dt;
|
|
486
|
+
this.pos.y += this.velocity.y * dt;
|
|
487
|
+
this.shape.pos = this.pos;
|
|
488
|
+
if (this.shape.update) this.shape.update(dt);
|
|
489
|
+
this.resolveCollisions();
|
|
490
|
+
}
|
|
491
|
+
resolveCollisions() {
|
|
492
|
+
this.isColliding = false;
|
|
493
|
+
if (!this.shape.boundingBox) return;
|
|
494
|
+
if (!this.scene) return;
|
|
495
|
+
for (const obj of this.scene.children) {
|
|
496
|
+
if (obj === this) continue;
|
|
497
|
+
let otherBBox = null;
|
|
498
|
+
if (obj instanceof StaticBody || obj instanceof _KinematicBody) {
|
|
499
|
+
if (obj.shape.boundingBox) otherBBox = obj.shape.boundingBox;
|
|
500
|
+
} else {
|
|
501
|
+
if (obj.boundingBox) otherBBox = obj.boundingBox;
|
|
502
|
+
}
|
|
503
|
+
if (otherBBox) {
|
|
504
|
+
const result = this.shape.boundingBox.checkCollision(otherBBox);
|
|
505
|
+
if (result.isColliding && result.mtv) {
|
|
506
|
+
this.isColliding = true;
|
|
507
|
+
this.pos.x += result.mtv.x;
|
|
508
|
+
this.pos.y += result.mtv.y;
|
|
509
|
+
this.shape.pos = this.pos;
|
|
510
|
+
if (this.shape.boundingBox) this.shape.boundingBox.pos = this.pos;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
400
513
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
ctx.fill();
|
|
405
|
-
ctx.closePath();
|
|
514
|
+
}
|
|
515
|
+
draw(ctx, selected) {
|
|
516
|
+
if (this.shape.draw) this.shape.draw(ctx, selected);
|
|
406
517
|
}
|
|
407
518
|
};
|
|
408
519
|
|
|
@@ -428,14 +539,14 @@ var InputManager = class extends Node {
|
|
|
428
539
|
this.mousePos = new Vector2D(event.clientX, event.clientY);
|
|
429
540
|
}
|
|
430
541
|
handleKeyDown(event) {
|
|
431
|
-
const key = event.
|
|
542
|
+
const key = event.code;
|
|
432
543
|
if (!this.keyState.get(key)) {
|
|
433
544
|
this.keyState.set(key, true);
|
|
434
545
|
this.keyJustPressed.add(key);
|
|
435
546
|
}
|
|
436
547
|
}
|
|
437
548
|
handleKeyUp(event) {
|
|
438
|
-
const key = event.
|
|
549
|
+
const key = event.code;
|
|
439
550
|
this.keyState.set(key, false);
|
|
440
551
|
this.keyJustPressed.delete(key);
|
|
441
552
|
}
|
|
@@ -474,10 +585,12 @@ var InputManager = class extends Node {
|
|
|
474
585
|
};
|
|
475
586
|
|
|
476
587
|
// src/nodes/Scene.ts
|
|
477
|
-
var
|
|
588
|
+
var Scene = class extends Node {
|
|
478
589
|
camera;
|
|
479
590
|
inputManager;
|
|
480
591
|
ctx;
|
|
592
|
+
animationFrameId = null;
|
|
593
|
+
running = false;
|
|
481
594
|
lastTime = 0;
|
|
482
595
|
totalTime = 0;
|
|
483
596
|
constructor(ctx, opts) {
|
|
@@ -502,7 +615,7 @@ var Scene2 = class extends Node {
|
|
|
502
615
|
canvas.width = width;
|
|
503
616
|
canvas.height = height;
|
|
504
617
|
}
|
|
505
|
-
|
|
618
|
+
updateFrame(deltaTime) {
|
|
506
619
|
this.camera.update(deltaTime);
|
|
507
620
|
this.children.forEach((child) => {
|
|
508
621
|
if (isUpdatable(child)) {
|
|
@@ -510,16 +623,20 @@ var Scene2 = class extends Node {
|
|
|
510
623
|
}
|
|
511
624
|
});
|
|
512
625
|
}
|
|
513
|
-
|
|
514
|
-
ctx.fillStyle = ctx.canvas.style.backgroundColor;
|
|
626
|
+
drawFrame(ctx) {
|
|
627
|
+
ctx.fillStyle = ctx.canvas.style.backgroundColor || "black";
|
|
515
628
|
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
629
|
+
ctx.save();
|
|
630
|
+
ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2);
|
|
516
631
|
this.children.forEach((child) => {
|
|
517
632
|
if (isDrawable(child)) {
|
|
518
633
|
child.draw(ctx);
|
|
519
634
|
}
|
|
520
635
|
});
|
|
636
|
+
ctx.restore();
|
|
521
637
|
}
|
|
522
|
-
|
|
638
|
+
run(callback, targetFPS = 60) {
|
|
639
|
+
this.running = true;
|
|
523
640
|
const frameInterval = 1e3 / targetFPS;
|
|
524
641
|
let lastFrameTime = 0;
|
|
525
642
|
const loop = (currentTime) => {
|
|
@@ -530,8 +647,8 @@ var Scene2 = class extends Node {
|
|
|
530
647
|
this.lastTime = currentTime;
|
|
531
648
|
this.totalTime += deltaTime;
|
|
532
649
|
lastFrameTime = currentTime - elapsed % frameInterval;
|
|
533
|
-
this.
|
|
534
|
-
this.
|
|
650
|
+
this.updateFrame(deltaTime);
|
|
651
|
+
this.drawFrame(this.ctx);
|
|
535
652
|
if (callback) {
|
|
536
653
|
callback(deltaTime, this.totalTime);
|
|
537
654
|
}
|
|
@@ -543,7 +660,14 @@ var Scene2 = class extends Node {
|
|
|
543
660
|
requestAnimationFrame(loop);
|
|
544
661
|
};
|
|
545
662
|
this.lastTime = performance.now();
|
|
546
|
-
requestAnimationFrame(loop);
|
|
663
|
+
this.animationFrameId = requestAnimationFrame(loop);
|
|
664
|
+
}
|
|
665
|
+
stop() {
|
|
666
|
+
if (this.animationFrameId) {
|
|
667
|
+
cancelAnimationFrame(this.animationFrameId);
|
|
668
|
+
this.animationFrameId = null;
|
|
669
|
+
}
|
|
670
|
+
this.running = false;
|
|
547
671
|
}
|
|
548
672
|
};
|
|
549
673
|
function isUpdatable(obj) {
|
|
@@ -553,6 +677,118 @@ function isDrawable(obj) {
|
|
|
553
677
|
return "draw" in obj;
|
|
554
678
|
}
|
|
555
679
|
|
|
680
|
+
// src/nodes/shapes/Circle.ts
|
|
681
|
+
var Circle = class extends Node {
|
|
682
|
+
vel = new Vector2D();
|
|
683
|
+
size = 10;
|
|
684
|
+
friction = 0.1;
|
|
685
|
+
style = {
|
|
686
|
+
fillStyle: "blue"
|
|
687
|
+
};
|
|
688
|
+
constructor(scene, config) {
|
|
689
|
+
super(scene);
|
|
690
|
+
this.vel = config?.vel || new Vector2D();
|
|
691
|
+
this.size = config?.size || 10;
|
|
692
|
+
this.friction = config?.friction || 0.1;
|
|
693
|
+
this.style = { ...this.style, ...config?.style };
|
|
694
|
+
if (config?.startsWithBoundingBox) {
|
|
695
|
+
this.boundingBox = new CircleBoundingBox(scene, this.size);
|
|
696
|
+
this.addObject(this.boundingBox);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
update(_deltaTime) {
|
|
700
|
+
if (this.boundingBox) {
|
|
701
|
+
this.boundingBox.pos = this.pos;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
draw(ctx, selected) {
|
|
705
|
+
const cameraPos = this.scene?.camera.pos || new Vector2D();
|
|
706
|
+
const cameraScale = this.scene?.camera.zoom || 1;
|
|
707
|
+
const relativePos = new Vector2D((this.pos.x - cameraPos.x) * cameraScale, (this.pos.y - cameraPos.y) * cameraScale);
|
|
708
|
+
if (selected) {
|
|
709
|
+
ctx.beginPath();
|
|
710
|
+
ctx.arc(relativePos.x, relativePos.y, this.size + 5, 0, Math.PI * 2);
|
|
711
|
+
ctx.fillStyle = "transparent";
|
|
712
|
+
ctx.lineWidth = 3;
|
|
713
|
+
ctx.strokeStyle = "white";
|
|
714
|
+
ctx.stroke();
|
|
715
|
+
ctx.closePath();
|
|
716
|
+
}
|
|
717
|
+
ctx.beginPath();
|
|
718
|
+
ctx.arc(relativePos.x, relativePos.y, this.size, 0, Math.PI * 2);
|
|
719
|
+
ctx.fillStyle = this.style.fillStyle || "blue";
|
|
720
|
+
ctx.fill();
|
|
721
|
+
if (this.style.strokeStyle) {
|
|
722
|
+
ctx.strokeStyle = this.style.strokeStyle;
|
|
723
|
+
ctx.lineWidth = this.style.lineWidth || 1;
|
|
724
|
+
ctx.stroke();
|
|
725
|
+
}
|
|
726
|
+
ctx.closePath();
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
// src/nodes/shapes/Square.ts
|
|
731
|
+
var Square = class extends Node {
|
|
732
|
+
vel = new Vector2D();
|
|
733
|
+
size;
|
|
734
|
+
friction = 0.1;
|
|
735
|
+
style = {
|
|
736
|
+
fillStyle: "orange"
|
|
737
|
+
};
|
|
738
|
+
constructor(scene, config) {
|
|
739
|
+
super(scene);
|
|
740
|
+
this.vel = config?.vel || new Vector2D();
|
|
741
|
+
this.size = config?.size || new Vector2D(10, 10);
|
|
742
|
+
this.friction = config?.friction || 0.1;
|
|
743
|
+
this.style = { ...this.style, ...config?.style };
|
|
744
|
+
if (config?.startsWithBoundingBox) {
|
|
745
|
+
this.boundingBox = new SquareBoundingBox(scene, this.size);
|
|
746
|
+
this.addObject(this.boundingBox);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
update(_deltaTime) {
|
|
750
|
+
if (this.boundingBox) {
|
|
751
|
+
this.boundingBox.pos = this.pos;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
draw(ctx, selected) {
|
|
755
|
+
const cameraPos = this.scene?.camera.pos || new Vector2D();
|
|
756
|
+
const cameraScale = this.scene?.camera.zoom || 1;
|
|
757
|
+
const relativePos = new Vector2D(
|
|
758
|
+
(this.pos.x - cameraPos.x) * cameraScale,
|
|
759
|
+
(this.pos.y - cameraPos.y) * cameraScale
|
|
760
|
+
);
|
|
761
|
+
const scaledSize = new Vector2D(this.size.x * cameraScale, this.size.y * cameraScale);
|
|
762
|
+
if (selected) {
|
|
763
|
+
ctx.strokeStyle = "white";
|
|
764
|
+
ctx.lineWidth = 3;
|
|
765
|
+
ctx.strokeRect(
|
|
766
|
+
relativePos.x - scaledSize.x / 2 - 5,
|
|
767
|
+
relativePos.y - scaledSize.y / 2 - 5,
|
|
768
|
+
scaledSize.x + 10,
|
|
769
|
+
scaledSize.y + 10
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
ctx.fillStyle = this.style.fillStyle || "orange";
|
|
773
|
+
ctx.fillRect(
|
|
774
|
+
relativePos.x - scaledSize.x / 2,
|
|
775
|
+
relativePos.y - scaledSize.y / 2,
|
|
776
|
+
scaledSize.x,
|
|
777
|
+
scaledSize.y
|
|
778
|
+
);
|
|
779
|
+
if (this.style.strokeStyle) {
|
|
780
|
+
ctx.strokeStyle = this.style.strokeStyle;
|
|
781
|
+
ctx.lineWidth = this.style.lineWidth || 1;
|
|
782
|
+
ctx.strokeRect(
|
|
783
|
+
relativePos.x - scaledSize.x / 2,
|
|
784
|
+
relativePos.y - scaledSize.y / 2,
|
|
785
|
+
scaledSize.x,
|
|
786
|
+
scaledSize.y
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
|
|
556
792
|
// src/main.ts
|
|
557
793
|
function getCanvas(id) {
|
|
558
794
|
const canvas = document.getElementById(id);
|
|
@@ -567,8 +803,12 @@ function getCanvas(id) {
|
|
|
567
803
|
Camera,
|
|
568
804
|
Circle,
|
|
569
805
|
CircleBoundingBox,
|
|
806
|
+
KinematicBody,
|
|
570
807
|
Node,
|
|
571
808
|
Scene,
|
|
809
|
+
Square,
|
|
810
|
+
SquareBoundingBox,
|
|
811
|
+
StaticBody,
|
|
572
812
|
TWO_PI,
|
|
573
813
|
Vector2D,
|
|
574
814
|
getCanvas
|