Debug Mode

Le projet  »projectiles objets » est bien entamé, mais j’ai dû ralentir le pas un peu la semaine dernière.  L’angle des mes *(big) bullets n’était n’est jamais bon.  Et là, je me gratte la tête, et me gratte la tête, pour finalement me dire que ça me fait chier de ne pas pouvoir suivre mes variables en temps réel.  Il me semble que ça m’aiderait à voir là ou ça cloche, non?  Et puis VisualStudio ne me permet pas de suivre des variables de cette façon.  Un breakpoint, ça n’aide pas dans un code de jeu vidéo…

Donc là, pas mal en retard vous me direz, je me suis dit que je n’avais qu’à m’en écrire un, debugeur!  Des fois j’oublie qu’un programmeur est supposé de programmer des trucs.

Voici donc le résultat, mais avec les *(big) bullets qui partent encore dans de drôles de sens.  Hey, je ne pouvais pas régler le problème, je créais des outils pour m’aider à potentiellement, un jour, régler le problème… ou non…

 

*Non, big bullets n’est pas une marque déposée.  Je voulais simplement spécifier que la balle du fusil ne sera pas grosse comme ça dans le produit fini.  Elle sera plutôt (normal) bullet 😉

 

Déjà 5 mois?

Hum, apparemment, j’ai perdu mon combat conter la réalité 😉

Cinq longs mois sans écrire une ligne de code, ni dessiner un petit bonhomme.

Et bien, qu’à cela ne tienne, je me relance plein d’énergie et surtout plein de nouvelles idées en ce beau mois de septembre!

Pour être franc, ça fait près de deux semaines que je suis de retour devant Visual Studio, mais j’ai eu quelques difficultés à synchroniser mon projet bien au chaud sur BitBucket avec mon nouveau PC (l’ancien est malheureusement décédé d’un cancer de la carte mère).  Il n’y a rien à faire, sans blague, même si je me sers de SourceTree sur une base très régulière, les arcanes profonds du monde du Repository me seront étrangers à tout jamais.

Mais à force de cliquer un peu partout, tout s’est reconnecté et nous voilà de retour avec un tout nouveau Visual Studio (2015) et un tout nouveau PhotoShop (CC2015), wow!

Sachez que, même si je suis resté tout l’été, à l’instar de la cigale, loin de mon clavier, j’ai malgré tout cogité sur le projet qui nous intéresse aujourd’hui.  Et j’en suis arrivée à la conclusion qu’il y avait un problème de gameplay majeur qui se dessinait à l’horizon.  Lorsque nous nous sommes laissé en mai dernier, mon  »méchant » avait enfin la capacité de faire feu sur notre héros.  La méthode du  »hitscan » était utilisée et même si elle avait l’avantage d’être relativement simple à programmer, je ne suis pas satisfait de l’effet que cette technique donne en jeu.

Vous vous souvenez peut-être que mon objectif est d’avoir une bonne quantité d’ennemis à chaque moment dans l’espace de jeu.  Je me retrouve donc avec de quatre à douze boches qui peuvent nous tirer dessus sans crier gare, et surtout sans que le joueur ait la chance d’éviter le coup ou de sortir le terrible bouclier.  J’ai retourné ça de tout les côtés, et je ne parviens pas à trouver un moyen convainquant d’avertir que le coup de feu s’en vient sans que nous voyons la balle se déplacer.  Il y aurait trop d’information à gérer en même dans l’interface il me semble.

Mon projet de septembre est donc d’implanter un nouveau système de projectile constitué d’objets, plutôt que de simples trajectoires.  Les balles iront donc plus lentement.  À quel point lentement, c’est ce qu’il nous restera à évaluer une fois le machin fonctionnel.

Le gameplay risque d’être plus agréable de cette façon, et le niveau de difficulté plus gérable.

Je me mets là-dessus de ce pas.

Bien content d’être de retour avec vous, dans mon sous-sol!  🙂

 

 

Défier la réalité

