Plonger dans la création d’un jeu vidéo à partir d’un simple jeu de société

J’ai créé un prototype de jeu vidéo basé sur un jeu de société. Découvrez cette histoire mêlant abandon, persévérance et évolution. Qui a mené à la création de ma chaine Youtube et à un besoin de partage.

Il y a quelques mois j’ai créé un prototype de jeu vidéo basé sur un jeu de société que j’apprécie nommé pingouin dans lequel on amasse des points en récupérant des poissons en déplaçant des pingouins sur des cases de banquises hexagonales.

Ce qui ne devait être qu’un prototype

Au début de ce projet mon but était de travailler sur des algorithmes de déplacements hexagonaux simples. Mais aussi de réfléchir et d’implémenter mon propre système d’intelligence artificielle. Ou encore de rendre le jeu multijoueur.

Tout était bien parti

Je me suis pris au jeu et j’ai fini par réaliser le jeu en 3 étapes

  • Créer le prototype jouable en mode console
  • Transfert du code dans Unity et création de l’affichage
  • Développement du mode multijoueur / jeu contre l’ordinateur

La première étape m’a pris 5 soirées, la seconde 2 soirées

Quand tout a dérapé

J’ai pris la décision de créer une interface avec un écran d’accueil, un écran de paramétrage de la partie, etc ce qui m’a pris plus de 10 bonnes soirées et 1 ou 2 week-end. Et c’est là que les temps de développement ont explosés mettant en péril la publication de mon projet.

Certes j’avais une interface graphique mais il fallait revoir la gestion du plateau, les couleurs, la police d’écriture, la génération du plateau et cela plusieurs fois. Chaque modification qui n’avait pas été prévue à commencer à me prendre un temps monstrueux jusqu’à ce que je ne prenne presque plus de plaisir sur ce projet. J’ai quand même persisté en ajoutant le jeu contre l’ordinateur et en réfléchissant à l’implémentation du mode multijoueur. Mais le mal était fait. J’avais visé trop haut pour une aventure de codeur en solitaire sur mon temps libre.

Une lumière au bout du tunnel

J’ai profité de l’été pour regagner quelques forces et reprendre des activités un peu plus sociales comme les barbecues ou les sorties au lac. Suite à de nombreuses discussions, des connaissances m’ont fait comprendre une chose importante à propos de mes différents projets.

Mes projets sont une source d’inspiration

Ce n’est pas parce que je galère qu’il ne faut pas persister et que la direction n’est pas la bonne, au contraire. Toutes les personnes avec qui j’ai parlé cet été m’ont avouées la suprématie de l’informatique dans le monde du travail et même dans la vie de tous les jours. Ils ont réussi à me faire prendre conscience de la force de mes compétences. Et à me rappeler toutes les galères que j’ai surmontées tout au long de mon parcours ce qui a fini par me décider à promouvoir plus mes projets et à mettre en avant mes réflexions, mes échecs, mes découvertes et mes réussites.

Ce qui m’a conduit à créer des vidéos

Il faut cultiver notre jardin, par cette phrase de Candide écrit par Voltaire j’entends désormais bien plus que le simple fait de reprendre chaque année un carré de terre pour en faire jaillir de beaux fruits et légumes. En effet, ça fait plus d’une dizaine d’année que je cultive moi même des connaissances en partageant une partie de ma production mais en oubliant une étape importante. Celle d’en partager les graines. Ces graines ce sont mes vidéos.

Et apprendre à mieux maitriser le sujet

En créant des vidéos j’ai commencé une nouvelle activité. La rédaction et la recherche d’informations pertinentes en plus du montage vidéo et de la création de contenu. Tout ça dans le but de mieux maitriser mon sujet et que la graine prenne dans mon audience.

Et c’est pourquoi

J’ai imaginé une nouvelle série de vidéos qui démarre par l’analyse entre les jeux de société auxquels j’aime jouer et leur portage en jeux vidéo. Ce qui implique toute une analyse comparative des avantage et des inconvénients de ces deux pratiques. Je découvre moi même un nouvel éclairage sur ce qui manquait à mon prototype initial et que j’aimerais pouvoir transmettre dans le futur par l’intermédiaire de mes vidéos.

Enfin la vidéo

Elle est à regarder sans modération. Et à partager si elle vous plait.

Pour mieux comprendre

Si vous ne l’avez pas encore vue, vous pouvez regarder ma série de trois vidéos qui traite de la création d’un jeu de société en utilisant uniquement un ordinateur, un logiciel libre de dessin vectoriel « Inkscape » ainsi qu’une imprimante et une paire de ciseaux ou un cutter.

Positionner un GameObject dans la hiérarchie (Unity3D)

Alors voilà, mon problème aujourd’hui est de positionner un gameObject fraichement initialisé dans mon script dans la hiérarchie d’un autre gameObject étant devenu son parent (SetParent()).

Pour cela j’ai trouvé la fonction setSiblingIndex() à appliquer sur le « transform » de votre objet à positionner dans la hiérarchie.

Le code :

 public void chargeAllButtonMap(){
        int i = 1;
        foreach (MapInfo mi in Global.param.tableMapInfo) {
            GameObject buttonMap = Instantiate(buttonMapPrefab, Vector3.zero, Quaternion.identity) as GameObject;
            buttonMap.transform.SetParent(mappemonde.transform);
            buttonMap.transform.SetSiblingIndex (1);
            buttonMap.name = "buttonMap_" + i.ToString("D3");
            buttonMap.transform.localPosition = new Vector3 (mi.x, mi.y);
            buttonMap.transform.localScale = new Vector3 (1, 1, 1);

            ActionButonLoadMap ablm = buttonMap.GetComponent<ActionButonLoadMap>();
            ablm.idPartieIs = i.ToString("D3");
            i++;
        }

        buttonIsCharged = true;
    }

