Gesichtsgesteuerte Spielmasken auf Instagram oder Doppelklick-Augen


Was für ein Unsinn, denkst du? Was für bedeutungslose Wörter? Aber leider oder Prost - so jemand, heute ist das kein Unsinn, sondern Realität. Der Artikel handelt von einem Spiel, das ich für Instagram geschrieben habe, in dem dein Gesicht als Controller verwendet wird, oder besser gesagt, nicht nur es, sondern manchmal den ganzen Kopf. Das Bewegen auf dem Spielfeld erfolgt durch Drehen und Neigen des Kopfes. Die Wahl der Aktion erfolgt durch Öffnen des Mundes oder durch Doppelklick (blinkende) Augen. Double Blink wäre es wahrscheinlich wert, es zu nennen ...

Oh schöne neue Welt! Wahrscheinlich werden die Hipster der Zukunft Skripte entwickeln, um schönen bunten Rauch hinter ihren leichten Raumkapseln zu erzeugen, oder Shader schreiben, um den schwarzen Toren eines persönlichen Teleports interessante visuelle Effekte zu verleihen, wie z. B. fallende Schneeflocken (Web 100.0) oder fraktaler Nebel (WebGL 100.0) oder ... Nein, vielleicht Ich habe nicht genug Vorstellungskraft, um mir vorzustellen, mit welchem ​​Unsinn wir in Zukunft umgehen könnten: Ich versuche, zu logisch zu denken. Aber vor ungefähr 30 Jahren hätten wir sicherlich unter keinen Umständen gedacht, dass wir heute Masken für ein soziales Netzwerk namens Instagram erstellen werden. Und außerdem erscheinen in diesen Masken vollwertige Spiele. Ich wurde ängstlich und interessant. Alles in allem beängstigend interessant. Und wie Sie bereits verstanden haben, konnte ich nicht widerstehen und schrieb auch ein solches Spiel.Zum Spielen benötigen Sie natürlich ein Smartphone auf Android oder iOS mit einer Frontkamera und der installierten Instagram-Anwendung.

Dieses Spiel ist Tic Tac Toe. Im Allgemeinen ist dies eines der ersten Spiele, die ich in meinem Leben erstellt habe, und vielleicht sogar das allererste - ich kann mich jetzt nicht genau erinnern. Aber ich habe es in Pascal zurückgeschrieben und dann diesen alten Algorithmus in Delphi gezogen. Danach erschien das Spiel natürlich auch im Internet, auf meiner Website: Nun, wo auf Ihrer persönlichen Seite ohne Ihren persönlichen Tic-Tac-Toe ... Und jetzt ist es Zeit, dieses epische Spiel auch auf Instagram zu veröffentlichen. Wenn ich in diesem Spiel ein Dolch oder ein Tac Toe wäre (eher wahrscheinlich ein Toe), könnte ich im Allgemeinen viel über mein langes, interessantes Leben erzählen ...

Was für Masken sind das?


Zunächst einmal - ein kurzer historischer Exkurs. Masken auf Instagram erschienen dank des belarussischen Teams, das die MSQRD-Selfie-Anwendung entwickelt hat. Nachdem diese Anwendung von Facebook gekauft wurde, integrierte das Team des Unternehmens seine Technologie weiter in Facebook-Produkte. Es gab also eine Plattform mit Augmented Reality-Funktionen, Spark AR. Im August 2019 verließ die Plattform den Beta-Status und stand allen Benutzern zur Verfügung, die jetzt Augmented-Reality-Inhalte für Facebook und Instagram erstellen können.

Masken wurden als Filter konzipiert, um ihrer Physiognomie mit der anschließenden Platzierung eines Selfies in einem sozialen Netzwerk lustige Effekte zu verleihen. Bei den Maskenspielen habe ich nicht so viele gefunden. Es gibt ein fliegendes Gesicht, ein Analogon von Flappy Bird, bei dem ein Vogel über den Bildschirm fliegt, und Sie müssen verhindern, dass er gegen Hindernisse stößt und im richtigen Moment blinkt. Ich habe auch ein Spiel gesehen, bei dem man den Mund von oben nach unten fallen lassen muss. Ein Schütze wie Invaders. Und ein 3D-Läufer, bei dem ein Charakter eine Stadtstraße entlang läuft und über Hindernisse springt. Vielleicht gibt es noch mehr. Im Allgemeinen ist das Thema ziemlich neu.

