You need one player object for all of the players to use. Call it something like obj_client. You're not running those all on the same machine. Each player will have their own instance but they will all be obj_client. So if I'm player 1, I would be playing as obj_client(0). Then my friend in Texas would be connected as obj_client(1). Still one object, just different instances. However we would only see obj_client. You only really need obj_client and obj_server. That's it. Do not create new objects for each player. You only need one client object period. You tell the server how many clients it should support.
How does it work? We're going to create a very basic TCP WAN server. (I can show you LAN and Bluetooth too but for simplicity and for the sake of a one sized fits all solution, we'll use WAN so anyone in the world can connect). You don't need to know about all these terms just yet, I'll explain them in Part 4. Now most people like to make a server project and a client project separate. It's a matter of preference. Keeping them separate is great for organization but personally, I hate sending two projects for one goal. So Here's what I do.
Create an object called obj_server.
obj_server > Create Event
Code:
///Initialize our Server.
var type = network_socket_tcp; //Creates a TCP Socket. The server can use network_socket_tcp, network_socket_udp, or network_socket_bluetooth.
//network_socket_tcp is more reliable and stable. TCP checks for errors in the packets. TCP is a connection based protocol.
//network_socket_udp is faster than tcp, but has a probability of dropping packets. UDP is a broadcast based protocol.
//network_socket_bluetooth is currently not supported natively but I it's stable and fast for a broadcast based protocol.
var port = 25653; //Will run the server on port 25653.
max_clients = 8; //Sets our max clients to 8.
server = network_create_server(type,port,max_clients); //Creates our server on the network and returns an id of server.
socket = noone; //Creates a null socket, since we don't have a socket yet.
obj_server > Game End Event
Code:
///Terminates our server to free memory.
network_destroy(server); //Destroys the server that we made in the create event. This will delete the server from the memory at the end of the game
obj_server > Networking Event
Code:
///Check for clients and data.
var type_event = async_load[? "type"]; //Grabbing the type from async_load using an accessor, then store that value in type_event
switch (type_event){
case network_type_connect: //If our type_event is equal to network_type_connect. If someone tries to connect.
//Add the client to the socket variable - When using multiple clients, use a data structure. This is a single client.
if (socket == noone){ //If No one is connected yet.
socket = async_load[? "socket"]; //Returns the socket from async_load using an accessor. Then store it in the socket.
}
break; //Break out of the switch event.
case network_type_disconnect: //If someone tries to disconnect.
//Remove the client from the socket variable
socket = noone
break;
case network_type_data: //If we are receiving data
//Handle the data.
var buffer = async_load[? "buffer"]; //Create a temporary buffer.
buffer_seek(buffer,buffer_seek_start,0) //Looks at the beginning of the buffer.
scr_received_packet(buffer); //Executes our script scr_recieved_packet, and pass the buffer to our script.
break;
}
Now we need to create a client. The client will click anywhere on the screen and it will show on the server. Create an object called obj_client
obj_client > Create Event
Code:
///Initialize our client.
var type = network_socket_tcp; //Defines a TCP Socket For Our Client (Use UDP for LAN, but I'll cover that separately as it needs different configuration)
var ip = get_string("Which IP address do you want to connect to?",""); //Creates an IP Address to connect to. Replace with server IP Address
var port = 25653; //Connects to port 25653. Make sure client and server use the same port.
socket = network_create_socket(type); //Creates a Socket using the type we defined above. Use network_create_socket_ext for LAN.
connection = network_connect(socket,ip,port); //Creates a connection to our socket, server, and port.
//Send Information To The Server.
var size = 1024; //Has a size of 1024 bytes (1MB)
var type = buffer_fixed; //Defines a Fixed Buffer, It does not change
var alignment = 1; //Sets the alignment to 1, commonly used for strings. See buffer_create
buffer = buffer_create(size,type,alignment); //Creates our buffer.
obj_client > Global Left Pressed
Code:
///Create a click, send it to the server.
instance_create(mouse_x,mouse_y,obj_click);
//Write the click to the buffer.
buffer_seek(buffer,buffer_seek_start,0); //Checks the beginning of the buffer
buffer_write(buffer,buffer_u8,1); //Writes our ID to an unsigned positive 8-Bit integer (0-256) to our buffer. [Our buffer looks like: 1]
buffer_write(buffer,buffer_u16,mouse_x); //Writes our mouse_x to an unsigned positive 16-Bit integer (0-65,535) to our buffer. [Our buffer looks like: 1, mouse_x]
buffer_write(buffer,buffer_u16,mouse_y); //Writes our mouse_y to an unsigned positive 16-Bit integer (0-65,535) to our buffer. [Our buffer looks like: 1, mouse_x, mouse_y]
//Send the buffer to the server
//We need to tell it which socket to connect to, which buffer to use, and what buffer size we are using.
network_send_packet(socket,buffer,buffer_tell(buffer)) //Buffer_tell is going to return the size of the buffer.
obj_client > Game End
Code:
///Destroys our socket and buffer to free memory
network_destroy(socket);
buffer_delete(buffer);
Now we're just going to create a dummy object. This will just be a ball that shows up on the screen so we have visual feedback. Create an object called obj_click.
obj_click > Draw Event
Code:
///Draws a spot wherever we click.
draw_set_alpha(1);
draw_circle_colour(x,y,10,c_red,c_red,0);
Lastly, we need to create a script that the server used in the Networking Event. Create a new script called scr_received_packet. Paste this in the script
Code:
///scr_WAN_received_packet(buffer)
var buffer = argument[0]; //Gets our input value when we execute the script [What our buffer will look like: 1,mouse_x,mouse_y]
var message_id = buffer_read(buffer,buffer_u8); //Reads our Unsigned 8Bit Integer from our buffer. [What our buffer will look like: mouse_x,mouse_y] We remove the 1 because when a buffer reads information, it removes that id from the buffer.
//You set which buffer ID you want to send information with. Maybe buffer id 1 sends mouse_x and mouse_y, id 2 sends Damage, id 3 sends health, etc.
switch(message_id) {
case 1: //If our message ID is equal to 1.
var mx = buffer_read(buffer,buffer_u16); //Reads our unsigned 16 Bit Integer from our buffer and assigns it to the variable mx. [Buffer equals: mouse_y] -We deleted our mouse_x from the buffer upon reading it
var my = buffer_read(buffer,buffer_u16); //Reads our unsigned 16 Bit Integer from our buffer and assigns it to the variable my. [Buffer equals:] -We deleted out mouse_y from the buffer upon reading it.
//Create the click instance on our server
instance_create(mx,my,obj_click);
break;
}
Lastly, we can create a controller that determines whether or not you're joining a server or hosting a server. Let's create an object called obj_clienttype_controller.
obj_clienttype_controller > Draw Event
Code:
///Draws our instructions on the bottom of the screen
draw_set_alpha(1);
draw_set_color(c_black);
draw_set_font(font_roboto);
draw_text(0,room_height-16,"Numpad 1 = Create Server, Numpad 2 = Create Client, ESC = End Game");
obj_clienttype_controller > ESC Pressed
Code:
///Ends the game
game_end();
obj_clienttype_controller > Keypad1 Pressed
Code:
///Creates the Server Object
instance_create(0,0,obj_server);
obj_clienttype_controller > Keypad2 Pressed
Code:
///Creates the Client Object
instance_create(0,0,obj_client);
Now let's create a standalone executable and open it three times. Drag one window on the left, and one on the right. And the last somewhere in the middle. On the left one,go ahead and create the server. On the right one, go ahead and create the client. On the middle one, create a client. Once all of them are running. Start clicking in the client window. You should start seeing dots appear on the screen.Using the other client, start clicking around and you should see those dots on the screen too. You may notice that the clients don't see the other clients, that's because we only programmed the clients to talk to the server but we didn't tell the server to talk back to the clients. It uses almost the same methods, we just need to send information back to their sockets using for loops. I did this to show that you only need one client object for the game.
This ends part 1. I'm writing up parts 2, 3, and 4 shortly.