pixijs / particle-emitter

A particle system for PixiJS
http://pixijs.io/particle-emitter/docs
MIT License
796 stars 125 forks source link

Question: How to properly import pixi-particles? #123

Closed KamiFightingSpirit closed 4 years ago

KamiFightingSpirit commented 4 years ago

I was using a CDN via:

<script src="https://cdn.jsdelivr.net/npm/pixi-particles-latest@3.2.0/dist/pixi-particles.js"></script>

However, this is throwing the following error: "PixiJS Deprecation Warning: PIXI.ticker.shared instance has moved to PIXI.Ticker.sharedDeprecated since v5.0.0"

I have my "pixi-particles-master" folder downloaded but I am not sure what I need to grab from there?

themoonrat commented 4 years ago

That's not an error that stops anything from working, just a deprecation error. The latest is https://cdn.jsdelivr.net/npm/pixi-particles@4.2.0/lib/pixi-particles.js which might have solved those deprecation issues

KamiFightingSpirit commented 4 years ago

edit sorry posted the wrong error Thanks for reply! That CDN is giving me a pixi-particles.js:10 Uncaught ReferenceError: exports is not defined at pixi-particles.js:10

Basically, I am trying to setup a particle emitter based off the example files, I have been trying all morning (noob here) and not sure what to do now.... I got it working under pixiv4 but converting to v5 and the latest pixi-particle has proven impossible. Could you possible help?

My PARTICLE FILE IS:

<html class="no-js">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <title>Particle Container Performance Tester</title>
    <meta name="description" content="smoke blast" />
    <link rel="stylesheet" href="css/main.css" />

    <!-- Required dependencies -->
    <script src="./js/pixi.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/pixi-particles@4.2.0/lib/pixi-particles.js"></script>
    <!-- Example scaffolding -->
    <script src="js/ParticleExample.js"></script>
  </head>
  <body>
    <div id="framerate"></div>
    <div id="particleCount"></div>
    <div id="instructions">Click Anywhere</div>
    <canvas id="stage" width="400" height="400"></canvas>
    <script>
      // See js/ParticleExample.js for actual setup
      new ParticleExample(
        // The image to use
        ["images/CartoonSmoke.png"],

        // Emitter configuration, edit this to change the look
        // of the emitter
        {
          alpha: {
            start: 0,
            end: 1
          },
          scale: {
            start: 0.01,
            end: 0.1,
            minimumScaleMultiplier: 0.001
          },
          color: {
            start: "#ffffff",
            end: "#bbe1f0"
          },
          speed: {
            start: 100,
            end: 200,
            minimumSpeedMultiplier: 1
          },
          acceleration: {
            x: 0,
            y: 1000
          },
          maxSpeed: 0,
          startRotation: {
            min: 0,
            max: 0
          },
          noRotation: false,
          rotationSpeed: {
            min: 0,
            max: 0
          },
          lifetime: {
            min: 0.5,
            max: 1
          },
          blendMode: "color_burn",
          frequency: 0.001,
          emitterLifetime: -1,
          maxParticles: 1000,
          pos: {
            x: 0,
            y: 0
          },
          addAtBack: false,
          spawnType: "ring",
          spawnCircle: {
            x: 0,
            y: 0,
            r: 100,
            minR: 50
          }
        },
        null,
        true
      );
    </script>
  </body>
</html>

AND MY SCAFFOLDING IS:

