Phaser 3 - Real-Time Multiplayer Game with Physics
What is so special about this example?
All the physics (MatterJS and Arcade) is entirely calculated on a NodeJS server. The client only received the positions {x, y} and other necessary properties like rotation, animation and tint of each object.
It uses a unmodified Phaser 3.16.2 version from npm.
The physics is entirely calculated on the server. The client only gets the coordinates {x, y, rotation}. This is why you will see the same boxes at the same place with the same rotation, regardless where you are in the world.
Thank you so much for making this! Iāve managed to get to the second row of stars, but no luck with the big guy yet.
Iām working on a project which will hopefully be built on Phaser and Matter, but I havenāt yet started my networking tests. Youāve not only shown me that itās possible, but also that it performs acceptably on mobile which has eased some concerns. I donāt want to derail your thread, but if you could answer some questions for me Iād appreciate it a ton. If theyāre too off topic I can shoot you a message.
Have you done anything special to account for tcp? If not, do you have any ideas or techniques in mind to account for network issues that may arise?
Is there any fancy client side predictions/corrections happening besides applying position/rotation/velocity on the client when data is sent from the server?
Are you utilizing Matterās āenableSleepingā? Iāve not been able to get it to work in my game, as it seems to disable the ability to control our character. Probably something to do with how velocity is being set, but I havenāt found a solution yet.
Have you done any stress testing? I found the specs of free heroku dynos and it looks like youāre working with 512MB of RAM and 1 core. How many simultaneous connections can you handle? How many physics bodies can you run in one instance?
Are there any big issues you ran into while working on this?
Sorry for all the questions! I appreciate any help you can give me in determining if this tech will work for us. Thanks again, and great work.
I have also only caught the big star twice. It works best in a team, putting 3 boxes below the star and then jump on each other to catch it.
No. For the client? You should probably spin up multiple servers in multiple regions to lower the latency. Otherwise you canāt do anything. If the client has a slow and/or unstable network connection, he canāt play an real-time online game.
Since this game works in real-time with multiple players, there is not client side correction (But you could of course implement this in another type of multiplayer game). Everything is calculated on the server. If the players latency is below 100ms, he will not notice anything. I guess, since youāre located in Austin, TX, your latency is much higher. Currently the server is located in Europe (where I live).
I use this.Matter.Sleeping.set(this.body, dead) only for ādeadā bodies. In this game dead bodies are the boxes which disappear after a certain time and will re-spawn later.
I could not find a way to debug it on Heroku. This is the first time I use this service and only have a free account. But I have tested in on my docker-machine on EC2 (t3.micro) which has 1GB RAM and 2 cors. Each player uses about 30 kBps download and 5 kBps upload. The t3.micro instance is capable of handling up to 5 Gbps. I was running 4 game instances (in the same node app) with 50 objects each and the memory was about 190MiB and 30% CPU.
Big issues, no. Everything works smoothly. The only thing special you have to do, is installing the required packages for canvas to work. But since I have dockerized the app, it does this automatically each time I publish it.
I can totally recommend you this approach for a real-time multiplayer game. I works great. Currently Iām about to program a RoomManager which will manage multiple socket-io rooms and create a new Phaser instance for each room (all in the same nodeJS app). I will also add a /stats url, where you can see stats about the appās cpu and memory usage and its logs.
For now, the game (same link as in my first post) creates a new room for each 4 players. Open 5 browser windows and you will see that the 5th player is alone in its own room (Phaser instance) and it shows its own public room id in the debug text.
I know that I wanted to publish it earlier, but I prefer to add all these great features first
I have now added the page /stats which logs all console.log()'s and some usefull information about the game, cpu and memory. Also check out /physics if you have not yet.
Thank you so much for the detailed reply Yannick! Youāve helped a ton. Iām going to continue along down this path and see where it leads us. That stats page is also incredibly awesome, so thank you for that as well.
I wish you the best of luck on this project, and many more to come. Hopefully Iāll be able to help you in turn some day.
The example with MatterJS is now more or less finished. Iām now about to implement Arcade physics, since most do know this better and it is much easier to use.
In the finished example, the client will be able to choose which physics engine he wants to use in the game. Its cool and it demonstrates how you can start multiple Phaser instances with different scenes and physics based on what the client chooses.
Youāve gotten Arcade Physics to work with Node? After a good amount of research, it looked like Arcade couldnāt be decoupled from the Phaser core and this was thought to be a bad idea.
I would LOVE to be able to use arcade, but networked gameplay is a requirement for us. Are you running phaser headless? Or have you managed to decouple the physics system completely?
I thought a lot about your question āHave you done anything special to account for tcp?ā And how, I finally have a good answer. Please take a look at topic #2080.
Thatās such a nice example. Iām really glad you published it on github.
Iād like you to elaborate or guide me on how is your webpack/nodemon configuration working. I have some questions:
Ā· Running ādevā will get webpack to recompile and nodemon to restart? Isnāt it too slow to recompile before each restart? Just asking, because I never done this myself.
Ā· With auto recompiling + auto restarting you just refresh the client page and voila, server with changes are being used?
Ā· Whatās the reason to separate physics and stats in different webpacks?
Thanks again, really!
ā EDIT ā
Extra question, is it really worth it using webpack for a project made with JS? Iām using āuse strictā in my server code and type=āmoduleā in my client for ES6 modules.
Glad to see youāre still working on this! Iām going to respond in your new topic, but I donāt want to clutter it up with potentially unrelated stuff so Iāll ask here.
What were the issues you encountered with this project that pushed you to create the UDP library?
Yes, it is slow. But you can tweak the webpack configs to improve it. If I would work on a large project, I would probably use webpack-dev-server to serve the /client, /physics and /stats over it, instead to serve it over the node server like in production. This will retranspile the code and restart the browser immediately. Also I would configure the /server to retranspile and restart via nodemon, only if a file needed by the server has changed. This will make development much easier.
Only for readability. You could of course merge them.
Yes, it is worth it! Since you can use ESNext syntax or TypeScript. Btw Iām using TypeScript in this project.
Please take a look at a starter template. It uses webpack and does a lot of work for you. You will see that it opens many new possibilities and it is just much easier to develop with it.
The only issue with this project is the TCP connection. Iām happy with anything in this multiplayer example except the connection. I tried a lot of stuff to improve it. I tried āNginx proxy with TCP_NODELAYā, I read a lot, but nothing seemed to improve the connection.
So I decided to make it work over UDP. I have built the core for my library by now. Now Iām about to build a nice user-friendly API for it (It should look similar to the one of socket.io). After that I will build another Real-Time Multiplayer Game with my new library and publish it in this forum