Expérience d'écriture d'un jeu en TypeScript et WebGL ou un récit sur la façon dont un backend-shch a plongé dans un frontend moderne

Bonne journée à tous habrozhitel. Je veux vous raconter comment je suis revenu à un développeur de jeux amateurs après 3 ans et plus, en changeant radicalement l'outil (et en cours de route - ma vision du monde), et ce qui en est sorti. Sous la coupe, vous:


  1. Une brève disposition de tous les faits au début du voyage. Comme l'image «AVANT» dans la publicité en ligne bon marché «AVANT» et «APRÈS».
  2. Une plongée volontaire dans une interface moderne dans le style de "Où est l'argent, Lebowski?!"
  3. Légères démangeaisons à un moment intime, se transformant en un désir brûlant d'apprendre quelque chose de nouveau en faisant quelque chose d'ancien.
  4. Conscience de l'impuissance
  5. Surmonter
  6. Belle fin, tout comme dans vos films.

Clause de non-responsabilité


Cet article était sous forme de brouillon sur github depuis deux ans, sa version quasi complète a été écrite fin 2017 dans la poursuite des événements.


Citoyen, présentez-vous!


Dans mon article précédent ( https://habrahabr.ru/post/244417/ ), j'ai écrit un peu sur moi, et plus précisément sur la façon dont moi et gamedev sommes connectés. De jure - pas du tout, de facto - j'écris des jeux et des moteurs pour le plaisir et la participation à des compétitions de lampes chaudes. Depuis lors, peu de choses ont changé.


Pour plus de narration et forçant l'atmosphère nécessaire, il est important qu'au début de ce conte je suis un développeur web professionnel .net qui peut utiliser html5, css3 et ... jquery. Pour renforcer l'inattendu «c'est un tournant», nous ajoutons qu'il y a de la méfiance et du dégoût pour JavaScript, assaisonné de:


  • une incompréhension franche de tout ce battage médiatique autour de la langue;
  • un ensemble de blagues sur la dactylographie, l'obsolescence accélérée des frameworks, le nombre + les chaînes-surprises, et plus encore. Vous savez, un ensemble de développeurs tellement standard et gentleman utilisant un langage plus ancien et plus établi (hé, je sais que la plate-forme .net est plus jeune que js, mais pas "adulte" au sens littéral).

Venez!


Septembre 2017. J'ai commencé un nouveau travail à chaud et à lampe avec une nouvelle pile technologique (.net core web api + angular 4) et ma tâche n'était que le backend. Le mot Angular me semblait abusif, npm et nodejs étaient fortement associés aux smoothies et au scooter gyroscopique. Timlid, voyant cela et comprenant, m'a enseigné un court cours sur la façon de lancer tout ce chaitanisme. Tout comme dans cette blague sur les Tchouktches et les chiens dans l'espace. Je me souviens des surnoms de chauve-souris dont j'ai besoin pour commencer (en me souvenant du démarrage de la course de npm, je l'ai trouvé extrêmement inutile pour ma nature tendre), et je me suis immergé dans une ambiance chaleureuse et tube Noyau LED .net.


Octobre 2017. La première cloche. Timlid dit que notre employé de première ligne coud 4 projets immédiatement et me propose de couper une section dans la zone d'administration. Motiver cela, disent-ils, c'est facile là-bas, répétez simplement comment cela a été fait pour l'entité N, seulement maintenant pour M. Au petit rire des collègues qui s'enfuient pour un scooter gyroscopique et une vape pour moi, lisant à la hâte un court programme éducatif sur Angular, par copier-coller et par chance, je Je donne naissance à une section qui, avec des réserves, fonctionne. Timlid est satisfait, je suis sous le choc, et il semble que des tâches sur le backend soient apparues sur le tableau ...


Mais non. Il y a beaucoup d'endossement arrière, il y a déjà peu de tâches pour eux et un champ non labouré à l'avant. Une nouvelle tâche, déjà directement sur le portail, me fait prendre au sérieux. Des collègues s'efforcent de rentrer mon pantalon et de m'emmener dans un salon de coiffure, et pendant une semaine, je me suis plongé dans la lecture de documents sur Angular, TypeScript, npm, webpack et plus encore. Soit dit en passant, l'article sur Javascript moderne pour les dinosaures a beaucoup aidé - https://habrahabr.ru/company/mailru/blog/340922/ .


Après un certain temps, j'ai pu clore des tâches frontales simples, me sentant comme un gardien en l'absence d'une femme de chambre. Toujours en riant de blagues sur le front-end, je suggère que mes collègues porteurs se réunissent et écoutent mon expérience banane-fraise. Tout le monde rit, mais en secret tout le monde veut comprendre quel genre de bouillonnement se produit dans ce front-end rapide (en fait, non).


