Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Festicare - Portfolio

Festicare est un jeu coop local à la Overcooked, où les deux joueurs, représentant des intervenants d’un organisme similaire au GRIP, se retrouvent à un festival et doivent servir des festivaliers en donnant des brochures et analysant des échantillons de drogues. 

Il s’agit d’un jeu sérieux réalisé dans le cadre du cours 8GIF225 (Atelier de production de jeu vidéo I) à l’UQAC en collaboration avec le NAD pour le GRIP. La période de production est de 5 mois et l’équipe est constituée de 9 artistes et 3 programmeurs (4 pour la réalisation de la tranche verticale). Le jeu a été développé sous Unreal 4.27 en C++ et en Blueprint pour le level design et les interfaces utilisateur.

But

Festicare a comme but d’informer les joueurs sur l’existence du GRIP comme ressource dans les festivals et de donner de l’information de base sur les effets et durée des drogues communément retrouvées dans les festivals, comme le MDMA, cocaïne, alcool, etc. Notre approche cherche à informer de manière neutre sans idolâtrer ou démoniser les drogues, en ne présentant que les faits, ce qui coïncide avec le but du GRIP, qui a comme moto “Si tu choisis de consommer, choisis aussi de t’informer”. Le projet a comme objectif de pouvoir être utilisé dans les stands du GRIP dans les festivals.

Description du Jeu

Festicare est un jeu en coop local inspiré des jeux de cuisine tel qu’Overcooked. Dans celui-ci les deux joueurs doivent travailler ensemble pour répondre aux vagues de clients cherchant de l’information ou voulant faire tester leur échantillon de drogue. Pour ce faire, les joueurs doivent apprendre les différents effets des drogues pour pouvoir donner les brochures demandées au festivalier. Bien sûr, les festivaliers n’ont pas une patience infinie, et chaque niveau est une course contre la montre pour répondre au plus grand nombre de festivaliers possibles.

Tâches effectuées

En tant que programmeur, j’ai eu à implémenter le système de déplacement des joueurs, la création et déplacement des festivaliers et la création des outils de design des niveaux, comme la déclaration des requêtes et du tutoriel.

Mouvements joueur

Ma première tâche réalisée dans le projet est l’implémentation des déplacements des joueurs. Pour réaliser cette tâche, en raison de la simplicité des mouvement sur un plan semi-2d, j’ai utilisé la class ACharacter built-in de unreal avec le component de mouvement de base d’Unreal (UCharacterMovementComponent) légèrement modifié pour obtenir un meilleur game flow. Cette utilisation des systèmes built-in d’Unreal permet une intégration facile des animations. 

Festivaliers

Pour les festivaliers, afin qu’ils puissent se déplacer en file, j’ai créé  un système de waypoints, ce qui leur permet de se déplacer de manière prévisible. Pour ce faire, j’ai créé un arbre AI relativement simple (voir image) permettant une représentation visuelle du comportement du festivalier. Pour aller avec cette approche, j’ai créé une BTTaskNode représentant le comportement de festivalier à l’arrivée du comptoir (ArriveAtWaypoint) dans laquelle le festivalier informe le waypoint de son arrivée et obtient le prochain waypoint. Cette approche permet également au festivalier d’attendre tant que le prochain waypoint n’est pas libre.

L'arbre de comportement des festivaliers

Pour les faire apparaître dans le monde, j’ai créé un acteur (factory) dans le monde permettant de les créer à partir d’une structure de données représentant sa définition, ce qui permet de simplifier leur création.

 

La node Blueprint permettant de faire apparaître un festivalier

Machine d'analyse

La machine d'analyse est un élément cœur du gameplay de notre projet, elle a pour but d'ajouter un délais fixe à la réalisation des commandes et d'ajouter un niveau de complexité par rapport aux requêtes de brochure simple. Notre plan initial par rapport à celle-ci était uniquement d'avoir un délais, mais après quelques tests, nous nous sommes rendu compte que la mécanique était trop simple et après en avoir discuté, nous avons décidé de modifier la boucle de jeu de la station d'analyse. Au lieu de redonner directement l'analyse au joueur, nous devons maintenant donner une brochure à la machine d'analyse. Cette modification ajoute une certaine complexité à la machine d'analyse, qui doit maintenant pouvoir mieux gérer son état. Pour ce faire, j'ai créé un composant d'acteur réutilisable de machine à états fini (finite state machine) permettant de séparer la logique de chaque état dans sa propre classe, allégeant énormément la classe de la machine d'analyse.

