@litecanvas/utils 0.22.0 → 0.24.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/dist/all.js CHANGED
@@ -40,6 +40,7 @@
40
40
  Grid: () => Grid,
41
41
  LEFT: () => LEFT,
42
42
  LINEAR: () => LINEAR,
43
+ Noise: () => Noise,
43
44
  ONE: () => ONE,
44
45
  RIGHT: () => RIGHT,
45
46
  TypedGrid: () => TypedGrid,
@@ -1015,14 +1016,15 @@
1015
1016
  }
1016
1017
  /**
1017
1018
  * @param {LitecanvasInstance} [engine]
1018
- * @returns {TweenController} this instance
1019
+ * @returns {this}
1019
1020
  */
1020
1021
  start(engine) {
1021
- if (!this.running) {
1022
- this.stop();
1022
+ if (this.running) {
1023
+ return this;
1023
1024
  }
1024
1025
  this._cu.stop(false);
1025
1026
  this._ch = this._cu = this;
1027
+ this.running = true;
1026
1028
  const fromValue = this._o[this._p] || 0;
1027
1029
  const toValue = this._rel ? fromValue + this._x : this._x;
1028
1030
  this._lc = this._lc || engine || globalThis;
@@ -1039,15 +1041,6 @@
1039
1041
  this.stop();
1040
1042
  }
1041
1043
  });
1042
- this.running = true;
1043
- return this;
1044
- }
1045
- /**
1046
- * @param {Function} callback
1047
- * @returns {this}
1048
- */
1049
- onEnd(callback) {
1050
- this._cb.push(callback);
1051
1044
  return this;
1052
1045
  }
1053
1046
  /**
@@ -1055,7 +1048,7 @@
1055
1048
  * @returns {this}
1056
1049
  */
1057
1050
  stop(completed = true) {
1058
- if (!this.running || !this._u) return;
1051
+ if (!this._u) return this;
1059
1052
  this.running = false;
1060
1053
  this._u();
1061
1054
  this._t = 0;
@@ -1066,6 +1059,21 @@
1066
1059
  }
1067
1060
  return this;
1068
1061
  }
1062
+ /**
1063
+ * @param {LitecanvasInstance} [engine]
1064
+ * @returns {this}
1065
+ */
1066
+ restart(engine = null, completed = false) {
1067
+ return this.stop(completed).restart(engine);
1068
+ }
1069
+ /**
1070
+ * @param {Function} callback
1071
+ * @returns {this}
1072
+ */
1073
+ onEnd(callback) {
1074
+ this._cb.push(callback);
1075
+ return this;
1076
+ }
1069
1077
  /**
1070
1078
  * @param {TweenController} another
1071
1079
  * @returns {this}
@@ -1120,6 +1128,136 @@
1120
1128
  }
1121
1129
  };
1122
1130
 
1131
+ // src/noise/index.js
1132
+ var PERLIN_YWRAPB = 4;
1133
+ var PERLIN_YWRAP = 1 << PERLIN_YWRAPB;
1134
+ var PERLIN_ZWRAPB = 8;
1135
+ var PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB;
1136
+ var PERLIN_SIZE = 4095;
1137
+ var scaled_cosine = (i) => 0.5 * (1 - Math.cos(i * Math.PI));
1138
+ var Noise = class {
1139
+ /**
1140
+ * Array to store Perlin noise values.
1141
+ * @type {number[]}
1142
+ * @private
1143
+ */
1144
+ _p = [];
1145
+ /**
1146
+ * Number of octaves for the Perlin noise. Higher values create more detail.
1147
+ * @type {number}
1148
+ * @private
1149
+ */
1150
+ _po = 4;
1151
+ /**
1152
+ * Amplitude falloff factor for Perlin noise. Determines the reduction of amplitude per octave.
1153
+ * @type {number}
1154
+ * @private
1155
+ */
1156
+ _pf = 0.5;
1157
+ /**
1158
+ * @type {LitecanvasInstance}
1159
+ * @private
1160
+ */
1161
+ _e = null;
1162
+ /**
1163
+ * @param {LitecanvasInstance} engine
1164
+ */
1165
+ constructor(engine) {
1166
+ this._e = engine || globalThis;
1167
+ this.noiseSeed();
1168
+ }
1169
+ /**
1170
+ * Generates Perlin noise for the given coordinates.
1171
+ * @param {number} x - X-coordinate.
1172
+ * @param {number} [y=0] - Y-coordinate (default is 0).
1173
+ * @param {number} [z=0] - Z-coordinate (default is 0).
1174
+ * @returns {number} A noise value in the range [0, 1).
1175
+ */
1176
+ noise(x, y = 0, z = 0) {
1177
+ if (x < 0) {
1178
+ x = -x;
1179
+ }
1180
+ if (y < 0) {
1181
+ y = -y;
1182
+ }
1183
+ if (z < 0) {
1184
+ z = -z;
1185
+ }
1186
+ let xi = Math.floor(x), yi = Math.floor(y), zi = Math.floor(z);
1187
+ let xf = x - xi;
1188
+ let yf = y - yi;
1189
+ let zf = z - zi;
1190
+ let rxf, ryf;
1191
+ let r = 0;
1192
+ let ampl = 0.5;
1193
+ let n1, n2, n3;
1194
+ for (let o = 0; o < this._po; o++) {
1195
+ let of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB);
1196
+ rxf = scaled_cosine(xf);
1197
+ ryf = scaled_cosine(yf);
1198
+ n1 = this._p[of & PERLIN_SIZE];
1199
+ n1 += rxf * (this._p[of + 1 & PERLIN_SIZE] - n1);
1200
+ n2 = this._p[of + PERLIN_YWRAP & PERLIN_SIZE];
1201
+ n2 += rxf * (this._p[of + PERLIN_YWRAP + 1 & PERLIN_SIZE] - n2);
1202
+ n1 += ryf * (n2 - n1);
1203
+ of += PERLIN_ZWRAP;
1204
+ n2 = this._p[of & PERLIN_SIZE];
1205
+ n2 += rxf * (this._p[of + 1 & PERLIN_SIZE] - n2);
1206
+ n3 = this._p[of + PERLIN_YWRAP & PERLIN_SIZE];
1207
+ n3 += rxf * (this._p[of + PERLIN_YWRAP + 1 & PERLIN_SIZE] - n3);
1208
+ n2 += ryf * (n3 - n2);
1209
+ n1 += scaled_cosine(zf) * (n2 - n1);
1210
+ r += n1 * ampl;
1211
+ ampl *= this._pf;
1212
+ xi <<= 1;
1213
+ xf *= 2;
1214
+ yi <<= 1;
1215
+ yf *= 2;
1216
+ zi <<= 1;
1217
+ zf *= 2;
1218
+ if (xf >= 1) {
1219
+ xi++;
1220
+ xf--;
1221
+ }
1222
+ if (yf >= 1) {
1223
+ yi++;
1224
+ yf--;
1225
+ }
1226
+ if (zf >= 1) {
1227
+ zi++;
1228
+ zf--;
1229
+ }
1230
+ }
1231
+ return r;
1232
+ }
1233
+ /**
1234
+ * Adjusts the detail level of the noise by setting the number of octaves and amplitude falloff.
1235
+ * @param {number} lod - Level of detail (number of octaves).
1236
+ * @param {number} falloff - Amplitude falloff per octave.
1237
+ */
1238
+ noiseDetail(lod, falloff) {
1239
+ if (lod > 0) {
1240
+ this._po = lod;
1241
+ }
1242
+ if (falloff > 0) {
1243
+ this._pf = falloff;
1244
+ }
1245
+ }
1246
+ /**
1247
+ * Sets a seed for the Perlin noise generator, ensuring deterministic results.
1248
+ * @param {number} value - Seed value.
1249
+ */
1250
+ noiseSeed(value = null) {
1251
+ if (value != null) {
1252
+ this._e.seed(value);
1253
+ }
1254
+ const random = this._e.rand || Math.random;
1255
+ for (let i = 0; i < PERLIN_SIZE + 1; i++) {
1256
+ this._p[i] = random();
1257
+ }
1258
+ }
1259
+ };
1260
+
1123
1261
  // src/_web.js
1124
1262
  globalThis.utils = Object.assign(globalThis.utils || {}, src_exports);
1125
1263
  })();