On pourrait croire, à ce titre, que je veux vous parler d’un concept de jeu vidéo, d’une méthode pour simuler la gravité, de l’impact d’un projectile ou du calcul de la simulation de la friction sur un tilemap, mais non.  Ce soir je veux vous parler de la vrai réalité, celle réelle, la réalité non virtuelle.

En cliquetant un peu hier soir, je me suis aperçu que je n’avais écris aucune entrée en avril.

Nada.

Bon, je ne mesure pas l’avancement de mes travaux en fonction du nombre de blogs que j’écris, ne vous inquiétez pas, mais il est notable que j’écris des trucs quand je suis excité à cause d’un avancement quelconque, ou d’un nouveau feature qui fonctionne bien.  Donc, en avril.. ouin…

À chaque année j’oublie qu’avec l’arrivée du printemps, mon ERPDJ (énergie résiduelle post day job) baisse à un niveau dramatiquement bas.  Oh, je suis encore de bonne humeur, et je fais la vaisselle et joue avec les enfants comme d’habitude, mais de me confronter à une tâche plus intello en soirée devient tout à coup un étrange passe temps.  Y’a vraiment des gens qui font ça après le boulot?  Je me surprends à vouloir m’écraser devant la télé, ou lire un roman léger de vacances (pas du Baudrillard, genre).  J’ai même écouté un bout de Pénélope McQuade plus tôt avec JO!  Shit…

Voici donc le moment de défier la réalité.  Ma réalité du moins.

Je me mets au défi, cette année, de continuer à produire du matériel malgré le parfum de chlore et de vinyle* qui plane, de tenter de ne pas tout mettre de côté pendant trois mois.  D’au moins y toucher sur une base régulière, à défaut de garder un rythme soutenu.

Et pour vous (me) prouver ma bonne foi, voici une petite nouveauté.  Je ne suis pas très satisfait de l’animation, à être retravailler.  Et l’impact de la balle arrive beaucoup trop de temps après le coup de feu.  Le hitscan se fait après que l’animation soit terminé, voilà pourquoi.  Je travaille là-dessus aussi.

Le point le plus intéressant ici n’est visible qu’avec les yeux du geek : l’animation du méchant est contrôlée par une toute nouvelle classe AnimationHelper qui va pouvoir désormais gérer toutes les animations.  Une belle petite classe concise et maléable – y’a même des commentaires!

Je travaille aussi sur le thème musical du jeu tranquillement.  J’ai écrit une partition de piano.  Ça devait faire un zillion d’années que je n’avais pas écrit une partition de piano…

On entendra ça un de ces quatre.

*Pour vous autre, c’est l’odeur du chlore qui vous vient en tête lorsque vous pensez au Club Piscine.  Moi, c’est l’odeur du vinyle qui compose les toiles neuves.  Ça c’est le vrai parfum du printemps!  Le chlore, je ne le sens plus depuis longtemps… 🙂

Ça ne  »scalera » pas ton affaire!

C’est la première chose que mon frère m’a dite en voyant le code de mon premier petit projet, un clone de Pong.  J’étais assez fier que mon code compile, et qu’en plus, le jeu fasse à peu près ce qu’il devait faire.  Mais là, mon code ne scalait pas?  Merde, je ne comprenais même pas ce que ça voulait dire.

Pour nous mettre en contexte, mon frère est programmeur de métier, ce qui fait de lui mon espèce de mentor.  Mentor qui me jette des répliques de ce genre et qui me laisse me démerder pour régler le problème 🙂  Est-ce que Aristote faisait ce genre de coup à Alexandre?  J’en doute…

Comme mon Pong était vaguement terminé, je le mis de côté, malgré qu’il lui manqua la vertu de scaler adéquatement, et je me mis à mon projet suivant, le super-super célèbre Fraisinette.  Ce jeu était plus ambitieux.  Il devait contenir plusieurs niveaux, une carte du monde, un tilemap, un engin de particules, de la musique, et j’en passe.

