1

this would be my first question ever on stackoverflow, hope this goes well. I've been working on a game (using corona SDK) and I used Node.js to write a small little server to handle some chat messages between my clients, no problems there. Now I'm working on expanding this little server to do some more, and what I was thinking to do is create an external file (module) that will hold an object that has all the functions and variables I would need to represent a Room in my games "Lobby", where 2 people can go into to play one against the other, and each time I have 2 players ready to play, I would create a copy of this empty room for them, and then initialize the game in that room. So I have an array in my main project file, where each cell is a room, and my plan was to import my module into that array, and then I can init the game in that specific "room", the players would play, the game will go on, and all would be well... but... my code in main.js:

var new_game_obj = require('./room.js');

games[room_id] = new_game_obj();

games[room_id].users = [user1_name,user2_name];

Now, in my room.js, I have something of the sort:

var game_logistics = {};

game_logistics.users = new Array();

game_logistics.return_users_count = function(){
    return game_logistics.users.length;
}

module.exports = function() {
    return game_logistics;
}

So far so good, and this work just fine, I can simply go:

games[room_id].return_users_count()

And I will get 0, or 1, or 2, depending of course how many users have joined this room. The problems starts once I open a new room, since Node.js will instance the module I've created and not make a copy of it, if I now create a new room, even if I eliminated and/or deleted the old room, it will have all information from the old room which I've already updated, and not a new clean room. Example:

var new_game_obj = require('./room.js');

games["room_1"] = new_game_obj();
games["room_2"] = new_game_obj();

games["room_1"].users = ["yuval","lahav"];

_log(games["room_1"].return_user_count()); //outputs 2...
_log(games["room_2"].return_user_count()); //outputs 2...

Even doing this:

var new_game_obj = require('./room.js');
games["room_1"] = new_game_obj();

var new_game_obj2 = require('./room.js');
games["room_2"] = new_game_obj2();

games["room_1"].users = ["yuval","lahav"];

_log(games["room_1"].return_user_count()); //outputs 2...
_log(games["room_2"].return_user_count()); //outputs 2...

Gives the same result, it is all the same instance of the same module in all the "copies" I make of it. So my question as simple as that, how do I create a "clean" copy of my original module instead of just instancing it over and over again and actually have just one messy room in the end?

Yuval
  • 149
  • 1
  • 1
  • 11

1 Answers1

1

What you're doing is this (replacing your require() call with what gets returned);

var new_game_obj = function() {
    return game_logistics;
}

So, every time you call new_game_obj, you return the same instance of game_logistics.

Instead, you need to make new_game_obj return a new instance of game_logistics;

// room.js
function Game_Logistics() {
    this.users = [];

    this.return_users_count = function(){
        return this.users.length;
    };
}

module.exports = function() {
    return new Game_Logistics(); 
}

This is quite a shift in mentality. You'll see that we're using new on Game_Logistics in module.exports to return a new instance of Game_Logistics each time it's called.

You'll also see that inside Game_Logistics, this is being used everywhere rather than Game_Logistics; this is to make sure we're referencing the correct instance of Game_Logistics rather than the constructor function.

I've also capitalized your game_logistics function to adhere to the widely-followed naming convention that constructor functions should be capitalized (more info).

Taking advantage of the prototype chain in JavaScript is recommended when you're working with multiple instances of functions. You can peruse various articles on "javascript prototypical inheritance* (e.g. this one), but for now, the above will accomplish what you need.

Matt
  • 74,352
  • 26
  • 153
  • 180
  • 1
    Yep, learn how to properly use the `new` keyword and write "proper" javascript classes rather than object literals. Check out [this article on javascript classes](http://www.phpied.com/3-ways-to-define-a-javascript-class/) for some good discussion on the options available to you and what makes them different. – Jason Apr 04 '14 at 14:39
  • Thanks for the information, this seems to work, I'm sorry my javascript is not "proper" enough, I'm from actionscript/lua/php background, and although I used to dab in javascript, html and xml in past, I was never an "expert", but I learn as I go with the help of some good people, thanks for the links, I will read those ASAP! :) – Yuval Apr 04 '14 at 14:50
  • 1
    @Yuval: No need to apologize, everyone was "new" once :). – Matt Apr 04 '14 at 14:55
  • @Jason thanks for the link to the article, it was very informative, short and to the point, and gave me just the information I was missing. – Yuval Apr 05 '14 at 09:25
  • Yep, it helped me out too, when I was learning this stuff. I started out writing my objects as literals, just like you did in your original code, I didn't fully understand how to use the prototyping strategy or why I would ever write something complex enough in javascript to require it (before I started with node). There's reasons to use both methods, but it's become clearer to me over time that the prototyping strategy was more useful more of the time. – Jason Apr 07 '14 at 14:06