
Prologue
Arcade js game. The prototype served as the so-called "Gonochki in a cage" (in some children's magazine saw). The point is that the track is drawn on the notebook sheet and the players walk in the cells. In one move, you can increase the speed by one or decrease. If you "crash" into the wall, then you continue from this place with a unit speed.

→
Game code')
The game is made using raphael.js and playground.js, with graphics rendering in SVG. On my average laptop (CPU 4 x 2.1 GHz) under chromium, the game gives out 50 fps for small tracks and 40fps for large ones.
Up to 5 racers (or racers) participate on one track. Opponent riders repeat the actions of previous players who have the best results on this track. In order for the tracer riser to register in the database, it is enough to come to the finish not the last. In the menu you can select the color of the riser and the name under which this result can be recorded (to display the results when finishing, and for the best - in the main menu).
Physics is implemented on a two-dimensional array. Riser rides (flies?) On the moves. Each turn, the player can change the speed (3 units more or 10 units less) and also the direction (left or right). Based on this data and the current position, the game looks where the current turn ends and checks the array for the presence of walls or finish. Depending on what is at this end point, further implementation of the corresponding algorithms follows. The creation of tracers is also implemented on this array (array indices are stored in the database, and not the actual size of the offsets).
The widths of the tracks vary from 500 units to 2000. There is no actual size limit, but the more, the smaller the fps is given by the browser.
For graphics, SVG is used with 11 children. 5 (path) - for drawing racers, 4 (path) - for drawing tracks, 1 (circle) - for animating collisions with walls and 1 (path) - for exhaust lights.

The database is represented by a single json-file with tracers. It is served by three php scripts. Maps are stored in the js variable. It would be possible to create json for maps, but they are static and they have a small size.
In the arcade there are sounds of collisions, sounds of racers (both of what is under the control of the player and others, as you approach them), and there is also the sound of whistling walls. I really liked this effect in the NFS series, and I tried to repeat it here. All sounds are downloaded from the
opengameart.org website. The background is Let the Games Begin (Section 31 - Tech), or alien swamp (unfortunately, the author is unknown).
Drawing route

First, I read an array of objects.
{i: size_i, j: size_j, size: indent_in_cell}
and get a chain of segments, each element of which is connected with the next, and the final with the first. And so I get a closed set of segments.
From this set of segments, using the functions of trigonometry, by indent_in_cell, I get a set of parallelepipeds (there should have been rectangles, but they did not work)

Then I, using all the same functions of trigonometry, determine whether an element of the array is located (which I created using the radius parameter, and initially it is filled with ones) in a lump of rectangles. If yes, then this element of the array is assigned the value 0.
At the very end, I draw all the rectangles with one “path” element.
For the finish line, I indicate the offset in width i. At this offset, the algorithm searches for the first segment of zero elements and takes the end and starting point from this segment, and then using the “path” element, it is drawn.
Values ​​for "boxes" are taken from an array of elements of type
{i: size_i, j: size_j, width: width_in_cels}
i and j are specified for the upper left corner, and width is the total size for the square. Then, based on these parameters, the main array is changed. The elements that fall into the "boxes" are assigned the values ​​of 3. Next on the array, I outline all the boxes. They are drawn, of course, all with one “path” element.
Creating and reading tracer.
A tracer is an array of objects of the type:
{ s: racer.speed, r: racer.root, i: racer.coord.i, j: racer.coord.j, wait: 0, }
where s is the speed of the riser, root is the direction, i, j are the coordinates to which the rayser is to be set in the current course, wait is the wait time. I add tracer information to the last element of the array:
time: this.timer, human_time: racer.human_time, start_i: racer.start.i, start_j: racer.start.j, road: settings.road, name: racer.name, color: racer.fill,
where, time is the total number of frames for which this rayser came to the finish, human_time is time in the format hh: ss, start_i, start_j are the coordinates for the starting position, road is the index of the route on which this tracer is received, name is the name tracer, color - the color of the riser.
At each player’s turn, an object is written to the array with the current parameters. Coordinates for the start of the course, direction and speed. If the speed is zero, then the wait parameter increments. Once a frame, 1 is added to this parameter and so on until the speed becomes
Above zero.
At the start of the rayser, the turn object is created and the wait starts incrementing (since the speed is first zero). Then, at each turn, when the frame counter equals zero, either the stroke object is written to the array or the wait is incremented.
When reading this array, the value wait first looks. If this parameter is greater than zero, then the render of this rayser is turned off and its own counter is incriminated. When the own counter is equal to the value of wait, then the next object of the turn looks further. Objects of the tracer, where wait is not zero, are processed by the same functions as the movements of the rayser under the control of the player. That is, the speed and direction of the object and the so-called goal of the move (the end point for this move) are set, and a standard set of functions is started to calculate the render parameters and draw the course of the riser.
Conclusion
As a result, I got a pretty smart arcade game with elements of network interaction between players. I didn’t check the cross-browser compatibility ... firefox, or rather, gave terrible fps when changing the scale, and I don’t know what this is about. If someone does not work, then chromium or, in extreme cases, chrom.
At first, I thought of something slow and puzzling, that is, I had to count the cells and find points from which one could not hit the wall on the next turn. And there were cells. But after I realized that at 50 fps, you can describe the racers with great speed and smoothness, then I redid everything and instead of a logical game of moves, an arcade turned out.
The game is about 3,000 lines of code and 4 megabytes.
UP 1: Someone knows why chromium under linux works fine (50fps), then only gives 20. Only why firefox doesn’t like viewBox and especially scaling so much? The whole render works on window.requestAnimationFrame ()