Projet image 2013 : Création d'un jeu vidéo à la première personne

De Ensiwiki
Aller à : navigation, rechercher
Project schedule.png
Titre du projet Création d'un jeu vidéo à la première personne
Cadre Projets de spécialité
Page principale Projets de spécialité image



L'équipe

Antoine Bardonnet (MMIS)

Sylvain Planès (MMIS)

Stanislas Radoux (MMIS)

Arnaud Sidrac (MMIS)


Introduction

La création d'un jeu vidéo fait appel à des domaines variés de l'informatique dans le but d'offrir au joueur un univers réaliste, interactif et fluide. Pour notre projet de spécialité, nous avons ainsi choisi d'appliquer différentes techniques acquises à l'Ensimag et plus particulièrement d'approfondir nos connaissances en informatique graphique au travers de la réalisation d'un jeu vidéo à la première personne.

L'action se déroule de nuit, dans un vaste environnement aux paysages variés où le joueur devra faire face à une population de zombies hostiles.

Objectifs

Nous avions deux objectifs principaux dans la réalisation de ce projet :

  • Générer un décors procédural se créant automatiquement et variant à chaque partie
  • Animer une population de zombies

A ces deux objectifs s'ajoute une contrainte transverse : l'ensemble de l'animation doit se dérouler en temps réel. Cette contrainte a des répercussions importantes sur la réalisation des deux objectifs, et sur l'ensemble du projet.

Mise en place du jeu

Scénario

Nous avons dû avant toute chose définir un univers et un scénario pour notre jeu. Ces choix ont été fait en fonction des différents défis techniques auxquels nous devons faire face.

  • La vue à la première personne en plus de rendre le jeu plus immersif permet de ne pas avoir à modéliser ni animer le personnage principal.
  • L'ambiance angoissante se conjugue bien avec la vue à la première personne. De plus le fait que l'action se déroule de nuit, avec un important brouillard permet de limiter le champ de vision du joueur, et donc le nombre d'éléments à afficher.
  • Dans ces conditions, il n'est presque pas étonnant de rencontrer des zombies. De tels ennemis ont surtout un comportement simple et peu réfléchi, qu'il peut être facile à simuler sans perdre en « réalisme ».

L'histoire se déroule sur une île, un camp d’entraînement militaire où ont lieu des expériences scientifiques visant à décupler les capacités physiques des soldats. Ces expériences ont malheureusement fini par transformer les soldats cobayes en zombies agressifs. De peur d'être tués ou contaminés, les membres de l'équipe scientifique ont lâchement fui l'île, laissant le risque d'une contamination à plus grande échelle. Tous sauf un, qui décide de rester une nuit de plus sur l'île afin d'activer les bombes de sécurité placées un peu partout dans le camp d'entraînement afin d'empêcher une catastrophe mondiale.

Intro.png

Immersion du joueur

Une partie qui ne semblait pas poser de problèmes scientifiques particuliers s'est tout de même imposée à nous, dans le but de faire un jeu vidéo réaliste : permettre au joueur d'être facilement plongé dans le jeu. Nous avons donc pensé à mettre en place différents "outils" facilitant l'immersion.

Sons

Que serait un jeu vidéo sans le son ? En outre, notre jeu est basé sur un jeu de tir, qui prend tout de suite plus de réalisme lors d'ajout de son. Nous avons donc appris à manipuler une librairie permettant l'utilisation de sons en trois dimensions : OpenAL. Ainsi, nous avons joué les bruits suivants:

  • bruits de pas lorsque le joueur se déplace, plus prononcés lors d'un sprint
  • essoufflement lorsque l'énergie du joueur est trop basse
  • bruit d'arme lors du tir avec le pistolet ou bien lors d'une attaque au couteau
  • une série de sons bien connue dans les jeux à la première personne, quand le joueur tue des zombies de manière effective.

Nous avons essayé de mettre un bruit de pas pour chaque zombie, mais cela impliquait l'utilisation de nombreux buffers pour les stocker (on génère environ 700 zombies et un buffer ne peut prendre en charge que 16 sons à la fois). Nous avons résolu le problème des zombies trop furtifs dans l'interface utilisateur (voir après).

Notons que les zombies sont sensibles aux sons et peuvent ainsi réagir lorsqu'ils entendent le joueur à proximité (cf gestion des zombies)