C’est là, après m’être empêtré quelques semaines dans tout ça, que j’ai compris ce qu’il voulait dire.  Apprendre un langage de programmation, les if et les float, les for et les semicolons, c’est une chose.  On lit, on réfléchit, on s’entraîne et ça entre, tranquillement.  Apprendre à architecturer du code pour qu’il ne devienne pas un immense spaghetti inextricable, c’est un art.  Et je ne dis pas ça légèrement.  On sort de la science des Sciences Informatiques et on entre dans l’Art informatique.

Donc, le terrible scaler veut dire que je dois structurer mon code pour que je puisse faire grandir le projet tout en :

a) évitant de tout briser ce qui est déjà fait.

b) tentant de garder le tout compréhensible / lisible.

c) s’assurant que je puisse ajouter des nouveaux trucs (features) simplement, sans avoir à réécrire des pans entiers de la machine.

Ok, alors je me mets au travail et je passe plusieurs mois à construire Fraisinette avec ces beaux préceptes en tête, et il me semble que ça se déroule pas mal.  Le jeu fait ce qu’il doit faire et mon petit Aristote de frère à même l’air de trouver ça pas pire.  Alors que le jeu est très avancé (pas mal dans son état actuel pour être franc – trois niveaux jouables), il jette un oeil sur mon repo (sur mon code) et… ça ne scalera pas ton affaire!

ARRRGG!

Bon, je ne suis pas complètement découragé.  J’ai appris beaucoup de chose en fabriquant Fraisinette (pour preuve, je sais de quoi il parle cette fois!), et somme toute, le programme fait ce que je lui demande de faire, ce qui est l’objectif principale d’un programme, non?  Mais il a un peu raison.  J’ai poussé le concept de l’orienté objet beaucoup plus loin cette fois, mais les classes ont beaucoup trop de responsabilités et il y a moyen de rendre les objets plus interchangeables, évidement.

En m’attaquant à One man’s, je savais que le défi allait en croissant et que le code de ce jeu avait un potentiel d’inflation immense.  Je me devais donc d’écrire chaque classe, chaque méthode, en ayant la scalabilité (est-ce que je pousse trop la francisation là?) en tête.

À chaque instant.

Je me suis donc appliqué à diviser les choses.  Le code pour le héros, du code pour chaque tableau, le code pour le premier ennemi, etc.  Mais là, il faut que je me rende à l’évidence. La classe qui gère mon héros est trop longue, contient trop de gestion d’états et de gestion d’animations.  Ça devient risqué de changer quelque chose.  La classe de l’ennemi est partie pour être tout aussi bordélique, avec la gestion de l’AI en plus.  Et la classe qui gère le premier niveau s’occupe de l’effet parallaxe et du brouillard, ça n’a pas de sens…

Alors, cette fois je me le dis moi-même : ça ne scalera pas mon affaire 🙂

Je me retrousse les manches, et je refactor et brasse la soupe pour améliorer le tout, et bientôt, il y aura un combat entre moi et ce boche, vous allez voir.

Ah oui, vraiment un art…

Penser en 16,7 millièmes de seconde

Lors d’une discussion avec un camarade indie développeur (!) il y a quelques temps, nous abordions le sujet de la  »game loop » et comment elle nous avait obligé à changer notre façon de penser.  Ou plutôt, comment nous avions eu une certaine difficulté à changer notre façon de penser!

Le code d’un jeu vidéo est une seule et immense boucle.  Dans le meilleur des mondes, cette boucle sera répétée 60 fois à toutes les secondes.  Cela signifie que le processeur repassera à travers tout le code, et dessinera tous les éléments du jeu présents à l’écran à tous les 16,7 millièmes de seconde.  La vitesse à laquelle un processeur pour digérer de l’information est astronomique et donne un peut le tournis.  À tous les 16,7 millièmes de seconde, l’ordinateur vérifie la position des éléments du jeu, vérifie s’il y a des  »inputs » provenant du clavier, de la souris ou de la manette de jeu, il s’assure que le son adéquat sort des hauts-parleurs, et redessine aussi les éléments à l’écran en fonction des règles établies par l’engin (sprites, effets, particules, ombres et lumières, éléments de l’interface de jeu tel le pointage et barres d’énergie).  Et étrangement, ça fonctionne…