Sans plus tarder, je raconte l'article ci-dessus de Habr, l'assaisonnant avec mes connaissances de base d'Angular. Mitap est livré avec un bang, et, par la suite, j'en passe une série - sur le front-end pour le backend, qui, cependant, n'est pas si important pour notre histoire. La seule chose importante est que leur mise en œuvre m'a conduit à une étude plus approfondie de la pile moderne de technologies frontales.


Démangeaisons


Au travail, tout s'est avéré, un moment plutôt calme est venu dans la vie de famille et des démangeaisons sont apparues. Tels, vous savez, petits, encore assez fragiles et vivant quelque part à la frontière du subconscient. Il y a trois ans, des pensées ont scintillé dans ma tête, disent-ils, j'ai presque complètement arrêté de faire mon passe-temps - la programmation de jeux. Mais que se passe-t-il si vous combinez de nouvelles connaissances et? ..


J'ai regardé WebGL pendant longtemps, mais plus tôt, j'ai été effrayé par le manque d'aide (saisie, saisie semi-automatique) lors de son utilisation. Et ici, s'il vous plaît - une balle d'argent inexistante dans la chair, Ce même marteau, une fois pris, tout devient des clous. TypeScript


Pour moi, en tant que personne qui connaissait la douleur de l'enfer de rappel, var self = this, bind (this), undefined n'est pas une fonction ... Donc, TypeScript ne me semblait même pas une bouffée d'air frais, mais une sorte de sorcier sur un vaisseau bleu, qui, descendant de ciel, paresseusement m'a jeté - fils, oubliez tout ce que vous saviez sur js avant, et je vais vous montrer à quelle profondeur le trou du lapin. L'analogie semble-t-elle chaotique et en général une sorte de méli-mélo d'autres analogies? Vrai, comme TypeScript lui-même en un coup d'œil.


Classes, interfaces, dactylographie, async, erreurs de compilation et fautes de frappe, complétion de code, travail sans tambourin, comportement let compréhensible au lieu de décourager la var fuck-the-scope. Bien sûr, après un certain temps, j'ai réalisé que le sponsor de la majeure partie de ce bonheur n'est pas du tout TypeScript, mais JavaScript lui-même, dans sa version moderne (ES6 et plus). Mais à ce moment, il semblait que j'avais trouvé un prophète qui mènerait le front à un brillant, communiste l'avenir. Ajoutez à cela les progrès suffisamment sérieux de divers IDE dans le domaine d'Intellisense et l'assistance au développeur, et vous comprendrez peut-être mon plaisir de chiot.


Impuissance


Le premier coup sérieux sous mon souffle fut TypeScript lui-même. Les tentatives de le fixer à un projet vide m'ont fait comprendre - je ne peux pas comprendre une putain de chose en dehors de l'angular et de l'angular-cli qui font beaucoup de sale boulot pour moi. Ai-je besoin d'un compilateur? Ok, vissez-le dans package.json, installez npm, exécutez tsc et ... rien. Ah, avez-vous encore besoin de l'installer globalement? En omettant les détails ennuyeux de ma guerre avec tout ça, je dirai que quelque temps plus tard j'ai appris à transformer main.ts en main.js. Mais devant moi, je m'occupais du webpack.


Oui, maintenant je me rends compte qu'il était possible de se passer de lui. Mais quand dans les mains maladroites de Typescript, tout autour ressemble à angular-cli. C'est déjà après l'implémentation du webpack que j'apprends que le compilateur TypeScript lui-même est capable de «surveiller» les changements dans les fichiers, que le problème d'importation / exportation peut être résolu sans webpack.


Surmonter


Après environ une semaine, j'ai pu créer un projet dans lequel j'ai écrit du code TypeScript, cliqué sur «Enregistrer» et tout s'est déroulé comme il se doit - Webpack a automatiquement recompilé tous mes fichiers en un seul paquet, exécutant d'abord le compilateur TypeScript sur eux, puis déposant la construction dans un dossier séparé où j'ai copié d'autres choses statiques, et dans le navigateur à ce moment-là, lite-server a rechargé la page. J'ai dit que tout s'est passé automatiquement? Non, tout s'est passé automatiquement . Joy ne connaissait pas de limites et je me suis assis pour écrire un simple tireur d'arène.


