Page 55 - MSDN Magazine, October 2017
P. 55
Figure 1 Cars Playing Soccer in Your Browser
Rendering The main goal in rendering is accessing the GPU. There are several tools that can fill this slot by simplifying the interface to WebGL. Babylon.js and Three.js have been used for many advanced Web games. For this game I used A-Frame, a rela- tively new library that allows you to build a 3D scene using HTML elements. A-Frame defines new HTML elements that you can use as building blocks. Also, A-Frame does a good job of modeling the objects using an Entity-Component-System design pattern. Another interesting advantage of A-Frame is that it was designed for virtual reality (VR), so the game can be easily made into a VR experience.
Physics Cannon.js is a relatively easy-to-use physics engine. It provides rigid-body mechanics with collision detection. It was writ- ten in JavaScript from scratch, which means the library is much smaller than transpiled engines such as ammo.js.
Object Serialization and Networking For the server to broadcast object positions and velocities, game objects need to be serialized. For this purpose I use the Lance game server (Lance.gg), an open source multiplayer engine. Game objects that derive the Lance GameObject base class will be serialized and forwarded to clients. Advanced game engines use UDP sockets for better performance, while Lance still uses TCP sockets. This is because of the complex- ity of WebRTC for client-server communication (as opposed to
”syncs” periodic updates
ClientEngine #2 ClientEngine #N
Figure 2 The Architecture of a Multiplayer Game msdnmagazine.com
peer-to-peer). This is one area where Web gaming significantly lags behind other platforms. However, in my experience, the resulting game provides a smooth experi- ence even at network lags of 150ms, which is typical within the conti- nental United States or Europe.
Client-Side Prediction Here, too, I relied on Lance to perform the extrapolation of positions and velocities. Lance implements the client-side collection of server broadcasts, calculates the neces- sary corrections for each position and orientation, and applies the correction incrementally over the progress of the rendering loop. Position corrections are applied by
calculating the vector difference, and dividing this difference into increments. Orientation corrections, in contrast, are applied by calculating the quaternion difference. The correction quaternion qΔ for a server quaternion qs and a client quaternion qc is given by qΔ = qs o qc -1. This quaternion can be represented as a rotation about a single axis, and then divided into increments about that axis.
The game architecture, then, consists of server logic, client logic and shared logic, as shown in Figure 2. The client logic must handle all aspects that involve the user, including the collection of inputs and the rendering work. The server logic is simpler by comparison, but it does need to take some authoritative steps, like accepting con- nections, creating game objects and deciding who scored.
The shared logic is the most interesting part of the implemen- tation, and is discussed in a separate section. It includes the main game logic, which must run on the authoritative server, but must also run on each client as the game progresses in between server broadcasts. Let’s start with the nuts and bolts of multiplayer games: the communication layer.
Client-Server Communication
A multiplayer game with an authoritative server requires commu- nication code. This code has many responsibilities. Initially, it must manage the bring-up of the servers, which listen on TCP/IP ports for incoming data. Next, there’s a handshake process when a client connects to the server. This handshake registers the new client at the server, and establishes a dedicated socket for the client. Some games may require an authentication or a matchmaking process, as well. The connection of a new client, and disconnection of an existing client, have implications for the game. The game needs to be notified so it can create a new car for the new client and assign the player to a team.
While the game executes, the server sends periodic broadcasts to all clients. The broadcasts describe the game’s current state. A state includes the position, velocity, orientation (quaternion) and angular velocity of each game object. Additionally, game objects may well have other non-physical attributes, such as strength, shield power, spell timeout and so forth. Here, the server needs to be very efficient
October 2017 51
ServerEngine GameEngine
ClientEngine #1
Renderer
GameEngine
GameWorld [objects]
SyncStrategy Extrapolate/ Interpolate
GameWorld [objects]