Open markcornwell opened 4 years ago
Looked into how people are doing multiplayer on youtube. Seeing a number of videos on using a conbination of node.js (for the server) and socket.io (for communications) and express (for file transfer).
I am thinking of going with a client server approach. Early multiplayer games were vulnerable to cheaters hacking the client side software and data. Only way to avoid this is to put player attributes and game physics in the server and lock it down. The client side takes care of rendering and user controls. The client server communications is mainly position updates from server to client, and control input from client to the server. So the software functions need to be split cleaning, with a well defined set of messages connecting the two. Also keep an eye on the bandwidth and latency to keep the game playable. I read about updates going 60 times a second between client and server. If we can get that without appreciable latency we will be in good shape.
Going to a node.js structure will be a pretty basic decision. Once we go that way, it may be hard to change to something else later. Want to prototype this a bit before going all in.
Also, what are the alternatives to node.js?
Doing some research. Prototyping some node.js code. Here are some links...
This tutorial got me started ... https://hackernoon.com/how-to-build-a-multiplayer-browser-game-4a793818c29b
Here is a link I used for installing node.js and npm on mac... https://www.taniarascia.com/how-to-install-and-use-node-js-and-npm-mac-and-windows/
More on nodejs and websockets... https://www.tutorialspoint.com/nodejs/index.htm https://en.wikipedia.org/wiki/WebSocket
A follow up on the tutorial addressing latency and lag.... https://medium.com/hackernoon/how-to-build-a-multiplayer-browser-game-part-2-2edd112aabdf?#.imv6b3b33
So here is the basic restructuring. Put the rendering in the client.js and all the physics movement calculations in the server. To do this we need to break out the physics calculations from the client side files.
Go through files one by one and look how partition them.
Set up basic skeleton to move commands (e.g. the button states) from client to the server. Server will manage all the physics calculations; then Server will transmit all the data needed to update the frame, ship positions, states, rotation, missile positions, star position to client for rendering.
The data will be encoded as JSON objects in each direction.
Easy, peasy!
First wrinkle. What coordinates to use on the server? Since players will be on different devices their screen/canvas coordinates may differ. Say one player is on a phone and another on a desktop. Still want them to see close to the same thing. Solutions?
One approach is to choose a nominal coordinate system for the server, then translate those coordinates on the client side to adjust for the local device resolution and aspect ratio. So, as a baseline approach the server coordinates are 1000 x 1000. Clients will adjust for local screen/window dimensions and resolution.
// // ISSUE: Server defines this in server coordinates, client needs it in client coordinates // // ANSWER: Server will send client the shapes in server coodinates, which the clients will // convert to client device coordinates at setup. // // NOTES: The translation between server and device coordinates can be specified with a few // simple parameters, essentially an canvasOffset and a scaleFactor, one for the // x-axis and one for the y-axis. To convert coordinates from server coords to client, // simply multiply by the scaleFactor and then add the canvas offset. That will map you // into a square field centered in your local canvas. This canvas offset and scaleFactor // can be calculated when the client starts up by inspecting the canvas dimensions. // They can also be recalculated any time the canvas is resized. //
In the midst of restructuring. Working on bringing up a minimal server for experimentation. Going with node.js. Magic words are:
npm init npm install --save express socket.io
Using Express framework to quickly set up server and socket.io package to handle WebSockets. Modeling my implementation onf Alvin Lins excellent post at https://medium.com/hackernoon/how-to-build-a-multiplayer-browser-game-4a793818c29b?
Turns out the transition to client/server twoplayer transformation did not go smoothly at all. Went back to the books and decided I need to transform the single player version to a less OO style of programming to support the partitioning needed. I had all sorts of mightmares with the behavior of "this" and the things breaking due to "lost context". The fixes like using call/apply/bind struck me as stacking patch upon patch and complicating, not simplifying the reasoning. Need to take a new tack. I have pushed this first attempt at a two player client server variant into a separate branch, where it will sit for reference and probably be orphaned. My new approach is to transform that serverless version into a functional style. I want to limit interactions with the environment (aka side effects) much as I can to simplify that amount of thinking required.
Also, I know I am on the wrong path, if I can't Implement a new piece of funcitonality in a day. That tranformation to client server hit almost every module had with radical changes, and everthing with objects in it was all in pieces with broken references to non-existant context when I tried assembling them separately on the client and server sides. What had looked like a clean module structure from the standpoint of understanability was not at all workable from the perspective of making that client server split. A a criterion for my architecture, is to make that split siimple and straightorward. A functional approach that separates functions from data; that minimizes side effects; that emphasizes small re-usable components could potentially be the answer.
I am going to try it and see.
Will create a new branch off the master called functional, and a new item in my task list called functional. Then will try this client/server split and see if it goes more smoothly.
Ok, going to give this a second shot. I did the transformation to functional style. That should help separate the client and server sides. Going to incpororate express and socket.io and work through the two player model.
Re-integrated the multiplayer framework using express and socket.io from the link above. I am impressed with the elegance of Alvin Lin's framework. Very much function for very little code. Simple, effective, beautiful.
Changes all checked in to a new feature branch called "multi"
Two player has turned into a bigger deal than I had forseen. Now I have an architecture (see the diagrams in the docs folder) for a multiplayer server. Current plan is to create docker containers for the servers and serve them up on AWS Elastic Beanstalk. I have been working the tutorials. Getting this up and running is the challenge of the day.
I have put up a repository at docker hub under the id markcornwell. Containerized versions of the servers should be available there shortly.
Game needs to support 2 players. Figure out how we are going to do this. Sharing one keyboard is a temporary solution. Need to think up a more general strategy for 2 players to work. Separate game controllers? Separate logins to a game server on the internet? What?