Interface

Le joueur doit être capable de connaître diverses informations sur le jeu, c'est pourquoi nous avons mis en place une interface composée de différentes textures "collées" à la caméra:

  • une barre de vie, qui diminue lors d'une attaque par un zombie
  • une barre d'endurance, qui se vide après un sprint ou un saut
  • un score affiché à l'écran, qui diminue au cours du temps et augmente lorsque le joueur parvient à tuer un zombie ou atteint un objectif
  • l'heure courante, pour que le joueur puisse correctement partager sa journée et ainsi profiter de l'extérieur et ne pas se couper du monde qui l'entoure
  • un radar qui indique le nord et repère des zombies dans un rayon de 20m, utile quand ceux-ci décident de vous attaquer par derrière!
  • une carte qui donne l'emplacement des objectifs et dévoile les zones de la carte déjà visitées.
  • un menu pause qui permet de quitter ou reprendre la partie, et affiche aussi l'objectif en cours
  • un menu qui s'affiche en cas de mort du personnage, et permet lui aussi de quitter le jeu, ou bien revenir au dernier objectif atteint

Ce système permet par ailleurs de simplifier énormément la gestion de la lumière : plutôt que de créer une lampe de type spot avec OpenGL et de la régler pour qu'elle ait le comportement souhaité, ce qui aurait en plus une influence sur les performances du jeu, nous appliquons simplement une texture à l'écran qui simule un éclairement de type "lampe de poche".

Gestion des collisions

La gestion des collisions est un élément clé dans un jeu vidéo. Nous avons géré les collisions du personnage avec les zombies, les arbres et autres éléments du décors, en utilisant une représentation en 2 dimensions du terrain. Ainsi lorsque le joueur essaie d'accéder à une zone interdite (définie par un cylindre, une case de 1m sur 1m ou encore un rectangle), son déplacement est immédiatement annulé.

Le joueur est également bloqué quand il essaie d'avancer dans une pente trop forte.

Création du décors

Le relief

On s'est fixé l'objectif de créer une carte de 1 km². Pour cela, on utilise une heightmap, c-à-d une fonction de R² dans R qui à un point du plan associe une altitude. Ainsi si le joueur est en position (x,y) sur plan, il suffira de le placer en (x,y,heightmap(x,y)) dans le monde 3D.

Une méthode classique pour générer une telle heightmap est d'utiliser un bruit de perlin. Un bruit de perlin est une sorte de bruit cohérent permettant d'éviter les discontinuités sur la carte. La question est de savoir sur combien de points on doit définir notre heightmap (et donc calculer une valeur de bruit). On choisit d'évaluer l'altitude tout les mètres. On a donc 1 km² = 10^3 * 10^3 = 10^6 points à évaluer et stocker. Sachant qu'un point est constitué de 3 float, on utilisera donc environ 12 Mo en mémoire ce qui est parfaitement acceptable. Il faut ensuite choisir une primitive pour afficher la surface générée. On utilise les GL_TRIANGLES car 4 points ne sont pas nécessairement coplanaires et le comportement des GL_QUADS n'est pas défini dans le cas échéant. On stocke les triangles dans une matrice et il faudra ensuite tracer les bons triangles au bon moment.

La carte est initialement découpé en 32x32 cases de 32x32 m² (ce qui donne un terrain de 1024x1024 m²). A chaque case on associe une liste des triangles correspondants et on tracera seulement les cases assez proches du joueur.

Voici un aperçu du résultat :

Média:oldgrille.avi


Problèmes rencontrés et solutions proposées:

