Tuto Complet: POO & MVC avec le Jeu de la Vie

Créations

Steph

il y a 11 mois

TUTO COMPLET sur le Jeu de la Vie



Je vous propose ici un tutoriel très complet s'appuyant sur une petite récréation mathématique, à défaut d’un véritable jeu au sens classique du terme, pour la Gamebuino META : le célèbre Jeu de la Vie, imaginé par John Conway dans les années 1970. Vous allez voir que c’est un petit exercice formidable, qui va nous permettre d’aborder de nombreux concepts et techniques de programmation. L’idée maîtresse qui m’a guidé tout au long de la rédaction de ce tutoriel était de proposer un exercice à la fois simple et riche en possibilités, que nous allions pouvoir traiter de manière différente, au travers d’une approche graduelle dans la complexité de la programmation, pour aboutir à une application finalisée avec une architecture maîtrisée.

Le tutoriel est disponible ici.

Ce que vous allez apprendre dans ce tutoriel :

  • programmer un automate cellulaire,
  • optimiser votre code pour :
    • accélérer la vitesse d’exécution,
    • économiser l’espace mémoire,
  • mieux organiser votre code avec la Programmation Orientée Objet,
  • concevoir vos applications avec une architecture Model View Controller,
  • intercepter les événements lorsque l’utilisateur appuie sur les boutons,
  • gérer des menus dans vos applications,
  • programmer un gestionnaire des LEDs de la console,
  • programmer un gestionnaire d’effets sonores.

N’hésitez pas à me communiquer vos commentaires, ou à me demander des précisions sur les éléments que vous n’avez pas bien compris.

Je tiens à préciser que cette application est ma première expérience de programmation en C++ … et oui ;-) moi aussi j’apprends comme vous ! Mon code est très probablement perfectible, aussi je compte sur les codeurs expérimentés de la communauté pour me faire part des améliorations possibles (ou nécessaires !). Je tâcherai de les intégrer dès que possible… parce-que j’ai quand même un TAF dans la vraie vie… et que je ne peux pas consacrer tout le temps que je voudrais à m’amuser avec cette super petite console !

Voir la création

jicehel

NEW il y a 11 mois

Bon autant te le dire tout de suite, le jeu de la vie, ce n'est pas mon truc, mais par contre bravo. Quel boulot sur le tuto... J'ai vu une petite erreur dans le graphique de "Calcul du voisinage", il est écrit i différent de 0 ou j différent de 0 alors que c'est et à la place du ou (d'ailleurs c'est bien marqué dans le texte en dessous) par contre c'est faux dans le programme d'exemple (c'est un ou de marqué alors que ça devrait être un et).

J'ai regard rapidement le reste car je vais me faire à manger mais le reste me parait très bien et quel beau tuto. Bien divisé en chapitre, très clair. En fait je pense que les tuto de la META devrais un peu s'inspirer des tiens pour la lisibilité et l’enchaînement. Je trouve la navigation dan les tutos beaucoup plus intuitive sur ton site. Si tu veux intégrer les miens à ta sauce, fais toi plaisir. 

Donc, bon le programme d'exemple, désolé, ce n'est pas mon truc mais les tutos, j'adore et j'espère que tu va continuer à en faire.  :)

Steph

il y a 11 mois

Merci pour ton commentaire fort sympathique. C'est très encourageant ! La rédaction m'a en effet demandé pas mal de boulot et je commençais à être impatient de voir le bout du tunnel...

Concernant ta remarque au sujet  d'une petite erreur que tu aurais relevée concernant le calcul du voisinage d'une cellule, et bien... j'en conclue que ma figure n'est pas assez claire. Je la referai donc demain (à La Réunion il est déjà 1:00 du matin passée et je dois me lever tôt demain pour aller bosser).

Il ne s'agit pas d'une erreur ! Le voisinage d'une cellule est bien défini par :

grid[x+j][y+i] lorsque i ∈ [-1,1] et j ∈ [-1,1] et que (i ≠ 0) OU (j ≠ 0)

Le cas où (i=0) ET (j=0) concerne la cellule centrale qui ne fait donc pas partie du voisinage ;-)

Je n'ai pas dû être assez clair (ou tu as lu trop vite ?)... je reformulerai ce passage demain.