Der Prozess zur Erstellung von Inhalten findet in der Spark AR Studio-Entwicklungsumgebung statt, die kostenlos für Windows heruntergeladen werden kann. Es lohnt sich auch, die Spark AR Player-Anwendung herunterzuladen, um die Effekte zu testen, die Sie auf Andrioid- oder iOS-Mobilgeräten erstellen, für die diese Effekte tatsächlich vorgesehen sind. Die Verbindung zum Computer erfolgt über ein USB-Kabel, zumindest in meinem Fall mit einem Android-Smartphone. Nachdem Sie die Maske über die Facebook / sparkarhub-Komponente heruntergeladen und die Moderation bestanden haben, steht Ihre Maske (oder Ihr Spiel) allen Instagram-Benutzern aus dem Internet zur Verfügung. Die Maske kann über einen direkten Link oder von der Seite des Erstellers auf Instagram bezogen werden.

Es ist überhaupt nicht schwierig zu verstehen, wie man in Spark AR Studio arbeitet. Ich werde nicht im Detail darauf eingehen, zumal das Internet voller Lektionen zu diesem Thema ist. Ich werde nur bemerken, dass es zwei Möglichkeiten gibt, eine mehr oder weniger interaktive Anwendung zu entwickeln, die mehr beinhaltet als nur eine Art statisches Sprite auf Ihr Gesicht anzuwenden: das Erstellen der sogenannten Patches und das Schreiben von Skripten. Die erste Methode ähnelt visuell der Arbeit mit Materialien in einem 3D-Editor, und die zweite Methode programmiert lediglich in Javascript mit einer speziellen API. Ich habe die zweite Option gewählt. Es verbietet jedoch niemand, beide Methoden zu kombinieren: Über Skripte besteht die Möglichkeit, auf alles zuzugreifen, was in den Patches geschieht.

Grafik


Für den Anfang wäre es also schön, einige grafische Elemente zu erstellen, die im Spiel verwendet werden. Öffnen Sie Ihr bevorzugtes 3D-Modellierungsprogramm und erstellen Sie es. Ich benutze Blender. Im Prinzip können Sie nur separate Sprites erstellen und diese dann mit Spark AR nach einer Verhaltenslogik fragen, ohne den 3D-Editor zu verwenden. Aber ich beschloss, voluminöse Figuren aus Kreuzen und Zehen zu machen, so dass ich ohne einen solchen Editor nicht auskommen konnte.

Als erstes erstellen Sie eine 2D-Textur. Kombinieren Sie alle Texturen in einem Atlas.


Textur Satin

Nun zu 3D-Modellen. Als Spiel-3D-Raum wird eine Ebene aus zwei Dreiecken verwendet, auf der die Feldmarkierung gestreckt wird (hier ist das große Netzfragment aus dem Texturatlas). Der Atlas selbst ist mit einem transparenten Alphakanal versehen. 9 blaue Quadrate, die ebenfalls aus jeweils zwei Dreiecken bestehen, werden in das Feld eingefügt. Zusätzlich zu den neun blauen enthält das 3D-Modell in den gleichen Koordinaten 9 grüne und rote Quadrate, die zu Beginn des Spiels ausgeblendet werden. Die Bedeutung ist, dass im Normalzustand die Farbe aller Quadrate des Feldes blau ist und Grün und Rot als Cursor verwendet werden, um die Position auszuwählen, an der Sie ein Kreuz bzw. eine Null setzen möchten. Zusätzlich werden Grün und Rot verwendet, um die Gewinnreihe von drei Zellen am Ende jeder Runde hervorzuheben. Es würde natürlich ausreichenVerwenden Sie 9 blaue und nur 3 grüne und rote Quadrate, aber dann müssten Sie zusätzlich zum Ein- / Ausblenden eine Art Bewegungslogik festlegen. Es schien mir, dass es einfacher wäre, sie nur zu verstecken und anzuzeigen, ohne die Koordinaten im Raum zu manipulieren, und das 3D-Modell würde sie unbedeutend laden.


Das Spielfeld