On remarque un premier problème au niveau de l'éclairage, on distingue facilement les triangles constituant le maillage lorsqu'on regarde le sol. On a dans un premier temps cru à un problème de calcul de normales (nécessaire à l'éclairage) mais cela provient en fait du nombre trop faibles de triangles : l'intensité lumineuse est calculé en chaque sommet puis elle est interpolée pour afficher le reste du triangle. On a donc décider d'augmenter le nombres de points et de triangles et on tente d'évaluer les points tout les dixièmes de mètres : le temps de calcul et la mémoire utilisée est ainsi multiplié par 10². L'environnement met alors une bonne minute pour s'initialiser et il est difficile d'afficher plus d'une case à la fois. On se devait d’abandonner cette idée, ne serait-ce que pour économiser de la mémoire. Néanmoins cela nous a donné l'idée de construire une grille "adaptative" : plus on s'éloigne du joueur, moins on trace de triangles. Cela permet évidemment de réduire le nombre de triangles affichés, mais aussi d'éviter le chargement brusque d'une case comme on pouvait le voir précédemment.

Grille adaptative : plus on s'éloigne, moins on affiche de trianglesMédia:supergrille.avi


De plus, il n'est plus nécessaire de construire un maillage de triangles de la map puisque les triangles changent selon la distance au joueur, on construit les triangles à la volé en choisissant les bons points de la carte. On gagne ainsi énormément en mémoire ! Auparavant, un point appartenait à 6 triangles, on stockait donc 6 pointeurs pour chaque points. L'économie est de 6 x 10^6 x 4 octets = 24 Mo.

Remarques: Un des avantages de la génération procédurale et qu'il est en fait inutile de stocker les points de la carte puisqu'on peut les retrouver à l'aide du bruit. On se permet ici de les garder en mémoire car la taille de la carte est relativement petite, cela permet d'éviter du temps de calcul en runtime et cela reste pratique par la suite. Au bout du compte, on a adopté les quads au lieu des triangles qui fonctionnaient en fait parfaitement. Même si 4 points ne sont pas nécessairement coplanaires, ils l'étaient presque dans notre cas.

Zones et chemins

On aimerait positionner différents types de zones : neige, sable, mer, foret et prairie. La neige, le sable et la mer dépendent simplement de l'altitude, mais les forêts et prairies non. On a simplement définie des valeurs seuils pour les premières, et l'on devait ensuite placer les autres entre la neige et le sable. On a d'abord essayé de placer ces zones aléatoirement mais cela ne donnait rien de convainquant. En fait le bruit de perlin est adapté pour ce genre de problème. Au lieu d'en créer un nouveau, on recycle l'ancien en utilisant sa transposée : le point (x,y) sera dans une prairie si heightmap(y,x) < seuil sinon il sera dans une forêt.

Pour des raisons scénaristiques, on a modifié la heightmap manuellement. On veut que le joueur démarre sur la plage, traverse des forêts et prairies, puis accède dans un second temps à des hauteurs enneigées pour atteindre le point culminant de la map pour vaincre le boss du jeu. On donc rajouté une gaussienne pour créer la montagne, et différentes fonctions pour créer un plateau et la plage. On perd beaucoup sur le coté aléatoire de la map, mais cela donne des points de repère au joueur et nous aide nous, les développeurs, pour définir un scénario plus cohérent.

Mapzmbmg.png

On aimerait également tracer des chemins sur la carte. Pris par le temps, on s'est contenté d'un algorithme simple donnant des résultats satisfaisants, On trace le chemin récursivement comme suit : pour deux points A et B donnés, on choisi le milieu du chemin C aléatoirement sur la médiatrice de AB, suffisament écarté du milieu de AB. On ré applique sur AC et CB etc.

Remarques :

Le chemin ne dépend pas du relief.

Textures et couleurs

La coloration de la carte n'a pas posé beaucoup de problèmes, à chaque point du relief on associe une couleur en fonction de sa zone, on peut même assez facilement faire des dégradés sur les zones de transition.

En revanche, l'application des textures est plus difficile. En effet, on trace la grille par groupe de 4 points (formant un quad) et on doit spécifier une coordonnée de texture par points. Le soucis est qu'un point appartient à 4 quads différents et donc possiblement à 4 environnements et textures différentes. On a donc associé à chaque quad de la grille une texture et il faut simplement charger la bonne au bon moment.

Remarques :

Il n'y pas de transition entre zones, le changement de texture est brutal. On aurait aimé améliorer cela. Plusieurs solutions sont envisageables : construire manuellement les textures de transitions avec un logiciel de retouche photo (gimp, photoshop...) utiliser de l'alpha blending et combiner différentes textures existantes

Optimisation des textures :

Le chargement des textures peuvent être source de pertes de performances. Pour éviter cela, on utilise une «mégatexture» regroupant toutes les textures de la map regroupées en une. On charge ainsi la texture une seule fois et il faut ensuite retrouver la bonne texture en renvoyant des coordonnées de textures précises.


Les prairies

Une fois le terrain texturé, les prairies nous semblaient trop vides et peu convaincantes. On a décidé d'utiliser des billboards pour augmenter le réalisme.

On s'est confronté à un gros problème de performance, nos portables tournant en dessous de 20 fps au lieu des 60 habituels. Néanmoins, l'effet obtenu nous a convaincu de garder ces billboards, il nous fallait donc optimiser cela.

Après recherche, on a repéré l'origine du problème : il venait du test de transparence (l'alpha testing). En effet, il suffisait de désactiver ce test pour retrouver un framerate normal. Mais l'alpha testing était nécessaire... De plus amples recherches nous ont apporté la solution : le mipmapping. Réduire la résolution de la texture en fonction de la distance permet de tester moins de pixels pour la transparence des herbes lointaines et nous fait gagner un précieux temps de calcul. (On passe aux alentours de 40-50 fps sur un pc portable standard.)

