Dandy tanks are a classic example of duckling syndrome in the video game plane. Modern games are so cool that it's hard to tell a screenshot from a photo. However, adult uncles can spend eight-bit pixels on the screen for hours, recalling a happy childhood.
I wanted battle, code writing and competition.
Based on the foregoing, the implementation had to satisfy some requirements.
- Maximizing the fun of the game,
- and from the use of new technologies during the implementation of the project.
- Lowest entry threshold for writing AI.
- Realtime battle on the big screen.
- Update "brains" on the fly.
- Cross-browser support for the latest version of chrome.
From the fan’s point of view, there were no alternatives to tanks: this is a spectacular realtime game with simple and familiar mechanics. The choice of tanks partially satisfied the second requirement: in a dandy you have only five buttons: a cross and a shoot. Exactly as many basic methods should have been in the AI prototype: this radically lowered the entry threshold, and the first thing most participants did was write a random bot:
this.move(['left', 'up', 'right', 'down'][Math.floor(Math.random() * 4)]); this.fire();
You can ride only in a straight line, shoot only where you go - these are the defining rules of the game. Everything else (acceleration, drifts, return on fire, ammunition accumulation) was introduced gradually and with the main condition: the effect on the gameplay and the result from each new feature should be minimal.
For data reduction of all mathematics (positions, collisions, falling), on Node.js was written engine . Quite quickly, a debug problem arose, the solution of which was the client Browserify-assembly, which is perfectly debugged in Chrome's DevTools.
At an early stage, the “thin” client, made to visualize battles, 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, diagonally flew to another tank and fired again ... in general, along with the noise of fans of sweating laptops, we quickly realized that we could not do without 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. The trigger of an event on one machine, listening to this event on another, threads ... on the server we just write frames to the stream, and on the client we listen to these frames. No buffering, memory issues, or a desync.
By the way, we wanted to write something on the Meteor framework. “Something” has become our client part. Modularity, high-level APIs, packages, isomorphism, Live Reload - although redundant in our case, but very nice things.
The most interesting requirement, from the point of view of technology, was the replacement of players “on the fly”: the battle is on, the tank shoots and drives, and its “brains” can completely change at any time at the request of the author. There can be no pre-moderation: the code should start executing on the server within a second after sending.
At first, we trusted each other, so new Function () was enough. But one good person wrote process.kill () in his bot, and it became clear that you can’t give such multiplayer in OpenSource. It is not possible to efficiently catch all kinds of horrors like setTimeout (while (true)) by the regulars, and here an absolutely safe sandbox could come to our aid, but we wanted to touch the newfangled virtual machine.
With the Node.js virtual machine, everything turned out to be simple, but interesting: for example, in the current really stable node version 0.10.36, the prototype falls off in the context object transferred to the virtual machine (and there is suddenly no MAX_SAFE_INTEGER there). In 0.12.0, not everything is good either , plus our working projects, such as 2gis.ru , do not work on it yet, due to problems with the assembly of 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 chosen by us. And this object does not have setTimeout, console.log, and other things that are in the global object. In addition, the virtual machine allows you to limit the execution of 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.
We studied web sockets and the Node.js virtual machine, poked Meteor and PIXI, peed AI, for many the first in my life, and most importantly, they fought with each other and got a lot of fun.
A side effect of the Browserify build is the single player, which you can play now: battle.2gis.ru . You can look at the engine itself here: github.com/2gis/Battlegis .