Le résultat :

Mes boutons se placent bien à l’index 1 entre Image et AcheterMapPanel. Ils ne seront plus affiché devant mon objet AcheterMapPanel mais bien derrière.

Comment fermer une fenêtre dans Unity3D ?

Aujourd’hui nous allons essayer de fermer une fenêtre ouverte dans Unity3D. Pour cela il faut une fenêtre ouverte (panel) dans un Canvas.

Problématique :

  • Nous ne voulons pas fermer cette fenêtre (InventoryWindows) d’une quelconque manière mais en appuyant simplement en dehors de celle-ci.
  • Il faut que la fermeture de la fenêtre puisse s’exécuter aussi sur mobile (soit sans curseur de souris).

Dans un premier temps je n’ai pas pensé à adapter cette fonctionnalité à l’utilisation d’un écran tactile. Or, mon premier réflexe a été d’ajouter un contrôle sur un booléen (mouseIsOut), si mouseIsOut vrai alors fermer la fenêtre, sinon ne rien faire. J’ai mis le tout dans la fonction LateUpdate() de la classe définissant la gestion de ma fenêtre. Quand la souris sors du Panel (Event Trigger –  PointerOut) alors on met mouseIsOut à vrai. Au contraire, à l’ouverture du panel ou l’entrée de la souris dans le panel on met mouseIsOut à faux.

Avec cette méthode qui marche très bien sur PC on rencontre bien vite un problème quand on passe sur un écran tactile. En effet, l’écran tactile ne considère pas de curseur tant que notre doit n’est pas en contact avec la surface. On ne peut donc pas détecter la sortie du curseur du Panel à l’aide de l’Event Trigger en mode PointerExit… (Sauf si l’utilisateur déplace son doigt sans le lever de l’intérieur à l’extérieur du panel.

Recherche d’une autre solution :

Pour palier à ce problème j’ai trouvé une solution facile à mettre en œuvre.

  • Faire d’un panel un bouton quitter géant et situé à l’arrière de notre fenêtre.

En bleu (écran + objet actif) vous pouvez voir le panel sur lequel j’ai ajouté un Event Trigger et le script permettant de mettre mouseIsOut à True si il y a détection de clic sur ce panel.

Il vous suffit alors de mettre mouseIsOut à false quand vous ouvrez la fenêtre (ici l’inventaire) et le tour est joué.

Note : vous pouvez aussi détecter si votre fenêtre est active (isActive = true) pour économiser l’utilisation d’un booléen.

Unity3D : gestion des bords de l’écran

Définition du problème

J’ai passé quelques temps à comprendre comment gérer la détection des bords de l’écran pour ne pas que mon gameobject en sorte.

Dans mon cas le gameobject dirigé par le joueur est un cube auquel on ajoute un BoxCollider, la caméra est fixe.

Dans Unity on gère la position d’un objet par son attribut position (un Vector3 donnant le positionnement du centre de l’objet).

Malheureusement pour moi le composant camera de Unity permet seulement de trouver la taille en pixels de l’écran (maCamera.pixelHeight et maCamera.pixelWidth) et donc je me suis mis à chercher un moyen de déterminer en pixel l’endroit où se trouve mon cube afin de savoir si celui-ci est en dehors ou en dedans de l’écran. En gros si mon cube est entièrement visible ou non !

De l’intérêt d’utiliser un BoxCollider

Pour déterminer le centre de mon cube ainsi que sa taille j’utilise les valeurs récupérables dans l’attribut bounds du composant :

//dans start()
joueurX = this.GetComponent<Collider>().bounds.size.x/2;
joueurY = this.GetComponent<Collider>().bounds.size.y/2;

//dans update()  centreJoueurX = this.GetComponent<Collider> ().bounds.center.x; centreJoueurY = this.GetComponent<Collider> ().bounds.center.y; 

Aux tests à effectuer

if (maCamera.WorldToScreenPoint(new Vector3(0,(centreJoueurY+joueurY),0)).y > pixelHeight) {
//on stop le déplacement
directionJoueur = 0;
this.gameObject.transform.localPosition += (-mouvementY * speed * Time.deltaTime);
} 
else if (maCamera.WorldToScreenPoint(new Vector3(0,(centreJoueurY-joueurY),0)).y  < 0) {
directionJoueur = 0;            this.gameObject.transform.localPosition += (mouvementY * speed * Time.deltaTime);
} 
else if (maCamera.WorldToScreenPoint(new Vector3((centreJoueurX+joueurX),0,0)).x > pixelWidth) {
directionJoueur = 0;             this.gameObject.transform.localPosition += (-mouvementX * speed * Time.deltaTime);
}
else if (maCamera.WorldToScreenPoint(new Vector3((centreJoueurX-joueurX),0,0)).x < 0) {
directionJoueur = 0;                                           this.gameObject.transform.localPosition += (mouvementX * speed  * Time.deltaTime);
}


Voilà pour le système utilisé actuellement, on peut bien entendu imaginer un système pour ne pas refaire les tests à chaque update() mais uniquement au moment voulu.