bach преди 1 година
родител
ревизия
d69c194cd3
променени са 1 файла, в които са добавени 283 реда и са изтрити 72 реда
  1. 283 72
      src/components/ConcernementMapItem.vue

+ 283 - 72
src/components/ConcernementMapItem.vue

@@ -111,14 +111,22 @@ export default {
         if(n){ // opened
           this.openClose(true);
         }else{ // closed
-          this.openClose(false)
+          this.openClose(false);
+        }
+      },
+      deep: true
+    },
+    opened_concernement: {
+      handler (n, o) {
+        if (!n) {
+          this.applyShuffleForces();
         }
       },
       deep: true
     },
     map_mode: {
       handler (n, o) {
-        console.log('watch map_mode', o, n);
+        // console.log('watch map_mode', o, n);
         if (n === 'terraindevie' && !this.opened_concernement) {
           this.applyShuffleForces(); // apply a little force to check the map when returning to terrain de vie
         }
@@ -297,10 +305,27 @@ export default {
     },
     getRandomPos(){
       let pad = 200;
-      return {
-        x: pad + this.ray/2 + Math.random()*(this.canvas.width - this.ray - pad),
-        y: pad + this.ray/2 + Math.random()*(this.canvas.height - this.ray - pad)
-      };
+      // if (this.concernement.id === 56) {
+      //   return {
+      //     x: Math.random() > 0.5 ? pad : this.canvas.width - pad,
+      //     y: pad + this.ray/2 + Math.random()*(this.canvas.height - this.ray - pad)
+      //   };
+      // } else {
+        return {
+          x: pad + this.getGaussianRandom()*(this.canvas.width - pad*2),
+          y: pad + this.getGaussianRandom()*(this.canvas.height - pad*2)
+        };
+      // }
+    },
+    getGaussianRandom(){
+      // INFO https://stackoverflow.com/a/49434653
+      let u = 0, v = 0;
+      while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
+      while(v === 0) v = Math.random();
+      let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
+      num = num / 10.0 + 0.5; // Translate to 0 -> 1
+      if (num > 1 || num < 0) return this.getGaussianRandom() // resample between 0 and 1
+      return num
     },
     initMatterBody (){
       
@@ -309,9 +334,10 @@ export default {
       if (!this.body) {
         // console.log('concernementItem creating body');
 
-        // https://github.com/liabru/matter-attractors/issues/8        
-        // https://github.com/liabru/matter-attractors/blob/master/index.js
-        // MatterAttractors.Attractors.gravityConstant = -5;
+        // INFO https://github.com/liabru/matter-attractors/issues/8        
+        // INFO https://github.com/liabru/matter-attractors/blob/master/index.js
+        // INFO https://github.com/liabru/matter-attractors/blob/master/build/matter-attractors.js#L180
+        MatterAttractors.Attractors.gravityConstant = -20;
         
         // Create parts of the body : main big circle & entities
         this.body_parts = [
@@ -321,6 +347,12 @@ export default {
           })
         ];
         
+        // map a range of numbers to another range of numbers
+        // INFO https://stackoverflow.com/a/46462321
+        let entite_range = [3, 100];
+        let mass_range = [5,15];
+        let mass = mass_range[0] + (this.entites.length - entite_range[0]) * (mass_range[1] - mass_range[0]) / (entite_range[1] - entite_range[0]);
+
         // create the body
         this.body = Matter.Body.create({
           parts: this.body_parts,
@@ -328,16 +360,41 @@ export default {
           id: this.concernement.id,
           frictionAir: 0,
           // mass: Math.pow(3, this.entites.length),
-          mass: 10,
+          // mass: 10,
+          mass: mass,
           restitution: 0.15,
           collisionFilter: {
             group: -1
           },
           plugin: {
             attractors: [
-              // there is a built in helper function for Newtonian gravity!
-              // you can find out how it works in index.js
+              // // there is a built in helper function for Newtonian gravity!
+              // // you can find out how it works in index.js
               MatterAttractors.Attractors.gravity
+              
+              // function(bodyA, bodyB) {
+              //   var force = {
+              //     x: (bodyA.position.x - bodyB.position.x) * 1e-6,
+              //     y: (bodyA.position.y - bodyB.position.y) * 1e-6
+              //   }
+              //   // apply force to both bodies
+              //   Matter.Body.applyForce(bodyA, bodyA.position, force);
+              //   Matter.Body.applyForce(bodyB, bodyB.position, Matter.Vector.neg(force));
+              // }
+
+              // INFO https://github.com/liabru/matter-attractors/blob/master/build/matter-attractors.js#L192
+              // function (bodyA, bodyB){
+              //   // use Newton's law of gravitation
+              //   var bToA = Matter.Vector.sub(bodyB.position, bodyA.position),
+              //       distanceSq = Matter.Vector.magnitudeSquared(bToA) || 0.0001,
+              //       normal = Matter.Vector.normalise(bToA),
+              //       magnitude = -MatterAttractors.Attractors.gravityConstant * (bodyA.mass * bodyB.mass / distanceSq),
+              //       force = Matter.Vector.mult(normal, magnitude);
+
+              //   // to apply forces to both bodies
+              //   Matter.Body.applyForce(bodyA, bodyA.position, Matter.Vector.neg(force));
+              //   Matter.Body.applyForce(bodyB, bodyB.position, force);
+              // }
             ]
           }
         });
@@ -1143,18 +1200,17 @@ export default {
         if (this.opened_concernement.id !== this.id) {
           this.pushAside()
         }
+      } else if (this.map_mode === 'puissancedagir' 
+        || this.map_mode === 'action'
+        || this.map_mode === 'doleancer'){ // apply focus forces : move unfocused on the sides and focused on the center
+        this.applyFocusForces(); //
       } else {
-        // apply focus forces : move unfocused on the sides and focused on the center
-        if (this.map_mode === 'action' 
-          || this.map_mode === 'puissancedagir'
-          || this.map_mode === 'doleancer'){
-          this.applyFocusForces(); //
-        }  
+        this.applyNormalForces(); // if terrain de vie apply force to gently reject items from the sides and so create a continuasly mvmt
       }
       
       // reset all matter rotation forces otherwise items will spin when colide 
-      Matter.Body.setAngle(this.body, 0);
-      Matter.Body.setAngularSpeed(this.body, 0);
+      // Matter.Body.setAngle(this.body, 0);
+      // Matter.Body.setAngularSpeed(this.body, 0);
     },
     applyFocusForces(){
       if(!this.isFocused()) {
@@ -1163,12 +1219,21 @@ export default {
         this.bringToCenter()
       }
     },
+    isFocused(){
+      return this.map_mode === 'terraindevie'
+          || (this.map_mode === 'action' && this.concernement.has_agissantes)
+          || (this.map_mode === 'puissancedagir' && this.concernement.has_puissancedagir)
+          || (this.map_mode === 'doleancer' && this.concernement.has_doleance);
+    },
     pushAside(){
       // console.log('pushAside', this.opened_concernement);
       // apply a force in direction of one side or an other depending of the start position
       // the force is exponentialy proportional to the distance from the side
       // INFO logarithmic force : https://stackoverflow.com/questions/846221/logarithmic-slider/846249#846249 
-      let pseudo_center_x = (this.canvas.width - this.cartouch_width) / 2;
+      // TODO cartouch width should change regarding actual cartouch is opened or not (and how many cartouch are opened) 
+      let pseudo_center_x = this.opened_concernement 
+        ? (this.canvas.width - this.cartouch_width) / 2
+        : this.canvas.width / 2;
       // get the direction to the closest side
       let dir = this.pos.x > pseudo_center_x
         ? 1 // to the right
@@ -1202,81 +1267,233 @@ export default {
           y: 0
         }
       );
+
+      this.body.frictionAir = 0.01;
     },
     bringToCenter(){
       // bring to the centre
-      let pseudo_center_x = (this.canvas.width - this.cartouch_width) / 2;
-      // get the direction to the centre
+      // apply a force in direction of one side or an other depending of the start position
+      // the force is exponentialy inversed proportional to the distance from the side
+      // INFO logarithmic force : https://stackoverflow.com/questions/846221/logarithmic-slider/846249#846249 
+      // TODO cartouch width should change regarding actual cartouch is opened or not (and how many cartouch are opened) 
+      let pseudo_center_x = this.opened_concernement 
+        ? (this.canvas.width - this.cartouch_width) / 2
+        : this.canvas.width / 2;
       let dir = this.pos.x > pseudo_center_x 
         ? -1 // to left 
         : 1; // to right
-        // max & min item position
-      let minp = 0;
-      let maxp = dir < 0
-        ? this.canvas.width - pseudo_center_x
-        : pseudo_center_x;
-      // max and min force
-      let minf = 0;
-      let maxf = 1;
-      // scale factor
-      let scale = (maxf-minf) / (maxp-minp);
       // get the inversed distance from the side
       let dist = dir < 0 
         ? this.pos.x - pseudo_center_x 
         : pseudo_center_x - this.pos.x; 
 
-      let x_force = Math.exp(minf + scale*(dist-minp)) * dir;
+      if (dist > this.canvas.width/6) { // apply decreasing forces and increasing friction air only out of center to let the items float in the center zone
+        // max & min item position
+        let minp = 0;
+        let maxp = dir < 0
+          ? this.canvas.width - pseudo_center_x
+          : pseudo_center_x;
+        
+        // X force decrsinsing near the center
+        // max and min force
+        let xminf = 0;
+        let xmaxf = 1 + Math.random()*4;
+        // scale factor
+        let xscale = (xmaxf-xminf) / (maxp-minp);
+        let x_force = Math.exp(xminf + xscale*(dist-minp)) * dir;
+        let ori_pos = dir < 0 
+          ? {x:this.canvas.width, y:this.body.position.y} 
+          : {x:0, y:this.body.position.y};
+        Matter.Body.applyForce(
+          this.body, 
+          ori_pos, 
+          {
+            x: x_force,
+            y: 0
+          }
+        );
+        
+        // Friction air fa (increasing near the center)
+        let fa_minf = 0;
+        let fa_maxf = 6;
+        // scale factor
+        let fa_scale = (fa_maxf-fa_minf) / (maxp-minp);
+        let fa = Math.exp(fa_minf + fa_scale*(dist-minp)*-1);
+        this.body.frictionAir = fa;
+        
+        console.log(`bringToCenter dist:${dist}, x_force:${x_force}, friction air:${fa}`);        
+      } else { // in the ceneter zone let items floats freely
+        let velocity = Matter.Body.getVelocity(this.body);
+        let velocityx = Math.abs(velocity.x);
+        // map a range of numbers to another range of numbers
+        // INFO https://stackoverflow.com/a/46462321
+        let velocity_range = [50, 1000];
+        let fa_range = [0,3];
+        let fa = fa_range[0] + (velocityx - velocity_range[0]) * (fa_range[1] - fa_range[0]) / (velocity_range[1] - velocity_range[0]);
+        console.log(`bringToCenter velocity.x:${velocity.x}, fa:${fa}`);
 
-      let ori_pos = dir < 0 
-        ? {x:this.canvas.width, y:this.body.position.y} 
-        : {x:0, y:this.body.position.y};
-      // let x_force = Math.pow(dist/800,10) * dir;
-      
-      this.body.frictionAir = 0.05;
+        this.body.frictionAir = fa;
+      }
 
-      Matter.Body.applyForce(
-        this.body, 
-        ori_pos, 
-        {
-          x: x_force,
-          y: 0
-        }
-      );
     },
     applyShuffleForces() {
+      // console.log('applyShuffleForces');
       // var dist, dir, x_velocity;
       // dir = this.pos.x > this.canvas.width/2 ? -1 : 1; // get the direction to the centre
       // dist = (dir < 0 ? this.pos.x - this.canvas.width/2 : this.canvas.width/2 - this.pos.x); // get the distance from the side
       // x_velocity = Math.pow(dist/650,10) * dir;
-      let pseudo_center_x = (this.canvas.width - this.cartouch_width) / 2;
+      // TODO cartouch width should change regarding actual cartouch is opened or not (and how many cartouch are opened) 
+      let pseudo_center_x = this.opened_concernement 
+        ? (this.canvas.width - this.cartouch_width) / 2
+        : this.canvas.width / 2;
       // get the direction to the centre
       let dir = this.pos.x > pseudo_center_x 
         ? -1 // to left 
         : 1; // to right
-        // max & min item position
-      let minp = 0;
-      let maxp = dir < 0
-        ? this.canvas.width - pseudo_center_x
-        : pseudo_center_x;
-      // max and min force
-      let minf = 0;
-      let maxf = 10;
-      // scale factor
-      let scale = (maxf-minf) / (maxp-minp);
       // get the inversed distance from the side
       let dist = dir < 0 
+        ? this.pos.x - pseudo_center_x 
+        : pseudo_center_x - this.pos.x;
+      
+      if (dist > this.canvas.width/6) { // apply decreasing forces and increasing friction air only out of center to let the items float in the center zone
+        // max & min item position
+        let minp = 0;
+        let maxp = dir < 0
+          ? this.canvas.width - pseudo_center_x
+          : pseudo_center_x;
+
+        // X max and min force
+        let xminf = 0;
+        let xmaxf = 4 + Math.random()*3;
+        // scale factor
+        let xscale = (xmaxf-xminf) / (maxp-minp);
+        
+        let x_velocity = Math.exp(xminf + xscale*(dist-minp))*dir;
+
+        // let y_velocity = 30 + Math.random() * 50;
+        // y_velocity = Math.random() > 0.5 ? -y_velocity : y_velocity;
+        // X max and min force
+        let yminf = 1;
+        let ymaxf = 2 + Math.random()*4;
+        // scale factor
+        let yscale = (ymaxf-yminf) / (maxp-minp);
+        
+        let y_velocity = Math.exp(yminf + yscale*(dist-minp)) * (Math.random() > 0.5 ? 1 : -1);       // let ori_pos = dir < 0 
+
+        //   ? {x:this.canvas.width, y:this.body.position.y} 
+        //   : {x:0, y:this.body.position.y};
+        // let x_force = Math.pow(dist/800,10) * dir;
+        console.log(`applyShuffleForces dir:${dir}, maxp:${maxp}, dist:${dist}, x_velocity:${x_velocity}, y_velocity:${y_velocity}`);
+        Matter.Body.setVelocity(this.body, {x: x_velocity, y: y_velocity});
+      } else { // if in center zone real shuffle velocity
+        // x_velocity = -50 + Math.random()*100;
+        // y_velocity = -50 + Math.random()*100;
+        // this.setInitBodyVelocity();
+      }
+      
+      this.body.frictionAir = 0.01;
+    },
+    applyNormalForces () {
+      // bring gently to the centre
+      // apply a force in direction of one side or an other depending of the start position
+      // the force is exponentialy inversed proportional to the distance from the side
+      // INFO logarithmic force : https://stackoverflow.com/questions/846221/logarithmic-slider/846249#846249 
+      // TODO cartouch width should change regarding actual cartouch is opened or not (and how many cartouch are opened) 
+      // X
+      let pseudo_center_x = this.opened_concernement 
+        ? (this.canvas.width - this.cartouch_width) / 2
+        : this.canvas.width / 2;
+      let xdir = this.pos.x > pseudo_center_x 
+        ? -1 // to left 
+        : 1; // to right
+      // get the inversed distance from the side
+      let xdist = xdir < 0 
         ? this.pos.x - pseudo_center_x 
         : pseudo_center_x - this.pos.x; 
 
-      let x_velocity = Math.exp(minf + scale*(dist-minp));
+      // Y
+      let pseudo_center_y = this.canvas.height / 2;
+      let ydir = this.pos.y > pseudo_center_y 
+        ? -1 // to top
+        : 1; // to bottom
+      // get the inversed distance from the side
+      let ydist = ydir < 0 
+        ? this.pos.y - pseudo_center_y 
+        : pseudo_center_y - this.pos.y; 
 
-      let y_velocity = -10 + Math.random() * 10;
-      // let ori_pos = dir < 0 
-      //   ? {x:this.canvas.width, y:this.body.position.y} 
-      //   : {x:0, y:this.body.position.y};
-      // let x_force = Math.pow(dist/800,10) * dir;
+      let k = 4;
+      if (xdist > this.canvas.width/k || ydist > this.canvas.height/k) { // apply decreasing forces and increasing friction air only out of center to let the items float in the center zone
+        // max and min force
+        let minf = 0;
+        let maxf = 0.1;
+
+        // X
+        // max & min item position
+        let xminp = 0;
+        let xmaxp = xdir < 0
+          ? this.canvas.width - pseudo_center_x
+          : pseudo_center_x;
+        // X force decrsinsing near the center
+        // scale factor
+        let xscale = (maxf-minf) / (xmaxp-xminp);
+        let x_force = Math.exp(minf + xscale*(xdist-xminp)) * xdir;
+        let xori_pos = xdir < 0 
+          ? {x:this.canvas.width, y:this.body.position.y} 
+          : {x:0, y:this.body.position.y};
+        Matter.Body.applyForce(
+          this.body, 
+          xori_pos, 
+          {
+            x: x_force,
+            y: 0
+          }
+        );
+
+        // Y
+        // max & min item position
+        let yminp = 0;
+        let ymaxp = ydir < 0
+          ? this.canvas.height - pseudo_center_y
+          : pseudo_center_y;
+        // X force decrsinsing near the center
+        // scale factor
+        let yscale = (maxf-minf) / (ymaxp-yminp);
+        let y_force = Math.exp(minf + yscale*(ydist-xminp)) * ydir;
+        let yori_pos = ydir < 0 
+          ? {x:this.body.position.x, y:this.canvas.height} 
+          : {x:this.body.position.x, y:0};
+        Matter.Body.applyForce(
+          this.body, 
+          yori_pos, 
+          {
+            x: 0,
+            y: y_force
+          }
+        );
+        
+        // // Friction air fa (increasing near the center)
+        // let fa_minf = 0;
+        // let fa_maxf = 6;
+        // // scale factor
+        // let fa_scale = (fa_maxf-fa_minf) / (maxp-minp);
+        // let fa = Math.exp(fa_minf + fa_scale*(dist-minp)*-1);
+        // this.body.frictionAir = fa;
+        
+        // console.log(`bringToCenter dist:${xdist}, x_force:${x_force}`);        
+      } else { // in the ceneter zone let items floats freely
+        // let velocity = Matter.Body.getVelocity(this.body);
+        // let velocityx = Math.abs(velocity.x);
+        // // map a range of numbers to another range of numbers
+        // // INFO https://stackoverflow.com/a/46462321
+        // let velocity_range = [50, 1000];
+        // let fa_range = [0,3];
+        // let fa = fa_range[0] + (velocityx - velocity_range[0]) * (fa_range[1] - fa_range[0]) / (velocity_range[1] - velocity_range[0]);
+        // console.log(`bringToCenter velocity.x:${velocity.x}, fa:${fa}`);
+
+        // this.body.frictionAir = fa;
+        this.body.frictionAir = 0.1;
+      }
 
-      Matter.Body.setVelocity(this.body, {x: x_velocity, y: y_velocity});
     },
     onAfterEngineUpdate (event) {
       // respawn element if outside screen
@@ -1294,12 +1511,6 @@ export default {
       // this.draw()
       this.handlePaperVisibility()
     },
-    isFocused(){
-      return this.map_mode === 'terraindevie'
-          || (this.map_mode === 'action' && this.concernement.has_agissantes)
-          || (this.map_mode === 'puissancedagir' && this.concernement.has_puissancedagir)
-          || (this.map_mode === 'doleancer' && this.concernement.has_doleance);
-    },
   },
   render() {
     // console.log('render()', this.ctx);