punkbit
punkbit

Reputation: 7717

Pixijs (or similar 2D WebGL/Canvas library): how to organise code?

I'm doing some studies using the Pixijs library, which I find amazing. I'll also have a look into Fabricjs, that seems to have a smaller footprint.

I've been working with Angularjs for some time now and I like conventions, instead of taking time in each project doing configuration and organizing code differently every time.

I would like to hear from some body who experienced Pixijs (or similar) with a framework to organise the code.

I understand that Angularjs is MVVM, but let me know about any tips or suggestion that you may think of?

I did some research this far and a few things came to my mind, such as Browserify (I do believe in convention instead of configuration like I've mentioned though and maybe this wouldn't be the best tool for me).

Upvotes: 2

Views: 979

Answers (1)

Patrick Fabrizius
Patrick Fabrizius

Reputation: 587

Kinda old question, but this is something I was looking for myself when starting out with PIXI, so I hope it could be of help to someone to get started.

I use the Revealing module pattern and separate the application into separate files/modules, and then use Browserify to create the application bundle. The HTML loads the app.js bundle which stems from the app.js source below.

index.html: Load your libs (PIXI et al) in <head> and then your app.js in the <body>.

app.js source example:

(function() {
  // App.js is the "bootstrap" that loads dependencies, takes care of pre-loading etc. 
  // I have a template of this which I copy into any new project and use as a checklist.

  var core = require("./core.js"); // Use a dummy module as application-wide namespace for easy access

  // Any external modules (f eg node modules) could go here 
  core.utilityLib = require("node-lib");

  // Application modules here
  core.myModule = require("./myModule.js");
  // core.myModule2 = require("./myModule2.js"); // .. you get the idea

  // Our main application module
  core.main = require("./main.js");

  // Init function to run when DOM/scripts have loaded
  var init = function() {

    // I have a generic screen module which sets up PIXI renderer depending on device compatibility using Modernizr (or weapon of choice). To keep it simple for the sake of the example, lets just create our renderer directly: 
    core.renderer = PIXI.autoDetectRenderer(screen.innerWidth,screen.innerHeight,{resolution:window.devicePixelRatio});

    // I also use a generic loader module that wraps PIXI.loader, taking a list of assets from a config file. Let's just call PIXI.loader directly for now:       
    PIXI.loader
      .add({name:"myasset",url:"/myasset.png"})
      .on('progress', loadProgressFunction)
      .once('complete',loadCompleteFunction) 
    })
    .load();
  }
  window.onload = init; // Tell browser to call init function when loaded

  // Optional loading progress bar
  var function = loadProgressCallback(e) {
  }

  // Call when mandatory assets has been loaded
  var loadCompleteFunction = function() {
    myModule.init(); // Init any mandatory modules, f eg to instantiate a player
    main.init(); // Tell our main application/game module that we're ready to do fancy stuff
  }

  // Method to make things move
  var animate = function() {
    // Send juice to modules that needs to be juiced (or use a ticker module on per-module basis).
    // core.main.animate(); 
    requestAnimationFrame(animate); 
  } 
  requestAnimationFrame(animate); // See comment below
}());

Comment: PIXI has an built-in requestAnimationFrame alias that takes care of fallback. If not using PIXI, you could use Paul Irish' gist.

core.js:

module.exports = {}; // Just a dummy object to create a module scope that all the modules 
// can use to communicate with each other, without running into circular reference problems

main.js:

// Main application/game module
module.exports = (function() {
  // Dependencies
  var core = require("./core.js"); // This way we can easily access all the necessary modules

  // Exports
  var exports = {}; // Everything put into this object will be "public"

  // Vars
  var stuff = 1; // Module vars

  exports.init = function() {
    // Application magic starts here :)
  }

  // Some other public method ...
  exports.publicMethod = function() {
  } 

  // Some private method
  var privateMethod = function() {
  }

  return exports; // Expose public functions to other modules
}());

Any additional modules can be organized in pretty much the same way as main.js.

Run browserify dev/app.js > html_root/app.js each time you want to "compile" your bundle (or create a Makefile, gulp-, node-, or webpack-script - whichever you prefer).

Upvotes: 1

Related Questions