Où ça commence patrie est le jeu pour moi? Bien sûr, avec des choses de base comme des vecteurs mathématiques et des matrices. J'ai réussi à surmonter le syndrome de Not Invented Here au travail, mais dans un passe-temps, il n'a pas disparu. Je ne voulais pas de bibliothèques prêtes à l'emploi, alors je me suis assis pour écrire mes mathématiques. Non, c'est trop fort. J'ai ouvert mon ancien framework FreePascal ( https://github.com/perfectdaemon/tiny-glr/ ) et commencé à convertir les mathématiques à partir de là.


Pour l'avenir, je dirai que, en général, mon tout nouveau framework est la conversion de l'ancien de Free Pascal en TypeScript. Compte tenu de plus d'une interruption de trois ans dans le développement de jeux, je ne pouvais pas trouver une meilleure architecture, ni même me rappeler quels étaient les inconvénients du passé.


Après un certain temps, j'ai commencé à m'essouffler: la motivation a naturellement diminué, la charge de travail a augmenté. Et puis sur igdc a annoncé un autre concours. Et croyez-moi, la compétition est un excellent motivateur externe qui fixe des limites thématiques, techniques et temporelles.


Compétition


J'ai déjà dit dans mon dernier article la folie igdc , mais je vais répéter brièvement ici - c'est une communauté de lampes chaleureuse qui organise des concours de courte ou moyenne durée pour développer des jeux sur un sujet donné. Sans prix en espèces, sponsors de renom et garanties de sécurité d'emploi. Oh oui, même sans publicité, sans enthousiasme et avec l'implication d'un don volontaire pour l'hébergement et le domaine. Et donc depuis près de 15 ans.


Thème du concours - Jeu d'ordures . Compte tenu d'un ensemble complet et diversifié de ressources graphiques. La tâche des participants est de faire le jeu en l'utilisant uniquement. Le genre et le thème ne sont pas limités, l'utilisation de tous les sons et de la musique est autorisée, car seuls les graphiques sont dans le pack. Il existe une limitation technique historique associée au lancement strictement hors ligne, sans programme d'installation, téléchargement, etc.


Ce dernier est un petit problème, car Chrome et la société interdisent beaucoup de choses lorsqu'un utilisateur ouvre un fichier html localement. WebGL peut ne pas s'activer, les scripts ne voudront pas être extraits, sans parler des ressources graphiques. Il existe un moyen de sortir - nous créons un super petit serveur Web local et un script de démarrage pour l'utilisateur qui le récupérera et ouvrira le navigateur préféré de l'utilisateur à l'adresse souhaitée.


La tâche est simple, je suis entré dans un exe de 6 kilo-octets en C # et un surnom de chauve-souris à proximité, qui définit le dossier racine du serveur et du port.


Mais, assez sur ce petit obstacle à un objectif grand et propre - écrire un jeu pour la compétition.


Jeu de compétition


En regardant les ressources, j'ai réalisé que le tireur d'arène avec leur utilisation se révélerait assez solide.


Après avoir terminé les choses de base, j'ai procédé à la sélection des ressources dont j'avais besoin. Le découpage final sous la forme d'un atlas de texture ressemble à ceci:



À propos, certaines choses cuites sur l'atlas n'ont jamais été utilisées dans le jeu. Après avoir chargé les ressources, j'ai commencé une nouvelle fonctionnalité pour moi - l'animation de sprite. J'étais heureux quand j'étais enfant quand tout s'est avéré:



Propre physique


