
Dandy Tanchiki is a classic example of duck syndrome in the plane of video games. Modern games are so cool that it is difficult to distinguish a screenshot from a photo. However, adult guys can spend eight-bit pixels on the screen for hours, recalling a happy childhood.
I wanted to do something like that, so that you could get together with your colleagues in a big meeting and have different kinds of drinks and have fun. This had to be related to professional activity: JavaScript or layout, because in order to plow to Kwaku or go to kebabs, it is not necessary to be a frontend developer.
')
So the idea was born to make JavaScript AI-challenges.
Alas, but most of these platforms did not suit us: the real condition, the observed competitiveness and the low threshold of entry were imperative. That is, artificial intelligence should be written from 5 minutes to 3 hours by a JavaScript programmer of any level, and not several weeks by a group of sishnikov, such as, for example, in AI Cup `s from Mail or Google.
I wanted a battle, code writing and competition.
Project
Based on the above, the implementation had to satisfy some requirements.
- Maximizing the fun of the game,
- and from the use of new technologies in the course of the project.
- The lowest threshold for entering the writing of AI.
- Realtime battle on the big screen.
- Update the "brains" on the fly.
- Cross-browser support for the latest version of chrome.
From the point of view of the fan, there were no alternatives to the tanks: this is a spectacular realtime game with simple and familiar mechanics. The choice of the tanks was partly satisfied with the second requirement: you only have five buttons on the dandy: the cross and the shoot. Exactly so many basic methods should have been in the prototype of the AI: it radically lowered the threshold for entry, and the first thing that most participants did was write a random bot:
this.move(['left', 'up', 'right', 'down'][Math.floor(Math.random() * 4)]); this.fire();
You can only ride in a straight line, shoot only where you are going - these are the determining rules of the game. Everything else (acceleration, drifts, recoil from shooting, accumulation of ammunition) was introduced gradually and with the main condition: the impact on the gameplay and the result of each new feature should be minimal.
Implementation
To calculate all the mathematics (position, collisions, hits), the
engine was written on Node.js. The debugging problem quickly arose, the solution of which was the client Browserify build, which is perfectly debugged in DevTools Chrome.
At an early stage, a thin client made for visualizing fights, ajax, requested the last N frames of the battle and rendered them with dom elements (no kidding!). It was very funny when the dom-projectile, hitting the target, flew diagonally to another tank and fired again ... well, together with the noise of fans of sweating laptops, we quickly came to understand that we can't do without the Canvas (thanks to the PIXI library) .
For networking, we used Socket.io. When you use web sockets, you understand that the 21st century has come. Trigger events on one machine, listening to this event on another, streams ... on the server, we simply write frames to the stream, and listen to these frames on the client. No buffering, problems with memory and out of sync.
By the way, we wanted to write something on the Meteor framework. "Something" was our client part. Modularity, high-level APIs, packages, isomorphism, Live Reload - albeit redundant in our case, but very nice things.
From the point of view of technology, the most interesting requirement was to replace players “on the fly”: the battle is on, the tank shoots and drives, and its “brains” at any moment can completely change at the request of the author. There can be no pre-moderation: the code within a second after sending should start executing on the server.
At first we trusted each other, so new Function () was quite enough. But one good person wrote process.kill () in his bot, and it became clear that such multiplayer should not be given to OpenSource. Effectively catching all sorts of horrors like setTimeout (while (true)) with regulars is not possible, and here an absolutely safe sandbox could come to our aid, but we wanted to touch the new-fashioned virtual machine.
With the Node.js virtual machine, everything turned out to be simple, but interesting: for example, in the current really stable node of version 0.10.36, the prototype falls off in the context object passed to the virtual machine (and there is suddenly no MAX_SAFE_INTEGER). At 0.12.0,
all is not well either, plus our work projects, such as
2gis.ru , are not yet working on it, due to problems with building some npm packages. In this regard, we now use the wonderful npm package
“n” to quickly switch the node version.
The work with the virtual machine itself is simple: we run the prepared eval script in the context of the js object we have chosen. And this object has no setTimeout, console.log and other things that are in the global object. In addition, the virtual machine allows you to limit the execution of the code by time: if the code runs for a long time, it is killed, and its last breath catches the closest catch in the stack.
Eventually
We studied the websockets and Node.js virtual machine, poked Meteor and PIXI with our wand, signed the AI, for many the first in my life, and, most importantly, fought with each other and got a lot of fun.
A side effect of Browserify-build was a single player, which you can go now:
battle.2gis.ru . Look at the engine itself, you can here:
github.com/2gis/Battlegis .
In the near future, we plan to make a dedicated server with a full-fledged multiplayer, where everyone will be able to compete with other JavaScript-programmers; and, of course, do bugfixes and cross-browser compatibility. Follow the news!