@litecanvas/utils 0.44.1 → 0.46.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.
package/README.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Small collection of tools for developing games with [Litecanvas](https://github.com/litecanvas/game-engine).
4
4
 
5
+ <!-- prettier-ignore -->
6
+ > [!TIP]
7
+ > **All modules of this package are automatically loaded on Litecanvas [playground](https://litecanvas.js.org/).**
8
+
5
9
  ## Install
6
10
 
7
11
  ### NPM package
package/dist/actor.js CHANGED
@@ -54,6 +54,25 @@
54
54
  return new Vector(x, y);
55
55
  };
56
56
 
57
+ // src/debug/assert.js
58
+ var assert_default = (condition, message = "Assertion failed") => {
59
+ if (!condition) throw new Error(message);
60
+ };
61
+
62
+ // src/collision/colrectcirc.js
63
+ var colrectcirc_default = (x1, y1, w1, h1, x2, y2, r2) => {
64
+ DEV: assert_default(isFinite(x1), "colrect: 1st param must be a number");
65
+ DEV: assert_default(isFinite(y1), "colrect: 2nd param must be a number");
66
+ DEV: assert_default(isFinite(w1), "colrect: 3rd param must be a number");
67
+ DEV: assert_default(isFinite(h1), "colrect: 4th param must be a number");
68
+ DEV: assert_default(isFinite(x2), "colcirc: 5th param must be a number");
69
+ DEV: assert_default(isFinite(y2), "colcirc: 6th param must be a number");
70
+ DEV: assert_default(isFinite(r2), "colcirc: 7th param must be a number");
71
+ let xx = x2 - Math.max(x1, Math.min(x2, x1 + w1));
72
+ let yy = y2 - Math.max(y1, Math.min(y2, y1 + h1));
73
+ return xx * xx + yy * yy <= r2 * r2;
74
+ };
75
+
57
76
  // src/actor/index.js
58
77
  var ANCHOR_CENTER = /* @__PURE__ */ vec(0.5, 0.5);
59
78
  var ANCHOR_TOP_LEFT = /* @__PURE__ */ vec(0, 0);
@@ -80,7 +99,7 @@
80
99
  /** @type {boolean} If `true` the actor will not be drawn. */
81
100
  hidden = false;
82
101
  /**
83
- * @param {Image|HTMLCanvasElement|OffscreenCanvas} sprite
102
+ * @param {Image|HTMLCanvasElement|OffscreenCanvas|ImageBitmap} sprite
84
103
  * @param {Vector} position
85
104
  * @param {Vector} anchor
86
105
  */
@@ -166,6 +185,7 @@
166
185
  this._s.y *= y;
167
186
  }
168
187
  /**
188
+ * @param {boolean} scaled
169
189
  * @returns {number[]}
170
190
  */
171
191
  getBounds(scaled = true) {
@@ -175,6 +195,27 @@
175
195
  const y = this.pos.y - h * this.anchor.y;
176
196
  return [x, y, w, h];
177
197
  }
198
+ /**
199
+ * Checks if the actor is colliding with a point (with optional radius).
200
+ * Useful to check clicks or touchs.
201
+ *
202
+ * @param {number} x
203
+ * @param {number} y
204
+ * @param {number} [radius=1]
205
+ * @returns {boolean}
206
+ */
207
+ in(x, y, radius = 1) {
208
+ return colrectcirc_default(...this.getBounds(), x, y, radius);
209
+ }
210
+ /**
211
+ * Checks if the actor is colliding with another actor.
212
+ *
213
+ * @param {Actor} other
214
+ * @returns {boolean}
215
+ */
216
+ col(other) {
217
+ return colrect(...this.getBounds(), ...other.getBounds());
218
+ }
178
219
  /**
179
220
  * Draw the actor
180
221
  *
@@ -191,7 +232,7 @@
191
232
  /**
192
233
  * @param {LitecanvasInstance} engine
193
234
  */
