papush!
e8be8b52ab
implémentation du patron Observateur dans la classe Observer qui permet à un objet d’être notifié quand une propriété d’un autre objet est modifiée. CollideRect observe maintenant les propriétés x et y de l’entité à laquelle il appartient et met à jour son rect accordément.
131 lines
5.9 KiB
Plaintext
131 lines
5.9 KiB
Plaintext
On a voulu commencer en écrivant le code le plus simple et efficace
|
||
qui permettait de réaliser un pac-man. Celui-ci n’utilisait que très
|
||
peu de classes ou patrons de conceptions, il était simple et efficace
|
||
mais aussi très spécifique et inflexible.
|
||
|
||
On a donc corrigé le tir en passant à une architecture de moteur de
|
||
jeu entité-composant.
|
||
|
||
Le moteur de jeu est entièrement séparé du jeu lui-même et d’autre jeu
|
||
pourraient être implémentés sur le même moteur sans le changer ou
|
||
presque.
|
||
|
||
Le système entité-composant se base principalement sur l’idée de
|
||
favoriser la composition par rapport à l’héritage. Son principe est
|
||
simple : chaque objet dans une scène d’un jeu (une scène étant un
|
||
« écran » de jeu ou une phase, comme un niveau mais aussi un menu…)
|
||
est une entité. Une entité consiste d’un ou plusieurs composants qui
|
||
lui ajoutent une fonctionalité ou un comportement. Cela permet de
|
||
simplifier la hiérarchie de classe, mais également de mettre en place
|
||
certaines optimisations du domaine de la programmation orientée
|
||
données. Avec l’entité et le composant, la troisième brique
|
||
élémentaire de cette architecture est le Système, aussi appelé Serveur
|
||
ou Moteur. Ceux-ci fonctionnent indépendamment et effectuent un
|
||
traitement sur sur toutes les entités qui possèdent un composant qui
|
||
touche un aspect similaire au serveur.
|
||
|
||
Plus concrètement, sur l’exemple de notre jeu pac-man : le pac-man,
|
||
les fantômes, le labyrinthe et les pac-dots sont des entités.
|
||
|
||
Ils ont tous un composant « représentation graphique » entre autres
|
||
qui permet de les afficher à l’écran et contient les données
|
||
nécessaire pour cela (leur image, mais aussi leur niveau/hauteur pour
|
||
savoir lesquels afficher au-dessus des autres).
|
||
|
||
Le moteur dispose d’un serveur graphique qui, à chaque itération de la
|
||
boucle principale de jeu, itère sur tous les composants graphiques et
|
||
en effectue le rendu pour finalement l’afficher dans la fenêtre du
|
||
jeu.
|
||
|
||
Un deuxième composant que beaucoup d’entités vont posséder est lui lié
|
||
à la gestion de la physique. Le serveur physique associé va à chaque
|
||
tour de boucle calculer les nouvelles position des entités (pour
|
||
celles qui doivent/peuvent se déplacer) mais aussi calculer et
|
||
résoudre les collisions, éventuellement en envoyant un signal aux
|
||
entités concernées en cas de collision.
|
||
|
||
Finalement, chaque entité peut avoir un comportement personalisé sous
|
||
forme d’une fonction appelée à chaque itération.
|
||
|
||
Le niveau lui est lu depuis une image basse résolution où chaque pixel
|
||
défini une case, est génère sa représentation graphique à partir de
|
||
celle-ci. Il créé également des composants physique de collision pour
|
||
chaque mur solide et les entités des pac-dots.
|
||
|
||
Pacman
|
||
|- comportement personalisé (appelé à chaque itération) :
|
||
| entrées = lire_entrées
|
||
| si entrée[gauche]:
|
||
| aller à gauche
|
||
| …
|
||
|- sprite (image : pacman.png)
|
||
|- boîte de collision (taille)
|
||
|
||
Niveau
|
||
|- sprite (image: le niveau, généré à partir d’une description)
|
||
|- boîte de collision mur 1
|
||
|- boîte de collision mur 2
|
||
|- …
|
||
|
||
Fantôme
|
||
|- comportement personalisé :
|
||
| déplacement automatisé (IA)
|
||
|- sprite (image: fantôme.png)
|
||
|- boîte de collision
|
||
|
||
Le moteur contient donc la définition d’une entité, des différents
|
||
composants et serveurs et de la boucle principale. Le jeu lui est
|
||
séparé du moteur et n’est qu’un ensemble de scènes, qui sont une
|
||
simple collection d’entitées avec des composants pré-établis et des
|
||
comportements personalisés.
|
||
|
||
|
||
En termes de patrons de conception utilisés :
|
||
|
||
- le système entité-composant est lui-même un patron (d’architecture
|
||
plus que de conception),
|
||
|
||
- le décorateur est utilisé à divers endroits, par exemple pour
|
||
ajouter diverse responsabilité à une boîte de collision et la
|
||
rendre traversable (simple zone de détection « trigger » comme pour
|
||
les pac-dots), solide statique (un mur), solide dynamique (pac-man,
|
||
les fantômes),
|
||
|
||
- le singleton, chaque serveur ne peut être instancié qu’une fois et
|
||
le patron singleton permet également de retrouver cette instance de
|
||
n’importe où dans le code plutôt que d’avoir à passer des
|
||
références de partout,
|
||
|
||
- observateur, pour synchroniser les propriétés des composants.
|
||
|
||
|
||
Évolutions futures possibles :
|
||
|
||
- système de gestion des entrées, chaque entité qui veut recevoir des
|
||
entrées (clavier, manettes) doit posséder un composant qui décrit
|
||
quelles actions l’intéresse et le comportement à adopter
|
||
lorsqu’elles sont reçues,
|
||
|
||
- système d’animation, celles-ci sont pour l’instant gérées
|
||
manuellement dans le comportement personalisé des entités mais
|
||
devraient être un composant spécialisé (le lecteur d’animation) qui
|
||
lit des animations qui seraient alors un nouveau type de resource
|
||
qui modifient les propriétés d’une entité (et ses composants) au
|
||
fil du temps, par exemple changer l’image d’un pac-man pour
|
||
utiliser alternativement celle avec bouche ouverte et celle avec
|
||
bouche fermée (waka-waka). On peut également penser à une machine à
|
||
état qui gère les états et transitions entre ces états (dans un jeu
|
||
3D, passage de l’état « debout » à l’état « courrir » qui ont
|
||
chacun leur animation, tout en effectuant une transition entre les
|
||
deux animations pour éviter les changements brutaux),
|
||
|
||
- gestion spécifique des resources, pour l’instant chaque composant
|
||
stocke les resources dont il a besoin, principalement des images.
|
||
un moteur de jeu plus complexe peut avoir une gestion des resources
|
||
spécialisée pour optimiser l’utilisation mémoire gérer
|
||
automatiquement les conversions entre différents formats,
|
||
|
||
- de manière globale, généraliser tous ce qui peut être généralisé
|
||
dans les fonctions personalisées de chaque entitée sous la forme de
|
||
composants.
|