0

I have node.js emit serverGameData that is converted to clientGameData on the client side. In the initial stages I run a for loop to check for status changes in the positions listed in the menu. I don't think the why is really that important in this case but anyone has questions I will answer them.

the gamedata packet sent from node.js

serverGameData = {
    positions: {
        Captain: {
            taken: false,
            by: null
        },
        Helm: {
            taken: false,
            by: null
        },
        Weapons: {
            taken: false,
            by: null
        },
        Science: {
            taken: false,
            by: null
        },
        Engineering: {
            taken: false,
            by: null
        },
        Communications: {
            taken: false,
            by: null
        }
    }

The for loop ran in update() {}

        for (var key in clientGameData.positions) {
            var _pos = clientGameData.positions;

        // Replaces button with grayed out sprite if position is taken by another player
            if (_pos[key].taken && _pos[key].by != socket.id) {
                if (this.availablePositions[key]) {
                    var _x = this['button' + key].x;
                    var _y = this['button' + key].y;

                    this['button' + key].kill();
                    this['button' + key] = this.add.sprite(_x, _y, 'mainMenuAtlas', key.toLowerCase() + '_t');
                    this.availablePositions[key] = false;
                }
        // Converts sprite back to fully functional button
            } else if (!_pos[key].taken) {
                if (!this.availablePositions[key]) {
                    var _x = this['button' + key].x;
                    var _y = this['button' + key].y;

                    this['button' + key].kill();
                    console.log("pre key: " + key);
/************************** PROBLEM AREA START ***********************************/
                    this['button' + key] = this.add.button(_x, _y,
                        'mainMenuAtlas', function () { this.buttonSelect(key); }, this, key.toLowerCase(), key.toLowerCase(), key.toLowerCase());
                    this.availablePositions[key] = true;
                    console.log("post key: " + key);
/*************************** PROBLEM AREA END ************************************/
                }
            }
        }

I don't have problems with any of this code except the "problem area". When I console.log() the key...both times it puts out the proper value. It even puts out the proper value in the key.toLowerCase() however, the function I set up: this.buttonSelect(key) will take the value of the last key iterated in the for loop. In this case, Communications. If I switch the order on the server, though, it will reflect here. Whatever is last in the serverGameData and thus clientGameData will be put into that function.

If this is just something wonky with phaser I can accept that but I can't come up with a way to fix it.

Styles2304
  • 143
  • 1
  • 14
  • That's because your callback function is called sometime LATER, after the `for` loop has finished. You need to create a closure to capture the value of `key` uniquely for each iteration or use `let` appropriately. – jfriend00 Oct 16 '16 at 04:02
  • I don't really follow. I mean I somewhat understand what you're saying but every other instance of `key` works properly. The button is positioned properly, the correct image from the atlas is selected...but it puts the wrong value in the function that is called when the button is clicked. – Styles2304 Oct 16 '16 at 04:10
  • Do you understand that the click handler function is called a long time later and that the `for` loop has already finished running when that function is called? If so, you should understand why `key` has been overwritten by the time the click handler function is called. – jfriend00 Oct 16 '16 at 04:12
  • Here's a couple ways to solve it: http://stackoverflow.com/questions/11488014/asynchronous-process-inside-a-javascript-for-loop/11488129#11488129 and http://stackoverflow.com/questions/21487187/why-is-the-loop-assigning-a-reference-of-the-last-index-element-to/21487254#21487254 – jfriend00 Oct 16 '16 at 04:15
  • I guess I don't? The way I understand it is I'm creating a button right then, telling it to call the buttonSelect function when clicked. I'm not understanding why the value of key would change since I've created the button and moved on. I feel like I'm not understanding something fundamental here. Regardless, replace var key with let key did the trick but I would still like to understand the issue. – Styles2304 Oct 16 '16 at 04:17
  • You've moved on, but the callback references the variable `key` that your loop is still changing. So, by the time the callback is called sometime later, the value in `key` is different. – jfriend00 Oct 16 '16 at 04:18
  • Thanks, I appreciate the guidance. I don't know why it doesn't really click with me but I'll accept it and now I know. Sorry it's a duplicate...I didn't know enough about my issue to form a decent question that could generate results. – Styles2304 Oct 16 '16 at 04:21

0 Answers0