Concernant la mise en page des tutos du site officiel, effectivement, je trouve qu'elle n'est pas mise en valeur et les contenus sont difficilement appréciables sous cette forme. C'est pourquoi j'ai préféré publier le mien sur un site perso, où je maîtrise la feuille de styles et la navigation :-)

Pour terminer, je conçois que le Jeu de la Vie ne passionne pas tout le monde. Néanmoins, dans le cadre de ce tuto, il ne faut pas le considérer en tant que tel, mais plutôt l'envisager comme une base pédagogique abordable par sa simplicité, et qui permet d'illustrer de nombreux concepts de programmation intéressants (voire fondamentaux) sans se heurter à la difficulté intrinsèque d'un cas d'étude plus complexe.

Encore merci pour ton commentaire !

Steph

NEW il y a 11 mois

jicehel jicehel

Merci pour ton commentaire fort sympathique. C'est très encourageant ! La rédaction m'a en effet demandé pas mal de boulot et je commençais à être impatient de voir le bout du tunnel...

Concernant ta remarque au sujet  d'une petite erreur que tu aurais relevée concernant le calcul du voisinage d'une cellule, et bien... j'en conclue que ma figure n'est pas assez claire. Je la referai donc demain (à La Réunion il est déjà 1:00 du matin passée et je dois me lever tôt demain pour aller bosser).

Il ne s'agit pas d'une erreur ! Le voisinage d'une cellule est bien défini par :

grid[x+j][y+i] lorsque i ∈ [-1,1] et j ∈ [-1,1] et que (i ≠ 0) OU (j ≠ 0)

Le cas où (i=0) ET (j=0) concerne la cellule centrale qui ne fait donc pas partie du voisinage ;-)

Je n'ai pas dû être assez clair (ou tu as lu trop vite ?)... je reformulerai ce passage demain.

Concernant la mise en page des tutos du site officiel, effectivement, je trouve qu'elle n'est pas mise en valeur et les contenus sont difficilement appréciables sous cette forme. C'est pourquoi j'ai préféré publier le mien sur un site perso, où je maîtrise la feuille de styles et la navigation :-)

Pour terminer, je conçois que le Jeu de la Vie ne passionne pas tout le monde. Néanmoins, dans le cadre de ce tuto, il ne faut pas le considérer en tant que tel, mais plutôt l'envisager comme une base pédagogique abordable par sa simplicité, et qui permet d'illustrer de nombreux concepts de programmation intéressants (voire fondamentaux) sans se heurter à la difficulté intrinsèque d'un cas d'étude plus complexe.

Encore merci pour ton commentaire !

jicehel

NEW il y a 11 mois

Hum, je ne comprends pas en effet. Si i=0 et j=-1 par exemple, la cellule fais bien partie du voisinage. Seul le cas ou i=0 et j=0 est à exclure du voisinage. Enfin c'est ce que je comprends moi. Donc le voisinage est i ∈ [-1,1] et j ∈ [-1,1] et i,j ≠ (0,0) soit i≠0 et j≠0. Si i=-1 ou 1 et j=0, la cellule fais bien partie du voisinage.

Si oui, je comprends tout à fais la base pédagogique et ça, c'est très bien fait et en effet, c'est un cas qui permet de bien illustrer différentes choses au travers des différents chapitre.

Steph

il y a 11 mois

Hi hi ... décidément...


Hum, je ne comprends pas en effet. Si i=0 et j=-1 par exemple, la cellule fais bien partie du voisinage. Seul le cas ou i=0 et j=0 est à exclure du voisinage. Enfin c'est ce que je comprends moi.

Tout à fait ! Le cas "i=0 ET j=-1" fait bien partie des cas où "i≠0 OU j≠0"


Seul le cas ou i=0 et j=0 est à exclure du voisinage. Enfin c'est ce que je comprends moi.

C'est exactement ça.


Donc le voisinage est i ∈ [-1,1] et j ∈ [-1,1] et i,j ≠ (0,0) soit i≠0 et j≠0.

Et non justement... (i,j) ≠ (0,0) <=> ! [i=0 ET j=0] <=> i≠0 OU j≠0 ;-)

Steph

NEW il y a 11 mois

jicehel jicehel

Hi hi ... décidément...


Hum, je ne comprends pas en effet. Si i=0 et j=-1 par exemple, la cellule fais bien partie du voisinage. Seul le cas ou i=0 et j=0 est à exclure du voisinage. Enfin c'est ce que je comprends moi.