Tout ça va tellement vite, qu’un humain ne peut tenter de raisonner toutes ces commandes en temps réel.  Le développeur doit faire exactement le contraire pour parvenir à s’y retrouver.  Il faut ralentir le tempo, il faut penser en 16,7 millièmes de seconde.  Il faut penser un seul tour de boucle, un seul cycle, et s’assurer qu’il ne se contredise pas et qu’il couvre tous les angles, toutes les possibilités.

Et là réside la difficulté.  Il faut se sortir de la peau du joueur qui voit le spectacle en mouvement, et s’installer confortablement dans un monde statique et figé.  Une seule  »frame » des fameuses  »frames per seconde ».

Un cas classique, à titre d’exemple (et qui était justement la base de notre discussion d’il y a quelques temps) : je veux déplacer le héros de mon jeu vers la droite.  Je programme donc le jeu pour qu’il déplace le personnage d’une petite distance vers la droite lorsque la flèche droite du clavier se fait enfoncer.  On démarre le jeu et… le héros ne bouge pas d’un iota, ou pire, il disparaît!  Je vérifie, et oui, je demande effectivement au héros de se déplacer.  Ça veut dire que quelque part, dans mon programme qui ne dure que quelques millièmes de seconde, je contredis cette commande et ramène le personnage à son emplacement initial!  Et ça va tellement vite que ça ne parait pas à l’écran.

Bordel…

Reste à déboguer maintenant.  Tranquillement.

À 16,7 millièmes de seconde …

Hitscan

Oh yeah!
Encore une fois, rien de visuellement spectaculaire, mais on touche à quelque chose là!

 

 

Bon, ce n’est peut-être pas très clair, mais quand le héros devient rouge, c’est parce qu’il vient de se faire descendre.
Et non, je ne triche pas. L’algorithme n’est pas  »if(méchant tire) {héros devient rouge;} 

Croyez-moi, il ne voulait pas devenir rouge au début 😉

J’utilise une technique qui se nomme  »hitscan » et qui est surtout utiliser dans les shooters 3D.  L’idée est de tracer une ligne partant de la mire du tireur et de considérer ce qu’elle rencontre comme cible atteinte.  Et évidement, dans mon cas présent, la ligne ne vérifie pas tout ce qu’elle croise. Elle ne vérifie qu’une chose : si elle croise un cercle de détection entourant le héros, une  »Bounding Sphere ». Comme le calcul à faire est très léger, il n’y a pas de hiérarchie de spères de détection ici. Si un jour je veux savoir si la balle atteind la tête du héros, ou son  »bas du corps » comme dirait les gars de hockey, j’aurai besoin de différentes sphères de différentes tailles, mais bon.

Pourquoi, me direz-vous, ne pas plutôt projeter une balle virtuelle du fusil et vérifier si elle entre en collision avec sa cible?

Parce que:

  • Faire des calculs de ballistique sur un objet supplémentaire (multiplié par les dizaines de projectiles que la mitraillette projète) dans le monde du jeu, c’est compliqué.  Le vent? Le spin du projectile? Sa vitesse? La gravité? Est-ce qu’il disparait une fois au sol? Le CPU moderne sont capables d’en prendre, mais pourquoi les taxer inutilement. Et je ne parle pas de la quantité de code nécessaire pour accomplir cette tâche.
  • Tout ces paramètres réalistes font que ce n’est pas du tout cool de jouer au jeu!  Le niveau de difficulté vient de quadruplé lorsque vient le temps d’abattre un ennemi. S’il faut calculer la vitesse de déplacement de l’ennemi en fonction de sa distance en plus du taux d’humidité relatif pour faire un  »kill », le fun factor tombe à une vitesse folle. Et oui, on se trouve pas mal bon à Call of Duty et Left For Dead parce que la physique des projectiles est complètement fausse!   Oh, et les chars dans la réalité ne se comportent pas comme dans Need For Speed sur la route non plus 😉
  •  À cause du tunneling (j’en reparlerai une autre fois si ça vous tente).