Im Spiel stimmen natürlich die Positionen der drei Felder in jeder der neun Gruppen überein. Hier habe ich sie nur vertikal in eine der Zellen gestreut, um deutlich zu machen, woraus das 3D-Modell insgesamt besteht. Beachten Sie, dass die Kästchen auf bestimmte Weise mit Namen versehen sind (in der Abbildung rechts): von b11 bis b33, von g11 bis g33 und von r11 bis r33, wobei sich jede Ziffer im Bereich von 1 bis 3 ändert. Mit anderen Worten, der Buchstabe bezeichnet eine Farbe, und die Zahlen sind die Zeile und Spalte. Dies ist erforderlich, um über die Namen aus dem Skript auf die Felder (Netze in 3D-Terminologie) zuzugreifen, damit sie bequem ausgeblendet und angezeigt werden können.

Dann modellierte ich die Figuren von Kreuzen und Zehen selbst und platzierte sie auch paarweise in jeder Zelle. (Aus Gründen der Klarheit hat er eine der Nullen angehoben.) Sehen Sie sich nicht die Tatsache an, dass ihre Textur bisher so „fröhlich“ ist. Ich habe dies getan, um einen UV-Scan bequem durchführen zu können. Dann habe ich im Texturatlas die Texturen der Figuren durch ruhigere ersetzt, die Sie im Spiel selbst sehen können.


Spielsteine

Schließlich habe ich 4 flache Pfeile modelliert, die die Richtung anzeigen, in die sich der Cursor im Spiel bewegt. Ich habe eine Textur auf ihre Geometrie angewendet: Im Sprite-Blatt ist dies ein weißer dreieckiger Pfeil in einem Strich.

Wir exportieren alle 3D-Modelle (alle drei, dh das Feld, die Formen und die Pfeile) in das FBX-Format, für das Spark AR Studio erforderlich ist.

In Spark AR Studio importieren


Starten Sie zunächst Spark AR Studio und importieren Sie dort 3D-Modelle. Sie werden in der Liste der Assets unten links angezeigt. Gleichzeitig erstellen wir für uns eine thematische Maske mit Kriegsbemalung in Form von „Tätowierungen“ eines Kreuzes und eines Zehs im Gesicht. Sie können aus Tausenden von Lektionen im globalen Netzwerk oder aus der offiziellen Dokumentation auf der Plattform lernen, wie Sie eine strukturierte Maske erstellen. Ich werde mich nicht darauf konzentrieren. Kurz gesagt: Laden Sie das "Leerzeichen" herunter, öffnen Sie es in Ihrem bevorzugten Grafikeditor, zeichnen Sie etwas darüber, speichern Sie es, importieren Sie das Bild in Spark AR Studio, passen Sie die Material- und Texturparameter an.


Ziehen Sie unsere Modelle von Assets in die Szenenliste oben. Außerdem müssen sie in einer bestimmten Reihenfolge gerendert werden: zuerst das Feld (field.fbx), dann das Modell der Figuren (fieldxo.fbx) und schließlich die Pfeile (pfeile.fbx). Darüber hinaus befindet sich auf der untersten Ebene auch faceTracker mit faceMesh - dies ist eine Maske für Ihr Gesicht. Sie können Modelle wahrscheinlich in beliebiger Reihenfolge auf die Bühne werfen. Ich beabsichtige jedoch, die Tiefenprüfung und die Tiefenprüfung sowie den Tiefenpuffer (in den Materialeigenschaften) für alle Materialien (außer Abbildungen) zu deaktivieren. Lassen Sie sie daher in der von mir manuell festgelegten Reihenfolge rendern: Maske - Feld - Figuren - Pfeile.

Stellen Sie in den Materialien jeder Ebene den Mischmodus = Alpha ein, damit die Objekte an den Stellen transparent werden, an denen dies in der Textur angegeben ist. Und wir werden die Texturen Filtering = Medium zum Glätten setzen. (Wenn Sie ein Material oder eine Textur aus der Liste links auswählen, werden alle für sie verfügbaren Eigenschaften auf der rechten Seite des Fensters angezeigt.)

Fügen Sie schließlich das Skriptelement zu den Elementen hinzu (indem Sie auf das Element unten links + Element hinzufügen klicken). Neben 3D-Modellen wird script.js in der Liste angezeigt, indem Sie darauf klicken, welcher externe Texteditor für Skripte geöffnet wird. Wenn Sie im Editor speichern, wird Ihr Programm in Spark AR Studio neu gestartet.

Programmierung


