Projet Image Box2D : Différence entre versions

De Ensiwiki
Aller à : navigation, rechercher
m
Ligne 1 : Ligne 1 :
 
[[Catégorie:Projets de spécialité]]
 
[[Catégorie:Projets de spécialité]]
 
+
{| class="toccolours" style="float: right; margin: 0 0 1em 1em; width: 24em; font-size: 90%;" cellspacing="5"
 +
|-
 +
<!-- logo et nom -->
 +
! style="width: 100%; text-align: center; font-size: larger;" colspan="2" {{!}}
 +
{{{!}} align="center" style="background: none;"
 +
{{!}} style="padding-right: 1em;" {{!}}
 +
{{!}} Box2D
 +
{{!}}}
 +
{{Infobox Logiciel/Ligne optionnelle
 +
| 1 = Projet
 +
| 2 = Projet de spécialité 2A
 +
}}
 +
{{Infobox Logiciel/Ligne optionnelle
 +
| 1 = Sous-projet
 +
| 2 = Image
 +
}}
 +
{{Infobox Logiciel/Ligne optionnelle
 +
| 1 = Étudiants
 +
| 2 = David AMAR (TEL), Alexis DORNIOL-PELE (TEL), Sylvain GIUDICELLI (TEL), Stéphane PIETTE (TEL), Florent PUGINIER (TEL)
 +
}}
 +
{{Infobox Logiciel/Ligne optionnelle
 +
| 1 = Promo
 +
| 2 = 2011
 +
}}
 +
{{Infobox Logiciel/Ligne optionnelle
 +
| 1 = Tuteur
 +
| 2 = Joëlle THOLLOT Joelle.Thollot@grenoble-inp.fr
 +
}}
 +
|}
 
