Jump to content

Problem with IIFE


BrunoHautenfaust
 Share

Recommended Posts

Hi, there! Newcomer here!  :)

  Last night I began exploring Phaser. First I wrote everything in one js file. Then I decided to use IIFEs to organize my code. But I stumbled upon a problem I don't know how to fix. I have player.js and main.js.

Player.js:

var hero = (function(){	var hero = {		init: function(){			hero = game.add.sprite(game.world.width / 2, 0, 'idle');   << ReferenceError			this.scale.setTo(0.6, 0.6);			game.physics.arcade.enable(this);			this.body.collideWorldBounds = true;		}	};	return hero;}());

And main.js has:

var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });........

The error I get(as some of you might already guess) is "Uncaught ReferenceError: game is not defined".

The only option I can think of so far is to instantiate another game in the player but that sounds completely wrong.  :wacko: I'm not too good with IIFEs and I find a perfect opportunity to understand them better while writing this game.

 

Thanks in advance!

 

Link to comment
Share on other sites

Err... how exactly?
What I tried now is this:

var hero = (function(parameter){	var hero = {		init: function(){			hero = parameter.add.sprite(parameter.world.width / 2, 0, 'idle');   << ReferenceError			this.scale.setTo(0.6, 0.6);			parameter.physics.arcade.enable(this);			this.body.collideWorldBounds = true;		}	};	return hero;}(game));

var h = Object.create(hero).init();

 

Passing the game to the IIFE itself. Doesn't do the trick. Then again, 'game' is still undefined.

 I was thinking about maybe doing some sort of property but I don't know.

EDITED.

Link to comment
Share on other sites

You're making an object called "hero" with one method, "init". The first line in "init" overrides the "hero" variable to be a sprite. Is that what you want? At the very least, "this" in the next line won't do what you want it to do; it won't be the sprite you just defined one line ago.

 

Why are you using IIFEs, here? Are you loading the script that defines hero after the one that defines your game?

Link to comment
Share on other sites

Err... how exactly?

What I tried now is this:

var hero = (function(parameter){	var hero = {		init: function(){			hero = parameter.add.sprite(parameter.world.width / 2, 0, 'idle');   << ReferenceError			this.scale.setTo(0.6, 0.6);			parameter.physics.arcade.enable(this);			this.body.collideWorldBounds = true;		}	};	return hero;}(game));

var h = Object.create(hero).init();

 

Passing the game to the IIFE itself. Doesn't do the trick. Then again, 'game' is still undefined.

 I was thinking about maybe doing some sort of property but I don't know.

EDITED.

In that case *I think* you should load main.js before Player.js or at least have phaser already initialized so that game holds a reference to a Phaser.Game object. You're probably passing game to hero when game is still undefined. 

 

Why are you using IIFEs?

 

EDIT: Ok I know how you can keep the IIFE and fix the error.

var hero = (function(){    var hero = {        init: function(game){             hero = game.add.sprite(game.world.width / 2, 0, 'idle'); << ReferenceError            this.scale.setTo(0.6, 0.6);            game.physics.arcade.enable(this);            this.body.collideWorldBounds = true;        }    };    return hero;}());

when you call hero.init()  you pass a reference to the game as an argument. hero.init(this.game) will work within a Phaser.State

Link to comment
Share on other sites

In that case *I think* you should load main.js before Player.js or at least have phaser already initialized so that game holds a reference to a Phaser.Game object. You're probably passing game to hero when game is still undefined. 

 

Why are you using IIFEs?

 

EDIT: Ok I know how you can keep the IIFE and fix the error.

var hero = (function(){    var hero = {        init: function(game){             hero = game.add.sprite(game.world.width / 2, 0, 'idle'); << ReferenceError            this.scale.setTo(0.6, 0.6);            game.physics.arcade.enable(this);            this.body.collideWorldBounds = true;        }    };    return hero;}());

when you call hero.init()  you pass a reference to the game as an argument. hero.init(this.game) will work within a Phaser.State

 

