Jump to content

Access variable in state from class?


piotr
 Share

Recommended Posts

Hi,

I have classes for single objects (players, enemies, weapons) and states. One of those, playstate, manages interaction between the objects.

How do I access a variable e.g. this.killedEnemies in playstate from e.g. the enemy object?

play.js

var playState = {
	
create: function() { //some code... },

update: function() {

this.killedEnemies = 0;


},

};

enemy.js

var Enemy = function (game, position) {
 //some code...
};

Enemy.prototype = Object.create(Phaser.Sprite.prototype);
Enemy.prototype.constructor = Enemy;

Enemy.prototype.die = function() {
    this.killedEnemies += 1;
};

Thanks

Link to comment
Share on other sites

There are many resources on using objects in JS, you'll want to read up on it because they will go in to more detail than I will here.

var playState = {
  update: function () {
    this.killedEnemies = 0
  }
}

This code creates an object, which has one initial member, a function called update (there are no methods in JS, but you might want to call it a method as its a function). The update function, when called, mutates its scope to create a new member, usually the scope will be `playState` so the usual outcome is that after you call `update()` your playState object will have 2 members, a function `update` and variable `killedEnemies`.

To access it from elsewhere you just perform a standard member lookup to access the contents of the variable, which is waffle for saying do:

console.log(playState.killedEnemies)

Looks like `playState` is a global so it'll be available everywhere.

// Warning: anti-patterns ahead, here be dragons

var playState = {
  update: function () {
    this.killedEnemies = 0
  }
}

playState.update()

var Enemy = function (game, pos) {
  // ...
}

Enemy.prototype.die = function () {
  playState.killedEnemies += 1
}

var enemy = new Enemy(...)

enemy.die()

console.log(playState.killedEnemies)

This code will set up a global play state and add an enemy, it then calls a function on the enemy which mutates the playState object.

Note this is exceptionally bad code.

It'll work, but it creates tight coupling, very tight coupling in fact. Look up why this is generally a bad thing, then decide if you want to write your code like this. 

Link to comment
Share on other sites

Thanks a lot @mattstyles for the thorough answer and for calling out my bad code. I'm a hacking a prototype and I could come up with the right syntax.

I'd love to avoid bad code and tight coupling, should I look into implementing something like an observer pattern or is there a way to make it better in a simpler way?

Link to comment
Share on other sites

At least add a method to the state object that then manipulates the internal variable i.e.

var playstate = {
  killedEnemies: 0,
 
  addKilledEnemies: function () {
    this.killedEnemies += 1
  }
}

This still tightly couples your enemy class (which will call playstate.addKilledEnemies) but you have some flexibility in how you implement this functionality and you keep the logic in a better place. For example, suppose you want to clamp the amount of enemies killed to a specific maximum, with this solution you'd just do:

var playstate = {
  killedEnemies: 0,

  addKilledEnemy: function () {
    if (killedEnemies > 100) {
      return
    }

    this.killedEnemies += 1
  }
}

With the previous solution you'd have to make that change in every class that is able to add a killed enemy, whereas now each class just calls `playstate.addKilledEnemy()` and doesn't care about the implementation.

Another possible change here is that you change killedEnemies to be a different variable type, for example, you decide to use a boolean as you might only want to know if the user has killed any enemies at all (bare in mind JS has very few type primitives but this pattern is inherited from different languages and still has some value). So, just change your killedEnemies member and change the implementation within addKilledEnemy, none of your dependents (e.g. enemy class) care about this change, they just hit the addKilledEnemy function and don't care about anything else. This is creating a good API for your objects, one that allows you to make changes without having to touch multiple parts of your code base, and it is a key skill for a developer and one that is best learnt through experience (although there are many resources available out there). The principle being that the more you have to touch multiple parts of your app for any change the more frail it becomes, plus, dependency chains get complex fast and you really want to avoid going there.

This is following well-established OOP principles, if you get a book or find a good resource on object-oriented programming they should cover this in great detail fairly early on. Good learning for any programmer, even if you ultimately don't like OOP.

An observer/pub-sub would probably be better, and would allow multiple observers to respond to the action when an enemy is killed, but its up to you how you want to go.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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