Browse Source

started to integrate matter for physics in the map

bach 1 year ago
parent
commit
772630d1a5

+ 11 - 0
package-lock.json

@@ -12,6 +12,7 @@
         "@material-design-icons/svg": "^0.14.2",
         "@mdi/font": "^7.1.96",
         "granim": "^2.0.0",
+        "matter-js": "^0.19.0",
         "pinia": "^2.0.21",
         "vue": "^3.2.38",
         "vue-router": "^4.1.5"
@@ -1752,6 +1753,11 @@
         "sourcemap-codec": "^1.4.8"
       }
     },
+    "node_modules/matter-js": {
+      "version": "0.19.0",
+      "resolved": "https://registry.npmjs.org/matter-js/-/matter-js-0.19.0.tgz",
+      "integrity": "sha512-v2huwvQGOHTGOkMqtHd2hercCG3f6QAObTisPPHg8TZqq2lz7eIY/5i/5YUV8Ibf3mEioFEmwibcPUF2/fnKKQ=="
+    },
     "node_modules/mime-db": {
       "version": "1.52.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -3748,6 +3754,11 @@
         "sourcemap-codec": "^1.4.8"
       }
     },
+    "matter-js": {
+      "version": "0.19.0",
+      "resolved": "https://registry.npmjs.org/matter-js/-/matter-js-0.19.0.tgz",
+      "integrity": "sha512-v2huwvQGOHTGOkMqtHd2hercCG3f6QAObTisPPHg8TZqq2lz7eIY/5i/5YUV8Ibf3mEioFEmwibcPUF2/fnKKQ=="
+    },
     "mime-db": {
       "version": "1.52.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",

+ 1 - 0
package.json

@@ -12,6 +12,7 @@
     "@material-design-icons/svg": "^0.14.2",
     "@mdi/font": "^7.1.96",
     "granim": "^2.0.0",
+    "matter-js": "^0.19.0",
     "pinia": "^2.0.21",
     "vue": "^3.2.38",
     "vue-router": "^4.1.5"

+ 8 - 0
src/assets/layout.scss

@@ -59,6 +59,14 @@ html,body{
     }
   }
   
+  #map-matter{
+    position: absolute;
+    z-index: -1;
+    top:0; left:0;
+    width:100%;
+    height:100%;
+  }
+
   #map-concernements{
     width:100%;
     height:100%;

+ 56 - 17
src/components/ConcernementMapItem.vue

@@ -1,14 +1,24 @@
 <script>
 
