Do next .io-game



the So-called .io games is a browser — based massively multiplayer action game in which a lot of people struggle with the excess of free time. Massively multiplayer means that the game is a multiplayer crowd from a large number (hundreds+) of players playing in common locations. There is a perception that all started with the game Agar.io (cells in a Petri dish). Other successful examples are Slither.io (snake) and Diep.io (tank). According to statistics, every day these games are played by millions of players. Today there are dozens of different .io games, most of which can be found, zaguglit on request "io games list".


I'll tell you how we did ours .io-game Oceanar.io — a game about fish and other sea inhabitants, I try to focus on issues of common technical devices of the entire system and give some humble advice.


I will Try to describe the system as simple as possible, in this format, in which it would be most understandable for me on the fingers, no indentations in the code.


the

gameplay


first, you need to decide what the game is. I thought about the game mechanics of two of the most successful representatives — agar. IO and Cliserio — we decided that the game should have the following properties:


    the
  1. Controlled character should gain strength gradually over a long time, and this set of forces should be reflected visually.
  2. the
  3. you Need to have a reason to play for very long many hours in a row. When a player loses 5 hours, should have a definite advantage over those who are lost 3.
  4. the
  5. competitive advantage should not depend solely on the time spent in the game. Should be a reasonable balance between time played and game skills. The man, who had a few minutes, you should be able to win someone who plays for several hours. Let this be very difficult, even here we need the luck factor, but this possibility needs to be.
  6. the
  7. Bonuses received as a result of victory for another player, should unconditionally accrue to the winner, other players should be able to grab them.
  8. the
  9. Have at least something original :)

We thought that it would be surprising if it will not grow the force game creatures directly, and the number of these creatures. The second idea is the ability to combine pairs of weaker creatures in one more powerful. Thus, at the beginning we have one creature that eventually grows into a pack, and the pack shrinks back to a smaller number of more powerful creatures. A couple creatures on the first level can collapse into the one being second, a pair of creatures, the second one being the third, and so on. So we get an exponentially-decreasing pumping that you can rock almost unlimited amount of time.


it Now remains to choose an artistic component. The choice was between a flock of microorganisms — viruses, bacteria, protists, prions, and a flock of sea inhabitants fish, crabs, jellyfish. After some thought, the choice was made in favor of the fish. This is done with the artistic part, and move on to the technical :)


I Have no experience in creating a serious MMO games, but bonabeau bumps on their past projects, as well as reading about the experience of different developers (example), I have formed the opinion that the client-server architecture .io games is fundamentally not much different from other MMO games- it is based on the same ideas. As one of the most important (and enjoyable for single developers) differences .io games, I would single out significantly simplified game rules: if a serious MMORPG for calculating damage from a blow with an axe on the head of a Goblin on the server need to play the whole verinica rules, in .io game it would be a simple formula in one line of code. That is, .io-the game — it's the same MMO with lots of players, but much more simple from the point of view of the organization of their innards. Simple enough so it could write one programmer and the client and server part.


the Game client is browser open it in an html page. The same technology that most other .io games, namely, programming language — JavaScript-graphics — WebGL, interaction with the game server through WebSockets. It so happened that .io-games are not made to sound (although all technical possibilities for this are available), so we decided that our game would be without sound (so as not to attract too much attention from superiors at work).


simply put, all the action occurs on the server, and the client is only a monitor-the Visualizer of this action. You can do the client in addition to passive visualization is to send to the server the player's actions (in our case the coordinates of the mouse cursor and the state of its buttons). More than anything the customer can not, and should not be able to — no game logic should not be executed on the client, otherwise it will immediately become a possibility for cheating. Thus, from a programmatic point of view, the client is the object that, among other things:


    the
  1. is Able to send to the server the user's actions.
  2. the
  3. is Able to receive server messages and dispatch them.
  4. the
  5. keep a copy of the game world, falling into his field of vision.
  6. the
  7. Renders the stored copy of the game world.

Here are examples of messages and actions for processing client-side:


to Show the fish ID, creature_id, which is in the given position, has a velocity vector velocity belongs to the player with the ID, owner_id, and is a fish type creature_type_id.


From the point of view of JavaScript, this will for example this object:


the
{
message_type_id: 1,
creature_id: 68328,
creature_type_id: 2,
owner_id: 9306,
position: { x: 1.436, y: -39.32 },
velocity: { x: -0.17235, y: -0.1157 }
}

if you receive this message, the client will add the fish in mapou fish, and when it comes to rendering a game scene, the fish will appear on the screen.


Fish ID id1 bit the fish with the identifier id2.


after Receiving this message, the client will take the coordinates of the fish with the identifier id2, and add with the same coordinates of the bubble in the bubbles array and a blood stain in an array of spots of blood. Further, the drawing displays them on the screen.


Thus we can say that the messages from the server to the client — it is basically a notification that the field of view of the client, something happened. Something the client should know that a proper and understandable way (graphically) to notify the player. Examples of other types of messages — "the game ends with this score, the game includes a player with such a name, a list of the top 10 players", "list all players and their coordinates" (to display them on the map), and so on.


the

the Server


the Server is the application inside which is the entire game. The server consists of the game rooms. The playroom is an instance of game locations. The room is adequate for the gameplay geometrical dimensions and the limit on the number of players in it. When all game rooms are full, the server creates a new room, and the players gradually distributed evenly between occupied and free rooms. Playrooms are unrelated, and work completely in isolation from each other. On the top level of the server is able to accept an incoming connection, select the suitable game room, if necessary — to create new, and send the player in your room.


Our server is written in C++ third-party libraries use Boost, the network part — Boost.Asio. Development and testing — Visual Studio / Windows server work — GCC / Linux.


the

Games room


happens Here all the game logic. Room is an object, which, among other things:


    the
  1. Keeps a container of game objects: creatures, food, observers.
  2. the
  3. is Able to accept from a customer and dispatch them.
  4. the
  5. Able to notify clients about events occurring in the room. Some of the notifications are sent only if the event data occurred in the field of view of the client.
  6. the
  7. performs periodic update of the game world over time (in our case 10 times per second).

Fat free interface game room to the pseudo-code:


the
class room
{
methods:
join(user);
update(dt);
dispatch(protocol::kill_creature);
dispatch(protocol::consume_food);
dispatch ...
dispatch ...
dispatch ...

properties:
container<creature> creatures;
container<food> foods;
container<observer> observers;
}

the

Update the game world


This feature implements changes to the game world that occur during a fixed interval of time dt (in our case 0.1 seconds), I will call this update function. In General terms, update a games room is call update for the game objects, that is, the call to update further down the ladder of aggregation, from the General to the particular. A simple example: suppose we have fish in the coordinate position, and moving with the velocity vector velocity. Then the function update is the computation of its position using dt time:


the
next_position = position + dt * velocity;

in Addition to moving fish it may be for dt to make a decision to go to some other place, and then, in addition to updating their coordinates, the result of the update may change its velocity vector velocity. The pseudo-code update the rooms as follows:


the
room::update(dt)
{
message_queue.dispatch(); // Dispetcherizaciya messages addressed to the room in a queue

foreach(creature in creatures)
{
creature.update(dt);
}

foreach(food in foods)
{
food.update(dt);
}

foreach(observer in observers)
{
observer.update(dt);
}

spawn_food();
spawn_npc();
}

the result of performing the underlying update (for instance update creature) can not sent messages to be processed at its sleduyushem update. For example — crab bitten by a fish, and the fish died. You need to remove the dead fish from the container of fish to create meals in the place of the dead fish and also to notify players about the death of fish and the appearance of food. To do this, the crab inside my update send room a message stating that he killed the fish and the room during dispatch of this message will perform all the necessary action — removal of fish, creating food, notifying clients.


the

Partitioning the game space


In some algorithms that implement the logic of the game, you need to be able to iterate over objects close to this. For example — to show the user all the fish in his field of vision, or to check whether the fish to bite someone out of their environment. If we iterate over pairs of objects by principle "each with each", we get a quadratic complexity, and that we don't need, neither for the CPU nor for traffic.


in order to get rid of the quadratic complexity, we use the following method: the space is divided into cells, and each cell stores a list of objects that are in the area of the playing space. Access to the list of cells on its coordinates has constant complexity.


If we are interested in the list of sites closest to this, we requested lists of cells, which is this object, and lists objects from neighboring cells. A total of 9 squares.