Verbinden Sie zu Beginn des Skripts die Module, die wir in diesem Projekt benötigen. Dies ist eine Szene, Gesichtsverfolgung, Module für die Arbeit mit Zeit, Ton und Animation.

const Scene = require('Scene');
const FaceTracking = require('FaceTracking');
const Time = require('Time');
const Audio = require('Audio');
const Animation = require('Animation');

Es gibt viele Möglichkeiten, Tic-Tac-Toe in Javascript zu implementieren. In diesem Artikel geht es nicht darum, dieses Spiel in einer bestimmten Programmiersprache zu implementieren, sondern darum, mit Hilfe einer Person zu verwalten. Ich werde wichtige Punkte beschreiben, die für die Interaktion mit dem Spark AR-System spezifisch sind, damit das Prinzip verstanden wird.

Zugriff auf das benannte Fragment des 3D-Modells (Netz), z. B. auf das blaue Quadrat in der ersten Zeile, zweite Spalte des Spielfelds:

Scene.root.find('b12');

(Erinnern Sie sich an b12 - so haben wir dieses Netz im 3D-Editor genannt.)

Zugriff auf das Kreuz an dieser Position:

Scene.root.find('x12');

Verstecke einen Zeh (o), setze ein Kreuz (x) und färbe die Zellen des Feldes '32' (dritte Reihe, zweite Spalte) grün (g):

// figure
Scene.root.find('o32').hidden = true;
Scene.root.find('x32').hidden = false;
// background
Scene.root.find('b32').hidden = true;
Scene.root.find('g32').hidden = false;
Scene.root.find('r32').hidden = true;



Grünes Kreuz mit grüner Hintergrundbeleuchtung im Feld '32'.

Abonnieren Sie die Ereignisse des Kopfdrehens und -kippens, um sich auf dem Feld zu bewegen.

//vert: fov+ back-
FaceTracking.face(0).cameraTransform.rotationX.monitor().subscribe(function(event) {
	var v = event.newValue;
	...
});

//hor: rt+ dn-
FaceTracking.face(0).cameraTransform.rotationY.monitor().subscribe(function(event) {
	var v = event.newValue;
	...
});

Hier ist alles sehr einfach. Wir nehmen aus dem Ereignis die Werte der Kopfdrehung oder -neigung (event.newValue) und prüfen, ob sie außerhalb eines bestimmten Bereichs liegen. Wenn ja, bewegen Sie den Cursor (grünes Feld) visuell in die gewünschte Richtung. Ein negativer Wert der Kopfdrehung entspricht ihrer Drehung nach links, positiv - nach rechts. Ebenso - den Kopf hin und her neigen, um sich entlang der Linien zu bewegen. Der gesamte Bereich reicht von -1 bis +1. So können Sie die Cursorbewegung implementieren und ...

Und dann dämmerte es mir


Plötzlich wurde mir klar, dass es unpraktisch war, den Cursor auf dem Feld so zu steuern, wie ich es gewählt hatte: Sie müssen Ihren Kopf drehen, um eine Zelle zu bewegen, dann Ihren Kopf in seine ursprüngliche Position zurückbringen und ihn dann für den nächsten Schritt erneut drehen und so weiter. Und warum nicht einfach die Bruchwerte verwenden, bei denen der Kopf zur Seite gedreht und hin und her gekippt wird, um sich sofort auf die gewünschte Zelle im Feld zu konzentrieren? Das heißt, wie man dem Cursor seine Position mit einem Blick oder vielmehr mit der Richtung des Kopfes anzeigt. Und dann ist die erste Methode ein zu hartes Training für den Hals. Sportunterricht ist natürlich gut, aber nicht in gleichem Maße. Natürlich werden wir uns an die aktuelle Position irgendwo in ap.cur = {x: 1, y: 1} erinnern, um den Cursor an der vorherigen Position zu löschen und die Koordinaten der neuen Position zu speichern, die anschließend für das „Klicken“ benötigt werden. AproposVisuelle Pfeile zur Angabe der Richtung der Cursorbewegung werden nicht mehr benötigt: Wir werfen ein 3D-Modell (arrows.fbx) aus dem Projekt. Sie können das Pfeilbild auch aus der Textur löschen.

Doppelter Blink?


