react-slime-simulation
Version:
A customizable React component for simulating slime mold behavior.
3 lines (2 loc) • 13 kB
JavaScript
import e,{useRef as t,useCallback as r,useEffect as n}from"react";function i(){return i=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)({}).hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},i.apply(null,arguments)}var a=["useRandomDefaults","svgShape"];function o(e,t,r){if(!e.s){if(r instanceof s){if(!r.s)return void(r.o=o.bind(null,e,t));1&t&&(t=r.s),r=r.v}if(r&&r.then)return void r.then(o.bind(null,e,t),o.bind(null,e,2));e.s=t,e.v=r;var n=e.o;n&&n(e)}}var s=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(t,r){var n=new e,i=this.s;if(i){var a=1&i?t:r;if(a){try{o(n,1,a(this.v))}catch(e){o(n,2,e)}return n}return this}return this.o=function(e){try{var i=e.v;1&e.s?o(n,1,t?t(i):i):r?o(n,1,r(i)):o(n,2,i)}catch(e){o(n,2,e)}},n},e}();function u(e){return e instanceof s&&1&e.s}function h(e,t){return Math.random()*(t-e)+e}function l(e){for(var t=e.length-1;t>0;t--){var r=Math.floor(Math.random()*(t+1)),n=[e[r],e[t]];e[t]=n[0],e[r]=n[1]}}var c=/*#__PURE__*/function(){function e(e,t){this.settingsRef=e,this.simulationDimensionsRef=t,this.position={x:0,y:0},this.angle=Math.random()*Math.PI*2;var r=e.current.baseHue+h(-20,20);this.color="hsl("+r+", 80%, 60%)",this.escapeThreshold=e.current.escapeThreshold,this.isEscaping=!1,this.escapeTime=0}var t=e.prototype;return t.sense=function(e){var t=this.angle+e*(Math.PI/180),r=this.settingsRef.current.sensorOffset,n=this.simulationDimensionsRef.current.width,i=this.simulationDimensionsRef.current.height,a=Math.cos(t),o=Math.sin(t),s={x:this.position.x+a*r,y:this.position.y+o*r};if(s.x<0||s.x>=n||s.y<0||s.y>=i)return{sum:0,maxDensity:0};var u=0,h=0,l=Math.floor(s.x),c=Math.floor(s.y),f=this.settingsRef.current.trailMap;if(!f)return{sum:0,maxDensity:0};for(var v=-1;v<=1;v++){var d=c+v;if(d>=0&&d<i)for(var m=d*n,g=-1;g<=1;g++){var p=l+g;if(p>=0&&p<n){var M=f[m+p];u+=M,M>h&&(h=M)}}}return{sum:u,maxDensity:h}},t.update=function(){var e,t,r,n,i=this.settingsRef.current,a=this.simulationDimensionsRef.current.width,o=this.simulationDimensionsRef.current.height,s=60*i.deltaTime,u=i.agentSpeed,l=i.edgeThreshold,c=this.sense(0).maxDensity>this.escapeThreshold;if(c&&!this.isEscaping?(this.isEscaping=!0,this.escapeTime=0):!c&&this.isEscaping&&this.escapeTime>1&&(this.isEscaping=!1),this.isEscaping){this.escapeTime+=s;var f=this.sense(45),v=this.sense(-45);f.maxDensity>v.maxDensity?this.angle-=.2*s:this.angle+=.2*s;var d=1.3*u,m={x:Math.cos(this.angle),y:Math.sin(this.angle)};e={x:this.position.x+m.x*d,y:this.position.y+m.y*d}}else{var g=this.position.x<l,p=this.position.x>a-l,M=this.position.y<l,y=this.position.y>o-l;if((g||p||M||y)&&i.edgeAvoidance>0){var x=h(-Math.PI*i.edgeAvoidance,Math.PI*i.edgeAvoidance);g?this.angle=x:p?this.angle=Math.PI+x:M?this.angle=Math.PI/2+x:y&&(this.angle=-Math.PI/2+x)}else{var w=this.sense(0).sum,S=this.sense(45).sum,T=this.sense(-45).sum,R=(r=(r=1234.5678*(t={x:this.position.x+.001*performance.now(),y:this.position.y+.001*performance.now()}).x)*r*r*123456+(n=9012.3456*t.y))*(n=n*n*n*654321+r)%4294967295/4294967295;w>S&&w>T?this.angle+=.1*(R-.5)*s:w<S&&w<T?this.angle+=2*(R-.5)*.5*s:T>S?this.angle-=.5*R*s:S>T&&(this.angle+=.5*R*s)}var P={x:Math.cos(this.angle),y:Math.sin(this.angle)};e={x:this.position.x+P.x*u,y:this.position.y+P.y*u}}(e.x<0||e.x>=a||e.y<0||e.y>=o)&&((e.x<0||e.x>=a)&&(this.angle=Math.PI-this.angle+h(-.2,.2)),(e.y<0||e.y>=o)&&(this.angle=-this.angle+h(-.2,.2)),e.x=Math.max(0,Math.min(a-.01,e.x)),e.y=Math.max(0,Math.min(o-.01,e.y))),this.position=e;var b=Math.floor(this.position.x),I=Math.floor(this.position.y),E=i.trailMap;if(b>=0&&b<a&&I>=0&&I<o&&E){var D=I*a+b;E[D]=Math.min(1,E[D]+i.trailStrength)}},e}(),f=function(f){var v=f.useRandomDefaults,d=void 0===v||v,m=f.svgShape,g=void 0===m?'\n <svg id="spawnShape" width="200" height="200" viewBox="0 0 200 200">\n \x3c!-- Remplacez ceci par votre SVG --\x3e\n <path d="M100,20 L180,180 L20,180 Z" fill="white"/>\n </svg>\n':m,p=function(e,t){if(null==e)return{};var r={};for(var n in e)if({}.hasOwnProperty.call(e,n)){if(-1!==t.indexOf(n))continue;r[n]=e[n]}return r}(f,a),M=t(null),y=t({}),x=t([]),w=t({width:0,height:0}),S=t(null),T=t(null),R=t(null),P=t(0),b=t(!1),I=t(null),E=r(function(e,t,r){try{return console.log("Rasterizing SVG string:",(null==e?void 0:e.substring(0,100))+"..."),Promise.resolve(new Promise(function(n){var i=(new DOMParser).parseFromString(e,"image/svg+xml"),a=i.querySelector("parsererror");if(a)return console.error("Error parsing SVG string:",a.textContent),void n([]);var o=i.documentElement;if(!o||"svg"!==o.nodeName)return console.error("Invalid SVG string provided - Could not find root <svg> element."),void n([]);var s=(new XMLSerializer).serializeToString(o),u="data:image/svg+xml;charset=utf-8,"+encodeURIComponent(s),h=new Image;h.onload=function(){var e=document.createElement("canvas");e.width=t,e.height=r;var i,a,o=e.getContext("2d"),s=h.naturalWidth/h.naturalHeight;t/r>s?i=(a=1.6*r)*s:a=(i=1.6*t)/s;var u=(t-i)/2,l=(r-a)/2;o.clearRect(0,0,t,r),o.drawImage(h,u,l,i,a);try{for(var c=o.getImageData(0,0,t,r).data,f=[],v=0;v<r;v++)for(var d=0;d<t;d++)c[4*(v*t+d)+3]>10&&f.push({x:d,y:v});console.log("Rasterized SVG: Found "+f.length+" valid pixels."),n(f)}catch(e){console.error("Error getting ImageData (possible CORS issue if SVG linked external resources, unlikely with data URL):",e),n([])}},h.onerror=function(e){console.error("Error loading SVG image for rasterization. Event:",e),console.error("SVG URL that failed:",u),n([])},h.src=u}))}catch(e){return Promise.reject(e)}},[]),D=r(function(){if(T.current&&y.current.trailMap)for(var e=y.current,t=w.current.width,r=w.current.height,n=e.brushSize,i=e.brushStrength,a=Math.floor(T.current.x),o=Math.floor(T.current.y),s=e.trailMap,u=-n;u<=n;u++)for(var h=-n;h<=n;h++)if(h*h+u*u<=n*n){var l=a+h,c=o+u;if(l>=0&&l<t&&c>=0&&c<r){var f=c*t+l,v=Math.sqrt(h*h+u*u),d=Math.max(0,1-v/n);s[f]=Math.min(1,s[f]+i*d)}}},[]),F=r(function(){var e=y.current,t=w.current.width,r=w.current.height,n=e.evaporationRate,i=e.trailMap,a=e.processedTrailMap;if(i&&a){D();for(var o=0;o<r;o++)for(var s=0;s<t;s++){var u=o*t+s,h=i[u];if(h<=.001)a[u]=0;else{for(var l=0,c=0,f=-1;f<=1;f++){var v=o+f;if(v>=0&&v<r)for(var d=v*t,m=-1;m<=1;m++){var g=s+m;g>=0&&g<t&&(l+=i[d+g],c++)}}a[u]=Math.max(0,.9*h+.1*(c>0?l/c:0)-n*e.deltaTime*60)}}y.current.trailMap=a,y.current.processedTrailMap=i}},[D]),z=r(function(){var e=M.current;if(e){var t=e.getContext("2d");if(t){var r=y.current,n=w.current.width,i=w.current.height,a=r.trailMap;if(a){t.fillStyle="rgba(0, 0, 0, 1)",t.fillRect(0,0,n,i);for(var o=t.createImageData(n,i),s=o.data,u=0;u<i;u++)for(var h=0;h<n;h++){var l=u*n+h,c=a[l];if(c>.01){var f=Math.min(1,c),v=r.baseHue+r.hueRange*(f-.5)*2,d=50+r.lightnessRange*(f-.5)*2,m=Math.min(255,Math.floor(255*f)),g=d/100,p=1*(1-Math.abs(2*g-1)),x=p*(1-Math.abs(v/60%2-1)),S=g-p/2,T=0,R=0,P=0;0<=v&&v<60?(T=p,R=x,P=0):60<=v&&v<120?(T=x,R=p,P=0):120<=v&&v<180?(T=0,R=p,P=x):180<=v&&v<240?(T=0,R=x,P=p):240<=v&&v<300?(T=x,R=0,P=p):300<=v&&v<360&&(T=p,R=0,P=x),T=Math.round(255*(T+S)),R=Math.round(255*(R+S)),P=Math.round(255*(P+S));var b=4*l;s[b]=T,s[b+1]=R,s[b+2]=P,s[b+3]=m}}t.putImageData(o,0,0)}}}},[]),A=r(function(){var e=M.current;if(e){var t=e.getContext("2d");if(t){var r=w.current.width,n=w.current.height;x.current.forEach(function(e){var i=Math.floor(e.position.x),a=Math.floor(e.position.y);i>=0&&i<r&&a>=0&&a<n&&(t.fillStyle=e.color,t.fillRect(i,a,1,1))})}}},[]),C=r(function(e,t){try{var r=[],n=c;if(t&&0!==t.length){var i=[].concat(t);l(i);for(var a=0,o=0;o<e;o++){a>=i.length&&(l(i),a=0);var s=new n(y,w),u=i[a];s.position={x:u.x,y:u.y},s.angle=Math.random()*Math.PI*2,r.push(s),a++}}else{console.warn("No valid pixels from SVG rasterization or SVG invalid. Spawning agents randomly.");for(var f=w.current.width,v=w.current.height,d=0;d<e;d++){var m=new n(y,w);m.position={x:h(0,f),y:h(0,v)},m.angle=Math.random()*Math.PI*2,r.push(m)}}return x.current=r,Promise.resolve()}catch(e){return Promise.reject(e)}},[]),L=r(function(e,t){try{var r=M.current,n=null==r?void 0:r.getContext("2d");if(!n||!y.current.initialAgents)return Promise.resolve();var i=y.current.initialAgents,a=w.current.width,h=w.current.height,l=0,c=function(e,t,r){for(var n;;){var i=e();if(u(i)&&(i=i.v),!i)return a;if(i.then){n=0;break}var a=r();if(a&&a.then){if(!u(a)){n=1;break}a=a.s}if(t){var h=t();if(h&&h.then&&!u(h)){n=2;break}}}var l=new s,c=o.bind(null,l,2);return(0===n?i.then(v):1===n?a.then(f):h.then(d)).then(void 0,c),l;function f(n){a=n;do{if(t&&(h=t())&&h.then&&!u(h))return void h.then(d).then(void 0,c);if(!(i=e())||u(i)&&!i.v)return void o(l,1,a);if(i.then)return void i.then(v).then(void 0,c);u(a=r())&&(a=a.v)}while(!a||!a.then);a.then(f).then(void 0,c)}function v(e){e?(a=r())&&a.then?a.then(f).then(void 0,c):f(a):o(l,1,a)}function d(){(i=e())?i.then?i.then(v).then(void 0,c):v(i):o(l,1,a)}}(function(){return l<e},function(){return l++},function(){return Promise.resolve(C(i,t)).then(function(){n.fillStyle="rgba(0, 0, 0, 1)",n.fillRect(0,0,a,h),A();var t=function(){if(l<e-1)return Promise.resolve(new Promise(function(e){return setTimeout(e,50)})).then(function(){})}();if(t&&t.then)return t.then(function(){})})});return Promise.resolve(c&&c.then?c.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},[C,A]),O=r(function(e){M.current&&b.current&&(y.current.deltaTime=P.current>0?Math.min(.1,(e-P.current)/1e3):1/60,P.current=e,F(),z(),x.current.forEach(function(e){return e.update()}),A(),S.current=requestAnimationFrame(O))},[F,z,A]),G=r(function(e){if(M.current){clearTimeout(R.current);var t=M.current.getBoundingClientRect();T.current={x:M.current.width/t.width*(e.clientX-t.left),y:M.current.height/t.height*(e.clientY-t.top)},R.current=setTimeout(function(){T.current=null},500)}},[]),V=r(function(){clearTimeout(R.current),T.current=null},[]),k=r(function(e){void 0===e&&(e=!1);try{if(!M.current)return Promise.resolve();if(!e&&b.current)return console.log("Simulation already initialized."),Promise.resolve();console.log(e?"Re-initializing simulation due to resize...":"Initializing simulation..."),b.current=!1,cancelAnimationFrame(S.current),S.current=null;var t=M.current;if(!t.getContext("2d",{alpha:!1}))return console.error("Failed to get 2D context"),Promise.resolve();var r={initialAgents:Math.floor(501*Math.random())+600,sensorOffset:Math.floor(25*Math.random())+5,edgeAvoidance:parseFloat(Math.random().toFixed(1)),agentSpeed:parseFloat((1.2*Math.random()+.75).toFixed(1)),trailStrength:parseFloat((2.5*Math.random()+.5).toFixed(1)),evaporationRate:parseFloat((.04*Math.random()+.005).toFixed(3)),baseHue:Math.floor(360*Math.random()),hueRange:Math.floor(60*Math.random())+30,lightnessRange:Math.floor(30*Math.random())+20,escapeThreshold:.5+.5*Math.random(),brushSize:4,brushStrength:1.5,pixelScale:6,edgeThreshold:3,reshuffleCount:10,startDelay:500},n=d?r:i({},r,p);Object.keys(r).forEach(function(e){if("number"==typeof r[e]){var t=n[e];if("string"==typeof t){var i=parseFloat(t);isNaN(i)?(console.warn("Invalid numeric value for prop "+e+': "'+t+'". Using default: '+r[e]),n[e]=r[e]):n[e]=i}else"number"!=typeof t&&(n[e]=r[e])}}),y.current=n;var a=y.current.pixelScale,o=Math.max(10,Math.floor(window.innerWidth/a)),s=Math.max(10,Math.floor(window.innerHeight/a));return w.current={width:o,height:s},t.width=o,t.height=s,t.style.width=window.innerWidth+"px",t.style.height=window.innerHeight+"px",t.style.display="block",t.style.background="#111",t.style.imageRendering="pixelated",t.style.cursor="crosshair",y.current.trailMap=new Float32Array(o*s),y.current.processedTrailMap=new Float32Array(o*s),Promise.resolve(E(g,o,s)).then(function(t){return Promise.resolve(L(y.current.reshuffleCount,t)).then(function(){b.current=!0,console.log("Initialization complete. Starting animation soon..."),y.current.startTimeoutId&&clearTimeout(y.current.startTimeoutId),y.current.startTimeoutId=setTimeout(function(){b.current&&!S.current&&(console.log("Starting animation loop."),P.current=performance.now(),S.current=requestAnimationFrame(O))},e?100:y.current.startDelay)})})}catch(e){return Promise.reject(e)}},[d,JSON.stringify(p),g,E,L,O]),j=r(function(){clearTimeout(I.current),I.current=setTimeout(function(){k(!0)},250)},[k]);return n(function(){console.log("SlimeSimulation component mounted or dependencies changed."),k(!1),window.addEventListener("resize",j);var e=M.current;return e&&(e.addEventListener("mousemove",G),e.addEventListener("mouseleave",V)),function(){console.log("Cleaning up SlimeSimulation..."),b.current=!1,cancelAnimationFrame(S.current),S.current=null,y.current.startTimeoutId&&clearTimeout(y.current.startTimeoutId),clearTimeout(I.current),clearTimeout(R.current),window.removeEventListener("resize",j),e&&(e.removeEventListener("mousemove",G),e.removeEventListener("mouseleave",V))}},[k,j,G,V]),/*#__PURE__*/e.createElement("canvas",{ref:M})};export{f as default};
//# sourceMappingURL=index.modern.js.map