[http://www.box2d.org/ Box2D] est un moteur physique disponible en open source et développé par Erin Catto. En bon moteur physique qu'il est, cet outil permet donc de gérer les positions d'objets dans un monde soumis aux lois physiques telles que la gravité, les collisions...
 
[http://www.box2d.org/ Box2D] est un moteur physique disponible en open source et développé par Erin Catto. En bon moteur physique qu'il est, cet outil permet donc de gérer les positions d'objets dans un monde soumis aux lois physiques telles que la gravité, les collisions...
  
Ligne 7 : Ligne 35 :
 
Nous avions pour sujet, proposé par notre tutrice Joëlle Thollot, l'étude de ce moteur physique à travers le développement d'un jeu ou d'une animation en 2D. Nous avons opté pour un jeu vidéo exploitant au maximum les capacités offertes par un moteur physique. En 2D, ces moteurs sont assez rarement utilisés, la question était donc de savoir ce qu'ils peuvent apporter et d'en étudier les possibles limites et capacités.
 
Nous avions pour sujet, proposé par notre tutrice Joëlle Thollot, l'étude de ce moteur physique à travers le développement d'un jeu ou d'une animation en 2D. Nous avons opté pour un jeu vidéo exploitant au maximum les capacités offertes par un moteur physique. En 2D, ces moteurs sont assez rarement utilisés, la question était donc de savoir ce qu'ils peuvent apporter et d'en étudier les possibles limites et capacités.
  
==Aspect pratique ==
+
==Aspect pratique ==
  
===Principe du jeu ===
+
===Principe du jeu ===
  
 
En exclusivité la plus totale, voici donc les premières images de notre jeu vidéo basé sur Box2D.
 
En exclusivité la plus totale, voici donc les premières images de notre jeu vidéo basé sur Box2D.
Ligne 17 : Ligne 45 :
 
Dans l'idée d'utiliser le plus possible le moteur physique, nous avons penché pour un jeu où l'interaction avec le décor serait importante. Du coup, outre certains éléments qui sont bien trop costauds pour être sensible à une quelconque modification, le personnage peut interagir avec tous les objets présents. Les pousser, éventuellement les casser, les porter etc...
 
Dans l'idée d'utiliser le plus possible le moteur physique, nous avons penché pour un jeu où l'interaction avec le décor serait importante. Du coup, outre certains éléments qui sont bien trop costauds pour être sensible à une quelconque modification, le personnage peut interagir avec tous les objets présents. Les pousser, éventuellement les casser, les porter etc...
  
Toutes ces actions seront possibles dans un but précis bien entendu : terminer les niveaux. Pour cela il faudra rallier une zone d'arrivée, située loin, et parfois même très loin, de la zone de départ du personnage. Et attention  pendant le parcours à ne pas se faire écraser, ou tout simplement à bloquer tout seul le chemin !
+
Toutes ces actions seront possibles dans un but précis bien entendu : terminer les niveaux. Pour cela il faudra rallier une zone d'arrivée, située loin, et parfois même très loin, de la zone de départ du personnage. Et attention  pendant le parcours à ne pas se faire écraser, ou tout simplement à bloquer tout seul le chemin !
  
 
[[Image:Box2DDebut.jpg|300px|center]]
 
[[Image:Box2DDebut.jpg|300px|center]]
Ligne 28 : Ligne 56 :
 
    
 
    
  
===Possibilités dans le jeu ===
+
===Possibilités dans le jeu ===
  
 
Comme vous pouvez vous en douter, notre petit personnage dispose de plein d'aide au cours de son périple. Sa seule force physique ne lui sera pas suffisante pour franchir tous les obstacles qui seront présents. Il est néanmoins assez costaud pour porter certains objets, pas trop lourds, et les lancer.
 
Comme vous pouvez vous en douter, notre petit personnage dispose de plein d'aide au cours de son périple. Sa seule force physique ne lui sera pas suffisante pour franchir tous les obstacles qui seront présents. Il est néanmoins assez costaud pour porter certains objets, pas trop lourds, et les lancer.
Ligne 47 : Ligne 75 :
 
Enfin, dans les cas les plus désespérés, il peut même modifier le monde et y créer des objets.
 
Enfin, dans les cas les plus désespérés, il peut même modifier le monde et y créer des objets.
  
===Editeur de niveaux ===
+
===Editeur de niveaux ===
  
Nous avons mis quelques niveaux à votre disposition. Cependant l'aventure n'est pas obligée de s'arrêter là. En effet il vous est possible de créer vous même vos niveau pour encore plus de plaisir !
+
Nous avons mis quelques niveaux à votre disposition. Cependant l'aventure n'est pas obligée de s'arrêter là. En effet il vous est possible de créer vous même vos niveau pour encore plus de plaisir !
  
 
Pour cela, vous avez à disposition tous les objets que nous utilisons (décrits dans le manuel ?), le reste dépend de votre imagination. Un aspect important lors de la création de niveau est de bien calibrer tous les objets. C'est-à-dire leur donner des densités cohérentes, régler la friction, le rebond, la fragilité etc... Tout cela est personnalisable, donc à ne pas choisir au hasard car toute la gestion physique des éléments se basera sur ces choix.
 
Pour cela, vous avez à disposition tous les objets que nous utilisons (décrits dans le manuel ?), le reste dépend de votre imagination. Un aspect important lors de la création de niveau est de bien calibrer tous les objets. C'est-à-dire leur donner des densités cohérentes, régler la friction, le rebond, la fragilité etc... Tout cela est personnalisable, donc à ne pas choisir au hasard car toute la gestion physique des éléments se basera sur ces choix.
  
==Aspect technique ==
+
==Aspect technique ==
  
 
Nous allons maintenant aborder une partie un peu plus technique, destinée à expliquer nos choix de conception et la façon dont nous avons réaliser un peu tout. Cela permettra de montrer nos expériences avec Box2D et une meilleure compréhension de notre code.
 
Nous allons maintenant aborder une partie un peu plus technique, destinée à expliquer nos choix de conception et la façon dont nous avons réaliser un peu tout. Cela permettra de montrer nos expériences avec Box2D et une meilleure compréhension de notre code.
  
===Interface ===
+
===Interface ===
  
 
Il faut savoir que Box2D se "contente" de calculer les coordonnées des différents objet contenus dans son monde. En soi, Box2d ne fournit donc qu'une liste de nombres.
 
Il faut savoir que Box2D se "contente" de calculer les coordonnées des différents objet contenus dans son monde. En soi, Box2d ne fournit donc qu'une liste de nombres.
Ligne 63 : Ligne 91 :
 
Une étape importante est donc d'interfacer ses données. Pour cela nous avons utilisé QT, permettant de créer des interfaces graphique, et sa librairie QGL Viewer qui permet de visualiser des données OpenGL. La principale difficulté que nous avons rencontré était la correspondance des coordonnées du monde Box2D avec celles de la fenêtre OpenGL. Nous avons donc dû redéfinir le repère de OpenGL avec celui de Box2D.
 
Une étape importante est donc d'interfacer ses données. Pour cela nous avons utilisé QT, permettant de créer des interfaces graphique, et sa librairie QGL Viewer qui permet de visualiser des données OpenGL. La principale difficulté que nous avons rencontré était la correspondance des coordonnées du monde Box2D avec celles de la fenêtre OpenGL. Nous avons donc dû redéfinir le repère de OpenGL avec celui de Box2D.
  
===Architecture générale ===
+
===Architecture générale ===
  
On pensait pourtant ne jamais avoir à se servir à nouveau de l'UML... Et pourtant il paraît qu'un dessin vaut mieux qu'un long discours ! Alors voilà une idée de l'architecture de notre programme.
+
On pensait pourtant ne jamais avoir à se servir à nouveau de l'UML... Et pourtant il paraît qu'un dessin vaut mieux qu'un long discours ! Alors voilà une idée de l'architecture de notre programme.
  
 
[[Image:Box2DDiagramme.png|1000px|center]]
 
[[Image:Box2DDiagramme.png|1000px|center]]
 
<center><small>''Diagramme de classe''</small></center>
 
<center><small>''Diagramme de classe''</small></center>
  
===Personnage ===
+
===Personnage ===
  
Le personnage a été réalisé dans une optique différente des autres objets. En effet contrairement aux autres objets, il doit tenir compte de deux contraintes parfois opposées : les lois physiques … et le joueur! Et pour concilier ces 2 aspects, certains choix ont du être fait.
+
Le personnage a été réalisé dans une optique différente des autres objets. En effet contrairement aux autres objets, il doit tenir compte de deux contraintes parfois opposées : les lois physiques … et le joueur! Et pour concilier ces 2 aspects, certains choix ont du être fait.
  
Tout d’abord, le personnage n’est représenté dans Box2D que par un seul bloc rectangulaire. A ce bloc, se fixent plusieurs zones de collisions (pieds, tête, bras etc...) qui déclenchent des animations différentes et des comportements différents quand elles sont activées. Comme ces zones ne sont pas redimensionnables dans Box2D, nous avons dû ajouter des zones de collisions virtuelles afin de gérer certains cas. Exemple : si le personnage s’accroupit, les zones de collisions correspondant à sa position debout passent en virtuelles et les zones de collisions correspondant à sa position accroupie deviennent réelles.
+
Tout d’abord, le personnage n’est représenté dans Box2D que par un seul bloc rectangulaire. A ce bloc, se fixent plusieurs zones de collisions (pieds, tête, bras etc...) qui déclenchent des animations différentes et des comportements différents quand elles sont activées. Comme ces zones ne sont pas redimensionnables dans Box2D, nous avons dû ajouter des zones de collisions virtuelles afin de gérer certains cas. Exemple : si le personnage s’accroupit, les zones de collisions correspondant à sa position debout passent en virtuelles et les zones de collisions correspondant à sa position accroupie deviennent réelles.
  
Ensuite, nous avons du désactiver son paramètre rotation dans box2D. En effet, cela posait beaucoup trop de problèmes de gameplay, le personnage se retrouvant alors fréquemment sur le ventre ou sur le dos. Le personnage ne pourra donc plus faire de salto !
+
Ensuite, nous avons du désactiver son paramètre rotation dans box2D. En effet, cela posait beaucoup trop de problèmes de gameplay, le personnage se retrouvant alors fréquemment sur le ventre ou sur le dos. Le personnage ne pourra donc plus faire de salto !
  
Enfin, pour illustrer le conflit entre joueur et physique, nous allons évoquer le problème de la marche du personnage. Notre premier réflexe pour la marche du personnage a été de juste changer les coordonnés du personnage lorsque celui-ci se déplace. Le problème, c’est que le personnage avait alors la fâcheuse tendance d’avoir certains comportements non physiques (traversée de mur, perte d’inertie etc…). Après plusieurs tentatives, nous avons finalement adopté la solution de lui appliquer une force quand il veut se déplacer. Avantage, le personnage a alors un comportement complètement physique mais le joueur à malheureusement l’impression de le voir « patiner » par moment…
+
Enfin, pour illustrer le conflit entre joueur et physique, nous allons évoquer le problème de la marche du personnage. Notre premier réflexe pour la marche du personnage a été de juste changer les coordonnés du personnage lorsque celui-ci se déplace. Le problème, c’est que le personnage avait alors la fâcheuse tendance d’avoir certains comportements non physiques (traversée de mur, perte d’inertie etc…). Après plusieurs tentatives, nous avons finalement adopté la solution de lui appliquer une force quand il veut se déplacer. Avantage, le personnage a alors un comportement complètement physique mais le joueur à malheureusement l’impression de le voir « patiner » par moment…
  
Pour ce qui est du rendu, nous avions le choix entre le représenter avec des « sprites » qu’il aurait fallu trouver et dessiner ou de le représenter de manière géométrique à partir des angles de ses bras et de ses jambes. Comme nous sommes plus proche des mathématiques que du dessin, nous avons retenu la deuxième approche. Celle-ci avait par ailleurs l’avantage d’être plus simple à implémenter pour une version test où le rendu n’est pas la priorité.
+
Pour ce qui est du rendu, nous avions le choix entre le représenter avec des « sprites » qu’il aurait fallu trouver et dessiner ou de le représenter de manière géométrique à partir des angles de ses bras et de ses jambes. Comme nous sommes plus proche des mathématiques que du dessin, nous avons retenu la deuxième approche. Celle-ci avait par ailleurs l’avantage d’être plus simple à implémenter pour une version test où le rendu n’est pas la priorité.
  
 
Le potentiel de Box2D ne s'arrête pas là. En effet, au vu des outils disponibles, il est envisageable de pouvoir créer un personnage entièrement articulé et disposant des réflexes humains permettant de tenir en équilibre. Cependant ce pourrait être un sujet à lui tout seul étant donné la complexité que cela induit.
 
Le potentiel de Box2D ne s'arrête pas là. En effet, au vu des outils disponibles, il est envisageable de pouvoir créer un personnage entièrement articulé et disposant des réflexes humains permettant de tenir en équilibre. Cependant ce pourrait être un sujet à lui tout seul étant donné la complexité que cela induit.
  
===Objets cassables ===
+
===Objets cassables ===
  
 
Box2D n'utilise que des objets solides. Donc de base il est impossible de casser un objet. Cependant pour la réalisation de notre jeu nous avions besoin de cette fonctionnalité. Nous avons donc utilisé deux méthodes différentes pour créer des objets qui peuvent être cassés.
 
Box2D n'utilise que des objets solides. Donc de base il est impossible de casser un objet. Cependant pour la réalisation de notre jeu nous avions besoin de cette fonctionnalité. Nous avons donc utilisé deux méthodes différentes pour créer des objets qui peuvent être cassés.
Ligne 90 : Ligne 118 :
 
Il faut tout d'abord dire que Box2D permet une grande maniabilité dans la gestion des contacts. Plus précisément, pour chaque contact qui se produit dans le monde, Box2D offre des possibilités d'interaction sur les objets concernés avant, pendant et après le contact. Cela permet donc de tester si la force du contact est assez puissante pour briser un objet, si les objets en question sont brisables, ce genre de chose.
 
Il faut tout d'abord dire que Box2D permet une grande maniabilité dans la gestion des contacts. Plus précisément, pour chaque contact qui se produit dans le monde, Box2D offre des possibilités d'interaction sur les objets concernés avant, pendant et après le contact. Cela permet donc de tester si la force du contact est assez puissante pour briser un objet, si les objets en question sont brisables, ce genre de chose.
  
* Forts de cela, la première méthode que nous avons utilisée pour casser des objets a été de construire des objets étant composés de plusieurs petits cubes (tout autre polygone aurait été possible). Nous avons étudié deux types de cassures : soit dès que l'objet se brise tous les cubes sont détachés et forment de nouveaux objets à part entière. Soit seul le cube qui est touché est détaché, et peu à son tour taper sur les cubes l'entourant selon la vitesse qu'il acquiert lors du choc.
+
* Forts de cela, la première méthode que nous avons utilisée pour casser des objets a été de construire des objets étant composés de plusieurs petits cubes (tout autre polygone aurait été possible). Nous avons étudié deux types de cassures : soit dès que l'objet se brise tous les cubes sont détachés et forment de nouveaux objets à part entière. Soit seul le cube qui est touché est détaché, et peu à son tour taper sur les cubes l'entourant selon la vitesse qu'il acquiert lors du choc.
  
 
[[Image:Box2DEclatable.jpg|300px|center]]
 
[[Image:Box2DEclatable.jpg|300px|center]]
Ligne 98 : Ligne 126 :
 
<center><small>''Objet cassable''</small></center>
 
<center><small>''Objet cassable''</small></center>
  
Remarque : cette méthode de faire des objets composés peut permettre des créer des polygones concaves qui ne sont de base pas gérés par Box2D.
+
Remarque : cette méthode de faire des objets composés peut permettre des créer des polygones concaves qui ne sont de base pas gérés par Box2D.
  
 
* La deuxième méthode consiste à couper un polygone en deux en fonction de la direction de la force de contact. Pour faire, on calcule l'intersection de cette droite de contact avec le polygone en question, puis les deux nouveaux points obtenus permettent de redéfinir deux polygones que l'on créé et qui sont les deux morceaux du polygone original. Nous avons limité la destruction à une aire minimale pour ne pas être envahit d'objets miniatures.
 
* La deuxième méthode consiste à couper un polygone en deux en fonction de la direction de la force de contact. Pour faire, on calcule l'intersection de cette droite de contact avec le polygone en question, puis les deux nouveaux points obtenus permettent de redéfinir deux polygones que l'on créé et qui sont les deux morceaux du polygone original. Nous avons limité la destruction à une aire minimale pour ne pas être envahit d'objets miniatures.
Ligne 107 : Ligne 135 :
 
Des comportements plus complexes peuvent être imaginés, tels que la propagation d'une fissure en créant une suite de points à l'intérieur du polygone. Il faudrait alors s'assurer que les polygones créés sont tous convexes, ou alors les "convexifier" d'une manière ou d'une autre.
 
Des comportements plus complexes peuvent être imaginés, tels que la propagation d'une fissure en créant une suite de points à l'intérieur du polygone. Il faudrait alors s'assurer que les polygones créés sont tous convexes, ou alors les "convexifier" d'une manière ou d'une autre.
  
===Le Grappin ===
+
===Le Grappin ===
  
 
Le grappin est constitué d'une tête qui permet de s'accrocher aux objets et de sa chaîne. La chaîne est constituée de 60 maillons représentés par des cercles. Les cercles consécutifs sont reliés par des joints rotatifs (b2RevoluteJoint). La taille de la chaine n'est pas constante car dans Box2D les joints sont élastiques. Ceci est un inconvénient dans le cas échéant mais nous avons utilisé cette propriété à son avantage par la suite. Le personnage doit pouvoir lancer le grappin, grimper et descendre à la chaine et la lâcher.
 
Le grappin est constitué d'une tête qui permet de s'accrocher aux objets et de sa chaîne. La chaîne est constituée de 60 maillons représentés par des cercles. Les cercles consécutifs sont reliés par des joints rotatifs (b2RevoluteJoint). La taille de la chaine n'est pas constante car dans Box2D les joints sont élastiques. Ceci est un inconvénient dans le cas échéant mais nous avons utilisé cette propriété à son avantage par la suite. Le personnage doit pouvoir lancer le grappin, grimper et descendre à la chaine et la lâcher.
  
Pour que le personnage monte à la chaine, on utilise des joints simple qui servent à garder une distance entre deux objets. Le personnage est attaché à la base au dernier maillon. Pour grimper, on supprime le joint actuel qui relie le joueur la chaîne et on créé un nouveau joint avec le maillon suivant. La distance du joint est ensuite réduite à zéro pour que le personnage se « raccroche » au maillon suivant. L'élasticité des joints est donc pratique dans ce cas là.
+
Pour que le personnage monte à la chaine, on utilise des joints simple qui servent à garder une distance entre deux objets. Le personnage est attaché à la base au dernier maillon. Pour grimper, on supprime le joint actuel qui relie le joueur la chaîne et on créé un nouveau joint avec le maillon suivant. La distance du joint est ensuite réduite à zéro pour que le personnage se « raccroche » au maillon suivant. L'élasticité des joints est donc pratique dans ce cas là.
  
 
Lorsque le personnage grimpe à la chaîne, les maillons s'écartent à cause de l'élasticité. Pour augmenter la force des joints entre deux objets, il faut augmenter leur masse donc leur densité. La chaîne devient alors vraiment lourde et il faut donc donner une force plus importante au personnage pour lancer le grappin. Il y alors un risque que le grappin soit trop lourd et emporte le joueur trop fortement. Il devient alors très difficile de calibrer toutes les variable pour que le jeu soit jouable et un minimum réaliste.
 
Lorsque le personnage grimpe à la chaîne, les maillons s'écartent à cause de l'élasticité. Pour augmenter la force des joints entre deux objets, il faut augmenter leur masse donc leur densité. La chaîne devient alors vraiment lourde et il faut donc donner une force plus importante au personnage pour lancer le grappin. Il y alors un risque que le grappin soit trop lourd et emporte le joueur trop fortement. Il devient alors très difficile de calibrer toutes les variable pour que le jeu soit jouable et un minimum réaliste.
  
  
===Rendu ===
+
===Rendu ===
  
 
Le rendu n'était pas notre principal objectif. Le temps que nous y avons consacré est donc moindre par rapport au reste. Cependant il nous a semblé essentiel pour un jeu de disposer d'un aspect agréable, et aussi de son. Donc toute la partie rendu réside dans l'adaptation de textures à nos objets et l'introduction du son.
 
Le rendu n'était pas notre principal objectif. Le temps que nous y avons consacré est donc moindre par rapport au reste. Cependant il nous a semblé essentiel pour un jeu de disposer d'un aspect agréable, et aussi de son. Donc toute la partie rendu réside dans l'adaptation de textures à nos objets et l'introduction du son.
  
Concernant les textures, nous avons opté pour un style cartoon. Nous avons choisi d'utiliser Qt afin d'ouvrir les fichiers de textures (« .png ») et de les transformer en un type texture géré par OpenGL. Afin d'optimiser le chargement des textures sur les objets, nous avons initialisé au lancement du jeu un tableau contenant toutes les textures. Chaque texture est ainsi identifiée par un numéro.
+
Concernant les textures, nous avons opté pour un style cartoon. Nous avons choisi d'utiliser Qt afin d'ouvrir les fichiers de textures (« .png ») et de les transformer en un type texture géré par OpenGL. Afin d'optimiser le chargement des textures sur les objets, nous avons initialisé au lancement du jeu un tableau contenant toutes les textures. Chaque texture est ainsi identifiée par un numéro.
  
 
Pour le son, nous avons utilisé les librairies OpenAL et libsndfile. Le fonctionnement de la librairie OpenAL est très proche de OpenGL. Nous avons créé un tableau de sons (chaque son étant identifié par un numéro) puis lorsque nous voulons appliquer un son, il faut appeler la fonction permettant de jouer le morceau choisi. La librairie libsndfile (librairie opensource) est utilisée pour transformer un fichier son (.wav, .ogg, …) en un type son (ALuint) géré par OpenAL.
 
Pour le son, nous avons utilisé les librairies OpenAL et libsndfile. Le fonctionnement de la librairie OpenAL est très proche de OpenGL. Nous avons créé un tableau de sons (chaque son étant identifié par un numéro) puis lorsque nous voulons appliquer un son, il faut appeler la fonction permettant de jouer le morceau choisi. La librairie libsndfile (librairie opensource) est utilisée pour transformer un fichier son (.wav, .ogg, …) en un type son (ALuint) géré par OpenAL.

Version du 17 juin 2010 à 09:01

Box2D
Projet Projet de spécialité 2A
Sous-projet Image
Étudiants David AMAR (TEL), Alexis DORNIOL-PELE (TEL), Sylvain GIUDICELLI (TEL), Stéphane PIETTE (TEL), Florent PUGINIER (TEL)
Promo 2011
Tuteur Joëlle THOLLOT Joelle.Thollot@grenoble-inp.fr

Box2D est un moteur physique disponible en open source et développé par Erin Catto. En bon moteur physique qu'il est, cet outil permet donc de gérer les positions d'objets dans un monde soumis aux lois physiques telles que la gravité, les collisions...

Box2Dlogo.gif

Nous avions pour sujet, proposé par notre tutrice Joëlle Thollot, l'étude de ce moteur physique à travers le développement d'un jeu ou d'une animation en 2D. Nous avons opté pour un jeu vidéo exploitant au maximum les capacités offertes par un moteur physique. En 2D, ces moteurs sont assez rarement utilisés, la question était donc de savoir ce qu'ils peuvent apporter et d'en étudier les possibles limites et capacités.

Aspect pratique

Principe du jeu

En exclusivité la plus totale, voici donc les premières images de notre jeu vidéo basé sur Box2D.

Box2DJeu.jpg

Dans l'idée d'utiliser le plus possible le moteur physique, nous avons penché pour un jeu où l'interaction avec le décor serait importante. Du coup, outre certains éléments qui sont bien trop costauds pour être sensible à une quelconque modification, le personnage peut interagir avec tous les objets présents. Les pousser, éventuellement les casser, les porter etc...

Toutes ces actions seront possibles dans un but précis bien entendu : terminer les niveaux. Pour cela il faudra rallier une zone d'arrivée, située loin, et parfois même très loin, de la zone de départ du personnage. Et attention pendant le parcours à ne pas se faire écraser, ou tout simplement à bloquer tout seul le chemin !

Box2DDebut.jpg
Début d'un niveau


Box2DFin.jpg
Fin d'un niveau



Possibilités dans le jeu

Comme vous pouvez vous en douter, notre petit personnage dispose de plein d'aide au cours de son périple. Sa seule force physique ne lui sera pas suffisante pour franchir tous les obstacles qui seront présents. Il est néanmoins assez costaud pour porter certains objets, pas trop lourds, et les lancer.

Box2DPriseObjet.jpg
Prise d'un objet

Grâce à une connaissance pointue de tout l'univers Star Wars, ayant participé au projet du développement de la troisième trilogie, et force de milliers d'heures d'entraînement, le personnage maîtrise maintenant la force. Enfin il maîtrise... disons qu'il sait envoyé une vague de force qui peut déplacer ou casser des objets.

Box2DForce.jpg
Utilisation de la force

Pour autant, il n'a pas oublié l'aspect pratique de certaines choses. Il dispose par exemple d'un grappin qu'il peut lancer pour s'accrocher à des objets, se balancer, ou tout autre chose qu'on peut imaginer faire avec un grappin.

Box2DGrappin.jpg
Utilisation du grappin

Enfin, dans les cas les plus désespérés, il peut même modifier le monde et y créer des objets.

Editeur de niveaux

Nous avons mis quelques niveaux à votre disposition. Cependant l'aventure n'est pas obligée de s'arrêter là. En effet il vous est possible de créer vous même vos niveau pour encore plus de plaisir !

Pour cela, vous avez à disposition tous les objets que nous utilisons (décrits dans le manuel ?), le reste dépend de votre imagination. Un aspect important lors de la création de niveau est de bien calibrer tous les objets. C'est-à-dire leur donner des densités cohérentes, régler la friction, le rebond, la fragilité etc... Tout cela est personnalisable, donc à ne pas choisir au hasard car toute la gestion physique des éléments se basera sur ces choix.

Aspect technique

Nous allons maintenant aborder une partie un peu plus technique, destinée à expliquer nos choix de conception et la façon dont nous avons réaliser un peu tout. Cela permettra de montrer nos expériences avec Box2D et une meilleure compréhension de notre code.

Interface

Il faut savoir que Box2D se "contente" de calculer les coordonnées des différents objet contenus dans son monde. En soi, Box2d ne fournit donc qu'une liste de nombres.

Une étape importante est donc d'interfacer ses données. Pour cela nous avons utilisé QT, permettant de créer des interfaces graphique, et sa librairie QGL Viewer qui permet de visualiser des données OpenGL. La principale difficulté que nous avons rencontré était la correspondance des coordonnées du monde Box2D avec celles de la fenêtre OpenGL. Nous avons donc dû redéfinir le repère de OpenGL avec celui de Box2D.

Architecture générale

On pensait pourtant ne jamais avoir à se servir à nouveau de l'UML... Et pourtant il paraît qu'un dessin vaut mieux qu'un long discours ! Alors voilà une idée de l'architecture de notre programme.

Box2DDiagramme.png
Diagramme de classe

Personnage

Le personnage a été réalisé dans une optique différente des autres objets. En effet contrairement aux autres objets, il doit tenir compte de deux contraintes parfois opposées : les lois physiques … et le joueur! Et pour concilier ces 2 aspects, certains choix ont du être fait.

Tout d’abord, le personnage n’est représenté dans Box2D que par un seul bloc rectangulaire. A ce bloc, se fixent plusieurs zones de collisions (pieds, tête, bras etc...) qui déclenchent des animations différentes et des comportements différents quand elles sont activées. Comme ces zones ne sont pas redimensionnables dans Box2D, nous avons dû ajouter des zones de collisions virtuelles afin de gérer certains cas. Exemple : si le personnage s’accroupit, les zones de collisions correspondant à sa position debout passent en virtuelles et les zones de collisions correspondant à sa position accroupie deviennent réelles.

Ensuite, nous avons du désactiver son paramètre rotation dans box2D. En effet, cela posait beaucoup trop de problèmes de gameplay, le personnage se retrouvant alors fréquemment sur le ventre ou sur le dos. Le personnage ne pourra donc plus faire de salto !

Enfin, pour illustrer le conflit entre joueur et physique, nous allons évoquer le problème de la marche du personnage. Notre premier réflexe pour la marche du personnage a été de juste changer les coordonnés du personnage lorsque celui-ci se déplace. Le problème, c’est que le personnage avait alors la fâcheuse tendance d’avoir certains comportements non physiques (traversée de mur, perte d’inertie etc…). Après plusieurs tentatives, nous avons finalement adopté la solution de lui appliquer une force quand il veut se déplacer. Avantage, le personnage a alors un comportement complètement physique mais le joueur à malheureusement l’impression de le voir « patiner » par moment…

Pour ce qui est du rendu, nous avions le choix entre le représenter avec des « sprites » qu’il aurait fallu trouver et dessiner ou de le représenter de manière géométrique à partir des angles de ses bras et de ses jambes. Comme nous sommes plus proche des mathématiques que du dessin, nous avons retenu la deuxième approche. Celle-ci avait par ailleurs l’avantage d’être plus simple à implémenter pour une version test où le rendu n’est pas la priorité.

Le potentiel de Box2D ne s'arrête pas là. En effet, au vu des outils disponibles, il est envisageable de pouvoir créer un personnage entièrement articulé et disposant des réflexes humains permettant de tenir en équilibre. Cependant ce pourrait être un sujet à lui tout seul étant donné la complexité que cela induit.

Objets cassables

Box2D n'utilise que des objets solides. Donc de base il est impossible de casser un objet. Cependant pour la réalisation de notre jeu nous avions besoin de cette fonctionnalité. Nous avons donc utilisé deux méthodes différentes pour créer des objets qui peuvent être cassés.

Il faut tout d'abord dire que Box2D permet une grande maniabilité dans la gestion des contacts. Plus précisément, pour chaque contact qui se produit dans le monde, Box2D offre des possibilités d'interaction sur les objets concernés avant, pendant et après le contact. Cela permet donc de tester si la force du contact est assez puissante pour briser un objet, si les objets en question sont brisables, ce genre de chose.

  • Forts de cela, la première méthode que nous avons utilisée pour casser des objets a été de construire des objets étant composés de plusieurs petits cubes (tout autre polygone aurait été possible). Nous avons étudié deux types de cassures : soit dès que l'objet se brise tous les cubes sont détachés et forment de nouveaux objets à part entière. Soit seul le cube qui est touché est détaché, et peu à son tour taper sur les cubes l'entourant selon la vitesse qu'il acquiert lors du choc.
Box2DEclatable.jpg
Objet éclatable


Box2DCassable.jpg
Objet cassable

Remarque : cette méthode de faire des objets composés peut permettre des créer des polygones concaves qui ne sont de base pas gérés par Box2D.

  • La deuxième méthode consiste à couper un polygone en deux en fonction de la direction de la force de contact. Pour faire, on calcule l'intersection de cette droite de contact avec le polygone en question, puis les deux nouveaux points obtenus permettent de redéfinir deux polygones que l'on créé et qui sont les deux morceaux du polygone original. Nous avons limité la destruction à une aire minimale pour ne pas être envahit d'objets miniatures.
Box2DCoupable.jpg
Objet coupable

Des comportements plus complexes peuvent être imaginés, tels que la propagation d'une fissure en créant une suite de points à l'intérieur du polygone. Il faudrait alors s'assurer que les polygones créés sont tous convexes, ou alors les "convexifier" d'une manière ou d'une autre.

Le Grappin

Le grappin est constitué d'une tête qui permet de s'accrocher aux objets et de sa chaîne. La chaîne est constituée de 60 maillons représentés par des cercles. Les cercles consécutifs sont reliés par des joints rotatifs (b2RevoluteJoint). La taille de la chaine n'est pas constante car dans Box2D les joints sont élastiques. Ceci est un inconvénient dans le cas échéant mais nous avons utilisé cette propriété à son avantage par la suite. Le personnage doit pouvoir lancer le grappin, grimper et descendre à la chaine et la lâcher.

Pour que le personnage monte à la chaine, on utilise des joints simple qui servent à garder une distance entre deux objets. Le personnage est attaché à la base au dernier maillon. Pour grimper, on supprime le joint actuel qui relie le joueur la chaîne et on créé un nouveau joint avec le maillon suivant. La distance du joint est ensuite réduite à zéro pour que le personnage se « raccroche » au maillon suivant. L'élasticité des joints est donc pratique dans ce cas là.

Lorsque le personnage grimpe à la chaîne, les maillons s'écartent à cause de l'élasticité. Pour augmenter la force des joints entre deux objets, il faut augmenter leur masse donc leur densité. La chaîne devient alors vraiment lourde et il faut donc donner une force plus importante au personnage pour lancer le grappin. Il y alors un risque que le grappin soit trop lourd et emporte le joueur trop fortement. Il devient alors très difficile de calibrer toutes les variable pour que le jeu soit jouable et un minimum réaliste.


Rendu

Le rendu n'était pas notre principal objectif. Le temps que nous y avons consacré est donc moindre par rapport au reste. Cependant il nous a semblé essentiel pour un jeu de disposer d'un aspect agréable, et aussi de son. Donc toute la partie rendu réside dans l'adaptation de textures à nos objets et l'introduction du son.

Concernant les textures, nous avons opté pour un style cartoon. Nous avons choisi d'utiliser Qt afin d'ouvrir les fichiers de textures (« .png ») et de les transformer en un type texture géré par OpenGL. Afin d'optimiser le chargement des textures sur les objets, nous avons initialisé au lancement du jeu un tableau contenant toutes les textures. Chaque texture est ainsi identifiée par un numéro.

Pour le son, nous avons utilisé les librairies OpenAL et libsndfile. Le fonctionnement de la librairie OpenAL est très proche de OpenGL. Nous avons créé un tableau de sons (chaque son étant identifié par un numéro) puis lorsque nous voulons appliquer un son, il faut appeler la fonction permettant de jouer le morceau choisi. La librairie libsndfile (librairie opensource) est utilisée pour transformer un fichier son (.wav, .ogg, …) en un type son (ALuint) géré par OpenAL.

Bilan

Retour sur Box2D

  • Box2D est un bon moteur physique qui donne un comportement physique très réaliste. Les interactions entre les objets sont bien gérées et le monde que Box2D crée respecte bien les principes physiques les plus communs.
  • Ce moteur physique est un peu long à prendre en main, mais il permet une grande accessibilité et maniabilité. Tous les objets que l'on crée sont disponibles, et toutes les interactions entre les objets peuvent être manipulées. En somme on peut très bien maîtriser le déroulement de la simulation et en récupérer les informations intéressantes.
  • Particularité pratique : toute la gestion de la mémoire est effectuée par Box2D lui-même. Cela simplifie grandement son utilisation. Cependant la gestion de mémoire n'est pas forcément optimale, ce qui fait que le monde est limité en nombre d'objets. Environ 800 pour notre jeu, un peu plus pour d'autres projets réalisés avec Box2D aussi.
  • Les points négatifs commencent ici. La documentation est peu développée. Il est souvent nécessaire d'aller chercher dans le code source des informations un peu précises. En fait documentation permet de se lancer dans Box2D, mais ne détaille pas les fonctionnalités les plus poussées.
  • Les erreurs liées à Box2D sont parfois hors-sujet, et ne permettent pas de bien comprendre où est le problème.
  • Box2D c'est un monde physique qui a lui aussi ses limites. Tous les objets gérés sont solides et incassables. Ils doivent de plus être convexes sous peine de comportements très irréels ! A noter qu'il faut aussi être familier du sens trigonométrique pour éviter de créer des polygones avec des aires négatives... Enfin les joints disponibles dans Box2D ont tendance à être un peu élastique.

Bilan du jeu

Le jeu tel quel que nous vous proposons n'est pas à proprement parlé un jeu. Quelques niveaux que nous avons créés existent, mais l'ensemble permet surtout, via l'éditeur de niveaux, de faire son propre jeu. Quelques points nous semblent quand même important à remarquer.

  • Des comportements plus réalistes peuvent encore être implémentés que ce soit pour le personnage ou pour les objets cassables. Par exemple il est envisageable de rendre le personnage complètement articulé, ou encore de rendre les cassures un peu plus aléatoires (fissures).
  • L'éditeur de niveau peut encore être amélioré en implémentant la suppression des objets graphiquement, ainsi que des améliorations de l'interface.
  • Enfin le gameplay est quelque peu ardu. Cependant comme dit au-dessus, c'est surtout un outil de création de jeu que nous avons finalement réalisé, donc libre à vous de trouver un gameplay qui vous correspond !


Liens

Voici le code source du jeu. Le README permet de savoir les librairies que nous avons utilisées et qui vous seront nécessaires si jamais vous voulez essayer le jeu (le finir on en doute, il est bien trop dur !).

Code source du jeu

Si jamais vous prenait l'envie de discuter du jeu, sentez-vous libre de nous contacter. Et si jamais, par le plus grand des hasards (obligation ?), vous voulez continuer ou améliorer ce projet, nous serons heureux de répondre à vos questions. Par contre la difficulté sera de trouver la personne qui pourra répondre à la question, vous aurez probablement une chance sur cinq...