Architecture de notre système particulaire

Grâce aux capacités des langages orientés objets, nous avons pu concevoir une architecture où modularité, évolutivité et réutilisabilité ne sont pas des mots en l'air.
Agora'Sim est fondé sur un système particulaire. C'est-à-dire que chaque mobile est représenté par une particule dont on calcule la position à intervalles de temps régulier. On peut distinguer 4 parties : le moteur, l'affichage, les particules, et l'environnement.

Les particules : le polymorphisme

Toutes les particules de notre système sont des objets dont la classe (le type) dérive d'une classe "Mobile" dite abstraite. On ne peut pas instancier d'objet directement à partir d'une classe abstraite car on y déclare en général des méthodes (des fonctions) qui ne sont pas implémentées. Les classes abstraties sont donc destinées à être dérivées en d'autres classes qui devront imple´menter toutes les fonctions déclarées dans leur classe "mère" sous peine de devenir elle-même une classe abstraite.

Voyons l'utilité de ce mécanisme en prenant pour exemple Agora'Sim.
Dans notre simulateur, tous les mobiles sont issus d'une classe abstraite "Mobile". Cette classe possède deux fonctions qui ne sont pas implémentées : bouge() et trace(). Nous sommes donc obligés de créer de nouvelles classes qui dérivent de Mobile pour implémenter les comportements de nos particules. L'intérêt est que pour tout le programme, les particules sont toutes vues comme étant des objets de types Mobile. Quelles que soient les impléemntations qui sont faites pour les particules, le moteur saura les faire bouger.
Ce mécanisme s'appelle le polymorphisme. Il nous permet de développer des particules avec de nouveaux comportements en n'ayant rien à modifier, et donc rien à revalider sur le reste du logiciel.

Les particules : l'hérédité

On a vu que toutes nos particules sont issues de classes dérivant la classe Mobile. C'est en fait encore un peu plus subtil. Le but de la manoeuvre est d'éviter la redondance, de ne pas avoir à coder, tester, deboguer plusieurs fois ce qui peut l'être une fois pour toutes.

La classe Mobile a tout d'abord été dérivé en une classe MobPhys qui implémente tous les comportements physiques des particules. MobPhys s'occupe de calculerla position et la vitesse de la particule en fonction de l'accélération à laquelle elle est soumise. Les collisions avec les murs et les autres particules sont aussi gérées ici. Seule la méthode bouge() est redéfinie, MobPhys reste donc une classe abstraite.

La classe MobPhys est à son tour dérivée en une classe MobComp. Cette classe regroupe toutes les méthodes nécessaires à l'élaboration du comportement des particules. Calculer le vecteur d'accélération à fournir pour tourner à gauche par exemple.

Enfin, les classes finales utilisent les services définis dans MobComp pour "construire" le vecteur d'accélération dont elles ont besoin, et le donnent en pâture aux méthodes définies dans MobPhys pour concrétiser leur déplacement.

Ce mécanisme, l'hérédité, nous a ainsi permis de modéliser de nombreuses particules aux comportements différents pour animer toutes les applets de ce site, avec très peu de code spécifique à chacune.

On pourrait répondre qu'une bibliothèque de fonctions rend le même service. En fait l'hérédité permet bien plus. Il est par exemple possible à MobPhys de bloquer aux classes qui la dérivent l'accès aux variables de la classe Mobile. Ainsi, pour changer la position du mobile, on est obligé d'utiliser les fonctions offertes par MobPhys (c'est l'encapsulation). On met ainsi les variables de Mobile en sécurité contre les erreurs de manipulation. Le fait d'être obligé de passer par des méthodes (fonctions) pour accéder aux données permet également de changer l'organisation interne des classes sans en changer les méthodes, ce qui a l'avantage d'être totalement transparent pour les autres classes.

L'environnement : même combat

Les "plans" utilisés par Agora'Sim sont un ensemble de zones qui offrent des services tels que tester si un mobile est dedans. Comme pour les particules, le polymorphisme est utilisé pour que l'utilisation des zones soit indépendante de leur implémentation.

Concrètement, on se moque de savoir si les zones sont rondes ou rectangulaires. Comme elle dérivent toutes de la classe Zone, l'affichage sait les afficher et les mobiles savent tester s'ls sont ou non dedans.

L'affichage : une offre de service

La méthode d'affichage est assez intéressante. Le module d'affichage ne sait afficher ni les zones ni les mobiles, puisque cela dépend de leur implémentation. Par contre, il sait qu'il peut leur demander de se tracer eux-mêmes. Tous les mobiles et toutes les zones sont en effet obligées de savoir le faire car c'est spécifié dans les classes abstraites Mobile et Zone.

De leur côté, les mobiles et les zones sont bien embêtés car ils ne connaissent que leur propre système de coordonnées (en flottants) et n'ont aucune idée de la rèsolution de l'écran ou du facteur de zoom utilisé. On peut presque dire que leur principal souci est de ne pas avoir à se soucier de ce genre de chose...

La solution utilisée est la suivante :

Le procédé est rigoureusement identique pour les zones.

Le moteur : jeu, thread et match

Le moteur de la simulation est une simple boucle qui demande aux mobiles de bouger (il demande en fait à la liste de mobiles...) puis à l'affichage de se rafraîchir. Le moteur attend un petit moment avant de recommencer.

Notre moteur est un thread, c'est-à-dire une unité de calcul parallèle. Il s'exécute en même temps que le reste du programme.
Ainsi, même si l'affichage est très lent, le moteur continue à calculer de nouvelles positions. Si quand il a terminé une boucle, l'affichage n'a pas fini d'afficher les résultats de la suivante, et bien tant pis ! Ainsi, un affichage lent donne une animation saccadée, mais non ralentie.

page suivante
retour au sommaire