Connecter la physique des autres avec le désir effréné d'inventer tout le mien semblait au moins blasphématoire, et, il me semble, n'était même pas considéré par mon organisme enthousiaste (je viens de vaincre l'animation de sprite, vous vous souvenez?). De plus, qu'est-ce qui peut être difficile dans un traitement de collision simple basé sur des rectangles (boîte englobante alignée sur l'axe, AABB) et des cercles? Beaucoup de choses. En commençant par coincer un personnage dans des coins invisibles et en terminant par le fait que vous amenez tous les objets de votre monde dans des rectangles et des cercles.


Il n'a pas été possible de résoudre tous les problèmes, mais une physique est néanmoins apparue:



Les sons


Je m'attendais discrètement à ce que ce soit difficile. En fait, cela s'est avéré d'une manière étrangement simple et efficace. Nous avons créé un contexte audio, créé un tampon audio, mis de la musique / des sons dans n'importe quel format acceptable pour le navigateur (j'ai utilisé wav), créé un nœud et dit à partir de quel tampon jouer.


Les sons que j'ai générés en utilisant bfxr ( https://www.bfxr.net/ ).


Kaki


Béquilles, décisions ad hoc, podhachivaniya - il est difficile de trouver une personne qui ne connaît ces mots que par ouï-dire. À la fin du concours, j'ai inséré quelques sauvegardes notables.


Il n'y avait pas de sortie de texte - HTML utilisé


À la fin du concours, il est devenu clair que je n'aurais pas le temps de transférer le rendu du texte au moteur. Même sans générateur. Il y avait de nombreuses options, en voici quatre principales:


  1. Rendu de texte sur un canevas 2D transparent qui se trouve au-dessus du canevas avec WebGL.
  2. Faire un jeu sans texte
  3. Cuire les mots nécessaires et les utiliser comme sprites
  4. HUD de sortie en html

Selon les termes du concours, il était possible d'utiliser uniquement la police de pixels personnalisée fournie, de sorte que la première option (rendre le texte sur une toile 2D) a été supprimée. Le canevas peut être rendu en utilisant uniquement les polices système. Les polices chargées dans css via fontface fonctionnent extrêmement instables.


Jouer sans texte est une excellente option créative. C'est dommage qu'avec la créativité à ce moment-là, je me sentais déjà mal.


Le vocabulaire minimum requis était important et gonflait la taille des actifs. De plus, l'affichage des nombres nécessitait encore une certaine logique.


Et enfin, nous sommes arrivés à la vraie béquille, que j'ai utilisée - je viens d'implémenter le HUD en tant que balisage html sous le canevas, de connecter @fontface à css et d'organiser la mise à jour via l'API DOM standard (getElementById).


Redémarrage du jeu - document.location.reload ()


Lorsqu'un joueur meurt, il veut soit fermer la partie, soit recommencer. Malheureusement, si vous ne fournissez pas de mécanisme de redémarrage dès le début et ne tachez pas l'état du jeu sur un tas de classes mal organisées, vous n'obtiendrez aucun bon redémarrage. Il y aura toujours un endroit magique qui n'a pas été remis à zéro.


Une excellente béquille dans ce cas était un rechargement de page banal via l'en-tête document.location.reload () mentionné dans l'en-tête. Compte tenu de la petite taille de la version finale (moins de 300 ko, toutes ressources comprises) et du fait que le jeu fonctionne localement, la vitesse de redémarrage peut être négligée.


Qu'est-il arrivé?



Vous pouvez l'essayer en ligne ici: https://perfectdaemon.imtqy.com/151/index.html
Lien vers le référentiel: https://github.com/perfectdaemon/ts-game
La version du référentiel avec le code source de ce jeu: https://github.com/perfectdaemon/ts-game/releases/tag/0.1.0


La conclusion est une fin agréable.


En conclusion, je voudrais brièvement décrire les avantages et les inconvénients subjectifs de l'écriture de jeux sur WebGL + TypeScript.


Avantages


  • Écrivez une fois, jouez / déboguez partout. C'est très cool que je puisse simplement mettre le jeu sur imtqy.com, et n'importe qui peut y jouer depuis n'importe quel appareil avec un navigateur. Naturellement avec un certain nombre de réserves.
  • Après certains paramètres et l'ajout de TypeScript, travailler avec JS moderne n'est pas si mal.
  • Pratique pour créer du contexte (par rapport à Win API et OpenGL)
  • Il existe un outil pratique (Visual Studio Code), qui est bien équipé avec des plugins et aide vraiment à écrire du code à travers des conseils, des extraits et des notes sur les zones à problème.

Inconvénients


  • Javascript s'exécute dans un seul thread. Et le problème n'est même pas que vous vouliez considérer la physique ou la logique dans des flux séparés. Le profilage a montré que les appels WebGL bloquent, c'est-à-dire ils attendent que le contrôle revienne du pilote de la carte vidéo avant de poursuivre l'exécution du code. Bien que la plupart des appels WebGL ne renvoient rien d'autre que nul. Les implémentations OpenGL de bureau (dans certains pilotes) pour de nombreuses fonctions rendent le contrôle instantanément, ce qui augmente considérablement la vitesse de rendu.
  • Un petit pas à gauche / à droite - et vous êtes complètement seul. Vous avez un problème avec Angular et Typescript? Les deux premiers liens vers le débordement de pile vous aideront. Il y avait un désir de se faire des amis avec Typescript séparément et un étrange bug / question est survenu? Préparez-vous au fait que vous pourriez bien être seul. Bien sûr, en tant que personne qui a déjà écrit sur la pile (non) très populaire de FreePascal + OpenGL, je suis habitué. Mais dans le cas d'un langage mature comme C ++, il y aura toujours un Indien qui a déjà résolu un tel problème. Et puis les Chinois, qui l'ont résolu en utilisant le contrôleur de Guitar Hero et Arduino.

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


All Articles