(function(window) {
    console.log("hello");
    /**
     *  Basic example setup
     *  @class ParticleExample
     *  @constructor
     *  @param {String[]} imagePaths The local path to the image source
     *  @param {Object} config The emitter configuration
     *  @param {null|"path"|"anim"} [type=null] Particle type to create.
     *  @param {boolean} [useParticleContainer=false] If a ParticleContainer should be used instead of a Container.
     *  @param {boolean} [stepColors=false] If the color settings should be manually stepped.
     */
    var ParticleExample = function(
        imagePaths,
        config,
        type,
        useParticleContainer,
        stepColors
    ) {
        var canvas = document.getElementById("stage");
        // Basic PIXI Setup
        var rendererOptions = {
            view: canvas
        };
        /*var preMultAlpha = !!options.preMultAlpha;
        if(rendererOptions.transparent && !preMultAlpha)
            rendererOptions.transparent = "notMultiplied";*/
        var stage = new PIXI.Container(),
            emitter = null,
            renderer = PIXI.autoDetectRenderer(
                canvas.width,
                canvas.height,
                rendererOptions
            ),
            bg = null;

        var framerate = document.getElementById("framerate");
        var particleCount = document.getElementById("particleCount");

        // Calculate the current time
        var elapsed = Date.now();

        var updateId;

        // Update function every frame
        var update = function() {
            // Update the next frame
            updateId = requestAnimationFrame(update);

            var now = Date.now();
            if (emitter) emitter.update((now - elapsed) * 0.001);

            framerate.innerHTML = (1000 / (now - elapsed)).toFixed(2);

            elapsed = now;

            if (emitter && particleCount)
                particleCount.innerHTML = emitter.particleCount;

            // render the stage
            renderer.render(stage);
        };

        // Resize the canvas to the size of the window
        window.onresize = function(event) {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            renderer.resize(canvas.width, canvas.height);
            if (bg) {
                //bg is a 1px by 1px image
                bg.scale.x = canvas.width;
                bg.scale.y = canvas.height;
            }
        };
        window.onresize();

        // Preload the particle images and create PIXI textures from it
        var urls,
            makeTextures = false;
        if (imagePaths.spritesheet) urls = [imagePaths.spritesheet];
        else if (imagePaths.textures) urls = imagePaths.textures.slice();
        else {
            urls = imagePaths.slice();
            makeTextures = true;
        }
        urls.push("images/bg.png");
        var loader = PIXI.Loader.shared;
        for (var i = 0; i < urls.length; ++i) loader.add("img" + i, urls[i]);
        loader.load(function() {
            bg = new PIXI.Sprite(PIXI.Texture.from("images/bg.png"));
            //bg is a 1px by 1px image
            bg.scale.x = canvas.width;
            bg.scale.y = canvas.height;
            bg.tint = 0x000000;
            stage.addChild(bg);
            //collect the textures, now that they are all loaded
            var art;
            if (makeTextures) {
                art = [];
                for (var i = 0; i < imagePaths.length; ++i)
                    art.push(PIXI.Texture.from(imagePaths[i]));
            } else art = imagePaths.art;
            // Create the new emitter and attach it to the stage
            var emitterContainer;
            if (useParticleContainer) {
                emitterContainer = new PIXI.ParticleContainer();
                emitterContainer.setProperties({
                    scale: true,
                    position: true,
                    rotation: true,
                    uvs: true,
                    alpha: true
                });
            } else emitterContainer = new PIXI.Container();
            stage.addChild(emitterContainer);
            window.emitter = emitter = new PIXI.particles.Emitter(
                emitterContainer,
                art,
                config
            );
            if (stepColors)
                emitter.startColor = PIXI.particles.ParticleUtils.createSteppedGradient(
                    config.color.list,
                    stepColors
                );
            if (type == "path")
                emitter.particleConstructor = PIXI.particles.PathParticle;
            else if (type == "anim")
                emitter.particleConstructor = PIXI.particles.AnimatedParticle;

            // Center on the stage
            emitter.updateOwnerPos(window.innerWidth / 2, window.innerHeight / 2);

            // Click on the canvas to trigger
            canvas.addEventListener("mouseup", function(e) {
                if (!emitter) return;
                emitter.emit = true;
                emitter.resetPositionTracking();
                emitter.updateOwnerPos(e.offsetX || e.layerX, e.offsetY || e.layerY);
                console.log();
            });

            // Start the update
            update();

            //for testing and debugging
            window.destroyEmitter = function() {
                emitter.destroy();
                emitter = null;
                window.destroyEmitter = null;
                //cancelAnimationFrame(updateId);

                //reset SpriteRenderer's batching to fully release particles for GC
                if (
                    renderer.plugins &&
                    renderer.plugins.sprite &&
                    renderer.plugins.sprite.sprites
                )
                    renderer.plugins.sprite.sprites.length = 0;

                renderer.render(stage);
            };
        });
    };

    // Assign to global space
    window.ParticleExample = ParticleExample;
})(window);
andrewstart commented 4 years ago

