为什么我的月饼会有物理效果?matter.js的使用

1,681 阅读5分钟

我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!

前言

这几天我闲着无聊,在看上网的时候发现了一个好玩的东西——matter.js

matter.js 介绍

matter.js 是一个用 JavaScript 编写的 2D 刚体物理引擎。该库可以帮助您轻松地在浏览器中模拟 2D 物理。它提供了许多功能,例如创建刚体并为它们分配物理属性(如质量、面积或密度)的能力。您还可以模拟不同类型的碰撞和力,例如重力和摩擦力。

matter.js 体验

我这里展示的效果只是这个引擎的一小部分

下面是官方的在线演示

matter.js在线演示: brm.io/matter-js/d…

matter.js 的使用

引入 matter.js

我们先要去将matter.js下载下来,然后再引入。

matter.js下载地址

如果不想要下载,可以引入在线链接

    <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>

使用 matter.js

HTML

HTML里面只需要引入matter.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 这里引入matter.js的在线地址 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
</head>
<body>
    
</body>
</html>

css

css里面其实里面可以什么都不用写,但是最好清除掉外边距和内边距,不然canavs与边框之间的空隙看着有些难受

* {
     margin: 0;
     padding: 0;
  }

写两行代码的时候可以写成 m0+p0 可以直接打出这两行代码

JavaScript

JavaScript就比较的复杂了

Engine 是引擎,引擎模块包含创建和操作引擎的方法

Render 是渲染器,基于HTML5画布的渲染器

Runner 是表演环境,演出舞台. Matter.js 中任何的物体都需要一个舞台/容器,而存放这些物体的地方,则称之为World(世界)

Bodies 可以用来创建各种形状的物体,用于创建各种形状的物体,物体必须添加到Wolrd中,然后由引擎运行世界

let Engine = Matter.Engine; // 创建引擎
let Render = Matter.Render; // 创建画布
let World = Matter.World; // 创建世界
let Bodies = Matter.Bodies; // 用于创建各种的物体

let engine = Engine.create();
//render(渲染器)将要渲染的物理引擎是上面的engine,而渲染的对象是html网页的body
let render = Render.create({ element: document.body, engine: engine ,
    options: {
        pixelRatio: 1, // 设置像素比 这个关系到性能
        background: '#76BAFE', // 设置全局背景颜色
        // 要设置背景颜色需要将线框模式为关
        wireframes: false, // 线框模
        // wireframeBackground: '#222'  线框模式时背景色
        // 要设置线框颜色需要打开线框模式
        // 但是打开之后就不能设置全局背景颜色了
    }
});

Bodies创建的方法

语法:

Bodies.rectangle = function(x, y, width, height, options)
// x,y 分别表示矩形中心点的坐标,坐标的原点(0,0)在 Canvas(画布)的左上角
// width,height 分别表示矩形的宽和高
// options:描述矩形的参数,是一个 json 对象

// rect = Bodies.rectangle(200, 100, 50, 50), // 矩形
// circle = Bodies.circle(300, 100, 25), // 圆
// polygon = Bodies.polygon(450, 100, 5, 25), // 多边形
// trapezoid = Bodies.trapezoid(590, 100, 50, 50, 3); // 梯形

我们创建两个物体

// 创建圆形
let round = Bodies.circle(100, 100, 50{
    density: .68, // 设置密度
    restitution: 1.5, // 设置物体的弹跳力
    render: {
        sprite: {
            // 设置贴图
            texture: '月饼.png'
        }
    }
})
// 创建矩形
let box = Bodies.rectangle(100, 150, 200, 200,{
    density: 1,
    restitution: 1.5,
    render: {
        sprite: {
            texture: 'https://momozi2006.github.io/qq%E5%A4%B4%E5%83%8F.png'
        }
    }
})
// 创建固定的物体
let ground = Bodies.rectangle(innerWidth / 2, innerHeight / 2, innerWidth * 2, 50, { 
    // isStatic设为true,表示物体静止
    isStatic: true 
})