Hey, it did the trick! :D Thanks a lot! I didn't thought about passing 'game' in the init(). Because I thought that the parameter should be passed first somehow directly to the IIFE itself. And then somewhere inside of it.

 Now to answer your and drhayes' question as to why do I use IIFEs? Last month I was in a team project. We had to write a game in JavaScript and we used IIFEs. It seemed cool. Beside that, everyone says how we shouldn't pollute the global scope and encapsulate our code. So I figured - hey, I should start with clean coding right away! 

 But Phaser doesn't use IIFEs in general, does it? I mean, it supports them since it's JS but they're not obligatory. The Phaser editor and MightyEditor have separate files for each thing but there's no encapsulation there, right? Just random files all called in one html file. But is that ok, is it good practice?  :mellow:

Link to comment
Share on other sites

 But Phaser doesn't use IIFEs in general, does it? I mean, it supports them since it JS but they're not obligatory. The Phaser editor and MightyEditor have separate files for each thing but there's no encapsulation there, right? Just random files all called in one html file. But is that ok, is it good practice?  :mellow:

You are polluting the global scope. You have game and hero as global vars and if you add enemy, map, etc. you will keep adding global variables.

 

A different alternative, and I think the most popular one, is putting everything inside one global object so it works as a namespace and you create just one global var.

var MyGame = MyGame || {}; //Create the namespace if it doesn't exist already.MyGame.MyClass = function (arg1, arg2) {   //Every instance of MyClass will get a copy of whatever you declare here   //...};MyGame.MyClass.prototype.method1 = function (arg1, arg2) {   //This function is available to all instances of MyClass   //but it's created only once in memory};MyGame.MyClass.prototype.method2 = function (arg1, arg2) {   //Same as method1};

More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript

 

 

Of course this is javascript and there are many other ways to do it. 

Link to comment
Share on other sites

@in mono Typescript should never be an excuse not to learn proper javascript. You should learn how javascript works and what its strengths and weaknesses are(Douglas Crockford's videos are great for that) and then, with sufficient knowledge, you can decide if one of the tools that compiles to javascript is better for you than just writing plain js.

 

Phaser is more than a hundred lines of code and it's written in plain js. Lots of people come from Java or C# and find javascript confusing so rather than learning how the language works, they just use something that feels comfortable and familiar. If you can figure what is what in javascript then learn javascript before using a higher level tool. 

Link to comment
Share on other sites

Phaser is more than a hundred lines of code and it's written in plain js. Lots of people come from Java or C# and find javascript confusing so rather than learning how the language works, they just use something that feels comfortable and familiar. If you can figure what is what in javascript then learn javascript before using a higher level tool. 

 

That's what I've been told, too. This is why there's classical OOP and Prototype OOP in JavaScript. Where the later is advised because when you write in JS it would make sense to abide to its ways. Not that the Classical way won't work or is wrong. I guess it depends on the team preferences, knowledge and maybe time constraints.

 Now, I'm no pro at programming but the language I know best so far is C#. And writing in JS(even though I've been learning it for the past 3 months now) feels lighter yet weird. As if trying to hold a fish in your hands. Slippery and elusive.

 

Anyway, I'll mark the thread as solved. Thank you all for your help. :)

Link to comment
Share on other sites

@in mono Typescript should never be an excuse not to learn proper javascript. You should learn how javascript works and what its strengths and weaknesses are(Douglas Crockford's videos are great for that) and then, with sufficient knowledge, you can decide if one of the tools that compiles to javascript is better for you than just writing plain js.

 

Phaser is more than a hundred lines of code and it's written in plain js. Lots of people come from Java or C# and find javascript confusing so rather than learning how the language works, they just use something that feels comfortable and familiar. If you can figure what is what in javascript then learn javascript before using a higher level tool. 

 

Yes, I know it's possible to write good code in plain JavaScript as well (that's what TypeScript transpiles to after all), but I don't think it's feasible.

I'd rather spend time on actual game logic than dealing with prototypes and everything. I by no means know JavaScript inside out; I understand things well enough and still prefer working with TypeScript.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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