Outils

Afin de simplifier le level design, j’ai créé deux bibliothèques blueprint en C++ permettant de simplifier la création des requêtes et du tutoriel dans le level blueprint, où sont créés les festivaliers, leur requêtes et où la gestion du tutoriel a lieu.

Requêtes

La première bibliothèque, et la plus simple, permet tout simplement de créer différents types de requêtes et objectifs de manière déclarative en blueprint. En utilisant le décorateur de fonction BlueprintPure il est possible de créer des fonctions n’utilisant pas la pin d’exécution. Cela simplifie beaucoup la création des requêtes.

Tutoriel

La deuxième bibliothèque permet elle aussi de créer un élément de design de manière déclarative à l’aide des blueprint, mais se concentre sur le tutoriel. Celui-ci étant une structure en arbre, il est assez difficile de créer une manière de le créer de manière efficace. Afin d’arriver à la créer de manière simple et intuitive, j’ai créé, comme pour les requêtes, des fonctions BlueprintPure, ce qui permet de déclarer l’entièreté du tutoriel sous forme d’arbre et d’associer des événements au cycle de vie de chaque node du tutoriel.

Un exemple de déclaration de tutoriel linéaire

Problèmes rencontrés

UI requêtes

Nous avons rencontré un certain nombre de problème de design, surtout lorsqu'il était question de relier notre structure de données relativement complexe à des interfaces graphiques. Par exemple, dans notre tranche verticale, nous avons créé un widget écoutant les événements de la requête, qui s'occupait à ce moment de la gestion de ses objectifs. Cette approche avait un assez grand nombre d'inconvénients, et lorsque nous avons modifié la structure pour que les objectifs puissent opérer de manière indépendante de leur requête, notre ancien système c'est écroulé, nous avons donc repensé notre approche et avons créé des widgets indépendants représentant chaque objectif, ce qui nous a permis de mieux gérer cette partie de l'interface utilisateur.

Cycle de vie des festivaliers

Un autre problème de design assez grand a été la gestion de l'état et de cycle de vie des festivaliers. Ceux-ci ont un grand nombre d'états possible: en route vers le bureau, en attente dans la file, en attente d'être répondu au bureau, en attente de completion de requête, sur le point de partir et finalement, en route vers le despawneur. Pour palier à ça, nous avons séparé une partie de la gestion du cycle de vie de celui-ci à sa requête et une autre partie à l'arbre de comportement tel que spécifié plus haut. Malgré cela, une attention particulière a été portée sur la gestion des états du festivalier.

Malgré le fait que la solution actuelle fonctionne, si nous avions eu plus de temps, nous aurions refactorisé cet aspect du jeu pour utiliser un système de machine à états finis, la même solution qui a été utilisée pour la machine d'analyse.

Crash causé par des timers

Notre projet utilise un assez grand nombre de timers, qui permettent d'appeler une fonction après qu'un certain temps soit passé. Nous les utilisons pour le temps d'attente des festivaliers, les requêtes et pour la machine d'analyse. Hors, vers la fin du projet, en faisant des play tests, nous avons découvert un crash qui semblait être entièrement dans du code moteur et qui ne générait pas de stack trace. Il a été très difficile pour nous de trouver l'origine de ce crash, mais après plusieurs heures de débogage, nous avons trouvé que les timers associé à un niveau n'étaient pas détruit lorsque l'on changeait de niveau, et que ceux-ci essayaient d'accéder au niveau qui venait d'être détruit lorsque le délais spécifié était passé. Une fois que l'on a trouvé le problème, il a été assez facile de détruire manuellement les timers lors de la destruction de l'objet parent.

Impacts et futur du projet

Le projet n'étant pas encore publié, les impacts de celui-ci ne sont pas encore clairs. Pour ce qui est du futur du projet, nous espérons que le GRIP trouve le projet assez intéressant et qu'il l'utilise pour faire la promotion de ses services et de la sensibilisation par rapport à l'effet des drogues. De plus, une partie de l'équipe serait potentiellement intéressée à travailler avec le client afin d'ajouter de nouvelles mécaniques que nous n'avons pas eu le temps d'intégrer, comme la distribution de bouteilles d'eau et de naloxone, deux services que le GRIP offre dans les festivals.

Support this post

Did you like this post? Tell us

In this post

Mentioned in this post