Godot Net-Code Blog #2

posted in Misc
Published April 24, 2024
Advertisement

This week I continued my experimentation on net-code in Godot. This is a continuation of the last post, so read here for context on what I will be discussing here.

When we left off we had a simple net-code project where players could host lobbies for others to join by entering an IP address. My first objective was to get a functional camera so that players could be tracked as they move around. I decided to use one camera that kept all of the players on screen zooming out if necessary.

The first step to creating this is that we first need knowledge about each of the players that have been spawned. Before I did not keep references to spawned players in any way but this is an easy fix. I just added a list to the player-manager that keeps track of the spawned players. The only caveat is that the players are only saved on the host's client. This is because if there were 2 players already and a 3rd joined their list would only contain themselves with no information about previously joined players. This could be solved but it makes the most sense to handle the tracking of players on the server side instead.

Now that we have this list we can supply it to the camera for it to do its work.

But what exactly is that work? Well, the goal is to have the camera be in the center of all of the players, and zoom out only as much as we need to keep them in the bounds of the viewport. Placing the camera in the center is easy, we can just take the average position of all the players that have joined.

The zoom level is a bit more difficult. The basis of this is to compare the distance between the camera center and each of the players to the size of the viewport. If the distance to a given player is more than half the size of the viewport then we know we need to zoom out. However, we need to break it down in terms of the x and y difference rather than pure distance since a screen's resolution is not generally square. So, for each given player we can find the x and y distance from the center of the camera. Then we can get a zoom ratio by dividing the initial viewport size in the given dimension by twice the x and y distances. After looking through all of the players then the smallest of these ratios can be used as the new zoom level. This will zoom the camera to what is needed, but to keep the camera from zooming in super far we can set a default zoom level of 1 so that it will not zoom in further than the default resolution, and to avoid too much snapping of zoom levels we can smoothly transition towards a given zoom level rather than setting it directly.

The next objective I wanted to complete was to allow players to disconnect from the game. The goal here would be for a player to disconnect from the server, have the player disappear from the world, and return that player's client to the main menu. Taking this one step at a time, disconnecting a player is rather easy, all we have to do is set the multiplayer peer to null. For proof of concept, I have it set to just disconnect when a player presses escape, but in reality, it would be better to put this in a menu to avoid accidental disconnects.

Then our next step is to remove the player from the game. The tricky part is to remove it from all client's versions of the game. It would be simple to just call queue_free on the client and be done with it, but that won’t transfer to other clients. This is where RPC functions come in. RPC functions allow us to call methods on other clients not just our own. To do so we mark a function as @rpc and provide arguments for how it should function. The details for these arguments aren’t super relevant for our purposes, other than ‘call_local’ which is necessary for our server to be able to call it on itself since our server is also a client.

First, there is a peer_disconnected signal that we can listen to similar to what we did for peer_connected. Then instead of emitting a spawn signal we emit a despawn signal.

Then we can do an RPC call on that player's destroy function to have it be called on all clients. Then inside this RPC function, we just call queue_free.

The last step of moving the disconnected player to the main menu scene is quite trivial. When we set the multiplayer peer to null, we can just also swap the scene back to the main menu and we are done.

Previous Entry Godot Net-Code Blog #1
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement