
Many of us played railroad as a child and dreamed of a second or third rail set to build our branch from the balcony to the hallway. Our team managed to take part in the virtual construction of a huge transsib with interchanges that amaze imagination.
By the way, on the website Kanobu a contest with tickets to Igromir as a prize will last another week.
Link to the gameand out of competition version (without Kanobu wrapper)
')
The plot of the game is the exact opposite of subway surfer, it is necessary to protect the train from the raids of idiots. Since this is an official game, the guard cannot get out of the train and hang on the game. The train can not get into an accident or even accidentally crush someone. In the process there were many tempting ideas, maybe sometime the world will see a version with a train that destroys crowds of zombies.
This article is not a hello-world for a crappy bird style HTML5 game. We are talking about a real project from the developer’s point of view, a crane for deadlines, writing a game with a bunch of hacks, making a huge chain of customers ringing the project on the last day, without a time reserve. Do you want a clean code - go to
github and torment our child as you want. The code is under the MIT license, but all art is not included here.
How RZD cares about security, we know from the huge screens at the stations. Personally, I think that if these videos were not censored, and were performed in the style of mortal kombat, the effect would have been much greater (Poezd wins. Fatality).

So, somewhere in RZD they decided that it would be nice to make a small promo with an emphasis on safety on the railways. A complex chain of intermediaries eventually led to us
TK was painted fairly straight: there should be a generated level, a top-side view, a train corresponding to the style of Russian Railways, 6 types of obstacles and 3 super heroes explaining how not to behave on the tracks. All this should work on adequate browsers, on PCs and tablets. Superman, Spiderman and “that guy from GTA San Andreas” were chosen as super heroes ...
Do you think we used our super-engine, which can render everything on DIV or on CANVAS2D or SVG and draws only those places where something has changed? Do you think we took our super-CMS to generate pages and script management? No, we took the easiest renderer in the world -
pixi.js , the easiest script
builder at the moment -
gulp +
browserify , the simplest library for single-app -
angular.js , the dumbest backend - node.js, the dumbest sprite slicer -
shoebox , the easiest to use 3d editor -
blender , the dumbest editor of polygons -
physicseditor , the best skeleton 2d-animator
spine . We have no infrastructure issues. We did not technically stand out.
A free plan was drawn up:
0) the train will pass the whole screen, and stop at the station until the next screen is generated.
1) it is necessary to have a path with a fixed curvature on the turns, which can be lengthened and from which it is possible to obtain the coordinates of the sleepers.
2) the path must be able to check for self-intersection. We use a simple grid, stored in each cell who crosses it. Smaller grid - more likely that the paths will begin to intersect.
3) the path must end somewhere on the right of the screen so that it can be continued when generating the next screen.
4) there must be a stupid algorithm that goes through such paths and chooses a prettier and more authentic one.
5) the result can be filled with different objects (trees and pebbles).
6) the train can be rented in 32 frames. It does not look very good, but the "turning the sprite" to the desired angle right in the game solves everything. This was done rather quickly, the result / time ratio was awesome, you could meditate on the demo:
first demoThe work was far ahead of the schedule, and the path generation could have been left as it was, but someone in the middle of the chain decided to play a serious customer, and said that another option was needed. With smooth scrolling. The damaged phone added something about arrows and additional paths, and this all led to three weeks of debugging, optimizations and transferring the brake generator to the webworker, for it inevitably affected the FPS.
second demoJust imagine that parts of the road that is generated when generating graphs need to be run through serialization in order to transfer from the webworker to the page. A real nightmare, it's very easy to forget some important parameters. At the same time, it is necessary to monitor and chop off the already passed screens in order not to litter the memory.
From one of the intermediate results, literally everyone was sick:
at one’s own fear ...Of the difficulties, we can especially note the case when, after an already generated screen, it was not possible to find a continuation for it, because some kind of rail ran into the next station, or at the edge of the screen. If it is not possible to generate a new screen in 30 passes, it rolls back 1 screen. Sometimes it is noticeable graphically, right along the train changes the future path.
Well, the process of merging and splitting paths also added hassle. We often began to walk in a circle:

The switch of the arrows ended up stabbed, and this upset us all very much.
No less than the companion similar to the hero from GTA. Upstairs they decided that he was too "bydlovat":

Then came the obstacles (in the literal sense, they had to be done according to the TK). It was here that we took revenge in full and showed how we can put obstacles in place: our “art director” went on vacation in August and, due to the lengthy rework of the generator, did not manage to coordinate many moments with the customer. I regularly approached the computer, reread the point about the obstacles, I did not understand what to do with it, and as a result I spent time optimizing the game (various 2d / webgl options, stuffing sprites into the atlas) instead of dealing with the artists and clarifying the script . Dissatisfaction with the lack of significant updates passed along the chain, starting with the main customer, and stopped at kanobu.ru, which tolerated, but behaved with us quite correctly. A week before the deadlock, this deadlock was jointly resolved, a detailed script was drawn up, idiots and other elements of obstacles were drawn. On the scheduled day everything worked as it should.
The server part is quite simple, it can record the results coming from ajax-requests. There were no problems with it, everything was done on the last day, and even enough time with protection from the most obvious hacks. I think those who break the system so that I do not notice, are worthy of prizes.
After the launch of the project, it turned out that on many devices the generator is too slow and does not have time to build a path in front. The output turned out to be trivial - they changed the json format of the card to a binary one and generated 100 thousand screens on the server side. This became possible because the game is divided into node.js modules and compiled using browserify. The player starts on a random screen in the first half, and until the cached screens run out and they have to use the generator for a long time instead of loading the screens from the server :)
This approach had an unexpected effect: in the “Far East”, very crooked roads appeared.

Due to the fact that in the binary we wrote float and not double, on the screens with a huge x-coordinate (tens of millions) there was a lack of accuracy of coordinates, the rails were joined with errors of 1-2 pixels. Yes,
Far lands began with us much earlier than in minecraft. The same error began to appear when drawing the rail
The curvature of the Far Eastern rail corrected the transition from global to local coordinates relative to the screen.
To start from any place, the whole road is divided into dozens of screens, and stored in different files. In this case, the final segments of the rails must be duplicated in the previous and next file, otherwise it will not be possible to start driving not from the first file. And we forgot to delete this duplicate rail when loading the next dozens of screens, and since the coordinates of the rail were calculated somewhat pertly so as not to go to the far east, the result looked just gorgeous:

Rivers and bridges are one of the most pervasive parts of the generator. The fact is that the river flows through several screens at once and this greatly influences the ability of our random generator to continue the path. Quite often, the screen with the beginning of the river falls under rollback, the rivers simply do not withstand evolutionary selection. Careful selection of constants and the next trick solved this problem: when a rail crosses a river, the generator tries to lengthen it and put a bridge under it. In the process of iterating the path, if the rail is removed, then the bridge must be removed along with it. True, in some cases only the bridge was removed. So there was a sawing bug.

Prospects for the game are excellent: based on the resulting generator, you can make a lot of new projects. You can add jokes and realism, which everyone craves so much (if the train does not crush the idiot, then at least the security will come out and take revenge).
You can write about what we have done innovative artificial intelligence, which generates ways for Russian Railways, win some prize in start-up parties, find an investor ...
PS Especially for Habrozhilov from today somewhere around the 2015th mark there is a small Easter egg.
PPS The article was accidentally published originally on GT, not for a long time;)