Game Maker Studio: Let's Build a Multiplayer Shooter #1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is going on my programming stallion said sack you're back with another game maker tutorial and today is the kickoff of our online multiplayer game series in this series we are going to be creating a top-down shooter game with full multiplayer functionality we're going to be going through a lot of parts but I want to lengthen these videos as well to really nail down these concepts that we're creating because this is going to be an advanced tutorial this is not for beginners if you're new to game maker I would recommend watching some of my other videos first and getting a real hold on it because you will not understand anything and really what I want to stress in this series is for you guys to understand what we're doing and what's going on rather than copying the code so we're gonna be creating a lot of stuff we're gonna be looking into a lot of stuff that I really haven't found anywhere on YouTube which is you know obviously a server client connection which will be global so if you want to pork forward your IP and host a server you can do that and so anywhere around the world you can really play this with people we're gonna be looking into obviously a shooting system I want to look into health bar systems game rounds game lobbies and account system in the game statistics tracking I want to visit lag compensation because that's a big one and we're really gonna do a lot of the stuff that you would need to actually create a multiplayer game that's very stable so even things like like reconnecting on a connection loss motion interpolation so that we can actually smooth everything out on the client-side and really make it look like a very polished very nicely fitted 2-d multiplayer game so without further ado let's go ahead and start so there's a couple things we need to know about when creating a multiplayer game first off that's a different connection types there's TCP and UDP so those are the two very basic sort of networks that we can use and this is something you're gonna have to decide what you want to use in this game we're going to be using TCP now the difference is the TCP server waits for packets to be received before sending the next one so it makes sure if this clients sending a message to the other client it's making sure that that client is receiving all of the data that it's been sent and it's waiting it's sort of in line of gathering that data one by one in order a UDP server just sends all the packets without waiting in whatever order right so it's the problem with that is you can have some data being lost and it's not 100% that it's actually getting received by the other client all right so the the perk of a UDP server though is that it's very fast so a lot of these games like the bigger games like Call of Duty they actually use a mixture of both they use TCP and UDP just for different things that they want to go ahead and do you know if they're not if they don't really care about you know some data getting lost then they can use it that but if you want sort of like a chat system or something you can't have data loss in between you know chat messages it just won't happen all right so like I said we're gonna go ahead and create a TCP server game here so let's go ahead and begin I'm gonna go ahead and create a script right off the bat number name it server create all right server Creek and every server is going to need a port and IP address and so on but since this is just the server we just need a port that that server is going to run on so we're gonna put any arguments the port support equals argument zero if you're unsure what an actual port is that's that's basically if you have an IP address let's say just for example there's not but let's say there's a hundred ports on that IP address so what you what the it's just sort of like different channels so if you want to be synced into like v port that would be different and send different data from the vi port to the v port so you can't actually cross the ports it's just on one single port it's kind of like tuning in on a radio station you got it just to an eye on that one and you only receive that data from the signal of the radio all right so then let's go ahead and say network create server raw and the type we're gonna say network socket TCP because we're using the TCP our pork is gonna be our port and our max clients this is however many clients can actually be in your game I'll just 824 now all right so pretty simple the reason why now if you take out this raw it'll still work but the reason why we're gonna use raw is because if we don't use raw the actual network create server functions are a little bit different so the network create server has more GameMaker specific code and it's just like another layer of TCP code pop on top of it if we do underscore raw this will actually allow us if we want it to in the future to create a server on c-sharp c++ whatever whatever other language we want to build the server in just out of pure speed it's a lot faster to do that then we can do that easily and we won't have to go back and change this to raw anymore so it works exactly the same and you'll have no problems creating a server with GameMaker but just in case you want to do something like that I would recommend that you use the raw functions which will we will be using the entire time all right and if we go ahead and look at our network create server you can see that if our value is less than zero then the connection will fail right so if we go ahead and let's whoops if we go ahead and create another variable server equals zero and then we set server to this then we can say if server is less than zero and we'll show an error but not create the server and here we'll say true for a board so just sort of like a fail-safe thing and then we're gonna go ahead and return the server all right so this is pretty basic code right now you should be understanding it so yeah so let's go ahead and create an object and we'll name it Oh server and in the create event we'll just call that script so just say server equals server create at the port of 9000 just make it easy pretty simple so now what we're gonna do is we're gonna go into an event and we're gonna click our asynchronous event and go to networking I'll put in some code here so if you renewed a multiplayer you probably have never used this event before and that's okay the networking event gets called when something happens with the network you know if there's somebody connecting to the network if there's a message from client to client happening it gets called in this event if someone if you know somebody is disconnecting from the server it gets called so anything that happens with our networking server this event will be called all right so pretty simple to go ahead and vary the type of message that were being sent we're going to use our async load functions which will tell us if we're you know getting a data type if we're getting a connecting a signal for getting a disconnecting and all that so I'm gonna make a switch statement and I'm gonna say async underscore load and here I'm going to say question mark type okay and that's because this is part of a DS map so if we go to async load in our networking event here as you can see we have all of our different constant types that we can have so we can have network type connect/disconnect data and our non-blocking connect which we won't actually use well we will use it but it's you can just think of it as the same thing as our connecting okay so again pretty simple yeah so let's go ahead and begin with that so in our switch statement we're just going to go ahead and use those different types that I just showed you so we say case Network type connect case Network type non-blocking connect I'll break it and we'll do a case Network type data and we'll keep pace Network type disconnect break that as well all right so all of these so this will be loaded when we're sending some sort of data this is disconnecting and this is connecting should be pretty simple so here we're gonna put in functions that we haven't actually got created so I'm gonna say server handle Connect and here I'm gonna want to put in my socket ID so async load question mark socket and our network data which is a server handle message async load question mark ID and we're actually gonna want to because we're gonna want to use something called a buffer now I'm gonna explain the sockets I'm gonna explain the buffers just let me finish putting this in right now so I'm gonna say async load we're gonna call the type of buffer and then down here we're gonna say server handle disconnect async load and this is gonna be socket again all right so every time a client connects it gets its own socket number against its basically it's an ID and we can pass this socket ID to the server to kind of keep track of who is who in the server so just automatically every time you connect it gets a socket ID now for the buffer the actual buffer is how we are going to send data it's basically just a stream of bytes so we will provide meaning to those bytes later on by you know passing through X values Y values for positioning purposes maybe username all sorts of stuff or it can be passing through these buffers so we're gonna need every time we want to handle a message we're gonna need the ID of the client and we're gonna need the buffer which is basically the data we're sending okay so let's go ahead and create these scripts so I'm gonna say server handle connect server handle message and server handle disconnect so here is a server handle connect we're going to put in our socket ID as the argument our handle message is a server and a message socket underscore ID and our buffer and here server handle disconnect and we're gonna put in our socket ID again so let's go ahead and go over to paint and before I go any further in let's explain what an actual server and client does so here we have our server let me move that over here actually and this server is basically the the central point for all the data so if we have let's say a client right here that connects to the server the server now takes in that to account let's say let's make them right here that's sort of like the brain so he knows that all right hey here's a client we have connected and what he also does when that client connects is this server pops out back at the client a socket ID which is what we did and this is how the server knows that client from let's say another client that connects and he pops in there we create another client so now the server down here says oh there's two clients in here this server pops out another socket ID to the client so now how does this client send a message to this client so it's kind of cool to think that on each client's side there's there's really not that actual climb is not actually in the game it's all ran through the server so in other words if we move our character here's our game come over our character from here to here it's going to send let me use a different color it's going to send that data of our X&Y to the server right that server is going to say okay he the X&Y positions are moving it just called since we're moving we're sending data in it called that networking event so that is going to push out the data to this client and on this screen here what we actually have going on is if let's say this is our main client this guy here and our other client all the way over here with a different socket ID is this guy here on our actual clients game we're gonna create an object called other client or something like that and this is gonna be an actual physical object inner game that it's job is to do nothing but copy what our client all the way over here which can be all the way on the other side of the world is doing so this certain this client sends the X&Y coordinates to the server the server then sends it to our client and that client code then says hey this other object in the game we're getting data that says that you moved over here so I'm gonna go ahead and do that that's basically what a server client system is alright so right now what we're doing is we're creating the server to take in those messages and to be able to set everything up so under connect disconnect we're gonna want to give client IDs we're gonna want to do all that fun stuff so yeah let's go ahead and keep on going so in our server handle Connect I'm gonna create a variable called socket ID and this is going to be arguments here and here we're gonna say l equals instance create zero zero oh server client and basically we're gonna create this object Oh server client and this is all server-side so basically we take this server client and it runs on the server so we need an actual object in the game to represent each other instance of a client that actually exists and on their side but it it has two so if you connect into a game the server has to create its own object called server client which basically keeps track of it all right so here I'm gonna say L dot socket ID equals socket ID and here we say L dot client ID equals and here what we want to do is create client IDs so our socket ID is good for identification but it's a random number so the ID can be from three to seven thousand to you know 37320 right so it's really abstract and it's not really gonna work for an identification system because we can't just if we wanted to do a four loop through all of the second IDs we really couldn't because we don't know what those numbers are so we need to create something more efficient like a client ID system every time a client connects so if we go to our server server create what we're gonna do is we're gonna say client ID underscore counter equals zero and in our server handle connect we're just gonna say client ID equals client ID counter plus plus so what this does is it will set a variable for a client ID on the server client to equal what our client ideas and then after it equals that this statement here with the plus plus just increments it by one so next time assert a client connects it'll be the client ID will equal 1 then 2 then 3 then 4 and so on alright so after that technically okay so technically this could be bad because if our client ID counter is greater than what an actual integer value can hold which is like 65,000 something then we're gonna we're gonna get in there so if there's 65,000 people that connect and you know one more connects and for that an integer can't actually go that high so we just need to create something that will loop it back in case it gets too high so I'll say if if client ID counter is greater than equal to 65 thousand then client ID counter equals zero so I'll just loops it back now the only way this would be bad and and we get some weird error would be that if our initial client was still connected after sixty five thousand other people connected and disconnected then it would go back and would try and override itself and it would just be it would just be weird so we're gonna change that later but for now that's fine you're probably not going to get sixty five thousand people connecting disconnecting all the first guys there just won't happen so let's go ahead and continue the next thing we're gonna have to do is create what's called a client map and this client map which is gonna be a DS map will hold all of our clients objects into this map so we can call them whenever we'd like so I'm gonna say client map I'm gonna do question mark and we're going to convert it to a string make sure you convert it to a string it will not work equals our instance so pretty simple we just added that to our our map using the object we just created with the socket ID all right so now let's go ahead and disconnect it real quick and here we're gonna just need the argument so of our socket ID equals argument 0 and here we can just destroy it so if I'm sorry with client man string socket ID I do that right there we go all right so with the client map we're just gonna instance destroy so we're gonna just destroy that object and we're just gonna say PS map delete and that's gonna be client map and our socket ID and actually when I prefer that to a string socket underscore IV now we're just this is just the server disconnecting portion of it this is not anywhere at the clients or anything like that so we'll have to get into that later when we start querying the clients all right so here's our disconnect functions we've got to connect functions everything's cool now we need to go ahead and start with the hard part which is our handling messages so here we just put in our socket ID argument zero and our buffer argument one all right so normally this will differ from any other game whether you have a zombie game or you're shooting people or whether you have a platformer game this is all dependent on what your game is and it's gonna be completely different in the long run if your game is anywhere unique so the way we're gonna do this is we're gonna create a while loop that's gonna loop through this and remember now this only gets called every time data is being sent through the server so what I'm gonna do is create a message ID which is basically saying okay if you if you're if the players moving then I want to put that into its own case method of okay the objects moving or if the object is shooting I want to put that into its own message idk shooting that is shooting so the server always knows what's going on whether again be moving whether it be shooting whether it be reloading whether it be aiming all anything in your game really work be sending through these message IDs so here I'm going to say while true and here I'm gonna say bar message ID equals and we're gonna read this as a buffer to buffer read and here I'm gonna say buffer and I'm gonna say buffer underscore u8 so again this is the server so we're gonna be reading and writing a lot of things so the server like and our paint the first thing it does if a client says something is it reads what's going on so the first thing we're gonna do is read are you moving are you shooting etc that's the first thing we're doing and then we're gonna read if let's say for example the message IV was move then we're gonna read what's your X and what's you knew why right once it reads all this then we're gonna have to write it back out to all the other clients updating them on what the new x and y-coordinates are of our client we're using a buffer you wait because if we go ahead and just look at it we're buffer you eight stands for an unsigned 8-bit integer so it's a positive value from 0 to 255 so it cannot go negative and if it over seeds this value then we're gonna get some weird stuff going on here you know you could do a sign which is negative 128 to 127 but normally in multiplayer situations you never want to actually do that because you're now cutting in half your numbers on the right side so always less data is good to send through because it's just faster so you know if we use you 16 unsigned 16 that says you're a 65,000 so you can kind of see the difference how many things it needs to go through and how much data is being sent so you always want to use the lesser number all right there's things like bool and string and texts and that's that's you know like sending true and false statements sending string values like a chat message all of that stuff all right so this is just kind of knowing what's going on with that all right so let's go ahead and create a switch statement called message underscore ID and in this case I want to make something for our moving so I'm gonna go into my macros and in our configuration I'm going to create a constant called message underscore move with a value of 1 and this is what we're gonna be sending so it's just under our constants it's disguised but we're really every time you send a message ID we're either just sending like the value of 1 the value of 2 the value of 3 and all of these have different cases for what they're actually doing so I'm gonna say case message move to break it now now that we are in the message move and we've read that okay it is we are moving now we can just exclusively send data that we're moving so I'm going to create a variable X X and this is gonna be buffer read from our buffer and I'm gonna say buffer underscore u16 because our room is gonna be bigger than 255 our YY is gonna be buffer read buffer buffer underscore u16 all right so now that we've gained all of what we're doing we now need to send it back we need to send it out for everybody so I'm gonna say buffer right and we're gonna write down our buffer which is actually what we need to do now because we need to create a new buffer that we can write on that's always going to be this we can make one main buffer that will send all of the data no matter what it is it can be through a chance system it can be through this through that we can use one main buffer type to send everything right so if we go to our server create and we say send buffer equals buffer create and we'll put it the size of 256 and we'll say buffer fixed which I'll show you in a minute and the alignment of 1 so our buffer fixed there's all sorts of different buffer types we've got buffer fixed which is just a fixed size which we just set us 256 we have buffer grow a buffer that will grow dynamically as data is added a buffer wrap which just wraps it from the end to the beginning and a buffer fast which is just used for extremely fast data to read and write to all right now this sounds silly but I actually forgot it's getting a little bit ahead of myself I forgot to actually add the client map as an actual Deus map so just a real quick thought right there create your client map in the server create a Zaidi's map and then we can actually use it down here apologize for that but we need to actually create it before we can start doing stuff with it all right so you can go ahead and read through these we're going to be using buffer fix just because that's exactly what we need and I put the size for 256 just because it's a number out there that we're really not going to exceed in bytes a 256 is pretty large well it's not extremely large but it'll do the job for exactly what we want to do all right so here we're gonna write out our buffer and we're going to use our send buffer and our type is going to be a buffer underscore u8 and we're gonna send our message move so here's what we're doing right now just so you're not copying the code that's exactly what I don't want you guys to do when watching this series I don't want you to be copying the code I want you to be understanding it so let's go ahead and go into notepad and here's what we need to do we are going to now that the server has received our x and y values and our message ID so that's the first thing it gets read it reads our message ID and then based on the message ID it'll either read the X&Y or the shooting position or whatever but since we only have our move it's gonna read the X&Y then it's gonna write out everything to all the other clients so first off it needs to write the message ID that is being broadcast with everybody it needs to write out the client ID so we need to know which client sent this message for so for one we don't send it back to them and for two on every other clients computers they know which object which server client object move all right then we need to send the X and the y variables and we are done so that's what we're doing now so the next thing we need to do is send our client ID which we're just gonna create it up here as a temporary variable we're gonna say client ID and we got to name it a current because if we name it just client ID it's going to get confused with our server create where is it our instance client ID there so obviously I named it current but it's essentially the same thing and we're gonna access the client map and say string socket ID dot client ID so this client map is essentially just taking the instance of our client ID and then we are going to write it so buffer write send buffer and here we're gonna say buffer u16 and client ID current because remember that our client ID can be anywhere from zero to 65,000 so we're gonna need our two bytes here because this goes from 0 to 65,535 now we can write our X so buffer right sound buffer and this will be you 16 again and this will be xx will be just read from and buffer right send buffer offer you 16 and by Y all right and then now that we've created this and we've read and we've written now we just need to access all the other server clients so we can do that by saying with Oh a server client and we want to make sure that we don't send data that we just posted to ourselves so we're going to say if client underscore ID does not equal client underscore ID or recurrent oops then we're just gonna say network send raw and we're gonna say socket underscore ID our Sun buffer and the size now the size as you can see here we can look at it so we're sending so one we're sending the message move we're sending our client ID our X and our Y so this would be 7 bytes that we're sending and so you can kind of just look at it like are you eight is one byte you sixteens are two bytes we go and look are you 32 s are three bytes and are used for our 4 bytes each so if we do our x and y which are 2 bytes each that's for our client ID that's another two so we have six and then our you eight is seven so we're setting the size of seven we're setting 7 bytes one thing that we need to know about sending in writing buffers is that it keeps writing anywhere it left off so if we didn't basically say all right we want to start back from the beginning because if not we would run through that 256 bytes like nothing then we can say before all of it I'll for seek send buffer and we'll say buffer seek start and I'll set it 0 so this is just gonna every time we start writing it's gonna bring it back to the beginning just as sort of like another failsafe let's say for example we do exceed the 256 bytes we need to not send that data and just break it off completely or else we're gonna get a crash out of game so I'm going to say if buffer tell buffer equals buffer underscore get underscore size our buffer then break after go and look at that we can see that when you rewrite data to a buffer using the buffer reader buffer right the current seek position is advanced by the bytes retina read and with this function you can get the current seat position for use and other Bob buffer function so we're just kind of just seeing where it's at how many how much data we're using and then this function just gets the size of the given buffer and bytes so it's just sort of like a failsafe I would put that in there of course all right so with all that we now have a server to run with our game so that's gonna be it for this tutorial Goldin you like go and subscribe let's go and try for 100 likes this time and if you didn't understand anything please re-watch the video and I look forward to seeing you guys tomorrow with the next video peace [Music]
Info
Channel: RealTutsGML
Views: 58,211
Rating: undefined out of 5
Keywords: Game, Maker, tutorial, beginner, gaming, studio, java, programming, lets, build, game, tutorials, game maker online, game maker online tutorial, game maker studio multiplayer, multiplayer tutorial, game maker multiplayer tutorial, game maker studio online game, game maker top down shooter tutorial, game maker studio online tds, game maker tds, game maker multiplayer game, game maker online multiplayer, game maker online multiplayer tutorial, game maker beginner multiplayer tutorial
Id: 4_bhmfhN20Y
Channel Id: undefined
Length: 37min 28sec (2248 seconds)
Published: Thu Jul 28 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.