Tout à fait ! Le cas "i=0 ET j=-1" fait bien partie des cas où "i≠0 OU j≠0"


Seul le cas ou i=0 et j=0 est à exclure du voisinage. Enfin c'est ce que je comprends moi.

C'est exactement ça.


Donc le voisinage est i ∈ [-1,1] et j ∈ [-1,1] et i,j ≠ (0,0) soit i≠0 et j≠0.

Et non justement... (i,j) ≠ (0,0) <=> ! [i=0 ET j=0] <=> i≠0 OU j≠0 ;-)

jicehel

NEW il y a 11 mois

Bon je n'insiste pas, c'est peut être moi qui me trompe mais si je suis d'accord avec ! [i=0 ET j=0] pour moi, le résultat est différent de i≠0 OU j≠0 ou du coup tu exclues la ligne i=0 et la colonne j=0 donc tu exclues 5 cases au lieu d'une selon moi dont la centrale mais aussi 4 autres. 


Steph

il y a 11 mois

Je t'assure que non !... simple règle de logique :

NON(A ET B) = NON(A) OU NON(B)

Steph

NEW il y a 11 mois

jicehel jicehel

Je t'assure que non !... simple règle de logique :

NON(A ET B) = NON(A) OU NON(B)

jicehel

NEW il y a 11 mois

ok, oui, il faut bien A=0 et B=0 pour avoir un résultat à 0, sinon on a 1, c'est vrai. Désolé, je dois être fatigué sans doute, mais oui, c'est vrai...

chris-scientist

NEW il y a 11 mois

Très bon tutoriel !

Tu as très bien décrit la POO et le MVC, c'est un bon complément à ce que j'ai écris. Je pense d'ailleurs que je vais ajouter un lien vers ton tutoriel.

Je pense que pour le framework que j'écris je vais m'inspirer de tes effets de lumières.

J'ai repéré deux petites coquilles, dans la partie "son et lumière", dans le dernier exemple de code :

  • tu indique qu'il s'agit du fichier GameController.h mais je pense qu'il s'agit du .cpp.
  • et pour la dernière méthode de cette classe tu as écrit le commentaire suivant "// idem lrosqu'il sort du mode édition :".

Steph

il y a 11 mois

Merci pour ton commentaire ! Je viens de corriger les coquilles :-)

Je pense effectivement que, pour les  apprenants, tes tutos et celui-ci constituent une bonne base pour se lancer dans la POO et l'architecture MVC. Ils ont tout à y gagner lorsque l'application prend de l'ampleur...

Concernant les lumières, oui, c'est plus facile de gérer ça dans un contrôleur dédié... et surtout... dans le référentiel HSL ! J'ai d'ailleurs suggéré à Soru (sur Discord) d'ajouter les fonctions rgb2hsl et hsl2rgb dans l'API de la bibliothèque officielle.

Steph

NEW il y a 11 mois

chris-scientist chris-scientist

Merci pour ton commentaire ! Je viens de corriger les coquilles :-)

Je pense effectivement que, pour les  apprenants, tes tutos et celui-ci constituent une bonne base pour se lancer dans la POO et l'architecture MVC. Ils ont tout à y gagner lorsque l'application prend de l'ampleur...

Concernant les lumières, oui, c'est plus facile de gérer ça dans un contrôleur dédié... et surtout... dans le référentiel HSL ! J'ai d'ailleurs suggéré à Soru (sur Discord) d'ajouter les fonctions rgb2hsl et hsl2rgb dans l'API de la bibliothèque officielle.

sautax

NEW il y a 11 mois

Par rapport à mon dépôt j'ai fait une branche qui restera la même pour toujours comme ça je peux faire des changements ^^

https://github.com/sautax/game-of-life-gamebuino/tree/0.4

Steph

il y a 11 mois

Merci sautax ! C'est très sympathique de ta part. Je pousserai la mise à jour du lien vers la bonne branche de ton dépôt dès ce soir.

Edit: c'est fait :-)

Party_Pete

NEW il y a 11 mois

C'est incroyable! Le tuto est trés complet, et il a connaissance beaucoup pour moi apprendre C++ sur la Gamebuino. Je ne parle pas français bien, mais je comprende assez de français essayer lire le tuto en français. Merci beaucoup pour vos poste!

Steph

