0

The title of the question may not be the best but here's the code I've written so far:

var menuState = {

    //state variables
   menuBttn: {
        x: _canvas.width/2, 
        y:_canvas.height/2, 
        img: imageArray[2], 
        over: false, 
        click: function() {
            changeState(2);
        }
    },

    preload: function () {

    },

    update: function(){
        surface.clearRect(0, 0, _canvas.width, _canvas.height);
        for (var i = 0; i < menuAssets; i++){
        surface.drawImage(//draw menuBttn);              
        }
    },

    exit: function(){

    },

};

What I want to do is essentially create a variable called menuButtn (which is an object) that only exists within menuState.

I thought I could do this by doing:

var menuState = {

        //state variables
       this.menuBttn = {
            x: _canvas.width/2, 
            y:_canvas.height/2, 
            img: imageArray[2], 
            over: false, 
            click: function(){
                changeState(2);
            }
        },
    }

This is the way it works in Phaser.io (a library for making games), but I'm trying to make my own game engine.

How do I go about it?

frei
  • 495
  • 3
  • 19
iansmathew
  • 367
  • 1
  • 3
  • 13
  • I don't know about *phaser*, but in a standard object literal you can't define a property name using `this.menuBttn`. I think you're expecting *this* to be the object you're assigning the literal to, which is incorrect. *this* is a parameter of an execution context, in global code it's the global object. It's set at runtime by how the function is called (or *bind*), not lexically (except for arrow functions, but they're irrelevant here). – RobG Jan 25 '17 at 02:55
  • @RobG I had a hinting that would be the case. Well, since that's out of the option do you have a way to declare a variable that exists only inside the scope of that one object/state *but* which can be shared between different properties of that object/state? – iansmathew Jan 25 '17 at 02:58
  • @RobG, wait are you saying that you cant do `obj = { this.subobjc = {...} }` ? Because I'm sure that's 100% valid and exactly how you are supposed to define objects that only are relevant to that context. In this case, `menuState` is available globally, but `menuBttn` wouldn't be available globally. – frei Jan 27 '17 at 06:27
  • @frei—it maybe valid for a syntax that is parsed by Phaser.js, but it's not valid javascript. See [*Self-references in object literal declarations*](http://stackoverflow.com/questions/4616202/self-references-in-object-literal-declarations) or [*Assigning the value of another key in javascript*](http://stackoverflow.com/questions/33535140/assigning-the-value-of-another-key-in-javascript) or [*Objects literal and 'this' in submodule pattern*](http://stackoverflow.com/questions/16766214/objects-literal-and-this-in-submodule-pattern). – RobG Jan 27 '17 at 09:49

3 Answers3

0

I think you're doing it right. The menu button only exists within the scope of the object you created, so other classes do not have access to menuBttn since it is inside of menuState. Using the this keyword is very smart as well.

The other option is to create a make_button function that creates a new button, and create it inside of the menuState object. It accomplishes the same thing.

frei
  • 495
  • 3
  • 19
  • The problem I've noticed in using the `this` keyword like I have is that the IDE shows an error saying " : expected". When I run the code in a browser, it doesn't show the same error but my code does not work. – iansmathew Jan 25 '17 at 02:51
  • Object's don't have a scope, execution contexts do. – RobG Jan 25 '17 at 02:58
  • @PixelProgrammer The error you described is because to assign to an object a variable and value you do not use an equal sign, you use a colon. In the part of your post where you say "I thought I could do this by doing:" change the equal sign to a colon and you should be good. – Ribs Jan 25 '17 at 03:27
  • @RobG oops, you're right about that. What I guess I meant to say is that if you define an object inside of an object it isn't accessible to outside objects unless you explicitly reference the parent object. – frei Jan 25 '17 at 04:27
0

You are probably looking for the "module pattern", which uses an immediately invoked function expression (IIFE) and closures to create "private" members, e.g.

var foo = (function() {
  
  // Private function
  function bar(text) {
    console.log(text);
  }
  
  // Private variable
  var private = 'initial value';
  
  // Object to assign to foo
  return { runBar: function(text) {
                     bar(text);
                   },
           setPrivate: function(value) {
                     private = value;
                   },
           getPrivate: function() {
                     return private;
                   }
          };
}());

console.log(foo.runBar('bar text')); // bar text
foo.setPrivate('new value');
console.log(foo.getPrivate());  // new value

There are lots of articles about this, start searching. ;-)

RobG
  • 142,382
  • 31
  • 172
  • 209
0
var menuState = (function () {
var menuBttn = {
    x: canvas.width / 2,
    y: canvas.height / 2,
    over: false,
    click: function () {
        console.log('clicked');
    }
};
var update = function () {
    console.log(menuBttn);
};
/* if you are in menuState scope then you can access menuBttn with out using menuState*/
console.log(menuBttn);
return{menuBttn: menuBttn, update: update};
})();

Doing it this way, like you have in your first example. This allows you to access menuBttn if you use "menuState.menuBttn" or if you wish to access menuBttn attributes. You can "menuState.menuBttn.x". Also you can't put single line comments in a function.

    surface.drawImage(//draw menuBttn);  

It breaks the function and will cause you an error.

Jonathon
  • 1
  • 3
  • This was the way I originally planned to go, however I ran into some issues which you can see here - http://stackoverflow.com/questions/41841512/why-cant-update-access-an-objects-img-properties?noredirect=1#comment70868556_41841512 – iansmathew Jan 25 '17 at 04:16
  • Updated my answer. Last code did not work as expected. – Jonathon Jan 25 '17 at 05:19