2D图形引擎<Matter.js>

2021-08-06 15-18-07.gif

🔥🔥Matter.js官方地址

本篇文章主要基于 Matter.js 的个别案例进行了注释,注释大多为个人理解,需要了解更多的可查看 官方文档

使用方法
  • js引入

matter.min.js下载地址

<script src="matter.js"></script>
  • npm安装
npm install matter-js
import Matter from 'matter-js'
  • html
 <div id="canvas"></div>
image.png
基本使用
2021-08-06 15-09-11.gif
 /**
     * Engine 是引擎
     * Render 是渲染器
     * Runner 是表演环境
     * Bodies 可以用来创建各种形状的物体。
     * Vertices 模块包含用于创建和处理顶点集的方法
     * Mouse 模块包含用于创建和操作鼠标输入的方法
     * MouseConstraint 用于创建鼠标约束的方法。鼠标约束用于允许用户交互,提供通过鼠标或触摸移动身体的能力。
     * Common 模块包含所有模块共有的实用程序功能
     * Composites 模块包含用于创建具有常用配置(例如,堆栈和链)的复合实体的工厂方法
     */
    var Engine = Matter.Engine,
      Render = Matter.Render,
      Runner = Matter.Runner,
      Bodies = Matter.Bodies,
      Composite = Matter.Composite,
      Vertices = Matter.Vertices;
    // 创建一个引擎
    var engine = Engine.create();

    //render(渲染器)将要渲染的物理引擎是之前所创建的engine,而渲染的对象是html网页的body
    var render = Render.create({
      element: document.getElementById('canvas'), //渲染容器
      engine: engine, //引擎
      options: {
        width: window.innerWidth,
        height: window.innerHeight,
        pixelRatio: 1.5, // 设置像素比 越高越清楚 越耗性能
        background: '#fafafa', // 全局渲染模式时背景色 线框模式为 false 生效
        wireframeBackground: '#222', // 线框模式时背景色 线框模式为 true 生效
        hasBounds: false,
        enabled: true,
        wireframes: true, // 线框模式
        showSleeping: true, // 刚体睡眠状态
        showDebug: false, // Debug 信息
        showBroadphase: false, // 粗测阶段
        showBounds: false, // 刚体的界限
        showVelocity: false, // 移动刚体时速度
        showCollisions: false, // 刚体碰撞点
        showSeparations: false, // 刚体分离
        showAxes: false, // 刚体轴线
        showPositions: false, // 刚体位置
        showAngleIndicator: false, // 刚体转角指示
        showIds: false, // 显示每个刚体的 ID
        showVertexNumbers: false, // 刚体顶点数
        showConvexHulls: false, // 刚体凸包点
        showInternalEdges: false, // 刚体内部边界
        showMousePosition: false // 鼠标约束线
      }
    });

    //参数(500,170,40,260)中,前两个是物体坐标,后两个分别是宽度和长度。 
    //需要注意的是,这里的坐标系统中,500和170是矩形的中心所在位置
    //而html的canvas中坐标描述的是矩形的左上角。
    var boxA = Bodies.rectangle(400, 200, 80, 80);
    var boxB = Bodies.rectangle(450, 50, 80, 80);
    //将isStatic设为true,即是静止的
    var ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true });

    // 把所有的身体加到世界上
    Composite.add(engine.world, [boxA, boxB, ground]);

    // run the renderer
    Render.run(render);

    // create runner
    var runner = Runner.create();

    // run the engine
    Runner.run(runner, engine);


基础图形创建
2021-08-06 15-28-02.gif
 var Engine = Matter.Engine,
      Render = Matter.Render,
      Runner = Matter.Runner,
      Bodies = Matter.Bodies,
      Composite = Matter.Composite,
      Vertices = Matter.Vertices;


    var engine = Engine.create();
    var render = Render.create({
      element: document.getElementById('canvas'), //渲染容器
      engine: engine, //引擎
      options: {
        width: window.innerWidth,
        height: window.innerHeight,
        pixelRatio: 1.5,// 设置像素比 越高越清楚 越耗性能
        wireframes: false, // 线框模式
      }
    })
    // 矩形创建 https://brm.io/matter-js/docs/classes/Bodies.html#method_rectangle
    var rectangle = Bodies.rectangle(400, 200, 80, 80);
    // 圆形创建  https://brm.io/matter-js/docs/classes/Bodies.html#method_circle
    var circle = Bodies.circle(450, 50, 40)
    // 顶点创建复合实体 https://brm.io/matter-js/docs/classes/Bodies.html#method_fromVertices
    var star = Bodies.fromVertices(200, 200, Vertices.fromPath('50 0 63 38 100 38 69 59 82 100 50 75 18 100 31 59 0 38 37 38'));
    // 多边形创建 https://brm.io/matter-js/docs/classes/Bodies.html#method_polygon
    // 3边 半径为60
    var polygon = Bodies.polygon(200, 460, 3, 60);
    // 梯形创建
    var trapezoid = Bodies.trapezoid(200, 10, 50, 50, .5)

    //创建一个地面 将isStatic设为true,即是静止的
    var ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true });
    // 把所有的身体加到世界上
    Composite.add(engine.world, [rectangle, circle, star, polygon, trapezoid, ground]);

    // run the renderer
    Render.run(render);

    // create runner
    var runner = Runner.create();

    // run the engine
    Runner.run(runner, engine);

