litecanvas 0.79.3 → 0.80.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/dist.dev.js CHANGED
@@ -8,7 +8,7 @@
8
8
  };
9
9
 
10
10
  // src/palette.js
11
- var colors = [
11
+ var defaultPalette = [
12
12
  "#111",
13
13
  "#6a7799",
14
14
  "#aec2c2",
@@ -50,7 +50,7 @@
50
50
  animate: true
51
51
  };
52
52
  settings = Object.assign(defaults, settings);
53
- let _initialized = false, _plugins = [], _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime = 1 / 60, _accumulated = 0, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rng_seed = Date.now(), _events = {
53
+ let _initialized = false, _plugins = [], _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime = 1 / 60, _accumulated = 0, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rng_seed = Date.now(), _colors = defaultPalette, _events = {
54
54
  init: false,
55
55
  update: false,
56
56
  draw: false,
@@ -60,8 +60,7 @@
60
60
  tapping: false,
61
61
  tapped: false
62
62
  }, _helpers = {
63
- settings: Object.assign({}, settings),
64
- colors
63
+ settings: Object.assign({}, settings)
65
64
  };
66
65
  const instance = {
67
66
  /** @type {number} */
@@ -82,6 +81,8 @@
82
81
  MOUSEY: -1,
83
82
  /** @type {number[]} */
84
83
  DEFAULT_SFX: [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
84
+ /** @type {string[]} */
85
+ COLORS: _colors,
85
86
  /** MATH API */
86
87
  /**
87
88
  * Twice the value of the mathematical constant PI (π).
@@ -875,6 +876,19 @@
875
876
  triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
876
877
  }
877
878
  },
879
+ /**
880
+ * Set or reset the color palette
881
+ *
882
+ * @param {string[]} [colors]
883
+ */
884
+ pal(colors = defaultPalette) {
885
+ DEV: assert(
886
+ Array.isArray(colors) && colors.length > 0,
887
+ "pal: 1st param must be a array of strings"
888
+ );
889
+ _colors = colors;
890
+ instance.setvar("COLORS", _colors);
891
+ },
878
892
  /**
879
893
  * Get a color by index
880
894
  *
@@ -886,7 +900,7 @@
886
900
  null == index || isNumber(index) && index >= 0,
887
901
  "getcolor: 1st param must be a number"
888
902
  );
889
- return colors[~~index % colors.length];
903
+ return _colors[~~index % _colors.length];
890
904
  },
891
905
  /**
892
906
  * Create or update a instance variable
@@ -1124,6 +1138,7 @@
1124
1138
  });
1125
1139
  on(root, "focus", () => {
1126
1140
  if (!_rafid) {
1141
+ _accumulated = 0;
1127
1142
  _rafid = raf(drawFrame);
1128
1143
  }
1129
1144
  });
package/dist/dist.js CHANGED
@@ -8,7 +8,7 @@
8
8
  };
9
9
 
10
10
  // src/palette.js
11
- var colors = [
11
+ var defaultPalette = [
12
12
  "#111",
13
13
  "#6a7799",
14
14
  "#aec2c2",
@@ -45,7 +45,7 @@
45
45
  animate: true
46
46
  };
47
47
  settings = Object.assign(defaults, settings);
48
- let _initialized = false, _plugins = [], _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime = 1 / 60, _accumulated = 0, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rng_seed = Date.now(), _events = {
48
+ let _initialized = false, _plugins = [], _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime = 1 / 60, _accumulated = 0, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rng_seed = Date.now(), _colors = defaultPalette, _events = {
49
49
  init: false,
50
50
  update: false,
51
51
  draw: false,
@@ -55,8 +55,7 @@
55
55
  tapping: false,
56
56
  tapped: false
57
57
  }, _helpers = {
58
- settings: Object.assign({}, settings),
59
- colors
58
+ settings: Object.assign({}, settings)
60
59
  };
61
60
  const instance = {
62
61
  /** @type {number} */
@@ -77,6 +76,8 @@
77
76
  MOUSEY: -1,
78
77
  /** @type {number[]} */
79
78
  DEFAULT_SFX: [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
79
+ /** @type {string[]} */
80
+ COLORS: _colors,
80
81
  /** MATH API */
81
82
  /**
82
83
  * Twice the value of the mathematical constant PI (π).
@@ -627,6 +628,15 @@
627
628
  triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
628
629
  }
629
630
  },
631
+ /**
632
+ * Set or reset the color palette
633
+ *
634
+ * @param {string[]} [colors]
635
+ */
636
+ pal(colors = defaultPalette) {
637
+ _colors = colors;
638
+ instance.setvar("COLORS", _colors);
639
+ },
630
640
  /**
631
641
  * Get a color by index
632
642
  *
@@ -634,7 +644,7 @@
634
644
  * @returns {string} the color code
635
645
  */
636
646
  getcolor: (index) => {
637
- return colors[~~index % colors.length];
647
+ return _colors[~~index % _colors.length];
638
648
  },
639
649
  /**
640
650
  * Create or update a instance variable
@@ -851,6 +861,7 @@
851
861
  });
852
862
  on(root, "focus", () => {
853
863
  if (!_rafid) {
864
+ _accumulated = 0;
854
865
  _rafid = raf(drawFrame);
855
866
  }
856
867
  });
package/dist/dist.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e=new AudioContext,t=(t=1,a=.05,n=220,i=0,l=0,r=.1,o=0,s=1,c=0,f=0,d=0,p=0,u=0,g=0,h=0,m=0,v=0,E=1,b=0,w=0,x=0)=>{let y=Math,T=2*y.PI,I=c*=500*T/44100/44100,S=n*=(1-a+2*a*y.random(a=[]))*T/44100,k=0,A=0,H=0,D=1,P=0,C=0,X=0,N=x<0?-1:1,L=T*N*x*2/44100,O=y.cos(L),Y=y.sin,z=Y(L)/4,F=1+z,G=-2*O/F,M=(1-z)/F,R=(1+N*O)/2/F,W=-(N+O)/F,B=0,U=0,q=0,V=0;for(i=44100*i+9,b*=44100,l*=44100,r*=44100,v*=44100,f*=500*T/85766121e6,h*=T/44100,d*=T/44100,p*=44100,u=44100*u|0,t*=.3*(globalThis.zzfxV||1),N=i+b+l+r+v|0;H<N;a[H++]=X*t)++C%(100*m|0)||(X=o?1<o?2<o?3<o?Y(k*k):y.max(y.min(y.tan(k),1),-1):1-(2*k/T%2+2)%2:1-4*y.abs(y.round(k/T)-k/T):Y(k),X=(u?1-w+w*Y(T*H/u):1)*(X<0?-1:1)*y.abs(X)**s*(H<i?H/i:H<i+b?1-(H-i)/b*(1-E):H<i+b+l?E:H<N-v?(N-H-v)/r*E:0),X=v?X/2+(v>H?0:(H<N-v?1:(N-H)/v)*a[H-v|0]/2/t):X,x&&(X=V=R*B+W*(B=U)+R*(U=X)-M*q-G*(q=V))),k+=(L=(n+=c+=f)*y.cos(h*A++))+L*g*Y(H**5),D&&++D>p&&(n+=d,S+=d,D=0),!u||++P%u||(n=S,c=I,D=D||1);(t=e.createBuffer(1,N,44100)).getChannelData(0).set(a),(n=e.createBufferSource()).buffer=t,n.connect(e.destination),n.start()},a=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(e={}){let n=globalThis,i=Math,l=2*i.PI,r=requestAnimationFrame,o=[],s=(e,t,a)=>{e.addEventListener(t,a,!1),o.push(()=>e.removeEventListener(t,a,!1))};e=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,antialias:!1,canvas:null,global:!0,loop:null,pauseOnBlur:!0,tapEvents:!0,keyboardEvents:!0,animate:!0},e);let c=!1,f=[],d,p=1,u,g=.5,h=1,m,v=1/60,E=0,b,w="sans-serif",x=20,y=Date.now(),T={init:!1,update:!1,draw:!1,resized:!1,tap:!1,untap:!1,tapping:!1,tapped:!1},I={settings:Object.assign({},e),colors:a},S={WIDTH:0,HEIGHT:0,CANVAS:!1,ELAPSED:0,CENTERX:0,CENTERY:0,MOUSEX:-1,MOUSEY:-1,DEFAULT_SFX:[.5,0,1750,,,.3,1,,,,600,.1],TWO_PI:l,HALF_PI:i.PI/2,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>i.PI/180*e,rad2deg:e=>180/i.PI*e,round:(e,t=0)=>{if(!t)return i.round(e);let a=10**t;return i.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*i.floor((e-t)/(a-t)),map(e,t,a,n,i,l){let r=(e-t)/(a-t)*(i-n)+n;return l?S.clamp(r,n,i):r},norm:(e,t,a)=>S.map(e,t,a,0,1),rand:(e=0,t=1)=>(y=(1664525*y+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>i.floor(S.rand(e,t+1)),seed:e=>null==e?y:y=~~e,cls(e){null==e?u.clearRect(0,0,u.canvas.width,u.canvas.height):S.rectfill(0,0,u.canvas.width,u.canvas.height,e)},rect(e,t,a,n,i,l){u.beginPath(),u[l?"roundRect":"rect"](~~e-g,~~t-g,~~a+2*g,~~n+2*g,l),S.stroke(i)},rectfill(e,t,a,n,i,l){u.beginPath(),u[l?"roundRect":"rect"](~~e,~~t,~~a,~~n,l),S.fill(i)},circ(e,t,a,n){u.beginPath(),u.arc(~~e,~~t,~~a,0,l),S.stroke(n)},circfill(e,t,a,n){u.beginPath(),u.arc(~~e,~~t,~~a,0,l),S.fill(n)},line(e,t,a,n,i){u.beginPath();let l=.5*(0!==g&&~~e==~~a),r=.5*(0!==g&&~~t==~~n);u.moveTo(~~e+l,~~t+r),u.lineTo(~~a+l,~~n+r),S.stroke(i)},linewidth(e){u.lineWidth=~~e,g=.5*(0!=~~e%2)},linedash(e,t=0){u.setLineDash(e),u.lineDashOffset=t},text(e,t,a,n=3,i="normal"){u.font=`${i} ${x}px ${w}`,u.fillStyle=S.getcolor(n),u.fillText(a,~~e,~~t)},textfont(e){w=e},textsize(e){x=e},textalign(e,t){e&&(u.textAlign=e),t&&(u.textBaseline=t)},image(e,t,a){u.drawImage(a,~~e,~~t)},paint(e,t,a,n={}){let i=n.canvas||new OffscreenCanvas(1,1),l=n.scale||1,r=u;if(i.width=e*l,i.height=t*l,(u=i.getContext("2d")).scale(l,l),a.push){let e=0,t=0;for(let n of(u.imageSmoothingEnabled=!1,a)){for(let a of n)" "!==a&&"."!==a&&S.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(u);return u=r,i.transferToImageBitmap()},ctx:e=>(e&&(u=e),u),push:()=>u.save(),pop:()=>u.restore(),translate:(e,t)=>u.translate(~~e,~~t),scale:(e,t)=>u.scale(e,t||e),rotate:e=>u.rotate(e),alpha(e){u.globalAlpha=S.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){u.fillStyle=S.getcolor(e),t?u.fill(t):u.fill()},stroke(e,t){u.strokeStyle=S.getcolor(e),t?u.stroke(t):u.stroke()},clip(e){u.clip(e)},sfx:(e,a=0,i=1)=>!(n.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||S.DEFAULT_SFX,(0!==a||1!==i)&&((e=e.slice())[0]=i*(e[0]||1),e[10]=~~e[10]+a),t.apply(0,e),e),volume(e){n.zzfxV=e},use(e,t={}){c?P(e,t):f.push([e,t])},listen:(e,t)=>(T[e]=T[e]||new Set,T[e].add(t),()=>T[e].delete(t)),emit(e,t,a,n,i){c&&(D("before:"+e,t,a,n,i),D(e,t,a,n,i),D("after:"+e,t,a,n,i))},getcolor:e=>a[~~e%a.length],setvar(t,a){S[t]=a,e.global&&(n[t]=a)},timescale(e){h=e},setfps(e){v=1/~~e},quit(){for(let e of(cancelAnimationFrame(b),S.emit("quit"),T=[],o))e();if(e.global){for(let e in S)delete n[e];delete n.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))S[e]=i[e];function k(){c=!0;let t=e.loop?e.loop:n;for(let e in T)t[e]&&S.listen(e,t[e]);for(let[e,t]of f)P(e,t);if(e.autoscale&&s(n,"resize",H),e.tapEvents){let e=(e,t)=>[(e-d.offsetLeft)/p,(t-d.offsetTop)/p],t=new Map,a=(e,a,n)=>{let i={x:a,y:n,startX:a,startY:n,ts:performance.now()};return t.set(e,i),i},i=(e,n,i)=>{let l=t.get(e)||a(e);l.x=n,l.y=i},l=e=>e&&performance.now()-e.ts<=300,r=e=>e.preventDefault(),o=!1;s(d,"mousedown",t=>{if(0===t.button){r(t);let[n,i]=e(t.pageX,t.pageY);S.emit("tap",n,i,0),a(0,n,i),o=!0}}),s(d,"mouseup",a=>{if(0===a.button){r(a);let n=t.get(0),[i,s]=e(a.pageX,a.pageY);l(n)&&S.emit("tapped",n.startX,n.startY,0),S.emit("untap",i,s,0),t.delete(0),o=!1}}),s(d,"mousemove",t=>{r(t);let[a,n]=e(t.pageX,t.pageY);S.setvar("MOUSEX",a),S.setvar("MOUSEY",n),o&&(S.emit("tapping",a,n,0),i(0,a,n))}),s(d,"touchstart",t=>{for(let n of(r(t),t.changedTouches)){let[t,i]=e(n.pageX,n.pageY);S.emit("tap",t,i,n.identifier+1),a(n.identifier+1,t,i)}}),s(d,"touchmove",t=>{for(let a of(r(t),t.changedTouches)){let[t,n]=e(a.pageX,a.pageY);S.emit("tapping",t,n,a.identifier+1),i(a.identifier+1,t,n)}});let c=e=>{r(e);let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,n]of t)a.includes(e)||(l(n)&&S.emit("tapped",n.startX,n.startY,e),S.emit("untap",n.x,n.y,e),t.delete(e))};s(d,"touchend",c),s(d,"touchcancel",c),s(n,"blur",()=>{for(let[e,a]of(o=!1,t))S.emit("untap",a.x,a.y,e),t.delete(e)})}if(e.keyboardEvents){let e=e=>e.toLowerCase(),t=new Set,a=new Set,i=(t,a)=>a?t.has("space"===e(a)?" ":e(a)):t.size>0;s(n,"keydown",n=>{t.has(e(n.key))||(t.add(e(n.key)),a.add(e(n.key)))}),s(n,"keyup",a=>{t.delete(e(a.key))}),s(n,"blur",()=>t.clear()),S.listen("after:draw",()=>a.clear()),S.setvar("iskeydown",e=>i(t,e)),S.setvar("iskeypressed",e=>i(a,e))}e.pauseOnBlur&&(s(n,"blur",()=>{b=cancelAnimationFrame(b)}),s(n,"focus",()=>{b||(b=r(A))})),S.emit("init",S),m=performance.now(),b=r(A)}function A(t){let a=0,n=(t-m)/1e3;if(m=t,e.animate){if(b=r(A),n>.3)return;for(E+=n;E>=v;)S.emit("update",v*h),S.setvar("ELAPSED",S.ELAPSED+v*h),a++,E-=v}else a=1;a&&(S.textalign("start","top"),S.emit("draw"))}function H(){let t=e.width||n.innerWidth,a=e.height||e.width||n.innerHeight;S.setvar("WIDTH",d.width=t),S.setvar("HEIGHT",d.height=a),S.setvar("CENTERX",S.WIDTH/2),S.setvar("CENTERY",S.HEIGHT/2),e.autoscale&&(d.style.display||(d.style.display="block",d.style.margin="auto"),p=i.min(n.innerWidth/S.WIDTH,n.innerHeight/S.HEIGHT),p=(e.pixelart?~~p:p)||1,d.style.width=S.WIDTH*p+"px",d.style.height=S.HEIGHT*p+"px"),(!e.antialias||e.pixelart)&&(u.imageSmoothingEnabled=!1,d.style.imageRendering="pixelated"),S.emit("resized",p),e.animate||r(A)}function D(e,t,a,n,i){if(T[e])for(let l of T[e])l(t,a,n,i)}function P(e,t){let a=e(S,I,t);for(let e in a)S.setvar(e,a[e])}if(e.global){if(n.ENGINE)throw Error("two global litecanvas detected");Object.assign(n,S),n.ENGINE=S}return d="string"==typeof(d=e.canvas||document.createElement("canvas"))?document.querySelector(d):d,S.setvar("CANVAS",d),u=d.getContext("2d"),s(d,"click",()=>n.focus()),d.style="",H(),d.parentNode||document.body.appendChild(d),"loading"===document.readyState?s(n,"DOMContentLoaded",()=>r(k)):r(k),S}})();
1
+ (()=>{var e=new AudioContext,t=(t=1,a=.05,n=220,i=0,l=0,r=.1,o=0,s=1,c=0,f=0,d=0,p=0,u=0,g=0,h=0,m=0,v=0,E=1,b=0,w=0,x=0)=>{let y=Math,T=2*y.PI,S=c*=500*T/44100/44100,I=n*=(1-a+2*a*y.random(a=[]))*T/44100,k=0,A=0,H=0,D=1,C=0,O=0,P=0,L=x<0?-1:1,X=T*L*x*2/44100,N=y.cos(X),Y=y.sin,z=Y(X)/4,F=1+z,R=-2*N/F,G=(1-z)/F,M=(1+L*N)/2/F,W=-(L+N)/F,B=0,U=0,q=0,V=0;for(i=44100*i+9,b*=44100,l*=44100,r*=44100,v*=44100,f*=500*T/85766121e6,h*=T/44100,d*=T/44100,p*=44100,u=44100*u|0,t*=.3*(globalThis.zzfxV||1),L=i+b+l+r+v|0;H<L;a[H++]=P*t)++O%(100*m|0)||(P=o?1<o?2<o?3<o?Y(k*k):y.max(y.min(y.tan(k),1),-1):1-(2*k/T%2+2)%2:1-4*y.abs(y.round(k/T)-k/T):Y(k),P=(u?1-w+w*Y(T*H/u):1)*(P<0?-1:1)*y.abs(P)**s*(H<i?H/i:H<i+b?1-(H-i)/b*(1-E):H<i+b+l?E:H<L-v?(L-H-v)/r*E:0),P=v?P/2+(v>H?0:(H<L-v?1:(L-H)/v)*a[H-v|0]/2/t):P,x&&(P=V=M*B+W*(B=U)+M*(U=P)-G*q-R*(q=V))),k+=(X=(n+=c+=f)*y.cos(h*A++))+X*g*Y(H**5),D&&++D>p&&(n+=d,I+=d,D=0),!u||++C%u||(n=I,c=S,D=D||1);(t=e.createBuffer(1,L,44100)).getChannelData(0).set(a),(n=e.createBufferSource()).buffer=t,n.connect(e.destination),n.start()},a=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(e={}){let n=globalThis,i=Math,l=2*i.PI,r=requestAnimationFrame,o=[],s=(e,t,a)=>{e.addEventListener(t,a,!1),o.push(()=>e.removeEventListener(t,a,!1))};e=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,antialias:!1,canvas:null,global:!0,loop:null,pauseOnBlur:!0,tapEvents:!0,keyboardEvents:!0,animate:!0},e);let c=!1,f=[],d,p=1,u,g=.5,h=1,m,v=1/60,E=0,b,w="sans-serif",x=20,y=Date.now(),T=a,S={init:!1,update:!1,draw:!1,resized:!1,tap:!1,untap:!1,tapping:!1,tapped:!1},I={settings:Object.assign({},e)},k={WIDTH:0,HEIGHT:0,CANVAS:!1,ELAPSED:0,CENTERX:0,CENTERY:0,MOUSEX:-1,MOUSEY:-1,DEFAULT_SFX:[.5,0,1750,,,.3,1,,,,600,.1],COLORS:T,TWO_PI:l,HALF_PI:i.PI/2,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>i.PI/180*e,rad2deg:e=>180/i.PI*e,round:(e,t=0)=>{if(!t)return i.round(e);let a=10**t;return i.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*i.floor((e-t)/(a-t)),map(e,t,a,n,i,l){let r=(e-t)/(a-t)*(i-n)+n;return l?k.clamp(r,n,i):r},norm:(e,t,a)=>k.map(e,t,a,0,1),rand:(e=0,t=1)=>(y=(1664525*y+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>i.floor(k.rand(e,t+1)),seed:e=>null==e?y:y=~~e,cls(e){null==e?u.clearRect(0,0,u.canvas.width,u.canvas.height):k.rectfill(0,0,u.canvas.width,u.canvas.height,e)},rect(e,t,a,n,i,l){u.beginPath(),u[l?"roundRect":"rect"](~~e-g,~~t-g,~~a+2*g,~~n+2*g,l),k.stroke(i)},rectfill(e,t,a,n,i,l){u.beginPath(),u[l?"roundRect":"rect"](~~e,~~t,~~a,~~n,l),k.fill(i)},circ(e,t,a,n){u.beginPath(),u.arc(~~e,~~t,~~a,0,l),k.stroke(n)},circfill(e,t,a,n){u.beginPath(),u.arc(~~e,~~t,~~a,0,l),k.fill(n)},line(e,t,a,n,i){u.beginPath();let l=.5*(0!==g&&~~e==~~a),r=.5*(0!==g&&~~t==~~n);u.moveTo(~~e+l,~~t+r),u.lineTo(~~a+l,~~n+r),k.stroke(i)},linewidth(e){u.lineWidth=~~e,g=.5*(0!=~~e%2)},linedash(e,t=0){u.setLineDash(e),u.lineDashOffset=t},text(e,t,a,n=3,i="normal"){u.font=`${i} ${x}px ${w}`,u.fillStyle=k.getcolor(n),u.fillText(a,~~e,~~t)},textfont(e){w=e},textsize(e){x=e},textalign(e,t){e&&(u.textAlign=e),t&&(u.textBaseline=t)},image(e,t,a){u.drawImage(a,~~e,~~t)},paint(e,t,a,n={}){let i=n.canvas||new OffscreenCanvas(1,1),l=n.scale||1,r=u;if(i.width=e*l,i.height=t*l,(u=i.getContext("2d")).scale(l,l),a.push){let e=0,t=0;for(let n of(u.imageSmoothingEnabled=!1,a)){for(let a of n)" "!==a&&"."!==a&&k.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(u);return u=r,i.transferToImageBitmap()},ctx:e=>(e&&(u=e),u),push:()=>u.save(),pop:()=>u.restore(),translate:(e,t)=>u.translate(~~e,~~t),scale:(e,t)=>u.scale(e,t||e),rotate:e=>u.rotate(e),alpha(e){u.globalAlpha=k.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){u.fillStyle=k.getcolor(e),t?u.fill(t):u.fill()},stroke(e,t){u.strokeStyle=k.getcolor(e),t?u.stroke(t):u.stroke()},clip(e){u.clip(e)},sfx:(e,a=0,i=1)=>!(n.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||k.DEFAULT_SFX,(0!==a||1!==i)&&((e=e.slice())[0]=i*(e[0]||1),e[10]=~~e[10]+a),t.apply(0,e),e),volume(e){n.zzfxV=e},use(e,t={}){c?O(e,t):f.push([e,t])},listen:(e,t)=>(S[e]=S[e]||new Set,S[e].add(t),()=>S[e].delete(t)),emit(e,t,a,n,i){c&&(C("before:"+e,t,a,n,i),C(e,t,a,n,i),C("after:"+e,t,a,n,i))},pal(e=a){T=e,k.setvar("COLORS",T)},getcolor:e=>T[~~e%T.length],setvar(t,a){k[t]=a,e.global&&(n[t]=a)},timescale(e){h=e},setfps(e){v=1/~~e},quit(){for(let e of(cancelAnimationFrame(b),k.emit("quit"),S=[],o))e();if(e.global){for(let e in k)delete n[e];delete n.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))k[e]=i[e];function A(){c=!0;let t=e.loop?e.loop:n;for(let e in S)t[e]&&k.listen(e,t[e]);for(let[e,t]of f)O(e,t);if(e.autoscale&&s(n,"resize",D),e.tapEvents){let e=(e,t)=>[(e-d.offsetLeft)/p,(t-d.offsetTop)/p],t=new Map,a=(e,a,n)=>{let i={x:a,y:n,startX:a,startY:n,ts:performance.now()};return t.set(e,i),i},i=(e,n,i)=>{let l=t.get(e)||a(e);l.x=n,l.y=i},l=e=>e&&performance.now()-e.ts<=300,r=e=>e.preventDefault(),o=!1;s(d,"mousedown",t=>{if(0===t.button){r(t);let[n,i]=e(t.pageX,t.pageY);k.emit("tap",n,i,0),a(0,n,i),o=!0}}),s(d,"mouseup",a=>{if(0===a.button){r(a);let n=t.get(0),[i,s]=e(a.pageX,a.pageY);l(n)&&k.emit("tapped",n.startX,n.startY,0),k.emit("untap",i,s,0),t.delete(0),o=!1}}),s(d,"mousemove",t=>{r(t);let[a,n]=e(t.pageX,t.pageY);k.setvar("MOUSEX",a),k.setvar("MOUSEY",n),o&&(k.emit("tapping",a,n,0),i(0,a,n))}),s(d,"touchstart",t=>{for(let n of(r(t),t.changedTouches)){let[t,i]=e(n.pageX,n.pageY);k.emit("tap",t,i,n.identifier+1),a(n.identifier+1,t,i)}}),s(d,"touchmove",t=>{for(let a of(r(t),t.changedTouches)){let[t,n]=e(a.pageX,a.pageY);k.emit("tapping",t,n,a.identifier+1),i(a.identifier+1,t,n)}});let c=e=>{r(e);let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,n]of t)a.includes(e)||(l(n)&&k.emit("tapped",n.startX,n.startY,e),k.emit("untap",n.x,n.y,e),t.delete(e))};s(d,"touchend",c),s(d,"touchcancel",c),s(n,"blur",()=>{for(let[e,a]of(o=!1,t))k.emit("untap",a.x,a.y,e),t.delete(e)})}if(e.keyboardEvents){let e=e=>e.toLowerCase(),t=new Set,a=new Set,i=(t,a)=>a?t.has("space"===e(a)?" ":e(a)):t.size>0;s(n,"keydown",n=>{t.has(e(n.key))||(t.add(e(n.key)),a.add(e(n.key)))}),s(n,"keyup",a=>{t.delete(e(a.key))}),s(n,"blur",()=>t.clear()),k.listen("after:draw",()=>a.clear()),k.setvar("iskeydown",e=>i(t,e)),k.setvar("iskeypressed",e=>i(a,e))}e.pauseOnBlur&&(s(n,"blur",()=>{b=cancelAnimationFrame(b)}),s(n,"focus",()=>{b||(E=0,b=r(H))})),k.emit("init",k),m=performance.now(),b=r(H)}function H(t){let a=0,n=(t-m)/1e3;if(m=t,e.animate){if(b=r(H),n>.3)return;for(E+=n;E>=v;)k.emit("update",v*h),k.setvar("ELAPSED",k.ELAPSED+v*h),a++,E-=v}else a=1;a&&(k.textalign("start","top"),k.emit("draw"))}function D(){let t=e.width||n.innerWidth,a=e.height||e.width||n.innerHeight;k.setvar("WIDTH",d.width=t),k.setvar("HEIGHT",d.height=a),k.setvar("CENTERX",k.WIDTH/2),k.setvar("CENTERY",k.HEIGHT/2),e.autoscale&&(d.style.display||(d.style.display="block",d.style.margin="auto"),p=i.min(n.innerWidth/k.WIDTH,n.innerHeight/k.HEIGHT),p=(e.pixelart?~~p:p)||1,d.style.width=k.WIDTH*p+"px",d.style.height=k.HEIGHT*p+"px"),(!e.antialias||e.pixelart)&&(u.imageSmoothingEnabled=!1,d.style.imageRendering="pixelated"),k.emit("resized",p),e.animate||r(H)}function C(e,t,a,n,i){if(S[e])for(let l of S[e])l(t,a,n,i)}function O(e,t){let a=e(k,I,t);for(let e in a)k.setvar(e,a[e])}if(e.global){if(n.ENGINE)throw Error("two global litecanvas detected");Object.assign(n,k),n.ENGINE=k}return d="string"==typeof(d=e.canvas||document.createElement("canvas"))?document.querySelector(d):d,k.setvar("CANVAS",d),u=d.getContext("2d"),s(d,"click",()=>n.focus()),d.style="",D(),d.parentNode||document.body.appendChild(d),"loading"===document.readyState?s(n,"DOMContentLoaded",()=>r(A)):r(A),k}})();
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.79.3",
4
- "description": "Lightweight HTML5 canvas game engine suitable for small projects and creative coding. Inspired by PICO-8 and P5/Processing.",
3
+ "version": "0.80.0",
4
+ "description": "Lightweight HTML5 canvas 2D game engine suitable for small projects and creative coding. Inspired by PICO-8 and P5/Processing.",
5
5
  "license": "MIT",
6
6
  "author": "Luiz Bills <luizbills@pm.me>",
7
7
  "contributors": [],
8
8
  "devDependencies": {
9
- "@swc/core": "^1.11.13",
10
- "ava": "^6.2.0",
11
- "esbuild": "^0.25.2",
9
+ "@swc/core": "^1.11.29",
10
+ "ava": "^6.3.0",
11
+ "esbuild": "^0.25.5",
12
12
  "gzip-size": "^7.0.0",
13
13
  "prettier": "^3.5.3"
14
14
  },
package/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { zzfx } from './zzfx.js'
2
- import { colors } from './palette.js'
2
+ import { defaultPalette } from './palette.js'
3
3
  import { assert } from './dev.js'
4
4
  import './types.js'
5
5
 
@@ -71,6 +71,8 @@ export default function litecanvas(settings = {}) {
71
71
  _fontSize = 20,
72
72
  /** @type {number} */
73
73
  _rng_seed = Date.now(),
74
+ /** @type {string[]} */
75
+ _colors = defaultPalette,
74
76
  /**
75
77
  * default game events
76
78
  * @type {Object<string,Set<Function>>}
@@ -92,7 +94,6 @@ export default function litecanvas(settings = {}) {
92
94
  */
93
95
  _helpers = {
94
96
  settings: Object.assign({}, settings),
95
- colors,
96
97
  }
97
98
 
98
99
  /** @type {LitecanvasInstance} */
@@ -124,6 +125,9 @@ export default function litecanvas(settings = {}) {
124
125
  /** @type {number[]} */
125
126
  DEFAULT_SFX: [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
126
127
 
128
+ /** @type {string[]} */
129
+ COLORS: _colors,
130
+
127
131
  /** MATH API */
128
132
  /**
129
133
  * Twice the value of the mathematical constant PI (π).
@@ -1038,6 +1042,20 @@ export default function litecanvas(settings = {}) {
1038
1042
  }
1039
1043
  },
1040
1044
 
1045
+ /**
1046
+ * Set or reset the color palette
1047
+ *
1048
+ * @param {string[]} [colors]
1049
+ */
1050
+ pal(colors = defaultPalette) {
1051
+ DEV: assert(
1052
+ Array.isArray(colors) && colors.length > 0,
1053
+ 'pal: 1st param must be a array of strings'
1054
+ )
1055
+ _colors = colors
1056
+ instance.setvar('COLORS', _colors)
1057
+ },
1058
+
1041
1059
  /**
1042
1060
  * Get a color by index
1043
1061
  *
@@ -1049,8 +1067,7 @@ export default function litecanvas(settings = {}) {
1049
1067
  null == index || (isNumber(index) && index >= 0),
1050
1068
  'getcolor: 1st param must be a number'
1051
1069
  )
1052
-
1053
- return colors[~~index % colors.length]
1070
+ return _colors[~~index % _colors.length]
1054
1071
  },
1055
1072
 
1056
1073
  /**
@@ -1359,6 +1376,7 @@ export default function litecanvas(settings = {}) {
1359
1376
 
1360
1377
  on(root, 'focus', () => {
1361
1378
  if (!_rafid) {
1379
+ _accumulated = 0
1362
1380
  _rafid = raf(drawFrame)
1363
1381
  }
1364
1382
  })
package/src/palette.js CHANGED
@@ -1,4 +1,4 @@
1
- export const colors = [
1
+ export const defaultPalette = [
2
2
  '#111',
3
3
  '#6a7799',
4
4
  '#aec2c2',
package/types/index.d.ts CHANGED
@@ -496,52 +496,20 @@ declare global {
496
496
  /** UTILS API */
497
497
  /**
498
498
  * Checks if a which key is pressed on the keyboard.
499
- * Note: use `iskeydown("any")` to check for any key pressed.
499
+ * Note: use `iskeydown()` to check for any key pressed.
500
500
  *
501
501
  * @param key
502
502
  * @returns `true` if the which key is down
503
503
  */
504
504
  function iskeydown(key: string): boolean
505
505
  /**
506
- * Check a collision between two rectangles
506
+ * Checks if a which key just got pressed on the keyboard.
507
+ * Note: use `iskeypressed()` to check for any key.
507
508
  *
508
- * @param x1 first rectangle position X
509
- * @param y1 first rectangle position Y
510
- * @param w1 first rectangle width
511
- * @param h1 first rectangle height
512
- * @param x2 second rectangle position X
513
- * @param y2 second rectangle position Y
514
- * @param w2 second rectangle width
515
- * @param h2 second rectangle height
509
+ * @param [key]
510
+ * @returns `true` if the which key was pressed
516
511
  */
517
- function colrect(
518
- x1: number,
519
- y1: number,
520
- w1: number,
521
- h1: number,
522
- x2: number,
523
- y2: number,
524
- w2: number,
525
- h2: number
526
- ): boolean
527
- /**
528
- * Check a collision between two circles
529
- *
530
- * @param x1 first circle position X
531
- * @param y1 first circle position Y
532
- * @param r1 first circle position radius
533
- * @param x2 second circle position X
534
- * @param y2 second circle position Y
535
- * @param r2 second circle position radius
536
- */
537
- function colcirc(
538
- x1: number,
539
- y1: number,
540
- r1: number,
541
- x2: number,
542
- y2: number,
543
- r2: number
544
- ): boolean
512
+ function iskeypressed(key: string): boolean
545
513
 
546
514
  /** PLUGINS API */
547
515
  /**
package/types/types.d.ts CHANGED
@@ -474,52 +474,20 @@ type LitecanvasInstance = {
474
474
  /** UTILS API */
475
475
  /**
476
476
  * Checks if a which key is pressed on the keyboard.
477
- * Note: use `iskeydown("any")` to check for any key pressed.
477
+ * Note: use `iskeydown()` to check for any key pressed.
478
478
  *
479
479
  * @param key
480
480
  * @returns `true` if the which key is down
481
481
  */
482
482
  iskeydown(key: string): boolean
483
483
  /**
484
- * Check a collision between two rectangles
485
- *
486
- * @param x1 first rectangle position X
487
- * @param y1 first rectangle position Y
488
- * @param w1 first rectangle width
489
- * @param h1 first rectangle height
490
- * @param x2 second rectangle position X
491
- * @param y2 second rectangle position Y
492
- * @param w2 second rectangle width
493
- * @param h2 second rectangle height
494
- */
495
- colrect(
496
- x1: number,
497
- y1: number,
498
- w1: number,
499
- h1: number,
500
- x2: number,
501
- y2: number,
502
- w2: number,
503
- h2: number
504
- ): boolean
505
- /**
506
- * Check a collision between two circles
507
- *
508
- * @param x1 first circle position X
509
- * @param y1 first circle position Y
510
- * @param r1 first circle position radius
511
- * @param x2 second circle position X
512
- * @param y2 second circle position Y
513
- * @param r2 second circle position radius
514
- */
515
- colcirc(
516
- x1: number,
517
- y1: number,
518
- r1: number,
519
- x2: number,
520
- y2: number,
521
- r2: number
522
- ): boolean
484
+ * Checks if a which key just got pressed on the keyboard.
485
+ * Note: use `iskeypressed()` to check for any key.
486
+ *
487
+ * @param [key]
488
+ * @returns `true` if the which key was pressed
489
+ */
490
+ iskeypressed(key: string): boolean
523
491
 
524
492
  /** PLUGINS API */
525
493
  /**