Quickpong — development of network game based on the Twisted framework

Developed and launched on a domain quickpong.com the online version of the game Pong. In the game (by design) provides only a multiplayer mode, that is, the game is not against the AI and against another person.

The game is a client-server application, the server part is written in Python framework Twisted, client — Vlasova framework FlashPunk.

This is my first experience of the development of asynchronous network applications that can handle thousands of simultaneous connections. Next, I will talk about how this program works, what problems I had to face when developing, what ideas I wanted to implement and which ultimately remained unfulfilled. Perhaps my experience will be for someone useful.

the

Two words about gameplay


On the playing field left and right there are 2 boards, is able to move vertically. Each of the boards operates. Between the boards to move the ball rebounding from the walls of the playing field and boards. The player's task — to prevent the ball gets over the wall, near which is his Board.

the

technologies used


In the development of new technologies and tools plays a vital role the presence of a competent detailed documentation. Choosing a server-side framework I considered Python, Twisted, Tornado and being on everyone's lips, Node.js.

Based on the fact that I have not had the experience of developing such applications, I chose Twisted. He wrote a very detailed introductory course, explaining the basics of the development of asynchronous applications are not dependent on any framework or programming language, and, of course, tells about the use of the Twisted. the Strongly recommend this course to anyone wishing to understand the basics of the development of asynchronous applications. The link above you will be able to find a translation of the course into Russian language.

In this project, for me the main interest was the development of backend for client development I decided not to bother and to do it in flash, the experience with which it already had, using the framework FlashPunk.

the

the Algorithm of interaction between client and server


The choice of algorithm of interaction between the client and the server I came not so thoughtfully as to the choice of frameworks. In the end, a working version of the algorithm I implemented only the third time, and the first two versions of the algorithm invented by myself and after two failures, a third version found on the Internet.

The main difficulty in such applications is the synchronization of the clients, we cannot allow the same time one customer saw one picture, the second client is another.

In addition, I would like to avoid fraud on the part of clients: the desire and ability of the client swf spacecraft can be modified and can transmit to the server the cheat data.

Thus, in the first version of the algorithm I decided to act as follows:
    the
  1. each client calculates the state of your game world (the position of the ball, his Board and Board opponent),
  2. the
  3. each client 20 times per second sends to the server for information about changing the provisions of its boards and information about the parameters of the ball (position, vector, speed) in your game world
  4. the
  5. the server sends each player the position information of the opponent Board,
  6. the
  7. the server calculates the current status of the game world and compares it with the data received from customers (paragraph 2). If it is between the States calculated by the client and the server, the server will returns customers in a state that considers proper.
Algorithm turned off. It could be a work only if all 3 party data sharing would have the same condition. In practice in 100% of cases were not in sync and it was impossible to play.
In the second version of the algorithm I decided to get rid of one of the links from sizing the state of the game world on the server:
    the
  1. each client is still himself expected the coordinates of the ball and boards and transmit data about their state to the server
  2. the
  3. server compared client status and if they differed, then forcibly returned to one of its clients to the state of the second.
This approach is also turned off. Even clients running on two identical machines counted the state of the world a little differently and, despite the fact that I compared 2 States, not 3, as in the previous case, still the condition of one of clients constantly forcibly changed, it looked to be a visible “jump” of the ball and play was impossible.

It became clear that, firstly, the state of the world must be calculated in only one place on the server, and, secondly, before proceeding with the experiments, to avoid such a waste of time, I should study the theory and experience of other developers.

Googling I found these interesting links here:
the
The algorithm described in the last link and was taken by me for this project. Its essence is this:
    the
  1. all calculations are conducted only on the server. Clients transmit to the server of the Delta changes its state, in my case this change of position of the Board relative to the previous data transfer.
  2. the
  3. the Server calculates the positions of the boards (suppressing possible catering client-side) and bulb and transmits the generated data frame to the clients.
  4. the
  5. Customers renderat received data frames, in my case, with a delay of 3 frames. This is an important point. The data from the server to the client come unevenly, for example due to network problems, the client can obtain this new position of the ball is not in the fixed 50 MS, 60-70 MS. That is, it may happen that the last data frame has already attenderen, and the new has not yet come. In this situation the client will not have data to draw the ball and, in my case, the ball will just stop waiting for receiving a new portion of data. To prevent such situation, the client renders data with a delay 3 data frame, which gives some margin, thanks to which even if the data from server is not received on time the customer will have something to render. Unpleasant side of this algorithm is a noticeable delay between the user action (pressing buttons on the keyboard) and the display changes to the screen. There are methods to eliminate this delay, but specifically in this case, I decided not to complicate the client.


the

Implementation


The source code of the server and client I posted on Github:
the
In this diagram: quickpong.com/images/quickpong.png demonstrates the logic of interaction between client and server.

From the point of view of server implementation, everything is quite transparent. 10080 for port starts the reactor (event loop), which operates the server factory class QuickpongServerFactory. When you initialize the factory creating an instance of the class Quickpong, which contains all of the logic for interaction between the server and client.

When you connect a new client calls the factory method buildProtocol and creates for each subscribing client an instance of the class QuickpongProtocol created object is passed to Quickpong. Thus, an object of class Quickpong has access to all the subscribing clients and can carry with them the necessary work to unite in pairs, to count the state of the world, etc.
An object of class QuickpongProtocol only contains methods to retrieve and transfer data from/to the client.

With the client implementation is also simple, the only interesting point was the following. Using FlashPunk I can set the refresh rate of the pictures (FPS), while FlashPunk can guarantee that he will render N frames per second, but can not guarantee that every frame is drawn in 1/N seconds. That is, at 50 FPS in the ideal case, each frame should be drawn for 20 MS, in the real case, one frame can be rendered in 15 MS, and 25 MS for the other. If the ball moves at a constant speed, e.g. 10 pixels per second, and rendering each of the data frame coincides with the rendering of the frame Flashdance, the ball will move unevenly, jerkily, as in one case, he will move 10 pixels at 15 MS, and the other 25.

This feature had to consider in the client and before drawing the frame I'm checking how much time has passed since the rendering of the previous frame, based on this, I determine to render a data frame fully or partially.

the

Testing and monitoring


The most interesting question for me — how many players online will be able to withstand this server? For the test I wrote in Python a client, which emulated the actions of the person.

The test was conducted on a virtual machine that is allocated 1 core Intel® Xeon® E31275 CPU @ 3.40 GHz.

By means of the same Twisted I hung on 10082 the port of the web server that outputs a comma-separated number of users online and number of active games. Based on this information, and with the help of Python library's psutil ligament rrdtool + py-rrdtool I wrote scripts, which displays information about the current number of users online and the resources consumed in a digestible form: quickpong.com/stats.html (image updated every minute).

At 5000 (5 thousand) players program eats away about 100 MB of RAM, loads of CPU on average 30-40%.

the

Roadmap


Ideas that are left unrealized:
the
    the
  • html5 client
  • the
  • more complex gameplay due to the change of the angle of rebound from the Board, depending on the point of contact between the ball and the Board,
  • the
  • the introduction of four games, one Board on each side of the playing field :)),
  • the
  • implementation of the algorithm lag compensation,
  • the
  • fix minor bugs.

At this point I lost interest in this project, maybe my achievements will seem to someone interesting or informative, so I posted the source code on Github:
the
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

Address FIAS in the PostgreSQL environment. Part 4. EPILOGUE

PostgreSQL: Analytics for DBA

Audit Active Directory tools with Powershell releases. Part 1