Une animation simple mais suffisante de vent à été ensuite ajouté pour toujours plus de réalisme. L'affichage de l'herbe se fait de manière progressive comme la grille.

Autre problème rencontré :

L'herbe ressortait du terrain de manière déconcertante sur les pentes trop raides. On a donc fait en sorte que l'herbe s'adapte aux pentes du relief.

Média:vegetation.wmv Média:affichagelimite.avi

Les forêts

Dans cette partie on va vous parler majoritairement des arbres qui sont disposés un peu partout sur la map. Tout d'abord, on s'est concentré sur un seul type d'arbre qui a utilisé une fonction récursive : partant d'un sommet de l'arbre en cours de création, on dessine 2 ou 4 branches et on appelle la fonction sur le sommet de chacune de ses branches. De cette manière, il était possible de générer des arbres différents assez facilement, mais la quantité d'arbres présents sur la carte imposait que l'on se concentre avant tout sur une optimisation du nombre de polygones dessinés.

On s'est donc concentré sur le niveau de détail des arbres, laissant de coté la génération aléatoire (et donc imposant un unique arbre). Le niveau de détail dépend de la distance du joueur à l'arbre : à plus de 10 mètres, le joueur ne perçoit que des grosses branches (variable "niveauDetail" à 0). Dès qu'il passe en dessous de 10 mètres, la variable passe a 1 et des polygones supplémentaires (modélisant des petites branches) sont dessinés. Pour que les branches n'apparaissent pas "subitement", leur taille est initialisée à 0 (branches d'épaisseur nulle) et augmente lorsque le joueur approche de l'arbre, jusqu'à ce qu'il soit a 4 mètres ou moins de celui ci. Cette façon de procéder permet de ne pas brusquer le joueur.

Ce premier type d'arbre se construit avec des cylindres (contenant beaucoup de polygones, et donc très couteux). On a donc modélisé un second type d'arbre (le sapin) qui utilise des GL_STRIP_LINE et des GL_TRIANGLES suivant le niveau de détail. Les lignes sont beaucoup moins couteuses et permettent de dessiner beaucoup d'arbres tout en conservant un FPS très correct. Mais lorsqu'on se rapproche trop du sapin, les lignes deviennent visibles. Pour corriger ce problème, on utilise encore les niveaux de détail pour passer des lignes à des triangles.

Bien que très couteux, on voulait tout de même utiliser le premier type d'arbre. Pour contrer ce problème, on a utilisé une méthode de chargement des données différente que nous expliquerons plus tard (cf. Vertex Buffer Object).

Média:lod.wmv

Animation de la population de zombies

Le deuxième objectif principal du projet était de réussir à modéliser le comportement de la foule de zombies qui peuple l'île. Il faut en particulier leur donner la possibilité de se regrouper, de patrouiller sur la carte, éventuellement d'attaquer le joueur ainsi qu'éviter certains obstacles.

Boids

Pour la gestion des mouvements de foule, nous nous sommes inspirés du programme « Boids » développé par Craig W. Reynolds, simulant le comportement d'oiseaux. Le principe est simple : définir un ensemble de règles modélisées par des forces physiques s'appliquant à chaque individu pour obtenir un déplacement cohérent. En effet, à partir de la somme des forces et du Principe Fondamental de la Dynamique, nous pouvons calculer le déplacement de l'individu en question. Les règles définies sont les suivantes :

  • L'individu est repoussé par les obstacles du terrain : on lui ajoute pour chaque obstacle à proximité une force répulsive en 1/r² où r est la distance entre le zombie et l'obstacle. Dans notre cas, un obstacle représente un arbre ou bien un autre zombie. Ceci permet d'éviter que le zombie traverse des objets.
  • Le zombie est attiré par le centre de masse de son groupe : Il subit une force attractive linéaire à la distance du zombie au centre de masse.
  • Le zombie cherche à se déplacer de la même manière que les zombies qui l'entourent : Le force reçue est linéairement dépendante de la différence de vitesses entre le zombie et la somme des vitesses des membres du groupe.
  • L'individu est repoussé par les limites du terrain : On ne veut pas qu'il essaie d'en sortir. C'est pourquoi on lui applique une force répulsive constante en provenance du bord, s'il s'en approche à moins de 5m.


Un zombie n'a pas la possibilité de connaître l'emplacement des autres zombies, ni même du joueur. Il est doté de sens qui lui permettent de connaître partiellement ses environs. Nous avons introduit un champ de vision (à 180°), qui est obstrué par les arbres. Les forces appliquées sur le zombie ne sont calculées que pour les zombies et obstacles qu'il voit. Il a par contre plusieurs moyens de repérer le joueur : il peut le voir ou l'entendre.

Un comportement plus complexe

Formation de troupes

Nous avons jugé utile d'ajouter plusieurs contraintes en plus des règles définies plus haut. En effet notre zombie n'a pas les moyens de connaître la position de chacun de ses congénères sur la carte, et nous voulons aussi que plusieurs groupes se créent.

Nous avons donc décidé d'ajouter des zombies particuliers, des « généraux », qui ont un comportement légèrement différent des autres zombies, et une influence sur eux :

  • Un zombie non général subit une force constante qui l'attire dans la direction de son général, peu importe où il se trouve par rapport à celui-ci.
  • Un zombie général (plus robuste qu'un zombie normal) est attiré par un point au hasard de la carte par une force constante. Une fois suffisamment proche du but, on en choisis un autre de nouveau au hasard. Ceci permet de créer une patrouille aléatoire.

Chaque zombie choisit pour général celui qui se trouve le plus proche de lui au début de la partie. Les généraux sont répartis sur la carte de façon à ce que les groupes soit de tailles semblables et couvrent toute la carte. Si le général meurt, les zombies qui le suivaient sont livrés à eux même : ils se comportent comme des généraux et patrouillent, mais n'influencent aucun zombie.


Modes de fonctionnement

Nous avons imaginé différents comportements pour les zombies. En effet, un zombie peut être influencé par son état, et nous avons définit trois types d'états : un zombie est initialement dans un état de ERRANCE, et on lui applique les forces imaginées avant.

Ensuite, le zombie peut entendre le joueur selon les actions de ce dernier (tire, sprint...) et depuis une certaine distance. Il se met alors en état de RECHERCHE et subit des modifications des forces existantes ainsi que l'ajout d'une nouvelle force :

  • Le zombie est attiré par une direction orthogonale à sa vitesse, ce qui le force à se tourner pour chercher le joueur.
  • Le zombie est encore plus repoussé par ses semblables, et est repoussé par le centre de masse du groupe : le groupe s'éparpille, ce qui permet de rechercher sur une zone plus vaste.
  • Sa vitesse ne s'aligne plus sur celle des autres
  • Il n'est plus attiré par son général, mais légèrement par le joueur qu'il a entendu.
  • Sa vitesse maximale est augmentée

Enfin, le zombie entre dans le dernier état lorsqu'il voit le joueur : il se met en CHASSE. Comme lors du passage à l'état CHERCHE, il subit plusieurs modifications (outre ses yeux rouges) :

  • Le zombie est fortement attiré par le joueur.
  • Il subit moins la force de répulsion des autres zombies et est indifférent au centre de masse : quand le joueur est en vue, c'est chacun pour soi !
  • Sa vitesse maximale est de nouveau augmentée

Un zombie qui était en CHASSE, mais perd le joueur de vue ne passe pas immédiatement en ERRANCE. Il sait que le joueur n'est pas bien loin, peut être caché derrière un arbre, et se met donc en phase de RECHERCHE.

Voir ou entendre le joueur n'est pas le seul moyen pour un zombie de passer d'un état à un autre. Un zombie qui aperçoit un individu en état de CHASSE comprend que quelque chose se passe et passe en état CHERCHE.

Fichier:Zombieattaque.png Média:zombieEtat.wmv

Problèmes rencontrés et optimisations

Il a fallu régler correctement les coefficients des forces pour chaque état afin de donner le comportement attendu aux zombies. Le plus compliqué à régler fut les forces de répulsions des arbres, notamment pour les états d' ERRANCE et de RECHERCHE. En effet, si cette force est trop faible, les zombies vont rentrer dans les arbres, et si elle est trop grande, les zombies ne pourront plus bouger. A l'origine, pour les zombies en forêt, qui ne voient presque que des arbres, cette force de répulsion était même la seule qu'ils percevaient, ce qui les bloquait souvent au milieu des arbres... Ceci a en partie été corrigé par l'ajout des généraux, qui permet aux zombies d'avoir toujours une force les attirant vers un endroit précis. De plus, nous avons limité le rayon d'action de la force : un zombie ne cherche à éviter un arbre que s'il est proche de celui-ci. Ceci permet de renvoyer une force suffisamment grande pour éviter les arbres, et limiter sa portée de manière plus sûre que la forme en 1/r² seule...

Nous avons par ailleurs dû effectuer un certain nombre d'optimisations sur le calcul du déplacement des zombies, afin de pouvoir en avoir le plus possible sur la carte. Comme les arbres sont stockées sous la forme d'une matrice de cases de 2*2 mètres, il est aisé de ne considérer que les arbres proches suceptibles d'être vus par le zombie. De même, les zombies sont stockes dans des cases représentant chacune 1 mètre carré, on a ainsi accès facilement aux zombies les plus proches .

D'autre part, l'ensemble des calculs est réalisé à l'aide d'un thread, car il n'est pas nécessaire de synchroniser le rythme des calculs avec celui de l'animation : une différence de forces sur un centième de secondes est négligeable. Le thread prend le temps de faire les calculs et on met à jour la vitesse du zombie en recevant un signal de fin (avec Qt), puis on relance le thread etc....

Enfin, nous avons introduit un niveau de détail concernant l'animation des zombies : seuls les généraux et les zombies les plus proches du joueur sont réellement animés grâce aux calculs expliqués plus haut. Les autres zombies ont simplement la même vitesse de déplacement que leur général.

Autres problèmes rencontrés

La majorité des problèmes que nous avons rencontrés sont liés aux performances du jeu, qui doit pouvoir tourner – et être fluide – sur le plus d'ordinateur possible. Notre objectif initial en terme de performances était de pouvoir jouer sur les ordinateurs de l'Ensimag. Cependant la bibliothèque OpenAL, utilisée pour la gestion du son n'est pas installée, et puisque nous possédons chacun des ordinateurs de configurations variées, nous pouvons malgré tout évaluer les besoins de notre jeu.

Nous avons déjà évoqué dans les différentes parties de cette page un certain nombre d'optimisations que nous avons du réaliser (niveaux de détails dans l'affichage et l'animation, ...)

Il restait malgré tout des ralentissement aux endroits ou beaucoup d'éléments doivent être affichés. Nous nous sommes rendus compte que c'était surtout la quantité de transferts entre la RAM de l'ordinateur et la mémoire de la carte graphique qui ralentissait le jeu, et non pas directement la quantité de polygones à afficher. Nous avons donc décidé d'enregistrer certains modèles souvent affichés (les cylindres utilisés pour de nombreux éléments de décors, les zombies) directement dans la carte graphique. Cela se fait sous OpenGL grâce aux Vertex Buffer Object. L'amélioration des performances est telle que certaines optimisations faite auparavant (le niveau de détail sur les branches des arbres par exemple) ne sont plus indispensables pour le moment ( mais pourraient redevenir utiles si nous souhaitons augmenter le nombre d'éléments, ou la qualité de ceux ci).


Nous avons eu finalement des problèmes assez importants au niveau de l'architecture de notre projet. Nous avons passé du temps à réfléchir à celle-ci, mais nous n'avions aucune expérience dans la création de jeu vidéo. Ainsi, après avoir passé quelques jours sans problèmes, les différents besoins d'optimisations nous ont amené à modifier la structure du code. Nous aurions dû refaire l'architecture globale du projet mais cela aurait été long et fastidieux...


Conclusion

La création d'un jeu vidéo est un projet sans réelle limite et très enrichissant. Après trois semaines de programmation, nous avons développé un jeu dont la jouabilité nous semble correcte et le réalisme du décors nous convient également. La segmentation des tâches que l'on s'était donné et la visualisation immédiate du résultat (en lançant simplement le jeu) sont des raisons caractérisant notre grande motivation dans la réalisation de ce projet, additionnées au contexte "graphique 3D" qui nous intéressait tous.

Bilan du projet

Partant d'une liste de tâches à réaliser, nous avons accompli plus de 90% de ce que nous espérions faire en deux semaines. Le rendu est volontairement assez réaliste, avec beaucoup de détails concernant le décors. Le scénario est basique mais respecté, et le jeu est relativement difficile à finir. Les zombies ont un comportement semblable à ce que l'on pourrait attendre d'eux. Il ne s'agit pas d'une IA très poussée mais elle est tout de même bien gérée. Nous espérons pour ceux qui l'essaieront que ce jeu vous plaira (bien que l'histoire soit peu développée).

Améliorations possibles

Nous avons développé plusieurs programmes essentiels pour que le jeu fonctionne correctement et seulement quelques points supplémentaires qui augmentent le réalisme, l'immersion, l'intéret du scénario. Cependant, nous aurions souhaité programmer d'autres fonctionnalités.

  • Avoir une plus grande diversité d'individus dans la population (pas seulement des zombies) qui soient eux aussi hostiles, ou tout simplement neutres (moutons...). Nous aurions alors géré les interactions entre les populations (exemple : mouton qui a peur des zombies mais aime bien les hommes).
  • Permettre la possession de plusieurs types d'armes. Une arme tel qu'un lance-flamme oblige la modélisation du feu et nécessite la propagation d'un incendie (mettre le feu à un arbre ne doit pas le laisser sans trace).
  • Augmenter le nombre d'interactions entre le joueur et le décors pour que le jeu soit plus complet. Entre autre, si le décors est destructible, le réalisme est augmenté.
  • Créer une atmosphère encore plus "angoissante" avec de la pluie, des orages, des éclairs...
  • La hauteur du personnage est calculée en fonction de ses coordonnées sur la carte, on ne gère pas d'endroits avec plusieurs hauteurs possibles, comme un étage ou un saut sur le toit de la cabane, ou encore une grotte en profondeur.
  • Diversifier le décors, avec l'ajout de plus d'arbres différents, ou d'autres éléments de décors. Une solution envisageable est d'importer des modèles réalisés à l'aide de logiciels 3D artistiques comme Blender ou Maya... (cf http://assimp.sourceforge.net/ pour importer facilement)
  • Nous nous sommes aussi intéressés à la génération procédurale de village (comme expliqué dans le deuxième article en référence), sans avoir le temps de l'implémenter réellement. L'article permet en outre de tracer des routes et chemins s'adaptant à un relief donné.
  • Une article entier est consacré à l'animation de prairies en temps réel, on pourrait s'en inspirer pour améliorer les nôtres.

Références

F.Perbet et M-P.Cani, (2001) "Animating Prairies in Real-Time".

A.Emilien, (2012) "Procedural Generation of Villages on Arbitrary Terrains".

Dachsbacher, C. (2006) "Interactive Terrain Rendering: Towards Realism with Procedural Models and Graphics Hardware". PhD thesis, Universität Erlangen-Nürnberg

Reynolds, C. W. (1987) "Flocks, Herds, and Schools: A Distributed Behavioral Model", in Computer Graphics, 21(4) (SIGGRAPH '87 Conference Proceedings) pages 25-34.

Reynolds, C. W. (2000) "Interaction with Groups of Autonomous Characters", in the proceedings of Game Developers Conference 2000, CMP Game Media Group (formerly: Miller Freeman Game Group), San Francisco, California, pages 449-460.