How do I create a multiplayer "text game" ?

0 favourites
From the Asset Store
Fully commented source code/event sheet & sprites to create a space shooter game
  • Hello everyone,

    I need to create a game for a research project (in linguistics), but I don't know anything about creating games. I have been trying to use Construct 2 and I think it is a very interesting tool. Nevertheless, I am not sure if what I am trying to do is possible. Here is a description of what I am trying to do :

    I need to create a multiplayer game in which players use a chat box to communicate. So, I am currently using the multiplayer chat room example as a basis. The purpose of the game is to name creatures. So, basically, players see a picture of a creature, they enter the name they want in a textbox, and they click on a "vote" button. They can chat during the whole process to come to an agreement. Players get points according to the number of other players who gave the same answer as them. Players must be separated in different chatrooms, so they can't communicate with everybody, but only with the people in their room.

    For example, if there are 9 players, they are divided in 3 groups of 3 players. Each player can chat with the two others in the same group, but not with the 6 others from the other groups. However, they get points even if people from others groups gave the same name as they did.

    I know it doesn't sound like a very entertaining game, but remember it's for research purpose. So here is a list of the most important questions I have :

    • Does this project seem doable on Construct 2 ?
    • Is it possible to make the system do an action only when every player answered ? (waiting for everyone to vote, then compare answers, give points and change picture)
    • Is it possible to compare a text answer across several chat rooms ?
    • Is it possible to make players change from one room to another, randomly, during the game ?

    Also, I saw there are a looooot of tutorials out there. So it would really help if you could indicate me which are the one you think will be the most important for me to read. And of course, any advice is welcome !

    If anything was not clear or you need more details, please ask.

    Edit : I realised that it was actually better to use a timer instead of waiting for every player to do an action, so forget about question 2.

    Here I am having a little problem : I am trying to make a random sprite appear every X seconds. I have a global variable "spawn" which is set to a floor random value between 1 and 30 every time an X second timer reach 0. And then I asked the system to create sprite 1 when "spawn" = 1, sprite 2 when "spawn" = 2, etc. On the debugger, I can see the "spawn" variable changing exactly as I wanted to, but the sprite never appear. Any idea what I did wrong ?

  • Hello again everybody,

    I am sorry for the double post, but I wanted to narrow down my questions and share my capx for people who think they can help me.

    So the link is here : dropbox.com/s/vzce7mxqet4o12d/ChatProject.capx?dl=0 (I don't know if I am doing this right)

    As you can see, the game is not very sophisticated. Actually, I don't have the sprites I want to use in the end, so I just use random pictures for now. I have 3 major problems so far:

    • I found a way to lead players to different chatrooms, but I am not satisfied since I have no way to keep balance between the different rooms. For exemple, I know I will be working with exactly 18 players, so I want to have exactly 6 in each room, but it has to be random.
    • I want the "creatures" (presently represented with big numbers from 1 to 30) to appear in a random order and appear only once. A new one should appear every time the timer reaches 0. Here, I can't even make them appear at all and I don't understand why.
    • I still have no idea at all for how to compare what players wrote in the "answer" textbox and give them point for every other player that gave the same answer. Also it would be cool if I could save what is written so it could appear on the "previous creatures" page later.

    Once again, I don't want you to do it for me, but just to tell me if you think this seems possible and what tutorial I should read. Thank you in advance for your help.

  • [quote:3pclflqo]On the debugger, I can see the "spawn" variable changing exactly as I wanted to, but the sprite never appear. Any idea what I did wrong ?

    Try this:

    • Add a family containing all the sprites, e.g."Sprites"
    • Add a family instance variable, e.g. "index"
    • Edit that variable for every Sprite and set it to the Sprite's number (don't set it in the event sheet, set it in the object properties)
    • Delete that long chain of conditions you referred to (Spawn=X, Spawn=Y,...) and replace it by this:

    ____________________________________________________________

    [quote:3pclflqo]I know I will be working with exactly 18 players, so I want to have exactly 6 in each room, but it has to be random.

    [quote:3pclflqo]I found a way to lead players to different chatrooms, but I am not satisfied since I have no way to keep balance between the different rooms.

    In your .capx, I can't find the way you are managing the different chatrooms...

    The way I would go about this, is the following:

    • since the Multiplayer-plugin included rooms can't communicate between each other, we need to have multiple game rooms in one actual multiplayer room
    • To assign peers to different rooms on joining, I'd use a global variable storing the room number you are in and using that variable to differentiate between messages that come from the host (to determine whether that message is important to you).

    I'd also use three dictionaries, one for each room, to determine how many people there are in one room and whether it is full or not.

    Those dictionaries are used by the host. When a peer joins, the host will go through the dictionaries one by one. As soon as one room is found where the dictionary's keycount is below 6, it will send the room number to the peer and add the peer to the dictionary. Randomness should be easy to add here.

    ________________________________________________________________

    [quote:3pclflqo]I want the "creatures" (presently represented with big numbers from 1 to 30) to appear in a random order and appear only once.

    I'd recommend you using blackhornet 's Smart Random plugin which allows you to get a random value out of a set amount of numbers while assuring that a set amount of numbers doesn't appear multiple times.

    _________________________________________________________________

    [quote:3pclflqo]A new one should appear every time the timer reaches 0. Here, I can't even make them appear at all and I don't understand why.

    I'd recommend giving the "creature distribution" task to the host only.

    The host would either have a "Every X seconds" or a "timer" behavior.

    (If you use the timer, broadcast the random value under the "On timer" event. Immediately after that, start a new timer)

    Try to transfer this task to the host only and see whether that fixes the issue, we will deal with that later if the problem remains.

    __________________________________________________________________

    [quote:3pclflqo]I still have no idea at all for how to compare what players wrote in the "answer" textbox and give them point for every other player that gave the same answer.

    Again, the best solution is to give those tasks to the host.

    Answer textbox:

    When a peer submits the content of the "answer" textbox, it will send it to the host. The host will store that in a dictionary, one for each room, or a single array.

    When the host receives an answer, he will check whether that answer already exists in the appropriate dictionary/array coordinate. If it does, it will add one to the value (dictionary) or the array's Z/Y value (array).

    If it doesn't exist yet, the host will add a new key (dict) or a new Y value (array).

    (In the array, the X value will be the room.)

    Note: dictionaries for this will be easier to handle, while an array will be more compact.

    Points for players:

    This will be a combination of host-/peer-sided to improve performance on the host.

    The host will use the same dictionaries /array as mentioned above.

    (But since points are room-independent, we don't need to compare the room variables here)

    Depending on whether you want the points to be given immediately after one creature round is over or after the whole game is over, there are different approaches.

    Immediately:

    When the peer submits an answer, he will save what he submitted in a variable to be able to send that to the host at the end of the creature round.

    When the round is over, he will send that value to the host.

    The host then checks with his dictionaries/array and see whether (and how many times) that answer has been given and send the appropriate amount of points to the peer that sent the answer.

    At the end:

    The peer will store all his answers in a dictionary, sorted historically.

    When the game is over, the peer will send his dictionary (as JSON) to the host. The host will have a dictionary for each peer which he loads from the JSON he just received.

    he will then go through his dictionaries/array and see how many times each item in the dictionary has been given before and give points.

    Note: since it's probably very unlikely that the same name will appear multiple times across different creatures, we can compare all the dictionaries/the whole array without differentiating between rounds.

    ______________________________________________________________

    [quote:3pclflqo]tell me if you think this seems possible

    Not a casual task, but yes, it is possible.

    Though I'd recommend you exporting the project to NW.js later since all that comparing on the host-side will take up some CPU and NW.js can use more CPU power than a browser tab.

    (Assuming, you don't use necessarily use high-end PCs only for that project)

    _____________________________________________________________

    [quote:3pclflqo]what tutorial I should read

    That depends on what topics you think you need help with. I won't put out links for every single object/behavior that will be used in this project, since that would be quite an amount.

    And since your project is a very specific, non-generic one, there won't be a tutorial tailored to your project.

    If you don't feel sure about a specific element in your project (e.g. arrays or dictionaries), just search for a tutorial for that or ask here or in the forum.

    ___________________________________________________________________

    ___________________________________________________________________

    That should be about it.

    *phew*

    PS: Don't think I am a C2 expert. I started using C2 in September this year, so I am in no way worth saying that I know everything about it. I just provide what I think is the best option.

    I am sure there are better ways to do this (that I don't know of), but this is the way I would do it.

  • Wow, what a long and detailed answer. Thank you very much for your help, I will try everything you suggested !

    Also, I realized the login/login events layouts does not appear when you open the .capx, maybe that is why you couldn't see what I did to send players to different rooms.

    Edits :

    • I can't use families right now because I am using the free version, but I should be able to buy a license soon, so I will keep that for later.
    • By the way, concerning the CPU power. I'm planning to have everybody playing in the same place, so I guess I could use a LAN and that would help a lot, right ?
    • The changes I made to login/login events layouts have not been save apparently, my bad.
  • [quote:223lsmr0]By the way, concerning the CPU power. I'm planning to have everybody playing in the same place, so I guess I could use a LAN and that would help a lot, right ?

    Well, that would at least double the upload/download speed.

    This would not decrease the amount the host has to deal with though since the data stays the same, it is just delivered faster.

  • So your advices made me think about something : let's consider that everybody is on the same room, but the host acts as a filter for messages and thus creates the "groups" of players.

    All I need is a global variable "group" for each player that is set on connection by smart random (start 1, end 3, threshold 0). Doing this would guarantee the balance between groups right ?

    This solution, if it works, would be good for several reasons. I actually need to create several versions of the game with slightly different parameters. Sometimes, I would need more than 3 groups (so I would need to change only the "end" value of the smart random). Sometimes, I would like to have just 1 player being able to see messages from 2 or more groups (so I would just need to add "& X & Y" to his "group" value).

    What do you think about it ? I haven't tried it yet, I'm actually thinking about how to do it properly.

    Also, when you say it will be hard for the host CPU, do you think that would actually take a lot of time to deal with all the comparisons ? More than 30 seconds ? Several minutes ? Of course it depends on the computer, but it's just to get an idea of how long it would take.

    Do you think it is best if the host is not a player and I just use my best computer only to deal with the host's tasks ?

    Edit : Ok, I tried something but I don't know if that would work. So, upon joining the room, each player get a random group value (smart random, 1, 3, threshold 0)

    When you are a peer, you send message with a tag corresponding to your group value. And even if you get messages from everyone, you display only those that has a tag corresponding to your group value.

    When you are the host, you also send message with a tag corresponding to your group value and you broadcast every message you get. However, you only display those who have a tag corresponding to your group value.

    I updated the capx. file, I edited the yellow information texts in event sheets to explain what I intended to do. Do you think that would work ?

    dropbox.com/s/247hslkh28garey/ChatProject.capx?dl=0

  • [quote:13vtgef4]All I need is a global variable "group" for each player that is set on connection by smart random (start 1, end 3, threshold 0). Doing this would guarantee the balance between groups right ?

    Well, actually it would have to be a bit different.

    Since there is a player limit for each room, you need to take into consideration whether the room is already full or not.

    The variable "group" won't be set on connection by the peer but by the host.

    The host will have three dictionaries, one for each room, in which he stores who is in that room.

    When a peer connects, the host will check the first dictionary whether it is full. If there is space, he will add the player to the dictionary and send him his group number.

    If the group is full, check the next dictionary.

    You can add randomness by multiple ways.

    One would be to have every player set a preferred group on start which is generated randomly (pun not intended). This value is sent to the host when connected. The host will then first look in the dictionary with the number that has been sent and continue looking numerically. (System condition "For each ordered").

    ___________________________________

    [quote:13vtgef4]Sometimes, I would need more than 3 groups

    You will have to add the appropriate amount of dictionaries and change the random generation like you said.

    (Checking of the dictionaries won't be affected since "For each" automatically looks at the count of the objects)

    You will also have to add events to the host "On [groupX] message" to cover all groups.

    ______________________________________

    [quote:13vtgef4]Also, when you say it will be hard for the host CPU, do you think that would actually take a lot of time to deal with all the comparisons ? More than 30 seconds ? Several minutes ?

    I don't have much experience with this, but I'd say not that much. Several minutes? Definitely not.

    It depends on many factors.

    Of course, it depends on the computer's specs, a bit on the internet speed (not that much though) and on the amount of messages that are posted by the players at the same time.

    You would really have to test this out.

    One thing to experiment with would be to create a new project, designed for the host only.

    This would be started first, would be no player, and his only task would be to handle everything host-related.

    Having a separate host instance would increase the performance for everyone, since there won't be one player who is always doing the host tasks and the host won't have to deal with the peer-only stuff.

    ________________________

    [quote:13vtgef4]When you are the host, you also send message with a tag corresponding to your group value and you broadcast every message you get. However, you only display those who have a tag corresponding to your group value.

    Assuming, you don't go with the separate host, that is correct.

    As a host, when receiving a message, you would have to get the group number of the user the message came from.

    (Compare "FromID" with ID in group dictionary)

    Then, you would broadcast the message to everyone with a group tag attached to it.

    As a peer, when receiving such a message from the host, you would have to parse the message to retrieve the group number. Shouldn't be too difficult. (If you need help, PM me or google for it)

    _________________________________________

    [quote:13vtgef4]When you are a peer, you send message with a tag corresponding to your group value. And even if you get messages from everyone, you display only those that has a tag corresponding to your group value.

    [quote:13vtgef4]When you are the host, you also send message with a tag corresponding to your group value and you broadcast every message you get. However, you only display those who have a tag corresponding to your group value.

    Almost correct! (Again, assuming, you don't have a separate host)

    As a host, you wouldn't need to send the message with a tag corresponding to your group value, thus, a regular message like a peer would send.

    You can simply broadcast it, since the peers will only display messages that come from the host and are declared as "host broadcasts messsage". (Like in your .capx, you probably just wrote that wrong)

    ________________________________________

    Something not related to the Multiplayer part:

    I noticed you still have the many, many Sprite1, Sprite2, Sprite3,... events.

    Did you try what I wrote on my first post? This would make it more compact and easier to handle.

    Try this:

    • Add a family containing all the sprites, e.g."Sprites"
    • Add a family instance variable, e.g. "index"
    • Edit that variable for every Sprite and set it to the Sprite's number (don't set it in the event sheet, set it in the object properties)
    • Delete that long chain of conditions you referred to (Spawn=X, Spawn=Y,...) and replace it by this:
  • [quote:2a1zbnt8]Since there is a player limit for each room, you need to take into consideration whether the room is already full or not.

    But with a threshold of 0 in the smart random, I would always get a balanced distribution. So even if I do not check if the group is full, the balance would still be maintained. For example, if the smart random generates something like this : 1-3-2 / 2-1-3 / 3-1-2 / 3-1-2 / 3-2-1 / 2-3-1 / 1-3-2 / 1-2-3 / 1-3-2 / ... (where "/" represents the end of a loop)

    As long as I have a number of player that is a multiple of 3, I would always get the exact same number of players in each group, right ? I am sorry to insist, I just want to be sure I understood what is wrong with this solution.

    [quote:2a1zbnt8]Did you try what I wrote on my first post? This would make it more compact and easier to handle.

    I wanted to try it, but I am using the free version for now, so I can't use "families" right now. I will have to keep that for later (I mentioned it in one of my edits above, but since it's a mess, you may have missed it XD)

    Edit : By the way, I will go for a non separated host for now and think about an alternative if the game is really running too slow. Because that is one fewer computer to put in a room, and that is a non negligible advantage

    Once again, thank you very much for your help (you definitely earned a special place in my thesis' acknowledgments section ha ha).

  • [quote:3hlelo8t]But with a threshold of 0 in the smart random, I would always get a balanced distribution. So even if I do not check if the group is full, the balance would still be maintained.

    I'm not sure if I misunderstand you. If I comprehend you correctly, you want to generate the group number from the peer, right? Each peer generates his own group number?

    If that is correct, I'll tell you why that won't work:

    The peer can generate a random number, 1, 2 or 3 and every number is generated just once.

    But the peer doesn't know whether a room is full.

    So if he generates 2, and keeps that number, he will be in room 2.

    But what if there were already 6 users in that room?

    Only the host should generate group numbers since _he_ knows whether a room is full.

    (I have the feeling, I really didn't understand you..)

    ___________________________

    [quote:3hlelo8t]I wanted to try it, but I am using the free version for now, so I can't use "families" right now.

    Ah, right, I forgot about that, sorry.

  • Well it is still very confusing to me how this whole multiplayer thing work, so maybe my explanations are not good. But let's suppose I don't actually put a limit to the number of member in a group. So nobody check for that (neither host nor peer nor the system or whatever).

    Instead, the group value is just given to every player by one and only infinite string of "1-2-3" loops (in random order) generated by the smart random. Upon connexion, every player gets the next value in the smart random list. Of course, this would work only if it is possible to use the same string of "1-2-3" to set the group value of every player. If this is possible, then, everytime the total number of player is a multiple of 3, I would automatically get a balanced distribution of player. The advantage is that I would not need to make any modification if I want to have bigger groups, just keeping sure the total number of player is a multiple of 3 would guarantee that the groups are balanced.

    I don't know if this is more clear...

  • [quote:ptttuyru] Upon connexion, every player gets the next value in the smart random list.

    Oooooooohh...........

    OOOHHH...

    Now I see where you are going. That's actually a waaaay more intelligent solution than mine. Wow.

    As long as you give that task to the host and the host only, it's fine.

    I didn't understand it at first, I thought you want to give that task to every peer on connection.

    (If you have problems with understanding and you didn't read it yet, take a look at this: Multiplayer tutorial: concepts)

  • Ah ah thanks. It's actually combining several of your ideas that made me think about it.

    I see one problem with using that solution though : in case anybody is disconnected and has to connect back, he will get a new number. So a single disconnection would ruin an entire gaming session. Well, disconnections are a problem anyway, it would be better if that does not happen. But that is something I should think about maybe (but later ).

    Concerning the multiplayer, I read that tutorial, but it is still unclear to me how events work in multiplayer. What is hard to understand, in particular, is what is common to all players and what is specific to each. For example, when you have a global variable, it's neither in the host or peer related event so it applies to both, but when you put an event to change that variable, each player can get a specific value (like in our example above). Another example, when I create an object such as a dictionnary on any layout, how does this work in a multiplayer ? Does every player gets its own dictionnary or do they all write in the same one ?

    And when you say to give that task to the host, do you mean the host is the one generating the smart random and then send their numbers to each peer ? Or even the peer has access to the smart random once it is create and so the host just has to create it ?

  • [quote:3g6wjlw4]in case anybody is disconnected and has to connect back, he will get a new number.

    To prevent this, you could add an array or a dictionary that store each player's group number together with their Multiplayer Alias.

    When a player connects, he will be assigned to his group and the host will save the player's alias to the dictionary.

    In case one player disconnects, he simply has to login again with the same alias. The host will then assign the player the group number that is stored under his name in the dictionary.

    _________________________________

    [quote:3g6wjlw4]what is common to all players and what is specific to each

    Basically, there are three groups:

    peer, host and common.

    You can't be peer and host at the same time.

    The first player that joins a multiplayer room, automatically becomes the host for that room.

    The main difference between peers and the host is:

    • the host can broadcast messages to all peers
    • peers can only send messages to the host or to a specific peer

    In the event sheet, you differentiate between these two to not include actions that can't be executed anyways (like trying to broadcast messages as a peer). You can also give host-specific tasks (like in your project) since the host is the only person that can broadcast messages.

    (You can test whether you are host or not by checking the condition "is host")

    __________________________________

    [quote:3g6wjlw4]when I create an object such as a dictionnary on any layout, how does this work in a multiplayer ?

    You need to keep one thing in mind:

    In Multiplayer, nothing apart from positions or angles can be directly shared between peers.

    You need to distribute information via messages and by using the host's broadcasting ability.

    ([object].AsJSON is very helpful there).

    Let's take the example of a dictionary:

    • The host would have the "ultimate" version of the dictionary
    • when something happens to a peer that needs to change the dictionary, the peer will send those information with an appropriate tag to the host
    • The host will read that message, edit his dictionary and broadcast his dictionary as JSON to all peers
    • The peers, on receiving the host's message, will load their dictionary from the JSON in the message
    • Now everybody has the same dictionary

    Also remember that, most of the time, you don't need to create separate objects for the host and the peers. Like in the dictionary example, you could add one dictionary to your project, that is used differently by peer and host.

    ______________________________________________

    [quote:3g6wjlw4]And when you say to give that task to the host, do you mean the host is the one generating the smart random and then send their numbers to each peer ?

    Exactly. It would be a mess if every user generated their own number.

    We need a central user who stores the group numbers of every player for later use.

    If every peer generated their own number and stored it locally, we would need to send that information one by one to each peer when it is needed. If it is stored at the host, he can simply broadcast what is needed for everyone and send messages to peers that require special information.

  • [quote:2vr3wg1l]In case one player disconnects, he simply has to login again with the same alias. The host will then assign the player the group number that is stored under his name in the dictionary.

    Well, actually I don't want them to have an alias since I don't want them to recognize each other in the actual room and try to communicate not using the chat. I deleted that option and made everybody's alias "player" so they will just be called "playerX". But actually, if anybody gets disconnected, then that player just has to connect back several times until he falls back in the right group (they will be informed of which group they are in). With the smart random set like this, it will take at most 3 tries to get back to the right group, so it's not a major problem.

    Concerning the multiplayer, I think some things are a little more clear now, I will try a few things and send another capx soon so you can give me your opinion about it (well, if you want, of course).

    Edit : - Just a naive question on the way smart random works. I see no way to ask for the "first" value in the meaning of "the first of the randomly generated string of value" but only in the meaning "lowest possible value (the opposite of end value)". So I suppose asking for the "next" value for the first time will actually give the first value in the string (and then the second for second time you ask for the "next" and so on). I don't know if I am being clear, but basically, I just want to be sure not to skip the first value everytime I use smart random just because I overlooked something.

    • I know I haven't put every creature sprites in a family yet, but for now I put another smart random on the "spawn" value. So it changes from 1 to 30 (using all values only once before going to game over) as I wanted, but I still have no idea why my ugly big black numbers that I use as sprite for now dont want to appear. Any idea ?

    I simply wanted to create something similar to what is shown here, but I can't figure out what I'm doing wrong : https://www. scirra.com/forum/create-random-object-every-x-seconds_t63037

    ==> Problem solved. I did a long list of 30 conditions to create the 30 sprite at the same time XD. I actually had to just separate them in different events. Yeaaaaah one fewer problem!

    • Actually I have trouble now I am using families (I could get the license, yay !) :

    [quote:2vr3wg1l]Try this:

    Add a family containing all the sprites, e.g."Sprites"

    Add a family instance variable, e.g. "index"

    Edit that variable for every Sprite and set it to the Sprite's number (don't set it in the event sheet, set it in the object properties)

    Delete that long chain of conditions you referred to (Spawn=X, Spawn=Y,...) and replace it by this:

    Image

    ____________________________________________________________

    This does not seem to work, or maybe I am doing something wrong...

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Hey ! Sorry for the double post, but I have done a lot of changes to the game so I wanted to post the new .capx : https://www. dropbox.com/s/tqpq5zedfi9iw1f/ChatProject.capx?dl=0

    Thanks to your explanations and some testing, this whole multiplayer thing is getting quite clear. I now have a license and two computers connected in LAN to do some testing.

    There are two points with which I am struggling :

    • I can't find a way to synchronize the "timer" global value. Everybody should have the host "timer", but I see no way to broadcast a number value.
    • I can't find a way to send to each peer, upon connection, the next value in the smart random to set there "Group" value.

    And a less important one :

    • Is there a way to simplify the list of 30 events for spawning creatures using family ?

    I feel like dictionnaries and arrays will come in handy here, but I am not yet familiar with those. Anyway, next step will be implementing the scoring system, so I will have to learn about it quite soon.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)