-// import { mapActions, mapState } from 'pinia'
-// import { ConcernementsStore } from '@/stores/concernements'
+// https://brm.io/matter-js/docs/classes/Engine.html
+import {
+  // Engine,
+  // Render,
+  // World,
+  Bodies,
+  Body,
+  Events,
+  Composite,
+  // Composites,
+  // Constraint,
+  // Vertices,
+  // Mouse,
+  // MouseConstraint,
+  // Query,
+  // Common
+} from "matter-js";
 
 
-// import LoginBlock from '@components/block/LoginBlock.vue'
-// import UserTools from '@components/block/UserTools.vue'
-
-// import MA from '/api/ma-axios'
-
 export default {
   inject: ['canvasMap'],
   data() {
@@ -21,18 +31,23 @@ export default {
       },
       ray: 60,
       time: 0,
-      salientPoints: []
+      salientPoints: [],
+      // matter
+      body: null
     }
   },
   props: ['concernement'],
   created () {
-    // console.log("ConcernementsMapItem concernement", this.concernement);
+    console.log("ConcernementsMapItem concernement", this.canvasMap);
     this.entites = this.concernement.entites
     this.parsePoints()
     this.getSalientPoints()
-    if (this.canvasMap) {
-      this.initCanvasMap()
-    }
+  },
+  mounted() {
+    // console.log('concernementItem mounted', typeof this.canvasMap.canvas);
+    // if (this.canvasMap) {
+    //   // this.initCanvasMap()
+    // }
   },
   watch: {
     // canvasMap (n, o) {
@@ -40,7 +55,7 @@ export default {
     // }
     canvasMap: {
       handler (n, o){
-        console.log("concernementItem watch canvasMap.ctx", o, n);
+        // console.log("concernementItem watch canvasMap.ctx", typeof this.canvas, o, n);
         if (!this.canvas) {
           this.initCanvasMap()
         }
@@ -50,12 +65,36 @@ export default {
   },
   methods: {
     initCanvasMap (){
+      // record canvas and ctx for rendering (drawing)
       this.canvas = this.canvasMap.canvas
       this.ctx = this.canvasMap.ctx
+
+      // define init position of the item
       this.pos.x = this.ray/2 + Math.random()*(this.canvas.width - this.ray)
       this.pos.y = this.ray/2 + Math.random()*(this.canvas.height - this.ray)
-      // listen for animate event dispatched from parent
-      this.canvas.addEventListener('animate', this.animate)
+      
+      // MATTER
+      // create the matter body and add it to the engine
+      if (!this.body) {
+        console.log('concernementItem creating body');
+        this.body = Bodies.circle(this.pos.x, this.pos.y, this.ray, {
+          frictionAir: 0,
+          mass: this.entites.length,
+          restitution: 0.9
+        });
+        // Body.setPosition(this.body, this.pos);
+        Body.setVelocity(this.body, {
+            x: -50 + Math.random()*50,
+            y: -50 + Math.random()*50
+          });
+        // console.log('concernementItem mass', this.body.mass);
+        Composite.add(this.canvasMap.matter.engine.world, this.body);
+      }
+
+      // // listen for animate event dispatched from parent
+      // this.canvas.addEventListener('animate', this.animate)
+      // listen for afterUpdate event from Matter.Engine object
+      Events.on(this.canvasMap.matter.engine, "afterUpdate", this.animate)
     },
     parsePoints (){
       // converts data (menace/maintien, actuel/future, prise) into atcual position x,y
@@ -120,11 +159,11 @@ export default {
       }
       console.log(`this.salientPoints ${this.concernement.id}`, this.salientPoints);
     },
-    animate () {
+    animate (event) {
       if (this.ctx) {
         // this var is only here to trigger the render()
         this.time = Date.now();
-        // this.pos.x += 0;
+        this.pos = this.body.position;
       }
     }
   },

+ 1 - 1
src/components/MapBackground.vue

@@ -11,7 +11,7 @@ export default {
   },
   mounted() {
     // this.initGradients()
-    this.initTrame()
+    // this.initTrame()
   },
   // computed: {
   // },

+ 72 - 11
src/components/MapConcernements.vue

@@ -1,40 +1,97 @@
 <script>
 
-import Granim from 'granim'
 // import { mapActions, mapState } from 'pinia'
 import { computed } from 'vue'
-// import LoginBlock from '@components/block/LoginBlock.vue'
 import MapBackground from '@components/MapBackground.vue'
 
-// import MA from '/api/ma-axios'
+// https://brm.io/matter-js/docs/classes/Engine.html
+import {
+  Engine,
+  // Render,
+  // World,
+  Bodies,
+  // Body,
+  // Events,
+  Composite,
+  // Composites,
+  // Constraint,
+  // Vertices,
+  // Mouse,
+  // MouseConstraint,
+  // Query,
+  // Common
+} from "matter-js";
 
 
-// https://www.digitalocean.com/community/tutorials/vuejs-vue-html5-canvas
-
 export default {
   data() {
     return {
       canvasMap: {
         canvas: null,
-        ctx: null
+        ctx: null,
+        matter: null
       },
       animateEvent: new Event('animate'),
-      granim: null
-
+      granim: null,
+      // MATTER
+      engine: null,
+      world: null,
+      render: null
     }
   },
   provide() {
+    // https://www.digitalocean.com/community/tutorials/vuejs-vue-html5-canvas
     return {
       // explicitly provide a computed property
       canvasMap: computed(() => this.canvasMap)
     }
   },
+  created() {
+    // MATTER
+    // create an engine
+    let engineOptions = {
+      enableSleeping: true,
+      timing: {
+        //timestamp: 0.5,
+        timeScale: 0.5
+      }
+    }
+    this.engine = Engine.create(engineOptions);
+    this.engine.gravity.scale = 0;
+    this.canvasMap.matter = {
+      engine: this.engine
+    }
+    this.world = this.engine.world;
+
+  },
   mounted() {
     this.canvasMap.canvas = this.$refs['canvas-map'];
     this.canvasMap.ctx = this.canvasMap.canvas.getContext('2d');
 
-    this.canvasMap.canvas.width = this.canvasMap.canvas.parentElement.clientWidth;
-    this.canvasMap.canvas.height = this.canvasMap.canvas.parentElement.clientHeight;
+    let canvas_w = this.canvasMap.canvas.width = this.canvasMap.canvas.parentElement.clientWidth;
+    let canvas_h = this.canvasMap.canvas.height = this.canvasMap.canvas.parentElement.clientHeight;
+
+    // MATTER
+    let wall_w = 5;
+    Composite.add(this.world, [
+        // walls
+        Bodies.rectangle(canvas_w/2, 0, canvas_w, wall_w, { isStatic: true }),                 // top
+        Bodies.rectangle(canvas_w/2, canvas_h-wall_w, canvas_w, wall_w, { isStatic: true }),   // bottom
+        Bodies.rectangle(0, canvas_h/2, wall_w, canvas_h, { isStatic: true }),                 // left
+        Bodies.rectangle(canvas_w-wall_w, canvas_h/2, wall_w, canvas_h, { isStatic: true })    // right
+    ]);
+
+    // this.render = Render.create({
+    //   canvas: this.$refs['canvas-engine'],
+    //   engine: this.engine,
+    //   options: {
+    //     width: canvas_w,
+    //     height: canvas_h,
+    //     showVelocity: true
+    //   }
+    // });
+    // Render.run(this.render);
+
     this.animate()
   },
   // computed: {
@@ -44,7 +101,8 @@ export default {
   methods: {
     animate () {
       this.canvasMap.ctx.clearRect(0, 0, this.canvasMap.canvas.width, this.canvasMap.canvas.height)
-      this.canvasMap.canvas.dispatchEvent(this.animateEvent)
+      // this.canvasMap.canvas.dispatchEvent(this.animateEvent)
+      Engine.update(this.canvasMap.matter.engine, 1)
       window.requestAnimationFrame(this.animate);
     }
   },
@@ -61,6 +119,9 @@ export default {
   <div id="map-backgrounds">
     <MapBackground />
   </div>
+  <div id="map-matter">
+    <canvas ref="canvas-engine"></canvas>
+  </div>
   <div id="map-concernements">
     <canvas ref="canvas-map"></canvas>
     <slot></slot>