添加鼠标控制
2021-08-06 15-28-20.gif
// 案列 https://brm.io/matter-js/demo/#airFriction
    var Engine = Matter.Engine,
      Render = Matter.Render,
      Runner = Matter.Runner,
      Bodies = Matter.Bodies,
      Composite = Matter.Composite,
      //* Mouse 模块包含用于创建和操作鼠标输入的方法
      //* MouseConstraint 用于创建鼠标约束的方法。鼠标约束用于允许用户交互,提供通过鼠标或触摸移动身体的能力。
      MouseConstraint = Matter.MouseConstraint,
      Mouse = Matter.Mouse;

    // 创建一个引擎
    var engine = Engine.create(),
      // 引擎内的世界
      world = engine.world;

    //渲染配置属性
    var render = Render.create({
      element: document.getElementById('canvas'),
      engine: engine,
      options: {
        width: window.innerWidth,
        height: window.innerHeight,
        showVelocity: true
      }
    });
    //    开始渲染
    Render.run(render);

    // 开始运行和加载引擎
    var runner = Runner.create();
    Runner.run(runner, engine);

    // 添加 物理块
    Composite.add(world, [
      // 下降的方块 frictionAir 空气的摩擦阻力
      Bodies.rectangle(200, 100, 60, 60, { frictionAir: 0.001 }),
      Bodies.rectangle(400, 100, 60, 60, { frictionAir: 0.05 }),
      Bodies.rectangle(600, 100, 60, 60, { frictionAir: 0.1 }),

      // 创建静止墙面
      Bodies.rectangle(400, 0, 800, 50, { isStatic: true }),
      Bodies.rectangle(400, 600, 800, 50, { isStatic: true }),
      Bodies.rectangle(800, 300, 50, 600, { isStatic: true }),
      Bodies.rectangle(0, 300, 50, 600, { isStatic: true })
    ]);

    // 添加鼠标控制事件---------------------------------
    var mouse = Mouse.create(render.canvas),
      mouseConstraint = MouseConstraint.create(engine, {
        mouse: mouse,
        constraint: {
          stiffness: 0.2,
          render: {
            visible: false
          }
        }
      });

    Composite.add(world, mouseConstraint);

    // 保持鼠标与渲染同步
    render.mouse = mouse;
    // ---------------------------------

    // 使渲染视图适合场景
    // Render.lookAt(render, {
    //   min: { x: 0, y: 0 },
    //   max: { x: 800, y: 600 }
    // });


matter-wrap 超出界面循环
2021-08-06 15-28-41.gif
// 案列 https://brm.io/matter-js/demo/#avalanche
    //   npm install MatterWrap 实现超出循环
    try {
      if (typeof MatterWrap !== "undefined") {
        // either use by name from plugin registry (Browser global)
        Matter.use("matter-wrap");
      } else {
        // or require and use the plugin directly (Node.js, Webpack etc.)
        Matter.use(require("matter-wrap"));
      }
    } catch (e) {
      // could not require the plugin or install needed
    }
    var Engine = Matter.Engine,
      Render = Matter.Render,
      Runner = Matter.Runner,
      Bodies = Matter.Bodies,
      Composite = Matter.Composite,
      Composites = Matter.Composites,
      //* Mouse 模块包含用于创建和操作鼠标输入的方法
      //* MouseConstraint 用于创建鼠标约束的方法。鼠标约束用于允许用户交互,提供通过鼠标或触摸移动身体的能力。
      MouseConstraint = Matter.MouseConstraint,
      Mouse = Matter.Mouse,
      Common = Matter.Common;

    // 创建一个引擎
    var engine = Engine.create(),
      // 引擎内的世界
      world = engine.world;

    //渲染配置属性
    var render = Render.create({
      element: document.getElementById("canvas"),
      engine: engine,
      options: {
        width: 800,
        height: 600,
        wireframes: false,
        showAngleIndicator: true //刚体转角指示
      }
    });
    // 开始渲染
    Render.run(render);

    // 开始运行和加载引擎
    var runner = Runner.create();
    Runner.run(runner, engine);

    /**
     * 创建一个新的复合材料,其中包含在网格排列中的回调中创建的实体。
     * 此功能使用身体的边界来防止重叠
     */
    var stack = Composites.stack(20, 20, 20, 5, 0, 0, function(x, y) {
      return Bodies.circle(x, y, Common.random(10, 20), {
        friction: 0.00001, //空气阻力
        restitution: 0.5, //反弹指数
        density: 0.001
      }); //密度
    });
    Composite.add(world, stack);

    // 添加 碰撞墙
    Composite.add(world, [
      Bodies.rectangle(200, 150, 700, 20, {
        isStatic: true,
        angle: Math.PI * 0.06,
        render: { fillStyle: "red" }
      }),
      Bodies.rectangle(500, 350, 700, 20, {
        isStatic: true,
        angle: -Math.PI * 0.06,
        render: { fillStyle: "blue" }
      }),
      Bodies.rectangle(340, 580, 700, 20, {
        isStatic: true,
        angle: Math.PI * 0.04,
        render: { fillStyle: "pink" }
      })
    ]);

    // 添加鼠标控制事件---------------------------------
    var mouse = Mouse.create(render.canvas),
      mouseConstraint = MouseConstraint.create(engine, {
        mouse: mouse,
        constraint: {
          stiffness: 0.2,
          render: {
            visible: false
          }
        }
      });

    Composite.add(world, mouseConstraint);

    // 保持鼠标与渲染同步
    render.mouse = mouse;
    // ---------------------------------

    // 使渲染视图适合场景
    Render.lookAt(render, Composite.allBodies(world));

    // 使用matter-wrap插件进行包装
    // 超出界面后循环
    for (var i = 0; i < stack.bodies.length; i += 1) {
      stack.bodies[i].plugin.wrap = {
        min: { x: render.bounds.min.x, y: render.bounds.min.y },
        max: { x: render.bounds.max.x, y: render.bounds.max.y }
      };
    }