194
- transform(engine) {
235
+ transform(engine = globalThis) {
195
236
  engine.translate(this.pos.x, this.pos.y);
196
237
  engine.rotate(engine.deg2rad(this.angle));
197
238
  engine.scale(
@@ -201,8 +242,9 @@
201
242
  }
202
243
  /**
203
244
  * @param {LitecanvasInstance} engine
245
+ * @param {boolean} alpha
204
246
  */
205
- drawImage(engine, alpha = true) {
247
+ drawImage(engine = globalThis, alpha = true) {
206
248
  const anchor = this.anchor;
207
249
  const x = -this.sprite.width * (this.flipX ? 1 - anchor.x : anchor.x);
208
250
  const y = -this.sprite.height * (this.flipY ? 1 - anchor.y : anchor.y);
package/dist/actor.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var x=Object.defineProperty;var a=(o,t)=>{for(var s in t)x(o,s,{get:t[s],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(o=!0)=>{for(let t in globalThis.utils)t!=="global"&&(o||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var p={};a(p,{ANCHOR_BOT_LEFT:()=>g,ANCHOR_BOT_RIGHT:()=>d,ANCHOR_CENTER:()=>u,ANCHOR_TOP_LEFT:()=>y,ANCHOR_TOP_RIGHT:()=>f,Actor:()=>h});var T=2*Math.PI,i=class{constructor(t=0,s=t){this.x=parseFloat(t)||0,this.y=parseFloat(s)||0}toString(){return`Vector (${this.x}, ${this.y})`}},l=o=>o instanceof i,e=(o=0,t=o)=>(l(o)&&(t=o.y,o=o.x),new i(o,t));var u=e(.5,.5),y=e(0,0),f=e(1,0),g=e(0,1),d=e(1,1),h=class{sprite;pos;_o;_s;flipX=!1;flipY=!1;angle=0;opacity=1;hidden=!1;constructor(t,s,r=y){this.sprite=t||{width:0,height:0},this.pos=s||e(0),this._o=e(r),this._s=e(1,1)}set x(t){this.pos.x=t}get x(){return this.pos.x}set y(t){this.pos.y=t}get y(){return this.pos.y}set anchor(t){this._o.x=t.x,this._o.y=t.y}get anchor(){return this._o}get width(){return this.sprite.width*this._s.x}get height(){return this.sprite.height*this._s.y}get scale(){return this._s}scaleTo(t,s=t){this._s.x=t,this._s.y=s}scaleBy(t,s=t){this._s.x*=t,this._s.y*=s}getBounds(t=!0){let s=this.sprite.width*(t?this._s.x:1),r=this.sprite.height*(t?this._s.y:1),c=this.pos.x-s*this.anchor.x,n=this.pos.y-r*this.anchor.y;return[c,n,s,r]}draw(t=globalThis,s=!0){s&&t.push(),this.transform(t),this.sprite.width&&this.sprite.height&&!this.hidden&&this.opacity>0&&this.drawImage(t),s&&t.pop()}transform(t){t.translate(this.pos.x,this.pos.y),t.rotate(t.deg2rad(this.angle)),t.scale((this.flipX?-1:1)*this._s.x,(this.flipY?-1:1)*this._s.y)}drawImage(t,s=!0){let r=this.anchor,c=-this.sprite.width*(this.flipX?1-r.x:r.x),n=-this.sprite.height*(this.flipY?1-r.y:r.y);s&&t.alpha(this.opacity),t.image(c,n,this.sprite)}};globalThis.utils=Object.assign(globalThis.utils||{},p);})();
1
+ (()=>{var f=Object.defineProperty;var g=(r,t)=>{for(var s in t)f(r,s,{get:t[s],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(r=!0)=>{for(let t in globalThis.utils)t!=="global"&&(r||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var a={};g(a,{ANCHOR_BOT_LEFT:()=>_,ANCHOR_BOT_RIGHT:()=>T,ANCHOR_CENTER:()=>m,ANCHOR_TOP_LEFT:()=>u,ANCHOR_TOP_RIGHT:()=>b,Actor:()=>h});var w=2*Math.PI,n=class{constructor(t=0,s=t){this.x=parseFloat(t)||0,this.y=parseFloat(s)||0}toString(){return`Vector (${this.x}, ${this.y})`}},d=r=>r instanceof n,o=(r=0,t=r)=>(d(r)&&(t=r.y,r=r.x),new n(r,t));var y=(r,t,s,e,i,c,p)=>{let x=i-Math.max(r,Math.min(i,r+s)),l=c-Math.max(t,Math.min(c,t+e));return x*x+l*l<=p*p};var m=o(.5,.5),u=o(0,0),b=o(1,0),_=o(0,1),T=o(1,1),h=class{sprite;pos;_o;_s;flipX=!1;flipY=!1;angle=0;opacity=1;hidden=!1;constructor(t,s,e=u){this.sprite=t||{width:0,height:0},this.pos=s||o(0),this._o=o(e),this._s=o(1,1)}set x(t){this.pos.x=t}get x(){return this.pos.x}set y(t){this.pos.y=t}get y(){return this.pos.y}set anchor(t){this._o.x=t.x,this._o.y=t.y}get anchor(){return this._o}get width(){return this.sprite.width*this._s.x}get height(){return this.sprite.height*this._s.y}get scale(){return this._s}scaleTo(t,s=t){this._s.x=t,this._s.y=s}scaleBy(t,s=t){this._s.x*=t,this._s.y*=s}getBounds(t=!0){let s=this.sprite.width*(t?this._s.x:1),e=this.sprite.height*(t?this._s.y:1),i=this.pos.x-s*this.anchor.x,c=this.pos.y-e*this.anchor.y;return[i,c,s,e]}in(t,s,e=1){return y(...this.getBounds(),t,s,e)}col(t){return colrect(...this.getBounds(),...t.getBounds())}draw(t=globalThis,s=!0){s&&t.push(),this.transform(t),this.sprite.width&&this.sprite.height&&!this.hidden&&this.opacity>0&&this.drawImage(t),s&&t.pop()}transform(t=globalThis){t.translate(this.pos.x,this.pos.y),t.rotate(t.deg2rad(this.angle)),t.scale((this.flipX?-1:1)*this._s.x,(this.flipY?-1:1)*this._s.y)}drawImage(t=globalThis,s=!0){let e=this.anchor,i=-this.sprite.width*(this.flipX?1-e.x:e.x),c=-this.sprite.height*(this.flipY?1-e.y:e.y);s&&t.alpha(this.opacity),t.image(i,c,this.sprite)}};globalThis.utils=Object.assign(globalThis.utils||{},a);})();
package/dist/all.js CHANGED
@@ -54,6 +54,7 @@
54
54
  choose: () => choose_default,
55
55
  colcirc: () => colcirc_default,
56
56
  colrect: () => colrect_default,
57
+ colrectcirc: () => colrectcirc_default,
57
58
  dd: () => dd_default,
58
59
  diff: () => diff_default,
59
60
  dist: () => dist_default,
@@ -65,7 +66,6 @@
65
66
  is: () => is_default,
66
67
  last: () => last_default,
67
68
  lerpAngle: () => lerp_angle_default,
68
- log: () => log_default,
69
69
  lpad: () => lpad_default,
70
70
  mag: () => mag_default,
71
71
  makeCircle: () => make_circle_default,
@@ -114,7 +114,8 @@
114
114
  vecSet: () => vecSet,
115
115
  vecSetMag: () => vecSetMag,
116
116
  vecSub: () => vecSub,
117
- vecToArray: () => vecToArray
117
+ vecToArray: () => vecToArray,
118
+ wave: () => wave_default
118
119
  });
119
120
 
120
121
  // src/camera/index.js
@@ -358,6 +359,20 @@
358
359
  return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) <= (r1 + r2) * (r1 + r2);
359
360
  };
360
361
 
362
+ // src/collision/colrectcirc.js
363
+ var colrectcirc_default = (x1, y1, w1, h1, x2, y2, r2) => {
364
+ DEV: assert_default(isFinite(x1), "colrect: 1st param must be a number");
365
+ DEV: assert_default(isFinite(y1), "colrect: 2nd param must be a number");
366
+ DEV: assert_default(isFinite(w1), "colrect: 3rd param must be a number");
367
+ DEV: assert_default(isFinite(h1), "colrect: 4th param must be a number");
368
+ DEV: assert_default(isFinite(x2), "colcirc: 5th param must be a number");
369
+ DEV: assert_default(isFinite(y2), "colcirc: 6th param must be a number");
370
+ DEV: assert_default(isFinite(r2), "colcirc: 7th param must be a number");
371
+ let xx = x2 - Math.max(x1, Math.min(x2, x1 + w1));
372
+ let yy = y2 - Math.max(y1, Math.min(y2, y1 + h1));
373
+ return xx * xx + yy * yy <= r2 * r2;
374
+ };
375
+
361
376
  // src/grid/index.js
362
377
  var Grid = class _Grid {
363
378
  /** @type {number} The grid width */
@@ -785,7 +800,7 @@
785
800
  /** @type {boolean} If `true` the actor will not be drawn. */
786
801
  hidden = false;
787
802
  /**
788
- * @param {Image|HTMLCanvasElement|OffscreenCanvas} sprite
803
+ * @param {Image|HTMLCanvasElement|OffscreenCanvas|ImageBitmap} sprite
789
804
  * @param {Vector} position
790
805
  * @param {Vector} anchor
791
806
  */
@@ -871,6 +886,7 @@
871
886
  this._s.y *= y;
872
887
  }
873
888
  /**
889
+ * @param {boolean} scaled
874
890
  * @returns {number[]}
875
891
  */
876
892
  getBounds(scaled = true) {
@@ -880,6 +896,27 @@
880
896
  const y = this.pos.y - h * this.anchor.y;
881
897
  return [x, y, w, h];
882
898
  }
899
+ /**
900
+ * Checks if the actor is colliding with a point (with optional radius).
901
+ * Useful to check clicks or touchs.
902
+ *
903
+ * @param {number} x
904
+ * @param {number} y
905
+ * @param {number} [radius=1]
906
+ * @returns {boolean}
907
+ */
908
+ in(x, y, radius = 1) {
909
+ return colrectcirc_default(...this.getBounds(), x, y, radius);
910
+ }
911
+ /**
912
+ * Checks if the actor is colliding with another actor.
913
+ *
914
+ * @param {Actor} other
915
+ * @returns {boolean}
916
+ */
917
+ col(other) {
918
+ return colrect(...this.getBounds(), ...other.getBounds());
919
+ }
883
920
  /**
884
921
  * Draw the actor
885
922
  *
@@ -896,7 +933,7 @@
896
933
  /**
897
934
  * @param {LitecanvasInstance} engine
898
935
  */
899
- transform(engine) {
936
+ transform(engine = globalThis) {
900
937
  engine.translate(this.pos.x, this.pos.y);
901
938
  engine.rotate(engine.deg2rad(this.angle));
902
939
  engine.scale(
@@ -906,8 +943,9 @@
906
943
  }
907
944
  /**
908
945
  * @param {LitecanvasInstance} engine
946
+ * @param {boolean} alpha
909
947
  */
910
- drawImage(engine, alpha = true) {
948
+ drawImage(engine = globalThis, alpha = true) {
911
949
  const anchor = this.anchor;
912
950
  const x = -this.sprite.width * (this.flipX ? 1 - anchor.x : anchor.x);
913
951
  const y = -this.sprite.height * (this.flipY ? 1 - anchor.y : anchor.y);
@@ -986,6 +1024,18 @@
986
1024
  // src/math/percent.js
987
1025
  var percent_default = (value, min = 0, max = 1) => max - min ? (value - min) / (max - min) : 0;
988
1026
 
1027
+ // src/math/wave.js
1028
+ var wave_default = (from, to, t, fn = Math.sin) => {
1029
+ DEV: assert_default(isNumber(from), "[litecanvas] wave() 1st param must be a number");
1030
+ DEV: assert_default(isNumber(to), "[litecanvas] wave() 2nd param must be a number");
1031
+ DEV: assert_default(isNumber(t), "[litecanvas] wave() 3rd param must be a number");
1032
+ DEV: assert_default(
1033
+ "function" === typeof fn,
1034
+ "[litecanvas] wave() 4rd param must be a function (n: number) => number"
1035
+ );
1036
+ return from + (fn(t) + 1) / 2 * (to - from);
1037
+ };
1038
+
989
1039
  // src/tween/index.js
990
1040
  var HALF_PI = Math.PI / 2;
991
1041
  var tween = (object, prop, toValue, duration = 1, easing = LINEAR) => {
@@ -1448,15 +1498,6 @@
1448
1498
  return typeof value === type;
1449
1499
  };
1450
1500
 
1451
- // src/debug/log.js
1452
- var log_default = (data, context, engine = globalThis) => {
1453
- return engine.text(
1454
- 16,
1455
- 16,
1456
- (context ? `${context}: ` : "") + (is_default(data, "object") ? JSON.stringify(data, null, 4) : data)
1457
- );
1458
- };
1459
-
1460
1501
  // src/debug/dd.js
1461
1502
  var dd_default = (data, context, engine = globalThis) => {
1462
1503
  engine.pal(["blue", "#fff"]);
@@ -1465,7 +1506,11 @@
1465
1506
  engine.textfont("monospace");
1466
1507
  engine.textsize(16);
1467
1508
  engine.textalign("start", "top");
1468
- log_default(data, context || "dd() output", engine);
1509
+ engine.text(
1510
+ 16,
1511
+ 16,
1512
+ `${context ?? "dd() output"}: ` + (is_default(data, "object") ? JSON.stringify(data, null, 4) : data)
1513
+ );
1469
1514
  engine.quit();
1470
1515
  };
1471
1516
 
package/dist/all.min.js CHANGED
@@ -1,3 +1,3 @@
1
- (()=>{var Lt=Object.defineProperty;var St=(s,t)=>{for(var e in t)Lt(s,e,{get:t[e],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(s=!0)=>{for(let t in globalThis.utils)t!=="global"&&(s||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var H={};St(H,{ANCHOR_BOT_LEFT:()=>is,ANCHOR_BOT_RIGHT:()=>hs,ANCHOR_CENTER:()=>rs,ANCHOR_TOP_LEFT:()=>et,ANCHOR_TOP_RIGHT:()=>os,Actor:()=>C,BACK_IN:()=>ps,BACK_IN_OUT:()=>fs,BACK_OUT:()=>us,BOUNCE_IN:()=>_t,BOUNCE_IN_OUT:()=>ds,BOUNCE_OUT:()=>Y,Camera:()=>g,DOWN:()=>ss,EASE_IN:()=>ns,EASE_IN_OUT:()=>cs,EASE_OUT:()=>ls,ELASTIC_IN:()=>_s,ELASTIC_IN_OUT:()=>ms,ELASTIC_OUT:()=>xs,Grid:()=>M,LEFT:()=>es,LINEAR:()=>ft,Noise:()=>U,ONE:()=>Qt,RIGHT:()=>ts,TypedGrid:()=>N,UP:()=>vt,Vector:()=>I,ZERO:()=>st,advance:()=>it,assert:()=>D,choose:()=>bt,colcirc:()=>j,colrect:()=>V,dd:()=>Nt,diff:()=>rt,dist:()=>at,flipImage:()=>xt,formatTime:()=>Tt,fract:()=>ot,head:()=>Mt,intersection:()=>b,is:()=>R,last:()=>wt,lerpAngle:()=>pt,log:()=>A,lpad:()=>At,mag:()=>nt,makeCircle:()=>yt,makeRectangle:()=>gt,mean:()=>lt,median:()=>ct,mod:()=>ht,percent:()=>ut,range:()=>It,resolverect:()=>X,rpad:()=>Rt,scaleImage:()=>mt,shuffle:()=>Et,sum:()=>P,tail:()=>Pt,tintImage:()=>dt,tween:()=>as,vec:()=>h,vecAbs:()=>Xt,vecAdd:()=>L,vecAngle:()=>Zt,vecAngleBetween:()=>Ut,vecCeil:()=>Dt,vecClamp:()=>qt,vecCross:()=>Ht,vecDist:()=>Bt,vecDist2:()=>Yt,vecDiv:()=>k,vecDot:()=>tt,vecEq:()=>F,vecFloor:()=>Vt,vecHeading:()=>v,vecIsZero:()=>$t,vecLerp:()=>Wt,vecLimit:()=>Ct,vecMag:()=>J,vecMag2:()=>Q,vecMove:()=>Kt,vecMult:()=>w,vecNorm:()=>O,vecRand:()=>Jt,vecReflect:()=>Ft,vecRem:()=>zt,vecRotate:()=>Ot,vecRound:()=>jt,vecSet:()=>$,vecSetMag:()=>G,vecSub:()=>S,vecToArray:()=>Gt});var g=class{_engine=null;x=0;y=0;ox=0;oy=0;width=0;height=0;rotation=0;scale=1;constructor(t=null,e=0,r=0,o=null,i=null){this._engine=t||globalThis,this.ox=e,this.oy=r,this.resize(o||this._engine.W-e,i||this._engine.H-r),this.x=this.width/2,this.y=this.height/2,this._shake={x:0,y:0,removeListener:null}}resize(t,e){this.width=t,this.height=e,this._engine.emit("camera-resized",this)}start(t=!1){this._engine.push(),t&&this._engine.clip(o=>{o.rect(this.ox,this.oy,this.width,this.height)});let e=this.ox+this.width/2,r=this.oy+this.height/2;this._engine.translate(e,r),this._engine.scale(this.scale),this._engine.rotate(this.rotation),this._engine.translate(-this.x+this._shake.x,-this.y+this._shake.y)}end(){this._engine.pop()}lookAt(t,e){this.x=t,this.y=e}move(t,e){this.x+=t,this.y+=e}zoom(t){this.scale*=t}zoomTo(t){this.scale=t}rotate(t){this.rotation+=t}rotateTo(t){this.rotation=t}getWorldPoint(t,e,r={}){let o=Math.cos(-this.rotation),i=Math.sin(-this.rotation);return t=(t-this.width/2-this.ox)/this.scale,e=(e-this.height/2-this.oy)/this.scale,r.x=o*t-i*e+this.x,r.y=i*t+o*e+this.y,r}getCameraPoint(t,e,r={}){let o=Math.cos(-this.rotation),i=Math.sin(-this.rotation);return t=t-this.x,e=e-this.y,t=o*t-i*e,e=i*t+o*e,r.x=t*this.scale+this.width/2+this.ox,r.y=e*this.scale+this.height/2+this.oy,r}getBounds(){return[this.ox,this.oy,this.width,this.height]}shake(t=1,e=.3){this.shaking||(this._shake.removeListener=this._engine.listen("update",r=>{this._shake.x=this._engine.randi(-t,t),this._shake.y=this._engine.randi(-t,t),e-=r,e<=0&&this.unshake()}))}unshake(){this.shaking&&(this._shake.removeListener(),this._shake.removeListener=null,this._shake.x=this._shake.y=0)}get shaking(){return this._shake.removeListener!==null}};var b=(s,t,e,r,o,i,a,n)=>{let l=Math.max(s,o),x=Math.min(s+e,o+a)-l,p=Math.max(t,i),m=Math.min(t+r,i+n)-p;return[l,p,x,m]};var X=(s,t,e,r,o,i,a,n)=>{let[l,x,p,m]=b(s,t,e,r,o,i,a,n),_="",y=s,c=t;return p<m?s<o?(_="right",y=o-e):(_="left",y=o+a):t<i?(_="bottom",c=i-r):(_="top",c=i+n),{dir:_,x:y,y:c}};var D=(s,t="Assertion failed")=>{if(!s)throw new Error(t)};var V=(s,t,e,r,o,i,a,n)=>s<o+a&&s+e>o&&t<i+n&&t+r>i;var j=(s,t,e,r,o,i)=>(r-s)*(r-s)+(o-t)*(o-t)<=(e+i)*(e+i);var M=class s{_w;_h;_c;constructor(t,e,r=[]){this._w=Math.max(1,~~t),this._h=Math.max(1,~~e),this._c=r}[Symbol.iterator](){let t=0;return{next:()=>({value:[this.indexToPointX(t),this.indexToPointY(t),this._c[t++]],done:t>this._c.length})}}clone(){return new s(this._w,this._h,this._c)}clear(){this.forEach((t,e)=>this.set(t,e,void 0))}get width(){return this._w}get height(){return this._h}set(t,e,r){this._c[this.pointToIndex(t,e)]=r}get(t,e){return this._c[this.pointToIndex(t,e)]}has(t,e){return this.get(t,e)!=null}check(t,e){return t>=0&&t<this._w&&e>=0&&e<this._h}get length(){return this._w*this._h}pointToIndex(t,e){return this.clampX(~~t)+this.clampY(~~e)*this._w}indexToPointX(t){return t%this._w}indexToPointY(t){return Math.floor(t/this._w)}forEach(t,e=!1){let r=e?this.length-1:0,o=e?-1:this.length,i=e?-1:1;for(;r!==o;){let a=this.indexToPointX(r),n=this.indexToPointY(r),l=this._c[r];if(t(a,n,l,this)===!1)break;r+=i}}fill(t){this.forEach((e,r)=>{this.set(e,r,t)})}clampX(t){return q(t,0,this._w-1)}clampY(t){return q(t,0,this._h-1)}toArray(){return this._c.slice()}toString(t=" ",e=!0){if(!e)return this._c.join(t);let r=[];return this.forEach((o,i,a)=>{r[i]=r[i]||"",r[i]+=a+t}),r.join(`
2
- `)}},N=class s extends M{constructor(t,e,r=Uint8Array){super(t,e,null),this._c=new r(this._w*this._h)}has(t,e){return this.get(t,e)!==0}clone(){let t=new s(this._w,this._h,this._c.constructor);return this.forEach((e,r,o)=>{t.set(e,r,o)}),t}};function q(s,t,e){return s<t?t:s>e?e:s}var z=Math.cos,K=Math.sin,kt=2*Math.PI,I=class{constructor(t=0,e=t){this.x=parseFloat(t)||0,this.y=parseFloat(e)||0}toString(){return`Vector (${this.x}, ${this.y})`}},d=s=>s instanceof I,h=(s=0,t=s)=>(d(s)&&(t=s.y,s=s.x),new I(s,t)),$=(s,t,e=t)=>(d(t)?$(s,t.x,t.y):(s.x=t,s.y=e),s),L=(s,t,e=t)=>d(t)?L(s,t.x,t.y):(s.x+=t,s.y+=e,s),S=(s,t,e=t)=>d(t)?S(s,t.x,t.y):(s.x-=t,s.y-=e,s),w=(s,t,e=t)=>d(t)?w(s,t.x,t.y):(s.x*=t,s.y*=e,s),k=(s,t,e=t)=>d(t)?k(s,t.x,t.y):(s.x/=t||1,s.y/=e||1,s),Ot=(s,t)=>{let e=z(t),r=K(t);return s.x=e*s.x-r*s.y,s.y=r*s.x+e*s.y,s},Ft=(s,t)=>{let e=O(h(t));return S(s,w(e,2*tt(s,e)))},G=(s,t)=>(O(s),w(s,t),s),J=s=>Math.hypot(s.x,s.y),Q=s=>s.x*s.x+s.y*s.y,O=s=>{let t=J(s);return t>0&&k(s,t),s},Ct=(s,t=1)=>(Q(s)>t*t&&G(s,t),s),Bt=(s,t)=>Math.hypot(t.x-s.x,t.y-s.y),Yt=(s,t)=>{let e=s.x-t.x,r=s.y-t.y;return e*e+r*r},v=s=>Math.atan2(s.y,s.x),Zt=s=>v(s),Ut=(s,t)=>Math.atan2(t.y-s.y,t.x-s.x),tt=(s,t)=>s.x*t.x+s.y*t.y,Ht=(s,t)=>s.x*t.y-s.y*t.x,Wt=(s,t,e)=>(s.x+=(t.x-s.x)*e||0,s.y+=(t.y-s.y)*e||0,s),Xt=s=>(s.x=Math.abs(s.x),s.y=Math.abs(s.y),s),Dt=s=>(s.x=Math.ceil(s.x),s.y=Math.ceil(s.y),s),Vt=s=>(s.x=Math.floor(s.x),s.y=Math.floor(s.y),s),jt=s=>(s.x=Math.round(s.x),s.y=Math.round(s.y),s),qt=(s,t,e)=>(s.x<t.x&&(s.x=t.x),s.x>e.x&&(s.x=e.x),s.y<t.y&&(s.y=t.y),s.y>e.y&&(s.y=e.y),s),zt=(s,t)=>(s.x%=t,s.y%=t,s),Kt=(s,t,e=1)=>L(s,t.x*e,t.y*e),F=(s,t,e=t)=>d(t)?F(s,t.x,t.y):s.x===t&&s.y===e,$t=s=>F(s,st),Gt=s=>[s.x,s.y],Jt=(s=1,t=s,e=globalThis.rand||Math.random)=>{let r=e()*kt,o=e()*(t-s)+s;return h(z(r)*o,K(r)*o)},st=h(0,0),Qt=h(1,1),vt=h(0,-1),ts=h(1,0),ss=h(0,1),es=h(-1,0);var rs=h(.5,.5),et=h(0,0),os=h(1,0),is=h(0,1),hs=h(1,1),C=class{sprite;pos;_o;_s;flipX=!1;flipY=!1;angle=0;opacity=1;hidden=!1;constructor(t,e,r=et){this.sprite=t||{width:0,height:0},this.pos=e||h(0),this._o=h(r),this._s=h(1,1)}set x(t){this.pos.x=t}get x(){return this.pos.x}set y(t){this.pos.y=t}get y(){return this.pos.y}set anchor(t){this._o.x=t.x,this._o.y=t.y}get anchor(){return this._o}get width(){return this.sprite.width*this._s.x}get height(){return this.sprite.height*this._s.y}get scale(){return this._s}scaleTo(t,e=t){this._s.x=t,this._s.y=e}scaleBy(t,e=t){this._s.x*=t,this._s.y*=e}getBounds(t=!0){let e=this.sprite.width*(t?this._s.x:1),r=this.sprite.height*(t?this._s.y:1),o=this.pos.x-e*this.anchor.x,i=this.pos.y-r*this.anchor.y;return[o,i,e,r]}draw(t=globalThis,e=!0){e&&t.push(),this.transform(t),this.sprite.width&&this.sprite.height&&!this.hidden&&this.opacity>0&&this.drawImage(t),e&&t.pop()}transform(t){t.translate(this.pos.x,this.pos.y),t.rotate(t.deg2rad(this.angle)),t.scale((this.flipX?-1:1)*this._s.x,(this.flipY?-1:1)*this._s.y)}drawImage(t,e=!0){let r=this.anchor,o=-this.sprite.width*(this.flipX?1-r.x:r.x),i=-this.sprite.height*(this.flipY?1-r.y:r.y);e&&t.alpha(this.opacity),t.image(o,i,this.sprite)}};var rt=(s,t)=>Math.abs(t-s)||0;var ot=s=>s%1||0;var it=(s,t,e,r=1)=>{e&&(t.x+=e.x*r,t.y+=e.y*r),s.x+=t.x*r,s.y+=t.y*r};var ht=(s,t)=>(t+s%t)%t;var at=(s,t,e,r)=>Math.hypot(e-s,r-t);var nt=(s,t)=>Math.hypot(s,t);var P=s=>{let t=0;for(let e=0;e<s.length;e++)t+=s[e];return t};var lt=s=>P(s)/s.length;var ct=s=>{let t=s.sort((r,o)=>r-o),e=Math.floor(t.length/2);return t.length%2===0?(t[e-1]+t[e])/2:t[e]};var pt=(s,t,e)=>{let r=(t-s)%360;return r>180?r-=360:r<-180&&(r+=360),s+r*e};var ut=(s,t=0,e=1)=>e-t?(s-t)/(e-t):0;var T=Math.PI/2,as=(s,t,e,r=1,o=ft)=>new B(s,t,e,r,o),ft=s=>s,ns=s=>s*s,ls=s=>-s*(s-2),cs=s=>s<.5?2*s*s:-2*s*s+4*s-1,ps=s=>s*s*s-s*Math.sin(s*Math.PI),us=s=>{let t=1-s;return 1-(t*t*t-t*Math.sin(t*Math.PI))},fs=s=>{if(s<.5){let e=2*s;return .5*(e*e*e-e*Math.sin(e*Math.PI))}let t=1-(2*s-1);return .5*(1-(t*t*t-t*Math.sin(s*Math.PI)))+.5},_s=s=>Math.sin(13*T*s)*Math.pow(2,10*(s-1)),xs=s=>Math.sin(-13*T*(s+1))*Math.pow(2,-10*s)+1,ms=s=>{if(s<.5){let r=Math.sin(13*T*(2*s)),o=Math.pow(2,10*(2*s-1));return .5*r*o}let t=Math.sin(-13*T*(2*s-1+1)),e=Math.pow(2,-10*(2*s-1));return .5*(t*e+2)},_t=s=>1-Y(1-s),Y=s=>s<4/11?121*s*s/16:s<8/11?363/40*s*s-99/10*s+17/5:s<9/10?4356/361*s*s-35442/1805*s+16061/1805:54/5*s*s-513/25*s+268/25,ds=s=>s<.5?.5*_t(s*2):.5*Y(s*2-1)+.5,B=class{running=!1;_o;_p;_x;_d;_w;_e;_rel;_cb=[];_t=0;_u=0;_ch=this;_cu=this;_lc;constructor(t,e,r,o,i){this._o=t,this._p=e,this._x=r,this._d=o,this._e=i,this._w=0}start(t){if(this.running)return this;this._cu.stop(!1),this._ch=this._cu=this,this.running=!0;let e=this._o[this._p]||0,r=this._rel?e+this._x:this._x;return this._lc=this._lc||t||globalThis,this._u=this._lc.listen("update",o=>{if(this._t<=this._w){this._t+=o;return}let i=this._t-this._w;this._o[this._p]=this._lc.lerp(e,r,this._e(i/this._d)),this._t+=o,i>=this._d&&(this._o[this._p]=r,this.stop())}),this}stop(t=!0){if(!this._u)return this;if(this.running=!1,this._u(),this._t=0,t)for(let e of this._cb)e(this._o);return this}restart(t=null,e=!1){return this.stop(e).restart(t)}onEnd(t){return this._cb.push(t),this}chain(t){return this._ch.onEnd(()=>{this._cu=t.start(this._lc)}),this._ch=t,this}reset(){return this._cb.length=0,this.stop()}relative(t=!0){return this._rel=t,this}delay(t){return this._w=t,this}get current(){return this._cu}get progress(){return this.running&&this._t>this._w?(this._t-this._w)/this._d:0}};var Z=s=>.5*(1-Math.cos(s*Math.PI)),U=class{_p=[];_po=4;_pf=.5;_e=null;constructor(t){this._e=t||globalThis,this.noiseSeed()}noise(t,e=0,r=0){t<0&&(t=-t),e<0&&(e=-e),r<0&&(r=-r);let o=Math.floor(t),i=Math.floor(e),a=Math.floor(r),n=t-o,l=e-i,x=r-a,p,m,_=0,y=.5,c,u,E;for(let W=0;W<this._po;W++){let f=o+(i<<4)+(a<<8);p=Z(n),m=Z(l),c=this._p[f&4095],c+=p*(this._p[f+1&4095]-c),u=this._p[f+16&4095],u+=p*(this._p[f+16+1&4095]-u),c+=m*(u-c),f+=256,u=this._p[f&4095],u+=p*(this._p[f+1&4095]-u),E=this._p[f+16&4095],E+=p*(this._p[f+16+1&4095]-E),u+=m*(E-u),c+=Z(x)*(u-c),_+=c*y,y*=this._pf,o<<=1,n*=2,i<<=1,l*=2,a<<=1,x*=2,n>=1&&(o++,n--),l>=1&&(i++,l--),x>=1&&(a++,x--)}return _}noiseDetail(t,e){t>0&&(this._po=t),e>0&&(this._pf=e)}noiseSeed(t=null){t!=null&&this._e.rseed(t);let e=this._e.rand||Math.random;for(let r=0;r<4096;r++)this._p[r]=e()}};var xt=(s,t=!0,e=!1,r=globalThis)=>r.paint(s.width,s.height,o=>{r.push(),r.scale(t?-1:1,e?-1:1),r.image(t?-s.width:0,e?-s.height:0,s),r.pop()});var mt=(s,t,e=!0,r=globalThis)=>r.paint(s.width*t,s.height*t,o=>{r.push(),o.imageSmoothingEnabled=!e,r.scale(t),r.image(0,0,s),r.pop()});var dt=(s,t,e=1,r=globalThis)=>r.paint(s.width,s.height,o=>{r.push(),r.alpha(e),r.rectfill(0,0,s.width,s.height,t),o.globalCompositeOperation="destination-atop",r.alpha(1),r.image(0,0,s),r.pop()});var yt=(s,t,{borderWidth:e=0,borderColor:r=0,engine:o=globalThis}={})=>{let i=s*2+e;return o.paint(i,i,()=>{o.circfill(i/2,i/2,s,t),e>0&&(o.linewidth(e),o.stroke(r))})};var gt=(s,t,e,{borderWidth:r=0,borderColor:o=0,engine:i=globalThis}={})=>{let a=s+r*2,n=t+r*2;return i.paint(a,n,()=>{let l=r>0;l&&i.cls(o),i.rectfill(l?r:0,l?r:0,s,t,e)})};var It=(s,t=0,e=1)=>[...Array(s|0).keys()].map(r=>t+e*r);var Et=(s,t=globalThis.rand||Math.random)=>{s=[...s];for(let e=s.length-1;e>0;e--){let r=Math.floor(t()*(e+1)),o=s[e];s[e]=s[r],s[r]=o}return s};var bt=(s,t=globalThis.rand||Math.random)=>s[Math.floor(t()*s.length)];var Mt=s=>s[0];var wt=s=>s[s.length-1];var Pt=s=>s.slice(1);var Tt=s=>~~(s/60)+":"+(s%60<10?"0":"")+~~(s%60);var Rt=(s,t,e="0")=>(s+"").padEnd(t,e);var At=(s,t,e="0")=>(s+"").padStart(t,e);var R=(s,t)=>typeof t=="function"?s instanceof t:typeof s===t;var A=(s,t,e=globalThis)=>e.text(16,16,(t?`${t}: `:"")+(R(s,"object")?JSON.stringify(s,null,4):s));var Nt=(s,t,e=globalThis)=>{e.pal(["blue","#fff"]),e.cls(0),e.ctx().resetTransform(),e.textfont("monospace"),e.textsize(16),e.textalign("start","top"),A(s,t||"dd() output",e),e.quit()};globalThis.utils=Object.assign(globalThis.utils||{},H);})();
1
+ (()=>{var Ft=Object.defineProperty;var St=(e,t)=>{for(var s in t)Ft(e,s,{get:t[s],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(e=!0)=>{for(let t in globalThis.utils)t!=="global"&&(e||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var H={};St(H,{ANCHOR_BOT_LEFT:()=>ae,ANCHOR_BOT_RIGHT:()=>he,ANCHOR_CENTER:()=>ie,ANCHOR_TOP_LEFT:()=>st,ANCHOR_TOP_RIGHT:()=>oe,Actor:()=>B,BACK_IN:()=>pe,BACK_IN_OUT:()=>xe,BACK_OUT:()=>fe,BOUNCE_IN:()=>_t,BOUNCE_IN_OUT:()=>ye,BOUNCE_OUT:()=>Y,Camera:()=>g,DOWN:()=>se,EASE_IN:()=>le,EASE_IN_OUT:()=>ue,EASE_OUT:()=>ce,ELASTIC_IN:()=>_e,ELASTIC_IN_OUT:()=>de,ELASTIC_OUT:()=>me,Grid:()=>E,LEFT:()=>re,LINEAR:()=>xt,Noise:()=>U,ONE:()=>vt,RIGHT:()=>ee,TypedGrid:()=>A,UP:()=>te,Vector:()=>b,ZERO:()=>et,advance:()=>ot,assert:()=>D,choose:()=>wt,colcirc:()=>j,colrect:()=>V,colrectcirc:()=>w,dd:()=>Lt,diff:()=>rt,dist:()=>ht,flipImage:()=>mt,formatTime:()=>Rt,fract:()=>it,head:()=>Et,intersection:()=>I,is:()=>N,last:()=>Pt,lerpAngle:()=>ut,lpad:()=>At,mag:()=>nt,makeCircle:()=>gt,makeRectangle:()=>bt,mean:()=>lt,median:()=>ct,mod:()=>at,percent:()=>pt,range:()=>Mt,resolverect:()=>X,rpad:()=>Nt,scaleImage:()=>dt,shuffle:()=>It,sum:()=>T,tail:()=>Tt,tintImage:()=>yt,tween:()=>ne,vec:()=>n,vecAbs:()=>Dt,vecAdd:()=>L,vecAngle:()=>Ut,vecAngleBetween:()=>Ht,vecCeil:()=>Vt,vecClamp:()=>zt,vecCross:()=>Wt,vecDist:()=>Yt,vecDist2:()=>Zt,vecDiv:()=>S,vecDot:()=>tt,vecEq:()=>O,vecFloor:()=>jt,vecHeading:()=>v,vecIsZero:()=>Gt,vecLerp:()=>Xt,vecLimit:()=>Ct,vecMag:()=>J,vecMag2:()=>Q,vecMove:()=>$t,vecMult:()=>P,vecNorm:()=>k,vecRand:()=>Qt,vecReflect:()=>Bt,vecRem:()=>Kt,vecRotate:()=>Ot,vecRound:()=>qt,vecSet:()=>$,vecSetMag:()=>G,vecSub:()=>F,vecToArray:()=>Jt,wave:()=>ft});var g=class{_engine=null;x=0;y=0;ox=0;oy=0;width=0;height=0;rotation=0;scale=1;constructor(t=null,s=0,r=0,i=null,o=null){this._engine=t||globalThis,this.ox=s,this.oy=r,this.resize(i||this._engine.W-s,o||this._engine.H-r),this.x=this.width/2,this.y=this.height/2,this._shake={x:0,y:0,removeListener:null}}resize(t,s){this.width=t,this.height=s,this._engine.emit("camera-resized",this)}start(t=!1){this._engine.push(),t&&this._engine.clip(i=>{i.rect(this.ox,this.oy,this.width,this.height)});let s=this.ox+this.width/2,r=this.oy+this.height/2;this._engine.translate(s,r),this._engine.scale(this.scale),this._engine.rotate(this.rotation),this._engine.translate(-this.x+this._shake.x,-this.y+this._shake.y)}end(){this._engine.pop()}lookAt(t,s){this.x=t,this.y=s}move(t,s){this.x+=t,this.y+=s}zoom(t){this.scale*=t}zoomTo(t){this.scale=t}rotate(t){this.rotation+=t}rotateTo(t){this.rotation=t}getWorldPoint(t,s,r={}){let i=Math.cos(-this.rotation),o=Math.sin(-this.rotation);return t=(t-this.width/2-this.ox)/this.scale,s=(s-this.height/2-this.oy)/this.scale,r.x=i*t-o*s+this.x,r.y=o*t+i*s+this.y,r}getCameraPoint(t,s,r={}){let i=Math.cos(-this.rotation),o=Math.sin(-this.rotation);return t=t-this.x,s=s-this.y,t=i*t-o*s,s=o*t+i*s,r.x=t*this.scale+this.width/2+this.ox,r.y=s*this.scale+this.height/2+this.oy,r}getBounds(){return[this.ox,this.oy,this.width,this.height]}shake(t=1,s=.3){this.shaking||(this._shake.removeListener=this._engine.listen("update",r=>{this._shake.x=this._engine.randi(-t,t),this._shake.y=this._engine.randi(-t,t),s-=r,s<=0&&this.unshake()}))}unshake(){this.shaking&&(this._shake.removeListener(),this._shake.removeListener=null,this._shake.x=this._shake.y=0)}get shaking(){return this._shake.removeListener!==null}};var I=(e,t,s,r,i,o,a,h)=>{let l=Math.max(e,i),_=Math.min(e+s,i+a)-l,u=Math.max(t,o),m=Math.min(t+r,o+h)-u;return[l,u,_,m]};var X=(e,t,s,r,i,o,a,h)=>{let[l,_,u,m]=I(e,t,s,r,i,o,a,h),x="",y=e,c=t;return u<m?e<i?(x="right",y=i-s):(x="left",y=i+a):t<o?(x="bottom",c=o-r):(x="top",c=o+h),{dir:x,x:y,y:c}};var D=(e,t="Assertion failed")=>{if(!e)throw new Error(t)};var V=(e,t,s,r,i,o,a,h)=>e<i+a&&e+s>i&&t<o+h&&t+r>o;var j=(e,t,s,r,i,o)=>(r-e)*(r-e)+(i-t)*(i-t)<=(s+o)*(s+o);var w=(e,t,s,r,i,o,a)=>{let h=i-Math.max(e,Math.min(i,e+s)),l=o-Math.max(t,Math.min(o,t+r));return h*h+l*l<=a*a};var E=class e{_w;_h;_c;constructor(t,s,r=[]){this._w=Math.max(1,~~t),this._h=Math.max(1,~~s),this._c=r}[Symbol.iterator](){let t=0;return{next:()=>({value:[this.indexToPointX(t),this.indexToPointY(t),this._c[t++]],done:t>this._c.length})}}clone(){return new e(this._w,this._h,this._c)}clear(){this.forEach((t,s)=>this.set(t,s,void 0))}get width(){return this._w}get height(){return this._h}set(t,s,r){this._c[this.pointToIndex(t,s)]=r}get(t,s){return this._c[this.pointToIndex(t,s)]}has(t,s){return this.get(t,s)!=null}check(t,s){return t>=0&&t<this._w&&s>=0&&s<this._h}get length(){return this._w*this._h}pointToIndex(t,s){return this.clampX(~~t)+this.clampY(~~s)*this._w}indexToPointX(t){return t%this._w}indexToPointY(t){return Math.floor(t/this._w)}forEach(t,s=!1){let r=s?this.length-1:0,i=s?-1:this.length,o=s?-1:1;for(;r!==i;){let a=this.indexToPointX(r),h=this.indexToPointY(r),l=this._c[r];if(t(a,h,l,this)===!1)break;r+=o}}fill(t){this.forEach((s,r)=>{this.set(s,r,t)})}clampX(t){return q(t,0,this._w-1)}clampY(t){return q(t,0,this._h-1)}toArray(){return this._c.slice()}toString(t=" ",s=!0){if(!s)return this._c.join(t);let r=[];return this.forEach((i,o,a)=>{r[o]=r[o]||"",r[o]+=a+t}),r.join(`
2
+ `)}},A=class e extends E{constructor(t,s,r=Uint8Array){super(t,s,null),this._c=new r(this._w*this._h)}has(t,s){return this.get(t,s)!==0}clone(){let t=new e(this._w,this._h,this._c.constructor);return this.forEach((s,r,i)=>{t.set(s,r,i)}),t}};function q(e,t,s){return e<t?t:e>s?s:e}var z=Math.cos,K=Math.sin,kt=2*Math.PI,b=class{constructor(t=0,s=t){this.x=parseFloat(t)||0,this.y=parseFloat(s)||0}toString(){return`Vector (${this.x}, ${this.y})`}},d=e=>e instanceof b,n=(e=0,t=e)=>(d(e)&&(t=e.y,e=e.x),new b(e,t)),$=(e,t,s=t)=>(d(t)?$(e,t.x,t.y):(e.x=t,e.y=s),e),L=(e,t,s=t)=>d(t)?L(e,t.x,t.y):(e.x+=t,e.y+=s,e),F=(e,t,s=t)=>d(t)?F(e,t.x,t.y):(e.x-=t,e.y-=s,e),P=(e,t,s=t)=>d(t)?P(e,t.x,t.y):(e.x*=t,e.y*=s,e),S=(e,t,s=t)=>d(t)?S(e,t.x,t.y):(e.x/=t||1,e.y/=s||1,e),Ot=(e,t)=>{let s=z(t),r=K(t);return e.x=s*e.x-r*e.y,e.y=r*e.x+s*e.y,e},Bt=(e,t)=>{let s=k(n(t));return F(e,P(s,2*tt(e,s)))},G=(e,t)=>(k(e),P(e,t),e),J=e=>Math.hypot(e.x,e.y),Q=e=>e.x*e.x+e.y*e.y,k=e=>{let t=J(e);return t>0&&S(e,t),e},Ct=(e,t=1)=>(Q(e)>t*t&&G(e,t),e),Yt=(e,t)=>Math.hypot(t.x-e.x,t.y-e.y),Zt=(e,t)=>{let s=e.x-t.x,r=e.y-t.y;return s*s+r*r},v=e=>Math.atan2(e.y,e.x),Ut=e=>v(e),Ht=(e,t)=>Math.atan2(t.y-e.y,t.x-e.x),tt=(e,t)=>e.x*t.x+e.y*t.y,Wt=(e,t)=>e.x*t.y-e.y*t.x,Xt=(e,t,s)=>(e.x+=(t.x-e.x)*s||0,e.y+=(t.y-e.y)*s||0,e),Dt=e=>(e.x=Math.abs(e.x),e.y=Math.abs(e.y),e),Vt=e=>(e.x=Math.ceil(e.x),e.y=Math.ceil(e.y),e),jt=e=>(e.x=Math.floor(e.x),e.y=Math.floor(e.y),e),qt=e=>(e.x=Math.round(e.x),e.y=Math.round(e.y),e),zt=(e,t,s)=>(e.x<t.x&&(e.x=t.x),e.x>s.x&&(e.x=s.x),e.y<t.y&&(e.y=t.y),e.y>s.y&&(e.y=s.y),e),Kt=(e,t)=>(e.x%=t,e.y%=t,e),$t=(e,t,s=1)=>L(e,t.x*s,t.y*s),O=(e,t,s=t)=>d(t)?O(e,t.x,t.y):e.x===t&&e.y===s,Gt=e=>O(e,et),Jt=e=>[e.x,e.y],Qt=(e=1,t=e,s=globalThis.rand||Math.random)=>{let r=s()*kt,i=s()*(t-e)+e;return n(z(r)*i,K(r)*i)},et=n(0,0),vt=n(1,1),te=n(0,-1),ee=n(1,0),se=n(0,1),re=n(-1,0);var ie=n(.5,.5),st=n(0,0),oe=n(1,0),ae=n(0,1),he=n(1,1),B=class{sprite;pos;_o;_s;flipX=!1;flipY=!1;angle=0;opacity=1;hidden=!1;constructor(t,s,r=st){this.sprite=t||{width:0,height:0},this.pos=s||n(0),this._o=n(r),this._s=n(1,1)}set x(t){this.pos.x=t}get x(){return this.pos.x}set y(t){this.pos.y=t}get y(){return this.pos.y}set anchor(t){this._o.x=t.x,this._o.y=t.y}get anchor(){return this._o}get width(){return this.sprite.width*this._s.x}get height(){return this.sprite.height*this._s.y}get scale(){return this._s}scaleTo(t,s=t){this._s.x=t,this._s.y=s}scaleBy(t,s=t){this._s.x*=t,this._s.y*=s}getBounds(t=!0){let s=this.sprite.width*(t?this._s.x:1),r=this.sprite.height*(t?this._s.y:1),i=this.pos.x-s*this.anchor.x,o=this.pos.y-r*this.anchor.y;return[i,o,s,r]}in(t,s,r=1){return w(...this.getBounds(),t,s,r)}col(t){return colrect(...this.getBounds(),...t.getBounds())}draw(t=globalThis,s=!0){s&&t.push(),this.transform(t),this.sprite.width&&this.sprite.height&&!this.hidden&&this.opacity>0&&this.drawImage(t),s&&t.pop()}transform(t=globalThis){t.translate(this.pos.x,this.pos.y),t.rotate(t.deg2rad(this.angle)),t.scale((this.flipX?-1:1)*this._s.x,(this.flipY?-1:1)*this._s.y)}drawImage(t=globalThis,s=!0){let r=this.anchor,i=-this.sprite.width*(this.flipX?1-r.x:r.x),o=-this.sprite.height*(this.flipY?1-r.y:r.y);s&&t.alpha(this.opacity),t.image(i,o,this.sprite)}};var rt=(e,t)=>Math.abs(t-e)||0;var it=e=>e%1||0;var ot=(e,t,s,r=1)=>{s&&(t.x+=s.x*r,t.y+=s.y*r),e.x+=t.x*r,e.y+=t.y*r};var at=(e,t)=>(t+e%t)%t;var ht=(e,t,s,r)=>Math.hypot(s-e,r-t);var nt=(e,t)=>Math.hypot(e,t);var T=e=>{let t=0;for(let s=0;s<e.length;s++)t+=e[s];return t};var lt=e=>T(e)/e.length;var ct=e=>{let t=e.sort((r,i)=>r-i),s=Math.floor(t.length/2);return t.length%2===0?(t[s-1]+t[s])/2:t[s]};var ut=(e,t,s)=>{let r=(t-e)%360;return r>180?r-=360:r<-180&&(r+=360),e+r*s};var pt=(e,t=0,s=1)=>s-t?(e-t)/(s-t):0;var ft=(e,t,s,r=Math.sin)=>e+(r(s)+1)/2*(t-e);var R=Math.PI/2,ne=(e,t,s,r=1,i=xt)=>new C(e,t,s,r,i),xt=e=>e,le=e=>e*e,ce=e=>-e*(e-2),ue=e=>e<.5?2*e*e:-2*e*e+4*e-1,pe=e=>e*e*e-e*Math.sin(e*Math.PI),fe=e=>{let t=1-e;return 1-(t*t*t-t*Math.sin(t*Math.PI))},xe=e=>{if(e<.5){let s=2*e;return .5*(s*s*s-s*Math.sin(s*Math.PI))}let t=1-(2*e-1);return .5*(1-(t*t*t-t*Math.sin(e*Math.PI)))+.5},_e=e=>Math.sin(13*R*e)*Math.pow(2,10*(e-1)),me=e=>Math.sin(-13*R*(e+1))*Math.pow(2,-10*e)+1,de=e=>{if(e<.5){let r=Math.sin(13*R*(2*e)),i=Math.pow(2,10*(2*e-1));return .5*r*i}let t=Math.sin(-13*R*(2*e-1+1)),s=Math.pow(2,-10*(2*e-1));return .5*(t*s+2)},_t=e=>1-Y(1-e),Y=e=>e<4/11?121*e*e/16:e<8/11?363/40*e*e-99/10*e+17/5:e<9/10?4356/361*e*e-35442/1805*e+16061/1805:54/5*e*e-513/25*e+268/25,ye=e=>e<.5?.5*_t(e*2):.5*Y(e*2-1)+.5,C=class{running=!1;_o;_p;_x;_d;_w;_e;_rel;_cb=[];_t=0;_u=0;_ch=this;_cu=this;_lc;constructor(t,s,r,i,o){this._o=t,this._p=s,this._x=r,this._d=i,this._e=o,this._w=0}start(t){if(this.running)return this;this._cu.stop(!1),this._ch=this._cu=this,this.running=!0;let s=this._o[this._p]||0,r=this._rel?s+this._x:this._x;return this._lc=this._lc||t||globalThis,this._u=this._lc.listen("update",i=>{if(this._t<=this._w){this._t+=i;return}let o=this._t-this._w;this._o[this._p]=this._lc.lerp(s,r,this._e(o/this._d)),this._t+=i,o>=this._d&&(this._o[this._p]=r,this.stop())}),this}stop(t=!0){if(!this._u)return this;if(this.running=!1,this._u(),this._t=0,t)for(let s of this._cb)s(this._o);return this}restart(t=null,s=!1){return this.stop(s).restart(t)}onEnd(t){return this._cb.push(t),this}chain(t){return this._ch.onEnd(()=>{this._cu=t.start(this._lc)}),this._ch=t,this}reset(){return this._cb.length=0,this.stop()}relative(t=!0){return this._rel=t,this}delay(t){return this._w=t,this}get current(){return this._cu}get progress(){return this.running&&this._t>this._w?(this._t-this._w)/this._d:0}};var Z=e=>.5*(1-Math.cos(e*Math.PI)),U=class{_p=[];_po=4;_pf=.5;_e=null;constructor(t){this._e=t||globalThis,this.noiseSeed()}noise(t,s=0,r=0){t<0&&(t=-t),s<0&&(s=-s),r<0&&(r=-r);let i=Math.floor(t),o=Math.floor(s),a=Math.floor(r),h=t-i,l=s-o,_=r-a,u,m,x=0,y=.5,c,p,M;for(let W=0;W<this._po;W++){let f=i+(o<<4)+(a<<8);u=Z(h),m=Z(l),c=this._p[f&4095],c+=u*(this._p[f+1&4095]-c),p=this._p[f+16&4095],p+=u*(this._p[f+16+1&4095]-p),c+=m*(p-c),f+=256,p=this._p[f&4095],p+=u*(this._p[f+1&4095]-p),M=this._p[f+16&4095],M+=u*(this._p[f+16+1&4095]-M),p+=m*(M-p),c+=Z(_)*(p-c),x+=c*y,y*=this._pf,i<<=1,h*=2,o<<=1,l*=2,a<<=1,_*=2,h>=1&&(i++,h--),l>=1&&(o++,l--),_>=1&&(a++,_--)}return x}noiseDetail(t,s){t>0&&(this._po=t),s>0&&(this._pf=s)}noiseSeed(t=null){t!=null&&this._e.rseed(t);let s=this._e.rand||Math.random;for(let r=0;r<4096;r++)this._p[r]=s()}};var mt=(e,t=!0,s=!1,r=globalThis)=>r.paint(e.width,e.height,i=>{r.push(),r.scale(t?-1:1,s?-1:1),r.image(t?-e.width:0,s?-e.height:0,e),r.pop()});var dt=(e,t,s=!0,r=globalThis)=>r.paint(e.width*t,e.height*t,i=>{r.push(),i.imageSmoothingEnabled=!s,r.scale(t),r.image(0,0,e),r.pop()});var yt=(e,t,s=1,r=globalThis)=>r.paint(e.width,e.height,i=>{r.push(),r.alpha(s),r.rectfill(0,0,e.width,e.height,t),i.globalCompositeOperation="destination-atop",r.alpha(1),r.image(0,0,e),r.pop()});var gt=(e,t,{borderWidth:s=0,borderColor:r=0,engine:i=globalThis}={})=>{let o=e*2+s;return i.paint(o,o,()=>{i.circfill(o/2,o/2,e,t),s>0&&(i.linewidth(s),i.stroke(r))})};var bt=(e,t,s,{borderWidth:r=0,borderColor:i=0,engine:o=globalThis}={})=>{let a=e+r*2,h=t+r*2;return o.paint(a,h,()=>{let l=r>0;l&&o.cls(i),o.rectfill(l?r:0,l?r:0,e,t,s)})};var Mt=(e,t=0,s=1)=>[...Array(e|0).keys()].map(r=>t+s*r);var It=(e,t=globalThis.rand||Math.random)=>{e=[...e];for(let s=e.length-1;s>0;s--){let r=Math.floor(t()*(s+1)),i=e[s];e[s]=e[r],e[r]=i}return e};var wt=(e,t=globalThis.rand||Math.random)=>e[Math.floor(t()*e.length)];var Et=e=>e[0];var Pt=e=>e[e.length-1];var Tt=e=>e.slice(1);var Rt=e=>~~(e/60)+":"+(e%60<10?"0":"")+~~(e%60);var Nt=(e,t,s="0")=>(e+"").padEnd(t,s);var At=(e,t,s="0")=>(e+"").padStart(t,s);var N=(e,t)=>typeof t=="function"?e instanceof t:typeof e===t;var Lt=(e,t,s=globalThis)=>{s.pal(["blue","#fff"]),s.cls(0),s.ctx().resetTransform(),s.textfont("monospace"),s.textsize(16),s.textalign("start","top"),s.text(16,16,`${t??"dd() output"}: `+(N(e,"object")?JSON.stringify(e,null,4):e)),s.quit()};globalThis.utils=Object.assign(globalThis.utils||{},H);})();
3
3
  /*! @litecanvas/utils by Luiz Bills | MIT Licensed */
package/dist/collision.js CHANGED
@@ -21,6 +21,7 @@
21
21
  __export(index_exports, {
22
22
  colcirc: () => colcirc_default,
23
23
  colrect: () => colrect_default,
24
+ colrectcirc: () => colrectcirc_default,
24
25
  intersection: () => intersection_default,
25
26
  resolverect: () => resolverect_default
26
27
  });
@@ -98,6 +99,20 @@
98
99
  return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) <= (r1 + r2) * (r1 + r2);
99
100
  };
100
101
 
102
+ // src/collision/colrectcirc.js
103
+ var colrectcirc_default = (x1, y1, w1, h1, x2, y2, r2) => {
104
+ DEV: assert_default(isFinite(x1), "colrect: 1st param must be a number");
105
+ DEV: assert_default(isFinite(y1), "colrect: 2nd param must be a number");
106
+ DEV: assert_default(isFinite(w1), "colrect: 3rd param must be a number");
107
+ DEV: assert_default(isFinite(h1), "colrect: 4th param must be a number");
108
+ DEV: assert_default(isFinite(x2), "colcirc: 5th param must be a number");
109
+ DEV: assert_default(isFinite(y2), "colcirc: 6th param must be a number");
110
+ DEV: assert_default(isFinite(r2), "colcirc: 7th param must be a number");
111
+ let xx = x2 - Math.max(x1, Math.min(x2, x1 + w1));
112
+ let yy = y2 - Math.max(y1, Math.min(y2, y1 + h1));
113
+ return xx * xx + yy * yy <= r2 * r2;
114
+ };
115
+
101
116
  // src/collision/_web.js
102
117
  globalThis.utils = Object.assign(globalThis.utils || {}, index_exports);
103
118
  })();
@@ -1 +1 @@
1
- (()=>{var x=Object.defineProperty;var w=(e,t)=>{for(var i in t)x(e,i,{get:t[i],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(e=!0)=>{for(let t in globalThis.utils)t!=="global"&&(e||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var h={};w(h,{colcirc:()=>T,colrect:()=>F,intersection:()=>c,resolverect:()=>g});var c=(e,t,i,a,r,s,o,l)=>{let u=Math.max(e,r),d=Math.min(e+i,r+o)-u,n=Math.max(t,s),b=Math.min(t+a,s+l)-n;return[u,n,d,b]};var g=(e,t,i,a,r,s,o,l)=>{let[u,d,n,b]=c(e,t,i,a,r,s,o,l),m="",p=e,f=t;return n<b?e<r?(m="right",p=r-i):(m="left",p=r+o):t<s?(m="bottom",f=s-a):(m="top",f=s+l),{dir:m,x:p,y:f}};var F=(e,t,i,a,r,s,o,l)=>e<r+o&&e+i>r&&t<s+l&&t+a>s;var T=(e,t,i,a,r,s)=>(a-e)*(a-e)+(r-t)*(r-t)<=(i+s)*(i+s);globalThis.utils=Object.assign(globalThis.utils||{},h);})();
1
+ (()=>{var M=Object.defineProperty;var w=(e,t)=>{for(var a in t)M(e,a,{get:t[a],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(e=!0)=>{for(let t in globalThis.utils)t!=="global"&&(e||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var f={};w(f,{colcirc:()=>x,colrect:()=>g,colrectcirc:()=>T,intersection:()=>u,resolverect:()=>F});var u=(e,t,a,i,r,s,m,o)=>{let l=Math.max(e,r),d=Math.min(e+a,r+m)-l,c=Math.max(t,s),b=Math.min(t+i,s+o)-c;return[l,c,d,b]};var F=(e,t,a,i,r,s,m,o)=>{let[l,d,c,b]=u(e,t,a,i,r,s,m,o),n="",p=e,h=t;return c<b?e<r?(n="right",p=r-a):(n="left",p=r+m):t<s?(n="bottom",h=s-i):(n="top",h=s+o),{dir:n,x:p,y:h}};var g=(e,t,a,i,r,s,m,o)=>e<r+m&&e+a>r&&t<s+o&&t+i>s;var x=(e,t,a,i,r,s)=>(i-e)*(i-e)+(r-t)*(r-t)<=(a+s)*(a+s);var T=(e,t,a,i,r,s,m)=>{let o=r-Math.max(e,Math.min(r,e+a)),l=s-Math.max(t,Math.min(s,t+i));return o*o+l*l<=m*m};globalThis.utils=Object.assign(globalThis.utils||{},f);})();
package/dist/debug.js CHANGED
@@ -21,8 +21,7 @@
21
21
  __export(index_exports, {
22
22
  assert: () => assert_default,
23
23
  dd: () => dd_default,
24
- is: () => is_default,
25
- log: () => log_default
24
+ is: () => is_default
26
25
  });
27
26
 
28
27
  // src/debug/assert.js
@@ -38,15 +37,6 @@
38
37
  return typeof value === type;
39
38
  };
40
39
 
41
- // src/debug/log.js
42
- var log_default = (data, context, engine = globalThis) => {
43
- return engine.text(
44
- 16,
45
- 16,
46
- (context ? `${context}: ` : "") + (is_default(data, "object") ? JSON.stringify(data, null, 4) : data)
47
- );
48
- };
49
-
50
40
  // src/debug/dd.js
51
41
  var dd_default = (data, context, engine = globalThis) => {
52
42
  engine.pal(["blue", "#fff"]);
@@ -55,7 +45,11 @@
55
45
  engine.textfont("monospace");
56
46
  engine.textsize(16);
57
47
  engine.textalign("start", "top");
58
- log_default(data, context || "dd() output", engine);
48
+ engine.text(
49
+ 16,
50
+ 16,
51
+ `${context ?? "dd() output"}: ` + (is_default(data, "object") ? JSON.stringify(data, null, 4) : data)
52
+ );
59
53
  engine.quit();
60
54
  };
61
55
 
package/dist/debug.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var u=Object.defineProperty;var e=(l,t)=>{for(var o in t)u(l,o,{get:t[o],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(l=!0)=>{for(let t in globalThis.utils)t!=="global"&&(l||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var i={};e(i,{assert:()=>f,dd:()=>a,is:()=>s,log:()=>r});var f=(l,t="Assertion failed")=>{if(!l)throw new Error(t)};var s=(l,t)=>typeof t=="function"?l instanceof t:typeof l===t;var r=(l,t,o=globalThis)=>o.text(16,16,(t?`${t}: `:"")+(s(l,"object")?JSON.stringify(l,null,4):l));var a=(l,t,o=globalThis)=>{o.pal(["blue","#fff"]),o.cls(0),o.ctx().resetTransform(),o.textfont("monospace"),o.textsize(16),o.textalign("start","top"),r(l,t||"dd() output",o),o.quit()};globalThis.utils=Object.assign(globalThis.utils||{},i);})();
1
+ (()=>{var a=Object.defineProperty;var u=(l,t)=>{for(var o in t)a(l,o,{get:t[o],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(l=!0)=>{for(let t in globalThis.utils)t!=="global"&&(l||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var i={};u(i,{assert:()=>r,dd:()=>f,is:()=>s});var r=(l,t="Assertion failed")=>{if(!l)throw new Error(t)};var s=(l,t)=>typeof t=="function"?l instanceof t:typeof l===t;var f=(l,t,o=globalThis)=>{o.pal(["blue","#fff"]),o.cls(0),o.ctx().resetTransform(),o.textfont("monospace"),o.textsize(16),o.textalign("start","top"),o.text(16,16,`${t??"dd() output"}: `+(s(l,"object")?JSON.stringify(l,null,4):l)),o.quit()};globalThis.utils=Object.assign(globalThis.utils||{},i);})();
package/dist/math.js CHANGED
@@ -29,7 +29,8 @@
29
29
  median: () => median_default,
30
30
  mod: () => mod_default,
31
31
  percent: () => percent_default,
32
- sum: () => sum_default
32
+ sum: () => sum_default,
33
+ wave: () => wave_default
33
34
  });
34
35
 
35
36
  // src/math/diff.js
@@ -110,6 +111,18 @@
110
111
  // src/math/percent.js
111
112
  var percent_default = (value, min = 0, max = 1) => max - min ? (value - min) / (max - min) : 0;
112
113
 
114
+ // src/math/wave.js
115
+ var wave_default = (from, to, t, fn = Math.sin) => {
116
+ DEV: assert_default(isNumber(from), "[litecanvas] wave() 1st param must be a number");
117
+ DEV: assert_default(isNumber(to), "[litecanvas] wave() 2nd param must be a number");
118
+ DEV: assert_default(isNumber(t), "[litecanvas] wave() 3rd param must be a number");
119
+ DEV: assert_default(
120
+ "function" === typeof fn,
121
+ "[litecanvas] wave() 4rd param must be a function (n: number) => number"
122
+ );
123
+ return from + (fn(t) + 1) / 2 * (to - from);
124
+ };
125
+
113
126
  // src/math/_web.js
114
127
  globalThis.utils = Object.assign(globalThis.utils || {}, index_exports);
115
128
  })();
package/dist/math.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var m=Object.defineProperty;var g=(r,t)=>{for(var e in t)m(r,e,{get:t[e],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(r=!0)=>{for(let t in globalThis.utils)t!=="global"&&(r||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var n={};g(n,{advance:()=>x,diff:()=>a,dist:()=>u,fract:()=>c,lerpAngle:()=>i,mag:()=>l,mean:()=>f,median:()=>y,mod:()=>p,percent:()=>h,sum:()=>s});var a=(r,t)=>Math.abs(t-r)||0;var c=r=>r%1||0;var T=2*Math.PI;var x=(r,t,e,o=1)=>{e&&(t.x+=e.x*o,t.y+=e.y*o),r.x+=t.x*o,r.y+=t.y*o};var p=(r,t)=>(t+r%t)%t;var u=(r,t,e,o)=>Math.hypot(e-r,o-t);var l=(r,t)=>Math.hypot(r,t);var s=r=>{let t=0;for(let e=0;e<r.length;e++)t+=r[e];return t};var f=r=>s(r)/r.length;var y=r=>{let t=r.sort((o,d)=>o-d),e=Math.floor(t.length/2);return t.length%2===0?(t[e-1]+t[e])/2:t[e]};var i=(r,t,e)=>{let o=(t-r)%360;return o>180?o-=360:o<-180&&(o+=360),r+o*e};var h=(r,t=0,e=1)=>e-t?(r-t)/(e-t):0;globalThis.utils=Object.assign(globalThis.utils||{},n);})();
1
+ (()=>{var b=Object.defineProperty;var M=(r,t)=>{for(var e in t)b(r,e,{get:t[e],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=(r=!0)=>{for(let t in globalThis.utils)t!=="global"&&(r||globalThis[t]===void 0)&&(globalThis[t]=globalThis.utils[t])};var a={};M(a,{advance:()=>u,diff:()=>n,dist:()=>x,fract:()=>c,lerpAngle:()=>y,mag:()=>l,mean:()=>f,median:()=>i,mod:()=>p,percent:()=>d,sum:()=>s,wave:()=>m});var n=(r,t)=>Math.abs(t-r)||0;var c=r=>r%1||0;var w=2*Math.PI;var u=(r,t,e,o=1)=>{e&&(t.x+=e.x*o,t.y+=e.y*o),r.x+=t.x*o,r.y+=t.y*o};var p=(r,t)=>(t+r%t)%t;var x=(r,t,e,o)=>Math.hypot(e-r,o-t);var l=(r,t)=>Math.hypot(r,t);var s=r=>{let t=0;for(let e=0;e<r.length;e++)t+=r[e];return t};var f=r=>s(r)/r.length;var i=r=>{let t=r.sort((o,h)=>o-h),e=Math.floor(t.length/2);return t.length%2===0?(t[e-1]+t[e])/2:t[e]};var y=(r,t,e)=>{let o=(t-r)%360;return o>180?o-=360:o<-180&&(o+=360),r+o*e};var d=(r,t=0,e=1)=>e-t?(r-t)/(e-t):0;var m=(r,t,e,o=Math.sin)=>r+(o(e)+1)/2*(t-r);globalThis.utils=Object.assign(globalThis.utils||{},a);})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litecanvas/utils",
3
- "version": "0.44.1",
3
+ "version": "0.46.0",
4
4
  "description": "Utilities to help build litecanvas games",
5
5
  "author": "Luiz Bills <luizbills@pm.me>",
6
6
  "license": "MIT",
@@ -37,8 +37,8 @@
37
37
  "litecanvas": "latest"
38
38
  },
39
39
  "devDependencies": {
40
- "esbuild": "^0.27.2",
40
+ "esbuild": "^0.27.3",
41
41
  "gzip-size": "^7.0.0",
42
- "prettier": "^3.8.0"
42
+ "prettier": "^3.8.1"
43
43
  }
44
44
  }
@@ -171,6 +171,27 @@ Set or get the actor sprite image. Useful to make animations.
171
171
  player.sprite = anotherSprite
172
172
  ```
173
173
 
174
- > The actor sprite must be a `Image`, `HTMLCanvas` or `OffscreenCanvas`.
174
+ > The actor sprite must be a `Image`, `ImageBitmap`, `HTMLCanvasElement` or `OffscreenCanvas`.
175
175
  >
176
- > Remember, you can create a image using the litecanvas' `paint()` built-in helper or [load a image](https://github.com/litecanvas/plugin-asset-loader?tab=readme-ov-file#loading-images).
176
+ > Remember, you can create images using the litecanvas' built-in `paint()` function or [loading a image](https://github.com/litecanvas/plugin-asset-loader?tab=readme-ov-file#loading-images).
177
+
178
+ ## Actor#in(x, y, radius)
179
+
180
+ Check taps (clicks and touchs).
181
+
182
+ ```js
183
+ function tapped(x, y) {
184
+ const pointArea = 8 // default = 1
185
+ if (player.in(x, y, pointArea)) {
186
+ console.log("tap!")
187
+ }
188
+ }
189
+ ```
190
+
191
+ ## Actor#col(other)
192
+
193
+ Check collision between actors
194
+
195
+ ```js
196
+ const collided = player.col(anotherActor)
197
+ ```
@@ -1,4 +1,5 @@
1
1
  import { Vector, vec } from "../vector/index.js"
2
+ import colrectcirc from "../collision/colrectcirc.js"
2
3
 
3
4
  export const ANCHOR_CENTER = /** @__PURE__ */ vec(0.5, 0.5)
4
5
  export const ANCHOR_TOP_LEFT = /** @__PURE__ */ vec(0, 0)
@@ -35,7 +36,7 @@ export class Actor {
35
36
  hidden = false
36
37
 
37
38
  /**
38
- * @param {Image|HTMLCanvasElement|OffscreenCanvas} sprite
39
+ * @param {Image|HTMLCanvasElement|OffscreenCanvas|ImageBitmap} sprite
39
40
  * @param {Vector} position
40
41
  * @param {Vector} anchor
41
42
  */
@@ -133,6 +134,7 @@ export class Actor {
133
134
  }
134
135
 
135
136
  /**
137
+ * @param {boolean} scaled
136
138
  * @returns {number[]}
137
139
  */
138
140
  getBounds(scaled = true) {
@@ -143,6 +145,29 @@ export class Actor {
143
145
  return [x, y, w, h]
144
146
  }
145
147
 
148
+ /**
149
+ * Checks if the actor is colliding with a point (with optional radius).
150
+ * Useful to check clicks or touchs.
151
+ *
152
+ * @param {number} x
153
+ * @param {number} y
154
+ * @param {number} [radius=1]
155
+ * @returns {boolean}
156
+ */
157
+ in(x, y, radius = 1) {
158
+ return colrectcirc(...this.getBounds(), x, y, radius)
159
+ }
160
+
161
+ /**
162
+ * Checks if the actor is colliding with another actor.
163
+ *
164
+ * @param {Actor} other
165
+ * @returns {boolean}
166
+ */
167
+ col(other) {
168
+ return colrect(...this.getBounds(), ...other.getBounds())
169
+ }
170
+
146
171
  /**
147
172
  * Draw the actor
148
173
  *
@@ -168,7 +193,7 @@ export class Actor {
168
193
  /**
169
194
  * @param {LitecanvasInstance} engine
170
195
  */
171
- transform(engine) {
196
+ transform(engine = globalThis) {
172
197
  engine.translate(this.pos.x, this.pos.y)
173
198
  engine.rotate(engine.deg2rad(this.angle))
174
199
  engine.scale(
@@ -179,8 +204,9 @@ export class Actor {
179
204
 
180
205
  /**
181
206
  * @param {LitecanvasInstance} engine
207
+ * @param {boolean} alpha
182
208
  */
183
- drawImage(engine, alpha = true) {
209
+ drawImage(engine = globalThis, alpha = true) {
184
210
  const anchor = this.anchor
185
211
  const x = -this.sprite.width * (this.flipX ? 1 - anchor.x : anchor.x)
186
212
  const y = -this.sprite.height * (this.flipY ? 1 - anchor.y : anchor.y)
@@ -14,6 +14,12 @@ Check a collision between two circles.
14
14
 
15
15
  Syntax: `colcirc(x1, y1, r1, x2, y2, r2): boolean`
16
16
 
17
+ ## colrectcirc
18
+
19
+ Check a collision between a rectangle and a circle.
20
+
21
+ Syntax: `colrectcirc(x1, y1, w1, h1, x2, y2, r2): boolean`
22
+
17
23
  ## intersection
18
24
 
19
25
  Returns the resulting rectangle of the intersection between two rectangles.
@@ -0,0 +1,29 @@
1
+ import assert from "../debug/assert.js"
2
+
3
+ /**
4
+ * Check a collision between a rectangle and a circle
5
+ *
6
+ * @param {number} x1 rectangle position X
7
+ * @param {number} y1 rectangle position Y
8
+ * @param {number} w1 rectangle width
9
+ * @param {number} h1 rectangle height
10
+ * @param {number} x2 circle position X
11
+ * @param {number} y2 circle position Y
12
+ * @param {number} r2 circle radius
13
+ * @returns {boolean}
14
+ */
15
+
16
+ export default (x1, y1, w1, h1, x2, y2, r2) => {
17
+ DEV: assert(isFinite(x1), "colrect: 1st param must be a number")
18
+ DEV: assert(isFinite(y1), "colrect: 2nd param must be a number")
19
+ DEV: assert(isFinite(w1), "colrect: 3rd param must be a number")
20
+ DEV: assert(isFinite(h1), "colrect: 4th param must be a number")
21
+ DEV: assert(isFinite(x2), "colcirc: 5th param must be a number")
22
+ DEV: assert(isFinite(y2), "colcirc: 6th param must be a number")
23
+ DEV: assert(isFinite(r2), "colcirc: 7th param must be a number")
24
+
25
+ let xx = x2 - Math.max(x1, Math.min(x2, x1 + w1))
26
+ let yy = y2 - Math.max(y1, Math.min(y2, y1 + h1))
27
+
28
+ return xx * xx + yy * yy <= r2 * r2
29
+ }
@@ -2,3 +2,4 @@ export { default as resolverect } from "./resolverect.js"
2
2
  export { default as intersection } from "./intersection.js"
3
3
  export { default as colrect } from "./colrect.js"
4
4
  export { default as colcirc } from "./colcirc.js"
5
+ export { default as colrectcirc } from "./colrectcirc.js"
package/src/debug/dd.js CHANGED
@@ -1,7 +1,7 @@
1
- import log from "./log.js"
1
+ import is from "./is.js"
2
2
 
3
3
  /**
4
- * Logs something and stops the engine.
4
+ * Dump and die: print something and stops the engine.
5
5
  *
6
6
  * @param {any} data
7
7
  * @param {string} context
@@ -14,6 +14,11 @@ export default (data, context, engine = globalThis) => {
14
14
  engine.textfont("monospace")
15
15
  engine.textsize(16)
16
16
  engine.textalign("start", "top")
17
- log(data, context || "dd() output", engine)
17
+ engine.text(
18
+ 16,
19
+ 16,
20
+ `${context ?? "dd() output"}: ` +
21
+ (is(data, "object") ? JSON.stringify(data, null, 4) : data)
22
+ )
18
23
  engine.quit()
19
24
  }
@@ -1,4 +1,3 @@
1
1
  export { default as assert } from "./assert.js"
2
2
  export { default as is } from "./is.js"
3
- export { default as log } from "./log.js"
4
3
  export { default as dd } from "./dd.js"
package/src/math/index.js CHANGED
@@ -9,3 +9,4 @@ export { default as median } from "./median.js"
9
9
  export { default as sum } from "./sum.js"
10
10
  export { default as lerpAngle } from "./lerp-angle.js"
11
11
  export { default as percent } from "./percent.js"
12
+ export { default as wave } from "./wave.js"
@@ -0,0 +1,21 @@
1
+ import assert from "../debug/assert.js"
2
+
3
+ /**
4
+ * Interpolate between 2 values using a periodic function.
5
+ *
6
+ * @param {number} from - the lower bound
7
+ * @param {number} to - the higher bound
8
+ * @param {number} t - value passed to the periodic function
9
+ * @param {(n: number) => number} [fn] - the periodic function (which default to `Math.sin`)
10
+ */
11
+ export default (from, to, t, fn = Math.sin) => {
12
+ DEV: assert(isNumber(from), "[litecanvas] wave() 1st param must be a number")
13
+ DEV: assert(isNumber(to), "[litecanvas] wave() 2nd param must be a number")
14
+ DEV: assert(isNumber(t), "[litecanvas] wave() 3rd param must be a number")
15
+ DEV: assert(
16
+ "function" === typeof fn,
17
+ "[litecanvas] wave() 4rd param must be a function (n: number) => number"
18
+ )
19
+
20
+ return from + ((fn(t) + 1) / 2) * (to - from)
21
+ }
package/src/debug/log.js DELETED
@@ -1,15 +0,0 @@
1
- import is from "./is.js"
2
-
3
- /**
4
- * @param {any} data
5
- * @param {string} [context]
6
- * @param {LitecanvasInstance} [engine]
7
- */
8
- export default (data, context, engine = globalThis) => {
9
- return engine.text(
10
- 16,
11
- 16,
12
- (context ? `${context}: ` : "") +
13
- (is(data, "object") ? JSON.stringify(data, null, 4) : data)
14
- )
15
- }