Bon, mon problème du moment est d’ajuster mon méchant pour qu’il ne soit pas trop bon, et ce n’est pas si facile.  Dans cette première itération, si le bouclier du héros n’est pas en fonction, il fait mouche à tous coups.  L’autre point est que, comme l’utilisation du bouclier sera un point important du gameplay, il faut que le joueur recoive un indice du moment à lequel l’ennemi va tirer. Il va donc falloir un truc visuel ou sonore pour avertir le joueur – mais il ne faut pas que ce soit trop évident non plus!
Avec l’engin qui commence à prendre forme, le gamedesign va prendre de plus en plus de place.

Bon, maintenant que le code fonctionne, je n’ai plus le choix.
À mes pinceaux!
La prochaine vidéo devrait montrer les mêmes trucs, mais visuellement intéressant.
Ça devrait…

 

Finite State Machine

Pour ceux d’entre vous qui sont familiers avec les Design Patterns en science informatique, le concept de  »State Machine » vous sonne probablement un son de cloche.

Il s’agit probablement de la façon la plus basique de générer de l’intelligence artificielle dans un jeu vidéo, mais généralement efficace dans le contexte d’un Hack ‘n Slash en 2D.

L’idée est de donner à un NPC (à mon ennemi / boche dans ce contexte) un arbre d’états possibles et de gérer ces états en fonction des événements se déroulant dans le monde du jeu.  Le terme  »finite » dans Finite State Machine signifie que le nombre d’états de l’intelligence est fini, et qu’il ne pourra y avoir qu’un état présenté à la fois.

Mon ennemi peut donc avoir faim, ou avoir soif, mais pas les deux en même temps 🙂

Dans l’exemple suivant, qui est mon premier prototype qui aura à être peaufiné (mais l’idée est pas mal là), le méchant présente différents états :

il peut patrouiller, pourchasser le héros, s’en éloigner pour avoir un bon angle de tir sans recevoir un coup de tomahawk sur la gueule, il peut aussi tirer et, comme il n’a que quatre balles dans son magasin, il doit aussi recharger parfois.

Oh, et je disais plus haut que l’algorithme ne permettait qu’un seul état à la fois, et bien j’ai un peu menti.  Ici, mon boche utilise deux arbres d’états superposés pour gérer son niveau de conscience du danger.  Pour le moment, il peut savoir que le joueur approche, ou non.  Plus tard, d’autres niveaux de conscience viendront d’ajouter.

Et comme j’ai judicieusement décidé de faire mes tests de code d’abord et de dessiner lorsque le tout serait concluant, il va falloir se servir de son imagination pour aujourd’hui 🙂

Couleur normal = non-conscient de la présence du héros

Bleu = conscient et pourchasse le héros

Vert = tente de garder une distance de tir raisonnable

rouge = prêt à tirer

clignote = il tir!

mauve = recharge après avoir écoulé ses quatre balles

 

Le tout aura à être ajusté bien sûr (vitesse variable, pause à certain moment, donner une impression d’un méchant un peu plus vivant), mais le résultat final sera assis sur cet arbre d’états.

Et comme il se fait tard, je vous raconterai une prochaine fois de quelle façon je m’y prends pour modifier l’état du bonhomme!

 

Keyboard

Bon, je viens de  »droper » le clavier comme contrôleur de jeu supporté pour la suite du développement.  Tout se passe sur la manette de XBoX maintenant.

En fait, je voulais ajouter le joystick de la dite manette (le DPad était déjà utilisable), et je me retrouvais à écrire le code des inputs en triple (clavier, DPad et joystick).

Quand on en sera au point où je vous fournirai une démo jouable (!), je réintégrerai le clavier pour ceux qui n’ont pas de contrôleur XBoX, mais en attendant, je me simplifie un peu la vie.

Faut se faire plaisir des fois…

Oh, et il y a un ennemi, un  »boche », de dessiné!

Il a une moustache, ce n’est assurément pas le boss de la fin :/

 

Boche