Und jetzt sind wir zu den interessantesten gekommen. Doppelklicken Sie auf die Augen. Gib es zu, du wolltest das von dem Moment an tun, als du am Anfang des Artikels davon erfahren hast? Jetzt werden Sie Ihren Freunden mitteilen, dass die Maus bereits veraltet ist und dass das doppelte Blinken heute für einen Klick verwendet wird! Doppeltes Blinken. Warum verdoppeln? Alles ist einfach: Eine einzelne Person tut dies unfreiwillig in regelmäßigen Abständen. Es wäre also Sadismus, Ereignisse an einem einzigen Augenblick festzuhalten.


In Spark AR gibt es Ereignisse leftEye.openness und rightEye.openness, durch deren Abonnieren Sie den Öffnungswert jedes Auges in event.newValue im Bereich von 0 bis 1 erhalten können. Wir betrachten das Auge als geschlossen mit einem Wert von weniger als 0,1. Und wir werden die Blink-Verarbeitungsfunktion ap.blink1 () aufrufen (ap ist ein Namespace, für mich nur bequemer).

//leftEye
FaceTracking.face(0).leftEye.openness.monitor().subscribe(function(event) {
	if  (event.newValue < 0.1) {
		ap.blink1();
	};
});

//leftEye
FaceTracking.face(0).rightEye.openness.monitor().subscribe(function(event) {
	if  (event.newValue < 0.1) {
		ap.blink1();
	};
});

In der Blinkverarbeitungsfunktion selbst definieren wir das Mindestintervall zwischen den Blinksignalen von 200 Millisekunden, damit diese Funktion beim Blinken mit beiden Augen nicht sofort zweimal funktioniert, da ihr Anruf an jedem Auge hängt. Ich denke es ist klar. Außerdem definieren wir die maximale doppelte Blinkzeit - 1 Sek. Wenn wir in diesen Bereich passen, funktioniert die Funktion action (), die das Kreuz an der aktuellen Position anzeigt. Gleichzeitig hängen wir action () an das Ereignis word.openness - damit der Spieler die Wahl hat, ob er beim doppelten Blinken oder beim Öffnen des Mundes ein Kreuz setzen möchte.

blink1:function () {
	var tmNew = Date.now();
	if  (tmNew - ap.blinkStart > 200) {
		ap.blinkCount++;
		if  (ap.blinkCount > 1) {
			//action
			if (tmNew - ap.blinkStart < 1000) {
				ap.action();
			};
			ap.blinkCount = 0;
			ap.blinkStart = 0;
		} else {
			ap.blinkStart = tmNew;
		};
	};
},

action:function() {
	if  (ap.fProc == false) {
		ap.fProc = true;
		xo.putx();
	};
},

//mouth
FaceTracking.face(0).mouth.openness.monitor().subscribe(function(event) {
	if  (event.newValue > 0.2) {
		ap.action();
	};
});

Geräusche


Ich fand sie in den lizenzfreien Abschnitten verschiedener Soundeffekt-Sites. Wichtiges Detail: Für Spark AR sind Audiodateien eines bestimmten Formats erforderlich, nämlich M4A, Mono, 44,1 kHz, 16 Bit. Online-Konverter von WAV und MP3 zu M4A sind im globalen Netzwerk verfügbar. Ich habe vier Ereignissen Sound hinzugefügt: Bewegen, Dolche gewinnen, Tac Toe gewinnen und Unentschieden. Die Gesamtlautstärke aller Sounds nach der Konvertierung betrug 105 Kb.

Um Sounds in einem Skript zu verwenden, müssen Sie ein Audiomodul im Skript anschließen, der Szene die gewünschte Anzahl von Lautsprechern anhand der Anzahl der Sounds hinzufügen (ich habe Speaker0, Speaker1, Speaker2, Speaker3), das Playback Controller-Modul zu Assets hinzufügen und die erforderliche Anzahl von AudioPlaybackController-Unterelementen entsprechend der Anzahl der Sounds erstellen und fügen Sie jedem Lautsprecher einen Ton hinzu.


Danach können Sie den Sound aus dem Skript wie folgt abspielen (z. B. den Sound eines Klicks):

var audioClick = Audio.getPlaybackController('audioPlaybackControllerClick');
audioClick.reset();
audioClick.setPlaying(true);

Endgültiger Build


