与 matter-js 一同使用

我们可以将2D物理引擎 matter-js 与spritejs一同使用。

物理引擎 - 图1

  1. // module aliases
  2. const {Engine, World, Composites, Composite, Bodies} = Matter;
  3. // create an engine
  4. const engine = Engine.create();
  5. // engine.world.gravity.scale = 0; //turn off gravity (it's added back in later)
  6. const stackA = Composites.stack(100, 100, 6, 6, 0, 0, (x, y) => {
  7. return Bodies.rectangle(x, y, 15, 15, {
  8. // friction: 0,
  9. // frictionAir: 0,
  10. // frictionStatic: 0,
  11. // restitution: 1
  12. });
  13. });
  14. const wall = Bodies.rectangle(400, 300, 500, 20, {
  15. isStatic: true,
  16. });
  17. World.add(engine.world, [stackA, wall]);
  18. const offset = 5;
  19. World.add(engine.world, [
  20. Bodies.rectangle(400, -offset, 800 + 2 * offset, 50, {
  21. isStatic: true,
  22. }),
  23. Bodies.rectangle(400, 600 + offset, 800 + 2 * offset, 50, {
  24. isStatic: true,
  25. }),
  26. Bodies.rectangle(800 + offset, 300, 50, 600 + 2 * offset, {
  27. isStatic: true,
  28. }),
  29. Bodies.rectangle(-offset, 300, 50, 600 + 2 * offset, {
  30. isStatic: true,
  31. }),
  32. ]);
  33. const scene = new Scene('#simple-demo', {viewport: ['auto', 'auto'], resolution: [800, 600]});
  34. const fglayer = scene.layer('fglayer');
  35. const blocks = [];
  36. function render() {
  37. Engine.update(engine, 16);
  38. const bodies = Composite.allBodies(engine.world);
  39. // console.log(bodies)
  40. for(let i = 0; i < bodies.length; i++) {
  41. const body = bodies[i],
  42. {position, angle} = body;
  43. const pos = [
  44. Math.round(position.x * 10) / 10,
  45. Math.round(position.y * 10) / 10,
  46. ],
  47. rotate = Math.round(180 * angle * 10 / Math.PI) / 10;
  48. let block = blocks[i];
  49. if(!block) {
  50. const {min, max} = body.bounds;
  51. block = new Sprite();
  52. block.attr({
  53. anchor: 0.5,
  54. size: [max.x - min.x, max.y - min.y],
  55. pos,
  56. rotate,
  57. bgcolor: body.render.fillStyle,
  58. });
  59. blocks[i] = block;
  60. fglayer.append(block);
  61. } else {
  62. block.attr({
  63. pos,
  64. rotate,
  65. });
  66. }
  67. }
  68. window.requestAnimationFrame(render);
  69. }
  70. render();

Matter.Render

上面的例子我们可以使用原生的 matter-js,另外我们提供了一个spritejs扩展 sprite-extend-matter,它重写了Matter.Render,这样可以快速使用内置的Render来渲染对象。

物理引擎 - 图2

  1. const scene = new Scene('#render-demo', {viewport: ['auto', 'auto'], resolution: [800, 600]});
  2. const fglayer = scene.layer('fglayer');
  3. const {Engine, World, Render, Runner, Common, Composites, Mouse, MouseConstraint, Bodies} = Matter;
  4. // create engine
  5. const engine = Engine.create(),
  6. world = engine.world;
  7. // create renderer
  8. const render = Render.create({
  9. layer: fglayer,
  10. engine,
  11. options: {
  12. showAngleIndicator: true,
  13. background: '#fff',
  14. wireframes: false,
  15. },
  16. });
  17. Render.run(render);
  18. // create runner
  19. const runner = Runner.create();
  20. Runner.run(runner, engine);
  21. // add bodies
  22. const stack = Composites.stack(20, 20, 10, 5, 0, 0, (x, y) => {
  23. let sides = Math.round(Common.random(1, 8));
  24. // triangles can be a little unstable, so avoid until fixed
  25. sides = (sides === 3) ? 4 : sides;
  26. // round the edges of some bodies
  27. let chamfer = null;
  28. if(sides > 2 && Common.random() > 0.7) {
  29. chamfer = {
  30. radius: 10,
  31. };
  32. }
  33. const width = 64;
  34. switch (Math.round(Common.random(0, 1))) {
  35. case 0:
  36. if(Common.random() < 0.6) {
  37. return Bodies.rectangle(x, y, Common.random(25, 50), Common.random(25, 50), {chamfer});
  38. } if(Common.random() < 0.8) {
  39. return Bodies.rectangle(x, y, Common.random(80, 120), Common.random(25, 30), {chamfer});
  40. }
  41. return Bodies.rectangle(x, y, width, width, {
  42. chamfer,
  43. render: {
  44. sprite: {
  45. attrs: {
  46. textures: {
  47. src: 'https://p5.ssl.qhimg.com/t01bd0523f7bc9241c2.png',
  48. srcRect: [32, 32, 64, 64],
  49. },
  50. size: [width, width],
  51. },
  52. },
  53. },
  54. });
  55. case 1:
  56. return Bodies.polygon(x, y, sides, Common.random(25, 50), {chamfer});
  57. default:
  58. break;
  59. }
  60. });
  61. World.add(world, stack);
  62. World.add(world, [
  63. // walls
  64. Bodies.rectangle(400, 0, 800, 50, {isStatic: true}),
  65. Bodies.rectangle(400, 600, 800, 50, {isStatic: true}),
  66. Bodies.rectangle(800, 300, 50, 600, {isStatic: true}),
  67. Bodies.rectangle(0, 300, 50, 600, {isStatic: true}),
  68. ]);
  69. // add mouse control
  70. const mouse = Mouse.create(render.canvas),
  71. mouseConstraint = MouseConstraint.create(engine, {
  72. mouse,
  73. constraint: {
  74. stiffness: 0.2,
  75. render: {
  76. visible: false,
  77. },
  78. },
  79. });
  80. World.add(world, mouseConstraint);
  81. // keep the mouse in sync with rendering
  82. render.mouse = mouse;