NEW il y a 11 mois

sautax sautax

Merci sautax ! C'est très sympathique de ta part. Je pousserai la mise à jour du lien vers la bonne branche de ton dépôt dès ce soir.

Edit: c'est fait :-)

YQN

NEW il y a 9 mois

MERCI steph :D

YQN

NEW il y a 9 mois

Une petite question : je vais essayer d'utiliser cette méthode pour créer un clone de Breakout, du coup la logique est d'avoir un MVC pour chaque élément ? (ex. Pad, PadView, PadController, Ball, BallView, BallController etc. ?)

Merci d'avance ! :)

Edit : Après avoir essayé j'imagine que ce n'est pas la bonne méthode, je suis un peu perdu :/

Steph

il y a 9 mois

Merci pour tes commentaires YQN :-)

Désolé pour le délai de réponse... mais quelques impondérables m'empêchent actuellement d'être très présent auprès de la communauté.

Pour répondre à ta question... il ne faut pas considérer que l'architecture MVC est la solution idéale qui s'applique à tous les cas de figures que tu vas rencontrer lorsque tu vas chercher à organiser ton code ! Loin de là ! Il est tout à fait inutile d'employer un marteau-piqueur pour enfoncer une punaise ;-) Cette architecture se prête très bien à la modularisation des composants de ton code lorsque celui-ci se complexifie. Il en facilite l'organisation et la compréhension en séparant bien la logique qui les articule. L'architecture que je propose dans le Jeu de la Vie en illustre la plupart des aspects. Mais vouloir à tout prix adopter cette organisation peut, au contraire, alourdir ton code et s'avérer parfaitement inutile. Dans des cas simples comme la gestion d'un paddle dans un jeu de casse-briques, le modèle et la vue peuvent être rassemblés au sein d'un même et unique composant (Paddle). Un contrôleur des événements utilisateurs (pour intercepter l'appui sur les boutons de la console) sera par contre très utile pour isoler la gestion de ce type d'interactions dans ton code. Le contrôleur pourra alors ensuite agir directement sur ton composant Paddle en le déplaçant (c'est-à-dire en envoyant un ordre ayant pour effet de modifier sa coordonnée selon l'axe horizontal). Et lorsque ce sera le moment (prévoir un point d'entrée à partir de la boucle de contrôle global loop), ce même Paddle pourra simplement se dessiner en fonction de ses coordonnées (qui représentent finalement son modèle). Il sera, à lui seul, son modèle et sa vue...

Est-ce que j'ai répondu à ta question ?

Steph

NEW il y a 9 mois

YQN YQN

Merci pour tes commentaires YQN :-)

Désolé pour le délai de réponse... mais quelques impondérables m'empêchent actuellement d'être très présent auprès de la communauté.

Pour répondre à ta question... il ne faut pas considérer que l'architecture MVC est la solution idéale qui s'applique à tous les cas de figures que tu vas rencontrer lorsque tu vas chercher à organiser ton code ! Loin de là ! Il est tout à fait inutile d'employer un marteau-piqueur pour enfoncer une punaise ;-) Cette architecture se prête très bien à la modularisation des composants de ton code lorsque celui-ci se complexifie. Il en facilite l'organisation et la compréhension en séparant bien la logique qui les articule. L'architecture que je propose dans le Jeu de la Vie en illustre la plupart des aspects. Mais vouloir à tout prix adopter cette organisation peut, au contraire, alourdir ton code et s'avérer parfaitement inutile. Dans des cas simples comme la gestion d'un paddle dans un jeu de casse-briques, le modèle et la vue peuvent être rassemblés au sein d'un même et unique composant (Paddle). Un contrôleur des événements utilisateurs (pour intercepter l'appui sur les boutons de la console) sera par contre très utile pour isoler la gestion de ce type d'interactions dans ton code. Le contrôleur pourra alors ensuite agir directement sur ton composant Paddle en le déplaçant (c'est-à-dire en envoyant un ordre ayant pour effet de modifier sa coordonnée selon l'axe horizontal). Et lorsque ce sera le moment (prévoir un point d'entrée à partir de la boucle de contrôle global loop), ce même Paddle pourra simplement se dessiner en fonction de ses coordonnées (qui représentent finalement son modèle). Il sera, à lui seul, son modèle et sa vue...

Est-ce que j'ai répondu à ta question ?