You want a slightly different URL: https://cdn.jsdelivr.net/npm/pixi-particles@4.2.0/lib/pixi-particles.js is what you currently have, it is the Node/CommonJS module file(which is why it is expecting exports to exist). https://cdn.jsdelivr.net/npm/pixi-particles@4.2.0/dist/pixi-particles.js is what you want (note the dist instead of lib). It is the web bundle that creates a global PIXI.particles namespace.

KamiFightingSpirit commented 4 years ago

Thanks! That got rid of the errors but as expected based off the moonrat's response it hasn't fixed the underlying issue. Is there an updated basic example scaffolding file that works? I am assuming it is an error in one of the other updates that I needed to make when going from v4 => v5.

andrewstart commented 4 years ago

Like themoonrat said, it isn't an error but a deprecation warning - the code will run fine. The warning shouldn't be happening though, unless the value of PIXI.VERSION from whatever build of PIXI you are loading is a weird value that is parsing as a valid number but also less than 5.

KamiFightingSpirit commented 4 years ago

Did you test it and if so did it work for you? I am so confused now as I get the framerate tracker in the top left but nothing else. Worked just fine with V4 and only V5+ is not rendering. I am using:

* pixi.js - v5.2.1
 * Compiled Tue, 28 Jan 2020 23:37:37 UTC

Just downloaded it again to make sure it wasn't something with the file as well as confirmed it via console.log(PIXI.VERSION) I am ONLY using the pixi.js file from pixi (not sure if there are other dependencies that I should include).

andrewstart commented 4 years ago

Ah, your current issue is a duplicate of https://github.com/pixijs/pixi-particles/issues/120 - the example code is built specifically for PIXI v4, and doesn't run on v5 due to changes with renderer creation.

KamiFightingSpirit commented 4 years ago

You are so the man! This was almost my entire day struggling with this and finally having an answer is such a breathe of fresh air. Thank you!

KamiFightingSpirit commented 4 years ago

Issue has been answered

KamiFightingSpirit commented 4 years ago

How should I setup the test file in order for it to run? I was using:

python -m SimpleHTTPServer 4000

However, this is causing an issue with node importing via require. Reading some responses on StackOverflow I think I would have to change the way I setup my server? Is that correct?

andrewstart commented 4 years ago

If you are hosting the example on a server, I am confused as to where node importing is coming in.

KamiFightingSpirit commented 4 years ago

The test file has a required statement so I am getting an error which reads: Uncaught ReferenceError: require is not defined at index.html:13

All that I did so far was transcompile the typescript file via tsc and then tried run on the python SimpleHTTPServer... Not sure where I am going wrong. What exactly do I need to do or read in order to understand how to make this work, this has unfortunately been incredibly difficult as someone new...

andrewstart commented 4 years ago

Sounds like you picked the wrong test for an example - pixi-v5-module is the Node importing test, pixi-v5-iife is the HTML script loading test that you want.

KamiFightingSpirit commented 4 years ago

Thanks for all your assistance @andrewstart after coming back to this project I was able to get it to work. I would like to propose some edits (that I would gladly contribute myself if people think they are helpful), these edits would be to assist people who are noobies and are quickly trying to use the particles library. The edits would thus fall into the "lower barriers to entry" category.

Proposed Edits:

  1. Within the example folders, have instructions at the top to state what version of pixi.js the examples will work with. (avoids the conflict of people trying to get v4 examples working in v5)
  2. Within the examples folders - have instructions to get them working (avoids people having to puzzle through it themselves and they can instead follow a step-by-step guide)
  3. Already have the renderer.ts file in the examples folder in renderer.js (avoids people having to learn how to perform the conversion)

Thoughts?

andrewstart commented 4 years ago

The code in docs/examples/js/ParticleExample.js should definitely have comments, but the code in tests/*/renderer.ts are intended to be tests, rather than examples. For commenting, I would make it clear that the example only works in V4, point out that the renderer initialization is what only works in V4, and direct people towards the documentation for creating Renderers in the latest PixiJS examples/docs (rather than explain how to create a renderer in V5). V6 is not even planned yet, but I wouldn't want to have the same issue crop up because we didn't specify how to create a renderer in any given future version.