贴图
image.png
import ball from './img/ball.png'
import box from './img/box.png'
// 案列 https://brm.io/matter-js/demo/#sprites
    var Engine = Matter.Engine,
      Render = Matter.Render,
      Runner = Matter.Runner,
      Bodies = Matter.Bodies,
      Composite = Matter.Composite,
      Composites = Matter.Composites,
      MouseConstraint = Matter.MouseConstraint,
      Mouse = Matter.Mouse,
      Common = Matter.Common

    // 创建一个引擎
    var engine = Engine.create(),
      // 引擎内的世界
      world = engine.world;

    //渲染配置属性
    var render = Render.create({
      element: document.getElementById('canvas'),
      engine: engine,
      options: {
        width: 800,
        height: 600,
        showAngleIndicator: false,// 刚体转角指示
        wireframes: false  // 线框模式
      }
    });
    //    开始渲染
    Render.run(render);

    // 开始运行和加载引擎
    var runner = Runner.create();
    Runner.run(runner, engine);

    //  添加墙壁属性
    var offset = 10,
      options = {
        isStatic: true
      };

    world.bodies = [];
    // 这些静态墙将不会在这个精灵的例子中渲染
    Composite.add(world, [
      Bodies.rectangle(400, -offset, 800.5 + 2 * offset, 50.5, options),
      Bodies.rectangle(400, 600 + offset, 800.5 + 2 * offset, 50.5, options),
      Bodies.rectangle(800 + offset, 300, 50.5, 600.5 + 2 * offset, options),
      Bodies.rectangle(-offset, 300, 50.5, 600.5 + 2 * offset, options)
    ]);

    /**
    * 创建一个新的复合材料,其中包含在网格排列中的回调中创建的实体。
    * 此功能使用身体的边界来防止重叠
    * stack 堆栈  (x,y,列,行,左右间距,上下间距) 
    */
    var stack = Composites.stack(20, 20, 10, 4, 0, 0, function (x, y) {
      if (Common.random() > 0.35) {
        return Bodies.rectangle(x, y, 64, 64, {
          render: {
            strokeStyle: '#ffffff',
            sprite: {
              texture: box
            }
          }
        });
      } else {
        return Bodies.circle(x, y, 46, {
          density: 0.0005,
          frictionAir: 0.06,
          restitution: 0.3,
          friction: 0.01,
          render: {
            sprite: {
              texture: ball
            }
          }
        });
      }
    });

    Composite.add(world, stack);

    // 添加鼠标控制事件---------------------------------
    var mouse = Mouse.create(render.canvas),
      mouseConstraint = MouseConstraint.create(engine, {
        mouse: mouse,
        constraint: {
          stiffness: 0.2,
          render: {
            visible: false
          }
        }
      });

    Composite.add(world, mouseConstraint);

    // 保持鼠标与渲染同步
    render.mouse = mouse;
    // ---------------------------------

    // 使渲染视图适合场景
    // Render.lookAt(render, {
    //   min: { x: 0, y: 0 },
    //   max: { x: 800, y: 600 }
    // });
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容