package/dist/all.min.js CHANGED
@@ -1,3 +1,3 @@
1
- (()=>{var Q=Object.defineProperty;var v=(e,t)=>{for(var s in t)Q(e,s,{get:t[s],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=()=>{for(let e in globalThis.utils)e!=="global"&&(globalThis[e]=globalThis.utils[e])};var k={};v(k,{ANCHOR_BOT_LEFT:()=>Ht,ANCHOR_BOT_RIGHT:()=>At,ANCHOR_CENTER:()=>It,ANCHOR_TOP_LEFT:()=>G,ANCHOR_TOP_RIGHT:()=>bt,Actor:()=>S,BACK_IN:()=>kt,BACK_IN_OUT:()=>Pt,BACK_OUT:()=>Lt,BOUNCE_IN:()=>J,BOUNCE_IN_OUT:()=>Bt,BOUNCE_OUT:()=>D,Camera:()=>f,DOWN:()=>Et,EASE_IN:()=>St,EASE_IN_OUT:()=>Dt,EASE_OUT:()=>Ct,ELASTIC_IN:()=>Xt,ELASTIC_IN_OUT:()=>Yt,ELASTIC_OUT:()=>Rt,Grid:()=>g,LEFT:()=>Mt,LINEAR:()=>Z,ONE:()=>mt,RIGHT:()=>wt,TypedGrid:()=>M,UP:()=>Tt,Vector:()=>p,ZERO:()=>F,advance:()=>q,diff:()=>V,fract:()=>$,intersection:()=>x,mod:()=>K,range:()=>z,resolve:()=>P,tween:()=>Ot,vec:()=>n,vecAbs:()=>ft,vecAdd:()=>H,vecAngle:()=>ht,vecAngleBetween:()=>at,vecCeil:()=>pt,vecClamp:()=>xt,vecCross:()=>ct,vecDist:()=>ot,vecDist2:()=>nt,vecDiv:()=>y,vecDot:()=>W,vecEq:()=>b,vecFloor:()=>_t,vecIsZero:()=>yt,vecLerp:()=>lt,vecLimit:()=>rt,vecMag:()=>U,vecMag2:()=>N,vecMove:()=>gt,vecMult:()=>_,vecNorm:()=>O,vecRand:()=>ut,vecReflect:()=>st,vecRotate:()=>et,vecRound:()=>dt,vecSet:()=>B,vecSetMag:()=>it,vecSub:()=>A,wave:()=>j});var x=(e,t,s,i,r,o,h,a)=>{let c=Math.max(e,r),L=Math.min(e+s,r+h)-c,d=Math.max(t,o),T=Math.min(t+i,o+a)-d;return[c,d,L,T]};var P=(e,t,s,i,r,o,h,a)=>{let[c,L,d,T]=x(e,t,s,i,r,o,h,a),u="",w=e,E=t;return d<T?e<r?(u="right",w=r-s):(u="left",w=r+h):t<o?(u="bottom",E=o-i):(u="top",E=o+a),{direction:u,x:w,y:E}};var f=class{_engine=null;x=0;y=0;ox=0;oy=0;width=0;height=0;rotation=0;scale=1;_shake={x:0,y:0,removeListener:null};constructor(t=null,s=0,i=0,r=null,o=null){this._engine=t||globalThis,this.ox=s,this.oy=i,this.resize(r||this._engine.WIDTH-s,o||this._engine.HEIGHT-i),this.x=this.width/2,this.y=this.height/2}resize(t,s){this.width=t,this.height=s,this._engine.emit("camera-resized",this)}start(t=!1){if(this._engine.push(),t){let r=path();r.rect(this.ox,this.oy,this.width,this.height),this._engine.clip(r)}let s=this.ox+this.width/2,i=this.oy+this.height/2;this._engine.translate(s,i),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,i={}){let r=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,i.x=r*t-o*s+this.x,i.y=o*t+r*s+this.y,i}getCameraPoint(t,s,i={}){let r=Math.cos(-this.rotation),o=Math.sin(-this.rotation);return t=t-this.x,s=s-this.y,t=r*t-o*s,s=o*t+r*s,i.x=t*this.scale+this.width/2+this.ox,i.y=s*this.scale+this.height/2+this.oy,i}getBounds(){return[this.ox,this.oy,this.width,this.height]}viewing(t,s,i,r){let o=this.width/2-this.x,h=this.height/2-this.y,a=this.width/this.scale,c=this.height/this.scale;return this._engine.colrect(t,s,i,r,o,h,a,c)}shake(t=1,s=.3){this.shaking||(this._shake.removeListener=this._engine.listen("update",i=>{this._shake.x=this._engine.randi(-t,t),this._shake.y=this._engine.randi(-t,t),s-=i,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 g=class e{_w;_h;_c;constructor(t,s,i=[]){this._w=Math.max(1,~~t),this._h=Math.max(1,~~s),this._c=i}[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,i){this._c[this.pointToIndex(t,s)]=i}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 i=s?this.length-1:0,r=s?-1:this.length,o=s?-1:1;for(;i!==r;){let h=this.indexToPointX(i),a=this.indexToPointY(i),c=this._c[i];if(t(h,a,c,this)===!1)break;i+=o}}fill(t){this.forEach((s,i)=>{this.set(s,i,t)})}clampX(t){return X(t,0,this._w-1)}clampY(t){return X(t,0,this._h-1)}toArray(){return this._c.slice()}toString(t=" ",s=!0){if(!s)return this._c.join(t);let i=[];return this.forEach((r,o,h)=>{i[o]=i[o]||"",i[o]+=h+t}),i.join(`
2
- `)}},M=class e extends g{constructor(t,s,i=Uint8Array){super(t,s,null),this._c=new i(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,i,r)=>{t.set(s,i,r)}),t}};function X(e,t,s){return e<t?t:e>s?s:e}var I=Math.sqrt,R=Math.cos,Y=Math.sin,tt=2*Math.PI,p=class{x;y;constructor(t=0,s=t){this.x=t,this.y=s}toString(){return`Vector (${this.x}, ${this.y})`}},l=e=>e instanceof p,n=(e=0,t=e)=>(l(e)&&(t=e.y,e=e.x),new p(e,t)),b=(e,t,s=t)=>l(t)?b(e,t.x,t.y):e.x===t&&e.y===s,B=(e,t,s=t)=>(l(t)?B(e,t.x,t.y):(e.x=t,e.y=s),e),H=(e,t,s=t)=>l(t)?H(e,t.x,t.y):(e.x+=t,e.y+=s,e),A=(e,t,s=t)=>l(t)?A(e,t.x,t.y):(e.x-=t,e.y-=s,e),_=(e,t,s=t)=>l(t)?_(e,t.x,t.y):(e.x*=t,e.y*=s,e),y=(e,t,s=t)=>l(t)?y(e,t.x,t.y):(e.x/=t||1,e.y/=s||1,e),et=(e,t)=>{let s=R(t),i=Y(t);return e.x=s*e.x-i*e.y,e.y=i*e.x+s*e.y,e},st=(e,t)=>{let s=O(n(t));return A(e,_(s,2*W(e,s)))},it=(e,t)=>(O(e),_(e,t),e),U=e=>I(e.x*e.x+e.y*e.y),N=e=>e.x*e.x+e.y*e.y,O=e=>{let t=U(e);return t>0&&y(e,t),e},rt=(e,t=1)=>{let s=N(e);return s>t*t&&(y(e,I(s)),_(e,t)),e},ot=(e,t)=>{let s=e.x-t.x,i=e.y-t.y;return I(s*s+i*i)},nt=(e,t)=>{let s=e.x-t.x,i=e.y-t.y;return s*s+i*i},ht=e=>Math.atan2(e.y,e.x),at=(e,t)=>Math.atan2(t.y-e.y,t.x-e.x),W=(e,t)=>e.x*t.x+e.y*t.y,ct=(e,t)=>e.x*t.y-e.y*t.x,lt=(e,t,s)=>(e.x+=(t.x-e.x)*s||0,e.y+=(t.y-e.y)*s||0,e),ut=(e=1,t=e,s=globalThis.rand||Math.random)=>{let i=s()*tt,r=s()*(t-e)+e;return n(R(i)*r,Y(i)*r)},ft=e=>(e.x=Math.abs(e.x),e.y=Math.abs(e.y),e),pt=e=>(e.x=Math.ceil(e.x),e.y=Math.ceil(e.y),e),_t=e=>(e.x=Math.floor(e.x),e.y=Math.floor(e.y),e),dt=e=>(e.x=Math.round(e.x),e.y=Math.round(e.y),e),xt=(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),gt=(e,t,s=1)=>H(e,t.x*s,t.y*s),yt=e=>b(e,F),F=n(0,0),mt=n(1,1),Tt=n(0,-1),wt=n(1,0),Et=n(0,1),Mt=n(-1,0);var It=n(.5,.5),G=n(0,0),bt=n(1,0),Ht=n(0,1),At=n(1,1),S=class{sprite;pos;_o;_s;flipX=!1;flipY=!1;angle=0;opacity=1;hidden=!1;constructor(t,s,i=G){this.sprite=t,this.pos=s||n(0),this._o=n(i),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),i=this.sprite.height*(t?this._s.y:1),r=this.pos.x-s*this.anchor.x,o=this.pos.y-i*this.anchor.y;return[r,o,s,i]}draw(t=globalThis,s=!0){this.hidden||this.opacity<=0||(s&&t.push(),this.transform(t),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 i=this.anchor,r=-this.sprite.width*(this.flipX?1-i.x:i.x),o=-this.sprite.height*(this.flipY?1-i.y:i.y);s&&t.alpha(this.opacity),t.image(r,o,this.sprite)}};var V=(e,t)=>Math.abs(t-e)||0;var j=(e,t,s,i=Math.sin)=>e+(i(s)+1)/2*(t-e);var $=e=>e%1||0;var z=e=>Array.from(Array(e).keys());var q=advance=(e,t,s,i=1)=>{s&&(t.x+=s.x*i,t.y+=s.y*i),e.x+=t.x*i,e.y+=t.y*i};var K=(e,t)=>(t+e%t)%t;var m=Math.PI/2,Ot=(e,t,s,i=1,r=Z)=>new C(e,t,s,i,r),Z=e=>e,St=e=>e*e,Ct=e=>-e*(e-2),Dt=e=>e<.5?2*e*e:-2*e*e+4*e-1,kt=e=>e*e*e-e*Math.sin(e*Math.PI),Lt=e=>{let t=1-e;return 1-(t*t*t-t*Math.sin(t*Math.PI))},Pt=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},Xt=e=>Math.sin(13*m*e)*Math.pow(2,10*(e-1)),Rt=e=>Math.sin(-13*m*(e+1))*Math.pow(2,-10*e)+1,Yt=e=>{if(e<.5){let i=Math.sin(13*m*(2*e)),r=Math.pow(2,10*(2*e-1));return .5*i*r}let t=Math.sin(-13*m*(2*e-1+1)),s=Math.pow(2,-10*(2*e-1));return .5*(t*s+2)},J=e=>1-D(1-e),D=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,Bt=e=>e<.5?.5*J(e*2):.5*D(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,i,r,o){this._o=t,this._p=s,this._x=i,this._d=r,this._e=o,this._w=0}start(t){this.running||this.stop(),this._cu.stop(!1),this._ch=this._cu=this;let s=this._o[this._p]||0,i=this._rel?s+this._x:this._x;return this._lc=this._lc||t||globalThis,this._u=this._lc.listen("update",r=>{if(this._t<=this._w){this._t+=r;return}let o=this._t-this._w;this._o[this._p]=this._lc.lerp(s,i,this._e(o/this._d)),this._t+=r,o>=this._d&&(this._o[this._p]=i,this.stop())}),this.running=!0,this}onEnd(t){return this._cb.push(t),this}stop(t=!0){if(!(!this.running||!this._u)){if(this.running=!1,this._u(),this._t=0,t)for(let s of this._cb)s(this._o);return 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}};globalThis.utils=Object.assign(globalThis.utils||{},k);})();
1
+ (()=>{var at=Object.defineProperty;var ct=(e,t)=>{for(var s in t)at(e,s,{get:t[s],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=()=>{for(let e in globalThis.utils)e!=="global"&&(globalThis[e]=globalThis.utils[e])};var B={};ct(B,{ANCHOR_BOT_LEFT:()=>Xt,ANCHOR_BOT_RIGHT:()=>Yt,ANCHOR_CENTER:()=>Lt,ANCHOR_TOP_LEFT:()=>J,ANCHOR_TOP_RIGHT:()=>Rt,Actor:()=>R,BACK_IN:()=>Ft,BACK_IN_OUT:()=>Vt,BACK_OUT:()=>Gt,BOUNCE_IN:()=>ot,BOUNCE_IN_OUT:()=>zt,BOUNCE_OUT:()=>Y,Camera:()=>T,DOWN:()=>Ct,EASE_IN:()=>Wt,EASE_IN_OUT:()=>Ut,EASE_OUT:()=>Bt,ELASTIC_IN:()=>jt,ELASTIC_IN_OUT:()=>Zt,ELASTIC_OUT:()=>$t,Grid:()=>b,LEFT:()=>kt,LINEAR:()=>rt,Noise:()=>W,ONE:()=>St,RIGHT:()=>Pt,TypedGrid:()=>S,UP:()=>Dt,Vector:()=>w,ZERO:()=>K,advance:()=>st,diff:()=>Q,fract:()=>tt,intersection:()=>I,mod:()=>it,range:()=>et,resolve:()=>F,tween:()=>Nt,vec:()=>n,vecAbs:()=>Et,vecAdd:()=>C,vecAngle:()=>gt,vecAngleBetween:()=>yt,vecCeil:()=>Mt,vecClamp:()=>Ht,vecCross:()=>mt,vecDist:()=>dt,vecDist2:()=>xt,vecDiv:()=>H,vecDot:()=>q,vecEq:()=>P,vecFloor:()=>It,vecIsZero:()=>Ot,vecLerp:()=>Tt,vecLimit:()=>_t,vecMag:()=>Z,vecMag2:()=>z,vecMove:()=>At,vecMult:()=>E,vecNorm:()=>L,vecRand:()=>wt,vecReflect:()=>ft,vecRotate:()=>ut,vecRound:()=>bt,vecSet:()=>$,vecSetMag:()=>pt,vecSub:()=>k,wave:()=>v});var I=(e,t,s,i,r,o,h,a)=>{let c=Math.max(e,r),x=Math.min(e+s,r+h)-c,u=Math.max(t,o),g=Math.min(t+i,o+a)-u;return[c,u,x,g]};var F=(e,t,s,i,r,o,h,a)=>{let[c,x,u,g]=I(e,t,s,i,r,o,h,a),d="",m=e,l=t;return u<g?e<r?(d="right",m=r-s):(d="left",m=r+h):t<o?(d="bottom",l=o-i):(d="top",l=o+a),{direction:d,x:m,y:l}};var T=class{_engine=null;x=0;y=0;ox=0;oy=0;width=0;height=0;rotation=0;scale=1;_shake={x:0,y:0,removeListener:null};constructor(t=null,s=0,i=0,r=null,o=null){this._engine=t||globalThis,this.ox=s,this.oy=i,this.resize(r||this._engine.WIDTH-s,o||this._engine.HEIGHT-i),this.x=this.width/2,this.y=this.height/2}resize(t,s){this.width=t,this.height=s,this._engine.emit("camera-resized",this)}start(t=!1){if(this._engine.push(),t){let r=path();r.rect(this.ox,this.oy,this.width,this.height),this._engine.clip(r)}let s=this.ox+this.width/2,i=this.oy+this.height/2;this._engine.translate(s,i),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,i={}){let r=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,i.x=r*t-o*s+this.x,i.y=o*t+r*s+this.y,i}getCameraPoint(t,s,i={}){let r=Math.cos(-this.rotation),o=Math.sin(-this.rotation);return t=t-this.x,s=s-this.y,t=r*t-o*s,s=o*t+r*s,i.x=t*this.scale+this.width/2+this.ox,i.y=s*this.scale+this.height/2+this.oy,i}getBounds(){return[this.ox,this.oy,this.width,this.height]}viewing(t,s,i,r){let o=this.width/2-this.x,h=this.height/2-this.y,a=this.width/this.scale,c=this.height/this.scale;return this._engine.colrect(t,s,i,r,o,h,a,c)}shake(t=1,s=.3){this.shaking||(this._shake.removeListener=this._engine.listen("update",i=>{this._shake.x=this._engine.randi(-t,t),this._shake.y=this._engine.randi(-t,t),s-=i,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 b=class e{_w;_h;_c;constructor(t,s,i=[]){this._w=Math.max(1,~~t),this._h=Math.max(1,~~s),this._c=i}[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,i){this._c[this.pointToIndex(t,s)]=i}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 i=s?this.length-1:0,r=s?-1:this.length,o=s?-1:1;for(;i!==r;){let h=this.indexToPointX(i),a=this.indexToPointY(i),c=this._c[i];if(t(h,a,c,this)===!1)break;i+=o}}fill(t){this.forEach((s,i)=>{this.set(s,i,t)})}clampX(t){return G(t,0,this._w-1)}clampY(t){return G(t,0,this._h-1)}toArray(){return this._c.slice()}toString(t=" ",s=!0){if(!s)return this._c.join(t);let i=[];return this.forEach((r,o,h)=>{i[o]=i[o]||"",i[o]+=h+t}),i.join(`
2
+ `)}},S=class e extends b{constructor(t,s,i=Uint8Array){super(t,s,null),this._c=new i(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,i,r)=>{t.set(s,i,r)}),t}};function G(e,t,s){return e<t?t:e>s?s:e}var D=Math.sqrt,V=Math.cos,j=Math.sin,lt=2*Math.PI,w=class{x;y;constructor(t=0,s=t){this.x=t,this.y=s}toString(){return`Vector (${this.x}, ${this.y})`}},y=e=>e instanceof w,n=(e=0,t=e)=>(y(e)&&(t=e.y,e=e.x),new w(e,t)),P=(e,t,s=t)=>y(t)?P(e,t.x,t.y):e.x===t&&e.y===s,$=(e,t,s=t)=>(y(t)?$(e,t.x,t.y):(e.x=t,e.y=s),e),C=(e,t,s=t)=>y(t)?C(e,t.x,t.y):(e.x+=t,e.y+=s,e),k=(e,t,s=t)=>y(t)?k(e,t.x,t.y):(e.x-=t,e.y-=s,e),E=(e,t,s=t)=>y(t)?E(e,t.x,t.y):(e.x*=t,e.y*=s,e),H=(e,t,s=t)=>y(t)?H(e,t.x,t.y):(e.x/=t||1,e.y/=s||1,e),ut=(e,t)=>{let s=V(t),i=j(t);return e.x=s*e.x-i*e.y,e.y=i*e.x+s*e.y,e},ft=(e,t)=>{let s=L(n(t));return k(e,E(s,2*q(e,s)))},pt=(e,t)=>(L(e),E(e,t),e),Z=e=>D(e.x*e.x+e.y*e.y),z=e=>e.x*e.x+e.y*e.y,L=e=>{let t=Z(e);return t>0&&H(e,t),e},_t=(e,t=1)=>{let s=z(e);return s>t*t&&(H(e,D(s)),E(e,t)),e},dt=(e,t)=>{let s=e.x-t.x,i=e.y-t.y;return D(s*s+i*i)},xt=(e,t)=>{let s=e.x-t.x,i=e.y-t.y;return s*s+i*i},gt=e=>Math.atan2(e.y,e.x),yt=(e,t)=>Math.atan2(t.y-e.y,t.x-e.x),q=(e,t)=>e.x*t.x+e.y*t.y,mt=(e,t)=>e.x*t.y-e.y*t.x,Tt=(e,t,s)=>(e.x+=(t.x-e.x)*s||0,e.y+=(t.y-e.y)*s||0,e),wt=(e=1,t=e,s=globalThis.rand||Math.random)=>{let i=s()*lt,r=s()*(t-e)+e;return n(V(i)*r,j(i)*r)},Et=e=>(e.x=Math.abs(e.x),e.y=Math.abs(e.y),e),Mt=e=>(e.x=Math.ceil(e.x),e.y=Math.ceil(e.y),e),It=e=>(e.x=Math.floor(e.x),e.y=Math.floor(e.y),e),bt=e=>(e.x=Math.round(e.x),e.y=Math.round(e.y),e),Ht=(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),At=(e,t,s=1)=>C(e,t.x*s,t.y*s),Ot=e=>P(e,K),K=n(0,0),St=n(1,1),Dt=n(0,-1),Pt=n(1,0),Ct=n(0,1),kt=n(-1,0);var Lt=n(.5,.5),J=n(0,0),Rt=n(1,0),Xt=n(0,1),Yt=n(1,1),R=class{sprite;pos;_o;_s;flipX=!1;flipY=!1;angle=0;opacity=1;hidden=!1;constructor(t,s,i=J){this.sprite=t,this.pos=s||n(0),this._o=n(i),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),i=this.sprite.height*(t?this._s.y:1),r=this.pos.x-s*this.anchor.x,o=this.pos.y-i*this.anchor.y;return[r,o,s,i]}draw(t=globalThis,s=!0){this.hidden||this.opacity<=0||(s&&t.push(),this.transform(t),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 i=this.anchor,r=-this.sprite.width*(this.flipX?1-i.x:i.x),o=-this.sprite.height*(this.flipY?1-i.y:i.y);s&&t.alpha(this.opacity),t.image(r,o,this.sprite)}};var Q=(e,t)=>Math.abs(t-e)||0;var v=(e,t,s,i=Math.sin)=>e+(i(s)+1)/2*(t-e);var tt=e=>e%1||0;var et=e=>Array.from(Array(e).keys());var st=advance=(e,t,s,i=1)=>{s&&(t.x+=s.x*i,t.y+=s.y*i),e.x+=t.x*i,e.y+=t.y*i};var it=(e,t)=>(t+e%t)%t;var A=Math.PI/2,Nt=(e,t,s,i=1,r=rt)=>new X(e,t,s,i,r),rt=e=>e,Wt=e=>e*e,Bt=e=>-e*(e-2),Ut=e=>e<.5?2*e*e:-2*e*e+4*e-1,Ft=e=>e*e*e-e*Math.sin(e*Math.PI),Gt=e=>{let t=1-e;return 1-(t*t*t-t*Math.sin(t*Math.PI))},Vt=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},jt=e=>Math.sin(13*A*e)*Math.pow(2,10*(e-1)),$t=e=>Math.sin(-13*A*(e+1))*Math.pow(2,-10*e)+1,Zt=e=>{if(e<.5){let i=Math.sin(13*A*(2*e)),r=Math.pow(2,10*(2*e-1));return .5*i*r}let t=Math.sin(-13*A*(2*e-1+1)),s=Math.pow(2,-10*(2*e-1));return .5*(t*s+2)},ot=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,zt=e=>e<.5?.5*ot(e*2):.5*Y(e*2-1)+.5,X=class{running=!1;_o;_p;_x;_d;_w;_e;_rel;_cb=[];_t=0;_u=0;_ch=this;_cu=this;_lc;constructor(t,s,i,r,o){this._o=t,this._p=s,this._x=i,this._d=r,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,i=this._rel?s+this._x:this._x;return this._lc=this._lc||t||globalThis,this._u=this._lc.listen("update",r=>{if(this._t<=this._w){this._t+=r;return}let o=this._t-this._w;this._o[this._p]=this._lc.lerp(s,i,this._e(o/this._d)),this._t+=r,o>=this._d&&(this._o[this._p]=i,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 nt=4,O=1<<nt,ht=8,qt=1<<ht,_=4095,N=e=>.5*(1-Math.cos(e*Math.PI)),W=class{_p=[];_po=4;_pf=.5;_e=null;constructor(t){this._e=t||globalThis,this.noiseSeed()}noise(t,s=0,i=0){t<0&&(t=-t),s<0&&(s=-s),i<0&&(i=-i);let r=Math.floor(t),o=Math.floor(s),h=Math.floor(i),a=t-r,c=s-o,x=i-h,u,g,d=0,m=.5,l,f,M;for(let U=0;U<this._po;U++){let p=r+(o<<nt)+(h<<ht);u=N(a),g=N(c),l=this._p[p&_],l+=u*(this._p[p+1&_]-l),f=this._p[p+O&_],f+=u*(this._p[p+O+1&_]-f),l+=g*(f-l),p+=qt,f=this._p[p&_],f+=u*(this._p[p+1&_]-f),M=this._p[p+O&_],M+=u*(this._p[p+O+1&_]-M),f+=g*(M-f),l+=N(x)*(f-l),d+=l*m,m*=this._pf,r<<=1,a*=2,o<<=1,c*=2,h<<=1,x*=2,a>=1&&(r++,a--),c>=1&&(o++,c--),x>=1&&(h++,x--)}return d}noiseDetail(t,s){t>0&&(this._po=t),s>0&&(this._pf=s)}noiseSeed(t=null){t!=null&&this._e.seed(t);let s=this._e.rand||Math.random;for(let i=0;i<_+1;i++)this._p[i]=s()}};globalThis.utils=Object.assign(globalThis.utils||{},B);})();
3
3
  /*! @litecanvas/utils by Luiz Bills | MIT Licensed */
package/dist/noise.js ADDED
@@ -0,0 +1,153 @@
1
+ (() => {
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
7
+
8
+ // src/_global.js
9
+ globalThis.utils = globalThis.utils || {};
10
+ globalThis.utils.global = () => {
11
+ for (const key in globalThis.utils) {
12
+ if ("global" === key) continue;
13
+ globalThis[key] = globalThis.utils[key];
14
+ }
15
+ };
16
+
17
+ // src/noise/index.js
18
+ var noise_exports = {};
19
+ __export(noise_exports, {
20
+ Noise: () => Noise
21
+ });
22
+ var PERLIN_YWRAPB = 4;
23
+ var PERLIN_YWRAP = 1 << PERLIN_YWRAPB;
24
+ var PERLIN_ZWRAPB = 8;
25
+ var PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB;
26
+ var PERLIN_SIZE = 4095;
27
+ var scaled_cosine = (i) => 0.5 * (1 - Math.cos(i * Math.PI));
28
+ var Noise = class {
29
+ /**
30
+ * Array to store Perlin noise values.
31
+ * @type {number[]}
32
+ * @private
33
+ */
34
+ _p = [];
35
+ /**
36
+ * Number of octaves for the Perlin noise. Higher values create more detail.
37
+ * @type {number}
38
+ * @private
39
+ */
40
+ _po = 4;
41
+ /**
42
+ * Amplitude falloff factor for Perlin noise. Determines the reduction of amplitude per octave.
43
+ * @type {number}
44
+ * @private
45
+ */
46
+ _pf = 0.5;
47
+ /**
48
+ * @type {LitecanvasInstance}
49
+ * @private
50
+ */
51
+ _e = null;
52
+ /**
53
+ * @param {LitecanvasInstance} engine
54
+ */
55
+ constructor(engine) {
56
+ this._e = engine || globalThis;
57
+ this.noiseSeed();
58
+ }
59
+ /**
60
+ * Generates Perlin noise for the given coordinates.
61
+ * @param {number} x - X-coordinate.
62
+ * @param {number} [y=0] - Y-coordinate (default is 0).
63
+ * @param {number} [z=0] - Z-coordinate (default is 0).
64
+ * @returns {number} A noise value in the range [0, 1).
65
+ */
66
+ noise(x, y = 0, z = 0) {
67
+ if (x < 0) {
68
+ x = -x;
69
+ }
70
+ if (y < 0) {
71
+ y = -y;
72
+ }
73
+ if (z < 0) {
74
+ z = -z;
75
+ }
76
+ let xi = Math.floor(x), yi = Math.floor(y), zi = Math.floor(z);
77
+ let xf = x - xi;
78
+ let yf = y - yi;
79
+ let zf = z - zi;
80
+ let rxf, ryf;
81
+ let r = 0;
82
+ let ampl = 0.5;
83
+ let n1, n2, n3;
84
+ for (let o = 0; o < this._po; o++) {
85
+ let of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB);
86
+ rxf = scaled_cosine(xf);
87
+ ryf = scaled_cosine(yf);
88
+ n1 = this._p[of & PERLIN_SIZE];
89
+ n1 += rxf * (this._p[of + 1 & PERLIN_SIZE] - n1);
90
+ n2 = this._p[of + PERLIN_YWRAP & PERLIN_SIZE];
91
+ n2 += rxf * (this._p[of + PERLIN_YWRAP + 1 & PERLIN_SIZE] - n2);
92
+ n1 += ryf * (n2 - n1);
93
+ of += PERLIN_ZWRAP;
94
+ n2 = this._p[of & PERLIN_SIZE];
95
+ n2 += rxf * (this._p[of + 1 & PERLIN_SIZE] - n2);
96
+ n3 = this._p[of + PERLIN_YWRAP & PERLIN_SIZE];
97
+ n3 += rxf * (this._p[of + PERLIN_YWRAP + 1 & PERLIN_SIZE] - n3);
98
+ n2 += ryf * (n3 - n2);
99
+ n1 += scaled_cosine(zf) * (n2 - n1);
100
+ r += n1 * ampl;
101
+ ampl *= this._pf;
102
+ xi <<= 1;
103
+ xf *= 2;
104
+ yi <<= 1;
105
+ yf *= 2;
106
+ zi <<= 1;
107
+ zf *= 2;
108
+ if (xf >= 1) {
109
+ xi++;
110
+ xf--;
111
+ }
112
+ if (yf >= 1) {
113
+ yi++;
114
+ yf--;
115
+ }
116
+ if (zf >= 1) {
117
+ zi++;
118
+ zf--;
119
+ }
120
+ }
121
+ return r;
122
+ }
123
+ /**
124
+ * Adjusts the detail level of the noise by setting the number of octaves and amplitude falloff.
125
+ * @param {number} lod - Level of detail (number of octaves).
126
+ * @param {number} falloff - Amplitude falloff per octave.
127
+ */
128
+ noiseDetail(lod, falloff) {
129
+ if (lod > 0) {
130
+ this._po = lod;
131
+ }
132
+ if (falloff > 0) {
133
+ this._pf = falloff;
134
+ }
135
+ }
136
+ /**
137
+ * Sets a seed for the Perlin noise generator, ensuring deterministic results.
138
+ * @param {number} value - Seed value.
139
+ */
140
+ noiseSeed(value = null) {
141
+ if (value != null) {
142
+ this._e.seed(value);
143
+ }
144
+ const random = this._e.rand || Math.random;
145
+ for (let i = 0; i < PERLIN_SIZE + 1; i++) {
146
+ this._p[i] = random();
147
+ }
148
+ }
149
+ };
150
+
151
+ // src/noise/_web.js
152
+ globalThis.utils = Object.assign(globalThis.utils || {}, noise_exports);
153
+ })();
@@ -0,0 +1 @@
1
+ (()=>{var w=Object.defineProperty;var S=(s,t)=>{for(var e in t)w(s,e,{get:t[e],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=()=>{for(let s in globalThis.utils)s!=="global"&&(globalThis[s]=globalThis.utils[s])};var b={};S(b,{Noise:()=>E});var H=4,_=1<<H,D=8,v=1<<D,a=4095,T=s=>.5*(1-Math.cos(s*Math.PI)),E=class{_p=[];_po=4;_pf=.5;_e=null;constructor(t){this._e=t||globalThis,this.noiseSeed()}noise(t,e=0,n=0){t<0&&(t=-t),e<0&&(e=-e),n<0&&(n=-n);let c=Math.floor(t),f=Math.floor(e),u=Math.floor(n),p=t-c,h=e-f,d=n-u,r,m,y=0,x=.5,l,o,g;for(let I=0;I<this._po;I++){let i=c+(f<<H)+(u<<D);r=T(p),m=T(h),l=this._p[i&a],l+=r*(this._p[i+1&a]-l),o=this._p[i+_&a],o+=r*(this._p[i+_+1&a]-o),l+=m*(o-l),i+=v,o=this._p[i&a],o+=r*(this._p[i+1&a]-o),g=this._p[i+_&a],g+=r*(this._p[i+_+1&a]-g),o+=m*(g-o),l+=T(d)*(o-l),y+=l*x,x*=this._pf,c<<=1,p*=2,f<<=1,h*=2,u<<=1,d*=2,p>=1&&(c++,p--),h>=1&&(f++,h--),d>=1&&(u++,d--)}return y}noiseDetail(t,e){t>0&&(this._po=t),e>0&&(this._pf=e)}noiseSeed(t=null){t!=null&&this._e.seed(t);let e=this._e.rand||Math.random;for(let n=0;n<a+1;n++)this._p[n]=e()}};globalThis.utils=Object.assign(globalThis.utils||{},b);})();
package/dist/tween.js CHANGED
@@ -137,14 +137,15 @@
137
137
  }
138
138
  /**
139
139
  * @param {LitecanvasInstance} [engine]
140
- * @returns {TweenController} this instance
140
+ * @returns {this}
141
141
  */
142
142
  start(engine) {
143
- if (!this.running) {
144
- this.stop();
143
+ if (this.running) {
144
+ return this;
145
145
  }
146
146
  this._cu.stop(false);
147
147
  this._ch = this._cu = this;
148
+ this.running = true;
148
149
  const fromValue = this._o[this._p] || 0;
149
150
  const toValue = this._rel ? fromValue + this._x : this._x;
150
151
  this._lc = this._lc || engine || globalThis;
@@ -161,15 +162,6 @@
161
162
  this.stop();
162
163
  }
163
164
  });
164
- this.running = true;
165
- return this;
166
- }
167
- /**
168
- * @param {Function} callback
169
- * @returns {this}
170
- */
171
- onEnd(callback) {
172
- this._cb.push(callback);
173
165
  return this;
174
166
  }
175
167
  /**
@@ -177,7 +169,7 @@
177
169
  * @returns {this}
178
170
  */
179
171
  stop(completed = true) {
180
- if (!this.running || !this._u) return;
172
+ if (!this._u) return this;
181
173
  this.running = false;
182
174
  this._u();
183
175
  this._t = 0;
@@ -188,6 +180,21 @@
188
180
  }
189
181
  return this;
190
182
  }
183
+ /**
184
+ * @param {LitecanvasInstance} [engine]
185
+ * @returns {this}
186
+ */
187
+ restart(engine = null, completed = false) {
188
+ return this.stop(completed).restart(engine);
189
+ }
190
+ /**
191
+ * @param {Function} callback
192
+ * @returns {this}
193
+ */
194
+ onEnd(callback) {
195
+ this._cb.push(callback);
196
+ return this;
197
+ }
191
198
  /**
192
199
  * @param {TweenController} another
193
200
  * @returns {this}
package/dist/tween.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var h=Object.defineProperty;var p=(t,e)=>{for(var s in e)h(t,s,{get:e[s],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=()=>{for(let t in globalThis.utils)t!=="global"&&(globalThis[t]=globalThis.utils[t])};var c={};p(c,{BACK_IN:()=>E,BACK_IN_OUT:()=>m,BACK_OUT:()=>x,BOUNCE_IN:()=>f,BOUNCE_IN_OUT:()=>y,BOUNCE_OUT:()=>l,EASE_IN:()=>d,EASE_IN_OUT:()=>T,EASE_OUT:()=>g,ELASTIC_IN:()=>I,ELASTIC_IN_OUT:()=>w,ELASTIC_OUT:()=>b,LINEAR:()=>u,tween:()=>_});var n=Math.PI/2,_=(t,e,s,i=1,o=u)=>new a(t,e,s,i,o),u=t=>t,d=t=>t*t,g=t=>-t*(t-2),T=t=>t<.5?2*t*t:-2*t*t+4*t-1,E=t=>t*t*t-t*Math.sin(t*Math.PI),x=t=>{let e=1-t;return 1-(e*e*e-e*Math.sin(e*Math.PI))},m=t=>{if(t<.5){let s=2*t;return .5*(s*s*s-s*Math.sin(s*Math.PI))}let e=1-(2*t-1);return .5*(1-(e*e*e-e*Math.sin(t*Math.PI)))+.5},I=t=>Math.sin(13*n*t)*Math.pow(2,10*(t-1)),b=t=>Math.sin(-13*n*(t+1))*Math.pow(2,-10*t)+1,w=t=>{if(t<.5){let i=Math.sin(13*n*(2*t)),o=Math.pow(2,10*(2*t-1));return .5*i*o}let e=Math.sin(-13*n*(2*t-1+1)),s=Math.pow(2,-10*(2*t-1));return .5*(e*s+2)},f=t=>1-l(1-t),l=t=>t<4/11?121*t*t/16:t<8/11?363/40*t*t-99/10*t+17/5:t<9/10?4356/361*t*t-35442/1805*t+16061/1805:54/5*t*t-513/25*t+268/25,y=t=>t<.5?.5*f(t*2):.5*l(t*2-1)+.5,a=class{running=!1;_o;_p;_x;_d;_w;_e;_rel;_cb=[];_t=0;_u=0;_ch=this;_cu=this;_lc;constructor(e,s,i,o,r){this._o=e,this._p=s,this._x=i,this._d=o,this._e=r,this._w=0}start(e){this.running||this.stop(),this._cu.stop(!1),this._ch=this._cu=this;let s=this._o[this._p]||0,i=this._rel?s+this._x:this._x;return this._lc=this._lc||e||globalThis,this._u=this._lc.listen("update",o=>{if(this._t<=this._w){this._t+=o;return}let r=this._t-this._w;this._o[this._p]=this._lc.lerp(s,i,this._e(r/this._d)),this._t+=o,r>=this._d&&(this._o[this._p]=i,this.stop())}),this.running=!0,this}onEnd(e){return this._cb.push(e),this}stop(e=!0){if(!(!this.running||!this._u)){if(this.running=!1,this._u(),this._t=0,e)for(let s of this._cb)s(this._o);return this}}chain(e){return this._ch.onEnd(()=>{this._cu=e.start(this._lc)}),this._ch=e,this}reset(){return this._cb.length=0,this.stop()}relative(e=!0){return this._rel=e,this}delay(e){return this._w=e,this}get current(){return this._cu}get progress(){return this.running&&this._t>this._w?(this._t-this._w)/this._d:0}};globalThis.utils=Object.assign(globalThis.utils||{},c);})();
1
+ (()=>{var h=Object.defineProperty;var p=(t,e)=>{for(var s in e)h(t,s,{get:e[s],enumerable:!0})};globalThis.utils=globalThis.utils||{};globalThis.utils.global=()=>{for(let t in globalThis.utils)t!=="global"&&(globalThis[t]=globalThis.utils[t])};var c={};p(c,{BACK_IN:()=>E,BACK_IN_OUT:()=>m,BACK_OUT:()=>x,BOUNCE_IN:()=>f,BOUNCE_IN_OUT:()=>y,BOUNCE_OUT:()=>l,EASE_IN:()=>d,EASE_IN_OUT:()=>T,EASE_OUT:()=>g,ELASTIC_IN:()=>I,ELASTIC_IN_OUT:()=>w,ELASTIC_OUT:()=>b,LINEAR:()=>u,tween:()=>_});var n=Math.PI/2,_=(t,e,s,i=1,r=u)=>new a(t,e,s,i,r),u=t=>t,d=t=>t*t,g=t=>-t*(t-2),T=t=>t<.5?2*t*t:-2*t*t+4*t-1,E=t=>t*t*t-t*Math.sin(t*Math.PI),x=t=>{let e=1-t;return 1-(e*e*e-e*Math.sin(e*Math.PI))},m=t=>{if(t<.5){let s=2*t;return .5*(s*s*s-s*Math.sin(s*Math.PI))}let e=1-(2*t-1);return .5*(1-(e*e*e-e*Math.sin(t*Math.PI)))+.5},I=t=>Math.sin(13*n*t)*Math.pow(2,10*(t-1)),b=t=>Math.sin(-13*n*(t+1))*Math.pow(2,-10*t)+1,w=t=>{if(t<.5){let i=Math.sin(13*n*(2*t)),r=Math.pow(2,10*(2*t-1));return .5*i*r}let e=Math.sin(-13*n*(2*t-1+1)),s=Math.pow(2,-10*(2*t-1));return .5*(e*s+2)},f=t=>1-l(1-t),l=t=>t<4/11?121*t*t/16:t<8/11?363/40*t*t-99/10*t+17/5:t<9/10?4356/361*t*t-35442/1805*t+16061/1805:54/5*t*t-513/25*t+268/25,y=t=>t<.5?.5*f(t*2):.5*l(t*2-1)+.5,a=class{running=!1;_o;_p;_x;_d;_w;_e;_rel;_cb=[];_t=0;_u=0;_ch=this;_cu=this;_lc;constructor(e,s,i,r,o){this._o=e,this._p=s,this._x=i,this._d=r,this._e=o,this._w=0}start(e){if(this.running)return this;this._cu.stop(!1),this._ch=this._cu=this,this.running=!0;let s=this._o[this._p]||0,i=this._rel?s+this._x:this._x;return this._lc=this._lc||e||globalThis,this._u=this._lc.listen("update",r=>{if(this._t<=this._w){this._t+=r;return}let o=this._t-this._w;this._o[this._p]=this._lc.lerp(s,i,this._e(o/this._d)),this._t+=r,o>=this._d&&(this._o[this._p]=i,this.stop())}),this}stop(e=!0){if(!this._u)return this;if(this.running=!1,this._u(),this._t=0,e)for(let s of this._cb)s(this._o);return this}restart(e=null,s=!1){return this.stop(s).restart(e)}onEnd(e){return this._cb.push(e),this}chain(e){return this._ch.onEnd(()=>{this._cu=e.start(this._lc)}),this._ch=e,this}reset(){return this._cb.length=0,this.stop()}relative(e=!0){return this._rel=e,this}delay(e){return this._w=e,this}get current(){return this._cu}get progress(){return this.running&&this._t>this._w?(this._t-this._w)/this._d:0}};globalThis.utils=Object.assign(globalThis.utils||{},c);})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litecanvas/utils",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Utilities to help build litecanvas games",
5
5
  "author": "Luiz Bills <luizbills@pm.me>",
6
6
  "license": "MIT",
@@ -26,7 +26,8 @@
26
26
  "dev": "esbuild src/_web.js --bundle --watch --outfile=dist/all.js --servedir=.",
27
27
  "build": "node scripts/build.js",
28
28
  "prepare": "npm run build",
29
- "prepublishOnly": "npm run build"
29
+ "prepublishOnly": "npm run build",
30
+ "format": "npx prettier -w ."
30
31
  },
31
32
  "files": [
32
33
  "src",
@@ -36,6 +37,8 @@
36
37
  "litecanvas": "*"
37
38
  },
38
39
  "devDependencies": {
39
- "esbuild": "^0.23.1"
40
+ "esbuild": "^0.23.1",
41
+ "gzip-size": "^7.0.0",
42
+ "prettier": "^3.3.3"
40
43
  }
41
44
  }
@@ -24,7 +24,7 @@ export default (x1, y1, w1, h1, x2, y2, w2, h2) => {
24
24
  x2,
25
25
  y2,
26
26
  w2,
27
- h2,
27
+ h2
28
28
  )
29
29
 
30
30
  let direction = ""
package/src/index.js CHANGED
@@ -6,3 +6,4 @@ export * from "./vector/index.js"
6
6
  export * from "./actor/index.js"
7
7
  export * from "./math/index.js"
8
8
  export * from "./tween/index.js"
9
+ export * from "./noise/index.js"
@@ -0,0 +1,74 @@
1
+ # Noise utils
2
+
3
+ **CDN**: https://unpkg.com/@litecanvas/utils/dist/noise.js
4
+
5
+ ## Usage
6
+
7
+ Generate procedural Perlin noise to use in your projects, such as terrain generation, animations, or particle effects.
8
+
9
+ ```js
10
+ import litecanvas from "litecanvas"
11
+ import { Noise } from "@litecanvas/utils"
12
+
13
+ const e = litecanvas()
14
+
15
+ // Create a new Noise instance
16
+ const noise = new Noise(e)
17
+
18
+ // Generate a noise value at 2D coordinates (x, y)
19
+ const value = noise.noise(0.5, 0.8)
20
+ console.log("Noise value at (0.5, 0.8):", value)
21
+
22
+ // Generate a noise value at 3D coordinates (x, y, z)
23
+ const value3D = noise.noise(1.2, 0.4, 0.9)
24
+ console.log("Noise value at (1.2, 0.4, 0.9):", value3D)
25
+ ```
26
+
27
+ ### Adjusting Noise Detail
28
+
29
+ You can configure the number of octaves and amplitude falloff to control the detail of the noise.
30
+
31
+ ```js
32
+ // Set 8 octaves and a 60% amplitude falloff
33
+ noise.noiseDetail(8, 0.6)
34
+
35
+ // Generate a new noise value with the updated settings
36
+ const detailedValue = noise.noise(0.3, 0.7)
37
+ console.log("Detailed noise value:", detailedValue)
38
+ ```
39
+
40
+ ## Seeding Noise
41
+
42
+ Ensure deterministic results by setting a seed for the noise generator.
43
+
44
+ ```js
45
+ // Set a specific seed
46
+ noise.noiseSeed(42)
47
+
48
+ // Generate consistent noise values
49
+ const seededValue = noise.noise(0.1, 0.1)
50
+ console.log("Seeded noise value at (0.1, 0.1):", seededValue)
51
+ ```
52
+
53
+ ## 2D Noise Grid
54
+
55
+ Create a grid of Perlin noise values and display them as ASCII art.
56
+
57
+ ```js
58
+ const noise = new utils.Noise()
59
+ noise.noiseDetail(4, 0.5)
60
+
61
+ // Generate a 8 by 8 noise grid
62
+ const gridSize = 8
63
+ let grid = ""
64
+
65
+ for (let y = 0; y < gridSize; y++) {
66
+ for (let x = 0; x < gridSize; x++) {
67
+ const value = noise.noise(x / gridSize, y / gridSize)
68
+ grid += value > 0.5 ? "#" : "."
69
+ }
70
+ grid += "\n"
71
+ }
72
+
73
+ console.log(grid)
74
+ ```
@@ -0,0 +1,4 @@
1
+ import "../_global.js"
2
+ import * as noiseUtils from "./index.js"
3
+
4
+ globalThis.utils = Object.assign(globalThis.utils || {}, noiseUtils)
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Further adapted from p5 Noise module
3
+ * https://github.com/processing/p5.js/blob/v1.11.1/src/math/noise.js
4
+ */
5
+
6
+ // import litecanvas types
7
+ import "litecanvas"
8
+
9
+ /**
10
+ * Constants for Perlin noise calculations.
11
+ */
12
+ const PERLIN_YWRAPB = 4
13
+ const PERLIN_YWRAP = 1 << PERLIN_YWRAPB
14
+ const PERLIN_ZWRAPB = 8
15
+ const PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB
16
+ const PERLIN_SIZE = 4095
17
+
18
+ /**
19
+ * Scaled cosine function used for smoothing transitions in Perlin noise.
20
+ * @param {number} i - Input value.
21
+ * @returns {number} Scaled cosine value.
22
+ */
23
+ const scaled_cosine = (i) => 0.5 * (1.0 - Math.cos(i * Math.PI))
24
+
25
+ /**
26
+ * Class for generating Perlin noise, a type of gradient noise often used in procedural generation.
27
+ */
28
+ export class Noise {
29
+ /**
30
+ * Array to store Perlin noise values.
31
+ * @type {number[]}
32
+ * @private
33
+ */
34
+ _p = []
35
+
36
+ /**
37
+ * Number of octaves for the Perlin noise. Higher values create more detail.
38
+ * @type {number}
39
+ * @private
40
+ */
41
+ _po = 4
42
+
43
+ /**
44
+ * Amplitude falloff factor for Perlin noise. Determines the reduction of amplitude per octave.
45
+ * @type {number}
46
+ * @private
47
+ */
48
+ _pf = 0.5
49
+
50
+ /**
51
+ * @type {LitecanvasInstance}
52
+ * @private
53
+ */
54
+ _e = null
55
+
56
+ /**
57
+ * @param {LitecanvasInstance} engine
58
+ */
59
+ constructor(engine) {
60
+ this._e = engine || globalThis
61
+
62
+ this.noiseSeed()
63
+ }
64
+
65
+ /**
66
+ * Generates Perlin noise for the given coordinates.
67
+ * @param {number} x - X-coordinate.
68
+ * @param {number} [y=0] - Y-coordinate (default is 0).
69
+ * @param {number} [z=0] - Z-coordinate (default is 0).
70
+ * @returns {number} A noise value in the range [0, 1).
71
+ */
72
+ noise(x, y = 0, z = 0) {
73
+ if (x < 0) {
74
+ x = -x
75
+ }
76
+ if (y < 0) {
77
+ y = -y
78
+ }
79
+ if (z < 0) {
80
+ z = -z
81
+ }
82
+
83
+ let xi = Math.floor(x),
84
+ yi = Math.floor(y),
85
+ zi = Math.floor(z)
86
+ let xf = x - xi
87
+ let yf = y - yi
88
+ let zf = z - zi
89
+ let rxf, ryf
90
+
91
+ let r = 0
92
+ let ampl = 0.5
93
+
94
+ let n1, n2, n3
95
+
96
+ for (let o = 0; o < this._po; o++) {
97
+ let of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB)
98
+
99
+ rxf = scaled_cosine(xf)
100
+ ryf = scaled_cosine(yf)
101
+
102
+ n1 = this._p[of & PERLIN_SIZE]
103
+ n1 += rxf * (this._p[(of + 1) & PERLIN_SIZE] - n1)
104
+ n2 = this._p[(of + PERLIN_YWRAP) & PERLIN_SIZE]
105
+ n2 += rxf * (this._p[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2)
106
+ n1 += ryf * (n2 - n1)
107
+
108
+ of += PERLIN_ZWRAP
109
+ n2 = this._p[of & PERLIN_SIZE]
110
+ n2 += rxf * (this._p[(of + 1) & PERLIN_SIZE] - n2)
111
+ n3 = this._p[(of + PERLIN_YWRAP) & PERLIN_SIZE]
112
+ n3 += rxf * (this._p[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3)
113
+ n2 += ryf * (n3 - n2)
114
+
115
+ n1 += scaled_cosine(zf) * (n2 - n1)
116
+
117
+ r += n1 * ampl
118
+ ampl *= this._pf
119
+ xi <<= 1
120
+ xf *= 2
121
+ yi <<= 1
122
+ yf *= 2
123
+ zi <<= 1
124
+ zf *= 2
125
+
126
+ if (xf >= 1.0) {
127
+ xi++
128
+ xf--
129
+ }
130
+ if (yf >= 1.0) {
131
+ yi++
132
+ yf--
133
+ }
134
+ if (zf >= 1.0) {
135
+ zi++
136
+ zf--
137
+ }
138
+ }
139
+ return r
140
+ }
141
+
142
+ /**
143
+ * Adjusts the detail level of the noise by setting the number of octaves and amplitude falloff.
144
+ * @param {number} lod - Level of detail (number of octaves).
145
+ * @param {number} falloff - Amplitude falloff per octave.
146
+ */
147
+ noiseDetail(lod, falloff) {
148
+ if (lod > 0) {
149
+ this._po = lod
150
+ }
151
+ if (falloff > 0) {
152
+ this._pf = falloff
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Sets a seed for the Perlin noise generator, ensuring deterministic results.
158
+ * @param {number} value - Seed value.
159
+ */
160
+ noiseSeed(value = null) {
161
+ if (value != null) {
162
+ this._e.seed(value)
163
+ }
164
+ const random = this._e.rand || Math.random
165
+ for (let i = 0; i < PERLIN_SIZE + 1; i++) {
166
+ this._p[i] = random()
167
+ }
168
+ }
169
+ }
@@ -59,7 +59,7 @@ function draw() {
59
59
 
60
60
  Starts the animation.
61
61
 
62
- Syntax: `.start(engine?: LitecanvasInstance): TweenController`
62
+ Syntax: `.start(engine?: LitecanvasInstance): this`
63
63
 
64
64
  ```js
65
65
  // if your litecanvas has config.global = false
@@ -69,7 +69,7 @@ const engine = litecanvas({
69
69
  })
70
70
 
71
71
  function init () {
72
- engine.tween(...).start(engine)
72
+ tween(...).start(engine)
73
73
  }
74
74
  ```
75
75
 
@@ -81,7 +81,7 @@ const engine = litecanvas({
81
81
 
82
82
  function init () {
83
83
  // just call start
84
- engine.tween(...).start()
84
+ tween(...).start()
85
85
  }
86
86
  ```
87
87
 
@@ -89,7 +89,7 @@ function init () {
89
89
 
90
90
  If enabled (`flag = true`) the tween we animate from a value to another relative value.
91
91
 
92
- Syntax: `.relative(flag?: boolean = true): void`
92
+ Syntax: `.relative(flag?: boolean = true): this`
93
93
 
94
94
  ```js
95
95
  const obj = { x: 0 }
@@ -113,14 +113,13 @@ tween(obj, "x", -100).relative()
113
113
 
114
114
  Make another tween start right after this tween ends.
115
115
 
116
- Syntax: `.relative(another: TweenController): TweenController`
116
+ Syntax: `.relative(another: TweenController): this`
117
117
 
118
118
  ```js
119
119
  const obj = { x: 0, angle: 0 }
120
120
 
121
121
  const moveRight = tween(obj, "x", 100, 1).relative()
122
122
  const moveLeft = tween(obj, "x", -100, 1).relative()
123
- const moveLeft = tween(obj, "angle", Math.PI, 1).relative()
124
123
 
125
124
  // move 100px to right, move 100px to left and rotate
126
125
  moveRight.chain(moveLeft)
@@ -131,7 +130,7 @@ moveRight.start()
131
130
 
132
131
  Enqueues a callback to be executed when the animation finishes.
133
132
 
134
- Syntax: `.onEnd(callback?: (object:any) => void): void`
133
+ Syntax: `.onEnd(callback?: (object:any) => void): this`
135
134
 
136
135
  ```js
137
136
  // lets imagine a animation
@@ -143,11 +142,17 @@ anim.onEnd(() => {
143
142
  })
144
143
  ```
145
144
 
145
+ ### TweenController#restart()
146
+
147
+ Stops and start again the animation.
148
+
149
+ Syntax: `.restart(engine?: LitecanvasInstance, completed: boolean = false): this`
150
+
146
151
  ### TweenController#stop()
147
152
 
148
153
  Stops the animation.
149
154
 
150
- Syntax: `.stop(complete?: boolean): void`
155
+ Syntax: `.stop(completed: boolean = true): this`
151
156
 
152
157
  ```js
153
158
  // lets imagine a animation with 5 seconds of duration
@@ -167,6 +172,8 @@ anim.stop(false)
167
172
 
168
173
  Stops the animation and remove all `.onEnd()` registered callbacks.
169
174
 
175
+ Syntax: `.reset(): this`
176
+
170
177
  ### TweenController#progress
171
178
 
172
179
  Returns the percentage of the animation's progress, a number between `0.0` and `1.0`. Where `0` represents 0% and `1` represents 100%.
@@ -8,7 +8,7 @@ const HALF_PI = Math.PI / 2
8
8
  * @param {number|number} toValue
9
9
  * @param {number} [duration]
10
10
  * @param {(n: number) => number} [easing]
11
- * @returns {TweenController}
11
+ * @returns {this}
12
12
  */
13
13
  export const tween = (object, prop, toValue, duration = 1, easing = LINEAR) => {
14
14
  return new TweenController(object, prop, toValue, duration, easing)
@@ -124,15 +124,16 @@ class TweenController {
124
124
 
125
125
  /**
126
126
  * @param {LitecanvasInstance} [engine]
127
- * @returns {TweenController} this instance
127
+ * @returns {this}
128
128
  */
129
129
  start(engine) {
130
- if (!this.running) {
131
- this.stop()
130
+ if (this.running) {
131
+ return this
132
132
  }
133
133
 
134
134
  this._cu.stop(false)
135
135
  this._ch = this._cu = this
136
+ this.running = true
136
137
 
137
138
  const fromValue = this._o[this._p] || 0
138
139
  const toValue = this._rel ? fromValue + this._x : this._x
@@ -156,17 +157,6 @@ class TweenController {
156
157
  }
157
158
  })
158
159
 
159
- this.running = true
160
-
161
- return this
162
- }
163
-
164
- /**
165
- * @param {Function} callback
166
- * @returns {this}
167
- */
168
- onEnd(callback) {
169
- this._cb.push(callback)
170
160
  return this
171
161
  }
172
162
 
@@ -175,7 +165,7 @@ class TweenController {
175
165
  * @returns {this}
176
166
  */
177
167
  stop(completed = true) {
178
- if (!this.running || !this._u) return
168
+ if (!this._u) return this
179
169
 
180
170
  this.running = false
181
171
 
@@ -191,6 +181,23 @@ class TweenController {
191
181
  return this
192
182
  }
193
183
 
184
+ /**
185
+ * @param {LitecanvasInstance} [engine]
186
+ * @returns {this}
187
+ */
188
+ restart(engine = null, completed = false) {
189
+ return this.stop(completed).restart(engine)
190
+ }
191
+
192
+ /**
193
+ * @param {Function} callback
194
+ * @returns {this}
195
+ */
196
+ onEnd(callback) {
197
+ this._cb.push(callback)
198
+ return this
199
+ }
200
+
194
201
  /**
195
202
  * @param {TweenController} another
196
203
  * @returns {this}