the division into cells is done in two independent duplicate layer — cells of small size to check neighbor interactions collisions, bites, poedanii, and cells of large size to resolve the questions of visibility — contact with objects in the field of view of the player.


Thus, the complexity remains quadratic, but square is being built already not the total number of game objects in the room, but only their number in the field of view of the algorithm.


the

Protocol


a Separate question — the Protocol of interaction between servers and clients. Under the Protocol, I mean the description of the collection and structure of messages that will be exchanged between the server and clients, they are serialized when sending and deserialized and dispatched upon receipt. I used my own simplified cycle solution — the code generator from JSON descriptor packets (as it happens). If you need a serious solution, not the bike, that is ru.wikipedia.org/wiki/Protocol_Buffers, which is also a code generator.


    the
  1. minimizes the code you need to write by hand.
  2. the
  3. Speed of the code generator you are not limited by any rules, you can generate the fastest possible code within the specific language.
  4. the
  5. the Amount of data transferred — you can (and should) tightly pack data in accordance with your needs, minimizing traffic (more on this separately below). With the code generator is especially useful to introduce additional attributes to the fields of a message that specifies the rules for packing these fields.

the

message Queuing


to send messages To the room used multiple producer single consumer queue. To send messages to customers — single producer single consumer. Both types of queues — zampino-Cycling. Probably, it was possible to use Boost.Lockfree but again, as it happens. For (de-)serialization and message dispatch traveling within the server, use the same ladogeneratory mechanism to transfer messages across the network.


I tried to describe the overall structure of the game and some of its single, important in my opinion points to you have formed a complete picture of the structure of the entire system. I hope I got it :)


the

Tips


If you are going to make their .io-game, I can only say — do it! :) And here are a few modest suggestions:


the

Boots


Together with the client and the server, immediately do the bots. And bots have to go to the server via a network, according to the same Protocol as the client, and "see" the same information that real players. This greatly facilitates debugging, and allows to estimate the resources consumed in conditions close to the fighting. How many players online will pull server? When we upremsya in the CPU or the width of the network channel? On these and other questions will help you to answer bots, thereby freeing you from unpleasant surprises after release. In addition, bots will make the game not too boring, yet there are not enough live players.


the

Network traffic


So, to minimize network traffic. Usually hosting providers traffic or paid by the meter or pre-paid package with the ability to rebuy or unlimited, but with an asterisk-a footnote, which is the caveat that actually it wasn't unlimited — the exhaustion of a certain amount you will have to wait for punitive action in the form of, for example, cuts the width of the channel, or still have to pay on top. So — think carefully about your Protocol and save every byte! We have 10000 live players, played for the day, generated over the day around 200 gigabytes of traffic. Perhaps it may not seem like much, but don't forget that the volume of consumed traffic will grow along with your audience. A few saved bytes in a single package can save hundreds of megabytes or even gigabytes of traffic per day.


Keep stats of the traffic layout according to the type of gaming packages. Most likely you will see that despite the fact that you have several dozen types of gaming packages, bulk traffic accounts for a few of them — they are something you should pay special attention.


the

HTTPS


If you want to make your game including the iframe-the game Vkontakte, you will have to forcibly move to HTTPS, as if he vk.com works via HTTPS, and then from inside the iframe then it will require the same Protocol. A site running on HTTPS can only work with SSL websockets.


the

List of technologies


Here is the complete list of technologies that you'll need to do .io-game:


    the
  1. HTML / CSS — layout website.
  2. the
  3. JavaScript programming the game client.
  4. the
  5. WebGL / OpenGL ES Shading Language — do grafon.
  6. the
  7. WebSocket — do network.
  8. the
  9. Protocol Buffers / Bicycle — making Protocol client-server communication.
  10. the
  11. the Language in which is written the game server. Here the choice is huge: Java, Scala, C++, Rust, Erlang, Haskell... What your heart desires.
  12. the
  13. PROFIT!

the

Result


Our game is still in beta, but look at the result, you can now: oceanar.io (currently available only for the desktop, mobile and tablet versions of the queue).


Thank you for your attention. In the comments to answer your questions.

Article based on information from habrahabr.ru

Комментарии

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

Templates ESKD and GOST 7.32 for Lyx 1.6.x

Monitoring PostgreSQL + php-fpm + nginx + disk using Zabbix

Custom table in MODx Revolution