Jump to content
This forum will be closing down. Please move to the respective dedicated project forums.

JS OOP outside prototype function call ( scope )


metalslug87
 Share

Recommended Posts

Hi,

I'm new to OOP and Phaser, and I'm writing a simple game script to learn the OOP principles.

//main game function
battleLevel.prototype = 
{   

    battle:function () {      
        this.obj1 = {
          enterMonsterMenu: function() {
            return console.log('enterMonsterMenu');
          }
        };    
    },    

} /* end OOP prototype */



//external contructor
var Hero = function (warpX, warpY, game, name, life, mana, speed) {
  //some code
};

Hero.prototype.monsterSelectUp = function() {
    console.log('monsterSelectUp');
    //this.enterMonsterMenu();
    battleLevel.prototype.battle.call(obj1);
};
I want to access enterMonsterMenu() method by calling the monsterSelectUp() but I can't call it properly. What I am doing wrong ?  
Link to comment
Share on other sites

You're a little ways off currently.

In your snippet you have a few things that won't work with JS.

Have a look at the docs for how function.call works, the first parameter basically ends up setting scope for the function, so its probably not what you want here. It almost looks like you want to setup a static method to be called from the `battleLevel` object, but you can't really do that in JS.

It looks like you are setting up a hierarchy and you want to perform some level actions when the Hero reaches a certain point, for example, when the Hero reaches the 'end' of a level (stairs up or whatever). If this is the case you probably want to decouple the level from the hero (or, objects/actors within that level), you might be best off employing pub/sub (using event emitters) to separate out your bits of logic.

If you went the pub/sub route then the hero object would emit a request via an event, anything listening to that event would then update. It would end up something like:


// There are many many event emitter libraries to create basic pub/sub, some get quite complex
var events = new EventEmitter()

// Level Constructor
var BattleLevel = function() {
  // Do whatever you need here but bind up a listener to the event emitter
  // e.g.

  events.on( 'EndLevel', this.battle )
}

BattleLevel.prototype.battle = function() {
  // Do stuff
}

// Hero
var Hero = function() { ... }

Hero.prototype.monsterSelectUp = function() {
  events.emit( 'EndLevel' )
}

In this terse example your 2 objects are totally decoupled, neither gives a monkeys about the others implementation, they literally know nothing about each other. The Hero object initiates an event, and the BattleLevel object is able to hear that event and respond to it.

There are other methods for doing this that would allow you to specifically use BattleLevel.enterMonsterLevel directly from your Hero object but I think that is a bad way to start learning this stuff.

Link to comment
Share on other sites

Thank you for your replies :), my problem is mainly about the scope. I just need to know if it's possible to reach the method inside other prototype from inside another like here:

//main game function
battleLevel.prototype = 
{   

    battle:function () {      

          function test_function () {
            console.log('test 1');
          }

    },    

}
 /* end OOP prototype */



//external contructor
var Hero = function (warpX, warpY, game, name, life, mana, speed) {
  //some code
};

Hero.prototype.monsterSelectUp = function() {
    console.log('monsterSelectUp');

    // call somehow the test_function here
    test_function();
};

 

Link to comment
Share on other sites

I would suggest taking a look at some of the Phaser templates, if you look in the basic template you'll notice they use what's called a Namespace, with the use of this namespace it keep everything out of global space as well as making all functions  available to you from anywhere. There are a few other ways to do this and I would recommend following the links above posted by others.

// This is the namespace
var BasicGame = {};

//Notice how we use it to create the function
BasicGame.Boot = function () {
};

BasicGame.Boot.prototype = {

	test: function () {
		console.log('Test function');
	}
};


// Outside of boot 	
BasicGame.Sprite= function () {
};

BasicGame.Sprite.prototype = {
	// I can call test function from boot above here by using the namespace
	BasicGame.Boot.prototype.test();
};

//You can also use it in global space
BasicGame.Boot.prototype.test();

 

Link to comment
Share on other sites

It'd be better if you explained what you're trying to accomplish with the code so we can help you. The obj1 at the end is undefined and even if it were, you would end up adding an obj1 property to it that contains { enterMonsterMenu: function() { return console.log('enterMonsterMenu'); } } . It seems that you wanted to call a function instead.

Link to comment
Share on other sites

Your code snippet,

battleLevel.prototype = {   
  battle:function () {      
    function test_function () {
      console.log('test 1');
    }
  }    
}

You need to try reading up about closures and how JS deals with scope. Very simply, the `battle` function creates a new scope (if you come from a managed background this would add stuff to the stack which gets deallocated at the end of the function), nothing leaks out from this scope unless you employ some mechanism to do so, in this case you don't so `test_function` is entirely captured (or scoped) to that `battle` function.

There's no need to place it there though, you could also add your test_function to the prototype and access it via `this`.

battleLevel.prototype = {   
  battle:function () {      
    this.test_function()
  },

  test_function: function () {
    console.log('test')
  }    
}

This places it as a public method (they all are in JS) on the `battleLevel` object, once instantiated (convention dictates that it should be `BattleLevel`, capitalised):

var level = new battleLevel()
level.test_function()

Instantiate objects, accessing static methods on prototypes becomes impossible when you start mixing in data to your objects, without an instantiation those bits of data won't be initialised and ready for use (not a problem if you're attaching pure functions to the prototype).

I agree with @Noid though, it sounds like maybe you are heading down the wrong track to solve whichever problem you're actually solving, or, more accurately, maybe there is a better solution

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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