matter-js icon indicating copy to clipboard operation
matter-js copied to clipboard

Cannot Load Texture Onto Body in Gatsby React Component

Open metalogica opened this issue 4 years ago • 1 comments

This is a continuation from a theme first identified in 2017: https://github.com/liabru/matter-js/issues/497#issuecomment-519113260

I'm having trouble loading a sprite into a Matter JS enabled component inside of React within a Gatsby project.

The component loads fine when I set options: { wireframes: true }. Otherwise it just freezes when I set: { wireframes: false }

// create a renderer
        var render = Render.create({
            element: this.refs.avalanche,
            engine: engine,
            options: {
                width: 600,
                height: 600,
                showAngleIndicator: true,
                wireframes: false
            }
        });

         // add bodies
         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, 
                render: {
                    sprite: {  
                        texture: './spring.png'
                    }
                }
            });
        });

I have confirmed that the path to the PNG is working.

The example code below is a hybrid taken from the Avalanche and Sprites example projects on the Matter.js demo set.

The full component code is below.

import React, { Component } from 'react';
import Matter from 'matter-js';

class Avalanche extends Component {
    constructor(props) {
        super(props);
        this.state = {};
    }

    componentDidMount() {
        // module aliases
        var Engine = Matter.Engine,
            Render = Matter.Render,
            Runner = Matter.Runner,
            Composite = Matter.Composite,
            Composites = Matter.Composites,
            Common = Matter.Common,
            MouseConstraint = Matter.MouseConstraint,
            Mouse = Matter.Mouse,
            World = Matter.World,
            Bodies = Matter.Bodies;

        // create an engine
        var engine = Engine.create(),
            world = engine.world;

        // create a renderer
        var render = Render.create({
            element: this.refs.avalanche,
            engine: engine,
            options: {
                width: 600,
                height: 600,
                showAngleIndicator: true,
                wireframes: false
            }
        });

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

         // create runner
        var runner = Runner.create();
        Runner.run(runner, engine);

         // add bodies
         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, 
                render: {
                    sprite: {  
                        texture: './sprite.png'
                    }
                }
            });
        });
        
        World.add(world, stack);

        World.add(world, [
            Bodies.rectangle(200, 150, 700, 20, { isStatic: true, angle: Math.PI * 0.06 }),
            Bodies.rectangle(500, 350, 700, 20, { isStatic: true, angle: -Math.PI * 0.06 }),
            Bodies.rectangle(340, 580, 700, 20, { isStatic: true, angle: Math.PI * 0.04 })
        ]);

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

        World.add(world, mouseConstraint);

        // keep the mouse in sync with rendering
        render.mouse = mouse;

        // fit the render viewport to the scene
        Render.lookAt(render, Composite.allBodies(world));

        // wrapping using matter-wrap plugin
        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 }
            };
        }

    }

    render() {
        return <div ref="avalanche" />;
    }
};

export default Avalanche;

metalogica avatar Apr 28 '20 16:04 metalogica

I've discovered the cause of the bug.

The Composites.js library will only work if Render.options.wireframes=true.

There is no meaningful error message coming back from the library, but I've pasted the part of the code that leads to the issue.

    var render = Render.create({
      element: this.refs.scene,
      engine: engine,
      options: {
        width: 600,
        height: 600,
        wireframes: false
      }
    });

// the following code will break the app
    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, 
            render: {
                sprite: {  
                    texture: 'btcIcon.png',
                    xScale: 100,
                    yScale: 100
                }
            }
        });
    });

My current workaround is to create a lot of manual bodies with sprites and then just import them into the engine.

var ballA = Bodies.circle(210, 100, 30, { 
    restitution: 0.5, 
    friction: 0.00001,
    density: 0.001, 
    render: { 
        sprite: { 
            xScale: 0.1,
            yScale: 0.1, 
            texture: 'btcIcon.png'
        }
    } 
});
    var ballB = Bodies.circle(110, 50, 30, { 
        restitution: 0.5, 
        friction: 0.00001,
        density: 0.001, 
        render: { 
            sprite: { 
                xScale: 0.1, 
                yScale: 0.1, 
                texture: 'btcIcon.png' 
            }
        }
    });
    World.add(engine.world, [ballA, ballB]);

metalogica avatar May 04 '20 14:05 metalogica

Closing as it looks like you managed to solve this one, thanks for sharing.

liabru avatar Apr 02 '23 23:04 liabru