Um Builds für alle unterstützten Mobilgeräte (Android, iOs) zu erstellen, klicken Sie einfach auf Datei -> Exportieren. Das Volumen des Spiels für jede mobile Plattform mit allen 3D-Modellen und Texturen betrug in meinem Fall etwa 1 MB. Dann müssen Sie über den Browser zum Spark AR Hub auf Facebook / sparkarhub gehen und dort die exportierte Datei hochladen. Sie müssen auch eine Beschreibung ausfüllen, nach Stichwörtern suchen und ein Demo-Video herunterladen. Außerdem muss es über die Instagram-Kamera am Telefon aufgenommen werden. Zu diesem Zweck gibt es im Hub einen Abschnitt "Vorschau-Kamera", der einen Link enthält. Dieser Link kann auf einem mobilen Gerät geöffnet werden. Die Instagram-Anwendung wird gestartet und Ihre Maske (Spiel) wird darin geöffnet. Der Link kann auch zum Testen an alle Ihre Freunde gesendet werden, die natürlich ein Smartphone mit installierter Instagram-Anwendung benötigen.Bis zum Ende des Moderationsprozesses ist die Maske nicht für alle Benutzer sichtbar und sie können sie erst dann zu ihrer Effektliste hinzufügen, wenn sie nur über diesen Link sichtbar ist.

Der Moderationsprozess dauert normalerweise einige Tage (es kann bis zu 10 Werktage dauern). So wie ich es verstehe, wird der Effekt zunächst einem Maschinentest unterzogen, zumindest einem Demo-Video - sicher, da ich eine Sekunde nach dem Senden eine Nachricht erhalten habe, dass die Moderation nicht bestanden hat. Grund - das Video enthält Text. Im Allgemeinen ist maskierter Text aus irgendeinem Grund grundsätzlich nicht erwünscht, wie die Regeln besagen. Ich musste die Spieloberfläche neu gestalten, damit die Punktzahl nicht wie zuvor ständig über dem Kopf des Spielers hing, sondern erst am Ende jeder Runde erschien. Und das Video erneut aufnehmen. Nachdem ich alle Änderungen vorgenommen hatte, reichte ich mein Spiel zur Moderation erneut ein.

Drei Tage später wurde das Spiel genehmigt, nachdem es in den Bereich „Kamerastile“ verschoben wurde. Ehrlich gesagt kann ich mich nicht erinnern, in welchen Abschnitt ich ihn ursprünglich eingefügt habe (und der Abschnitt oder mit anderen Worten die Kategorie musste ausgewählt werden). Dies ist nicht offensichtlich, da es keinen Spieleabschnitt für Instagram gibt. Aber okay, jetzt wissen wir, wo wir neue Spiele platzieren können. Wenn die Spiele in Zukunft erscheinen, sollte Instagram wahrscheinlich einen neuen Abschnitt hinzufügen.

Gesamt


Sie können eine Maske anprobieren, indem Sie auf Instagram zum Profil ihres Erstellers gehen und auf das Symbol der Masken unten klicken (Emoticon mit zwei Pluspunkten). Gleiches gilt natürlich auch für maskierte Spiele. Zuvor war es beim Betatest von Masken auch erforderlich, den Autor zu abonnieren. Aber jetzt wurde diese Regel aufgehoben.

Sie zahlen kein Geld für das Erstellen von Masken und es gibt keinen bezahlten Maskenladen, in dem sie verkauft werden können, wie Anwendungen in bekannten Geschäften. Außerdem müssen Sie nicht für die Platzierung der Maske bezahlen, die Sie in Ihrem Profil erstellt haben. Sie müssen nur auf die Moderation warten. Viele Blogger und Unternehmen bestellen jedoch die Entwicklung von Markenmasken für sich. Natürlich können Sie Ihre Abonnenten bitten, die von Ihnen erstellten Masken anzuprobieren, Ihre Spiele zu spielen und dies alles auf Instagram zu übertragen. Solche Aktionen können einen sogenannten viralen Effekt hervorrufen, insbesondere wenn das Spiel interessant ist. Dies kann dazu beitragen, Ihr Konto zu bewerben. Jetzt ist jedoch nicht jeder zu faul, um Masken zu machen. Die Idee von Instagram-Maskenspielen ist jedoch noch recht neu. Darüber hinaus gibt es eine höhere Eintrittsschwelle und weniger Wettbewerb,da nicht jeder Maskenhersteller ein Programmierer ist, um ein vollwertiges Spiel zu schreiben.

Source: https://habr.com/ru/post/undefined/


All Articles