Jump to content

call an external function with arg in another file


espace
 Share

Recommended Posts

hi,

assuming i have two files. I prefer work with separates files for a question of hierarchy and to understand more simply my code.

one file for my effect (like a animation for a text) and the game itself.

i would at a certain time invoke a function in my separate file with a argument in my game.js. The problem is that i don't know the good syntax to do this. Could you learn a little more about that ?

https://jsfiddle.net/espace3d/senvc2d2/
 

/////////////////////////////////////////////////////////////////////////////////////
//EFFECT.JS
// in a different file for example effect.js
var e ={}

function draw_e() {
e.print_name=function(name){
console.log(name)
}

return e

}

/////////////////////////////////////////////////////////////////////////////////////
//GAME.JS
// assuming this is my main file for example game.js
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { create: create });

var character
var utils // my external file

function create() {
character={}
character.name="teddy"

//declaring my variable who'is in a external file
utils=draw_e()

//this is what i'm looking for
character_subfunction=function(Fonction,name){
Fonction(name)
// i have also try this :
// () => Fonction(name)
// but that don't work
}

character_subfunction(utils.print,character.name)
//result must be : teddy but the error is Fonction is not a function
}

 

 

Link to comment
Share on other sites

You're a little way off there, although, from the code, its pretty tough to work out what you're trying to do.

If you want a module system, use a proper one. There is one coming for the browser which will follow commonJS spec, the syntax will differ slightly but it'll be basically the same as the one used by node, so any node tutorials regarding modularisation will be of use. You can use Browserify, Webpack, Rollup or SystemJS (there will be others) to create a browser-ready bundle from your modular code.

Or, you can go old school and use some sort of namespacing to try to mitigate global leak and simply include all those files in your html (or, even better, concatenate and, if necessary, minify/uglify them and include just the one file).

// Utils.js

window.AB = window.AB || {}

AB.utils.capitalise = function capitalise (word) {
  return word.replace(/^./, ch => ch.toUpperCase())
}

// Game.js

window.AB = window.AB || {}

var game = new Phaser.Game(800, 600 /*...*/)

function create () {
  var character = {}
  character.name = AB.utils.capitalise('dave')

  /* do something with character */
}

In this example we have created a namespace, AB (maybe our game is called Action Blast?), and we are applying most of our code to this namespace. We don't have to, but, we might want to include other third-party code that also leaks globals and we don't want awkward conflicts so we'll leak just the one, note also that I've explicitly tacked our namespace on to window, this is deliberate so that its clear what we are doing. Leaking globals isn't great so we need to call out what we are doing. Note also that with a proper module system you needn't leak anything to the window.

Our html includes `utils.js` first and then `game.js` although, this is the other awkward thing about not using a proper module system, inclusion order becomes very important. We have mitigated it a little by using `window.AB = window.AB || {}` but its still a concern, particularly for any consumer of our functions.

I'd also suggest poking through the Intro files for Phaser and the Pixi library, both have standalone browser builds that use multiple source files, they are both great examples of how to do this, although more complex than these examples.

I guess my point would be, learn how to use Browserify or Webpack, particularly as you sound serious about modularisation, and forget about this awkward way of doing things.

Link to comment
Share on other sites

hi mattstyle,

Thanks for this explanation. i'm going to study browserify, it look great. there is some good videos tutorials about that.

 

unless I am mistaken there is error in your example file, why do you use utils ? i make this without utils and with my previous snippet and it works according to your specifications.

https://jsfiddle.net/82gwzgme/

 

Link to comment
Share on other sites

Yes, you are correct, I tried to add a method to the utils object without first declaring the utils object. Doh!

I added utils in to show that the utils.js file is responsible for the utils object which it then tacks on to the application namespace (or doesn't, in this case, oops!). You get the theory though, so thats good.

I'd still recommend browserify over other methods, its simpler, it tends to just work out of the box and it has many many plugins and presets that handle a drastic amount of use-cases. The only things I've found that are awkward are hot-module-reloading, which is possible, but awkward (it only works with some specific projects anyway). Webpack, rollup et al extoll the virtues of tree-shaking, but, in practise, using techniques to reduce bundle sizes produce minimal gains and break many existing modules, although keep checking back with this because its a real concern for developers working with browsers and it's up to modules to support ways of doing this. (just as an example, I've been testing browserify and rollup, mainly for tree-shaking capability using lodash as a large module to target specific parts of, rollup gave me a fairly small improvement on build size, roughly 5%, but broke some other stuff, whereas I could use a babel plugin with lodash that shaved off well over 60% from the build by performing its own tree-shaking with zero downsides, also note that lodash exposes each method as its own module so with either solution that would have reduced the bundle size even further). 

Link to comment
Share on other sites

6 hours ago, mattstyles said:

Oh, something I should mention, browserify (or any of the other module systems) don't work with Phaser, a couple of people have tried but its non-trivial changes to make it work nicely, just include Phaser as a global on the page and run browserify/whatever over the rest of your code.

Could you tell me a little more about that...it would be nice if you could post à short snippet about that...

Link to comment
Share on other sites

Browserify isn't a massive fan of globals, you have to do a little bit of config to get it playing nicely with globals (although, strictly, nothing in JS can stop you from accessing global variables), it basically wraps all of your modules in closures and references them by id when you want them, thus eliminating globals from your bundle.

I think the crux of the problem with using Phaser with browserify is that Phaser relies on a custom build of Pixi (currently) and it expects things to be global, when they aren't it can't do its job. There are custom builds of Phaser and there definitely is a way to change it to make it happen, but, its non-trivial, a few people have tried to require Phaser with a module system and failed (as far as I know) and, given that there is fairly active development in Lazer, and now Phaser 3 as well, these things might well be solved and we can just import Phaser from a module repository, such as npm, until then, the best solution is to just include the script in the page and be confident that the Phaser global will be available when you need it. It's no big deal for one module/framework, or even a few, but its a problem that can grow and get out of hand quickly so you don't, generally, want to be leaking too many globals.

Link to comment
Share on other sites

Its not much used and its quite complex, but, it is a crucial piece of the JS ecosystem as it is likely to form part of the puzzle when modules hit natively in the browser. By all means read up on it, but its far more complex to use than something like browserify, rollup or webpack. The issue it solves is that of delivery, systemjs allows asynchronous loading of assets, which is great as it means proper modularisation in a manner which makes sense to a browser i.e. load only what you need for initial render and save loading more stuff until when you need it. Browserify, rollup and webpack traditionally create single bundles (although they can be made to be smarter) that means that you load everything all in one hit, even if you don't need parts of it until later. Whilst the asynchronous pattern is very attractive, it makes life significantly more difficult and in practise its much easier just to create a single bundle, have you html load that entire bundle and only worry about it when that bundle becomes too large to load happily, the crux here being that you may never reach that stage where your bundle is too large so why bother with the additional complexity if the gains are marginal?

I haven't seen Phaser work with any module system, it likes to be global in the page (something to do with how it loads Pixi I think), given that it is a large framework (in terms of features) I wouldn't see this as a real issue and I'd strongly recommend just living with it. Load Phaser into the page, then load your module code, two scripts is unlikely to break the bank.

Use a module system to bundle up your code, any one you like and leave Phaser as a global.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...