创建物体之后将它添加进入世界

然后运行引擎和渲染器

World.add(engine.world, [round, box, ground]);// 将所有物体添加到世界中
Engine.run(engine);//运行引擎
Render.run(render);//运行渲染器

让我们来看一下现在的效果

1662969216922.gif 它这里面还有一个鼠标控制的事件

我们可以添加该事件

// Composites 模块包含用于创建具有常用配置(例如,堆栈和链)的复合实体的工厂方法
let Composite = Matter.Composite;
// MouseConstraint 用于创建鼠标约束的方法。鼠标约束用于允许用户交互,提供通过鼠标或触摸移动身体的能力。
let MouseConstraint = Matter.MouseConstraint;
// Mouse 模块包含用于创建和操作鼠标输入的方法
let Mouse = Matter.Mouse;

// 添加鼠标控制事件
let mouse = Mouse.create(render.canvas);
let mouseConstraint = MouseConstraint.create(engine, {
    mouse: mouse,
    constraint: {
        stiffness: 0.2,
        render: {
            visible: false
            }
        }
})
// 将世界添加进入鼠标事件
Composite.add(engine.world, mouseConstraint);
// 保持鼠标与渲染同步
render.mouse = mouse;

添加完事件之后就可以使用鼠标去拖拽这些物体

1662969499359.gif

看到这里你应该就学会简单的使用mater.js了

如果想要了解更多的使用方法,可以去看看官方的教程或者别的文章

总结

将引擎、渲染器、世界这些东西设置好,再创建一些想要的物体,最后再运行引擎和渲染器就大功告成了。其实这个东西还是挺简单的

以下是所有的代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./matter.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <script>
        window.onload = function () {
            let Engine = Matter.Engine;
            let Render = Matter.Render;
            let World = Matter.World;
            let Bodies = Matter.Bodies;

            let engine = Engine.create();
            let render = Render.create({
                element: document.body,
                engine: engine,
                options: {
                    pixelRatio: 1, // 设置像素比 这个关系到性能
                    background: '#76BAFE', // 设置全局背景颜色
                    // 要设置背景颜色需要将线框模式为关
                    wireframes: false, // 线框模式

                    // wireframeBackground: '#222'  线框模式时背景色
                    // 要设置线框颜色需要打开线框模式
                    // 但是打开之后就不能设置全局背景颜色了
                }
            })

            let Composite = Matter.Composite;
            let MouseConstraint = Matter.MouseConstraint;
            let Mouse = Matter.Mouse;

            let canvas = document.querySelector('canvas');
            canvas.width = innerWidth;
            canvas.height = innerHeight;


            let roundA = Bodies.circle(100, 100, 50, {
                density: .68, // 设置密度
                restitution: 1.5, // 设置弹力
                render: {
                    sprite: {
                        texture: '月饼.png'
                    }
                }
            })
            let boxA = Bodies.rectangle(100, 150, 200, 200, {
                density: 1,
                restitution: 1.5,
                render: {
                    sprite: {
                        texture: 'qq头像.png'
                    }
                }
            })
            World.add(engine.world, [roundA, boxA]);

            let ground = Bodies.rectangle(innerWidth / 2, innerHeight - 30, innerWidth * 2, 50, { isStatic: true });
            World.add(engine.world, [ground]);

            Engine.run(engine);
            Render.run(render);

            let mouse = Mouse.create(render.canvas);
            let mouseConstraint = MouseConstraint.create(engine, {
                mouse: mouse,
                constraint: {
                    stiffness: 0.2,
                    render: {
                        visible: false
                    }
                }
            })
            Composite.add(engine.world, mouseConstraint);
            render.mouse = mouse;
        }

    </script>
</body>

</html>

拓展

这是一个有关 render 的 options 对象:

width: 800,

height: 600,

pixelRatio: 1, 设置像素比

background: '#fafafa', 全局渲染模式时背景色

wireframeBackground: '#222', 线框模式时背景色

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 鼠标约束线