il y a 6 ans
Dans les parties précédentes nous avons vu les bases de notre programme, la gestion de la caméra, la gestion de l'affichage et la gestion du personnage. Nous allons voir dans cette cinquième et dernière partie la gestion de la physique et la gestion de la partie, ainsi à la fin de cette partie nous serons en mesure de faire déplacer une caisse par le personnage, de s'arrêter face à un mur et de déterminer si la partie est terminée.
Les pré-requis de ce tutoriel sont :
Je vous invite à télécharger le code qui est le résultat de la quatrième partie, ceci pour partir sur des bases communes.
Il faut pouvoir rester bloqué si l'on cherche à franchir un mur, sachez qu'il s'agit de l'affaire de quelques lignes et que tout ce passe dans CharacterController.
D'abord, nous allons écrire la méthode pour détecter que le sprites (que nous nommerons aReplacedSprites) est un mur, il s'agit de la méthode isWall, voici le pseudo code :
SI aReplacedSprites = mur ALORS Retourner vrai SINON Retourner faux FIN SI
Ceci dit ce pseudo code peut-être optimisé, en effet la condition renvoye vrai ou faux, le pseudo code est ainsi :
Retourner (aReplacedSprites = mur)
Voici le code de la méthode :
const bool CharacterController::isWall(const char aReplacedSprites) const { return (aReplacedSprites == TypeOfSprites::WALL_TYPE); }
Enfin nous avons plus qu'à interdire le déplacement si le sprite est un mur. Rappelez-vous du pseudo code du déplacement vers le haut par exemple, qui était le suivant :
Calculer la position fictive relative à un déplacement vers le haut Récupérer le sprites relatif à la position fictive SI nous sommes toujours sur la carte avec la position fictive ALORS Ecraser la position fictive avec la tuile correspondant au joueur Remplacer l'ancienne position du joueur par le sprites qui s'y trouvait avant Stocker le sprites relatif à la position fictive Mettre à jour la position du personnage SINON Réintialiser la position fictive FIN SI
Voici le pseudo code d'un déplacement vers le haut qui interdit de franchir un mur :
Calculer la position fictive relative à un déplacement vers le haut
Récupérer le sprites relatif à la position fictive
SI nous sommes toujours sur la carte avec la position fictive ET le sprites où nous voulons aller n'est pas un mur
ALORS
Ecraser la position fictive avec la tuile correspondant au joueur
Remplacer l'ancienne position du joueur par le sprites qui s'y trouvait avant
Stocker le sprites relatif à la position fictive
Mettre à jour la position du personnage
SINON
Réintialiser la position fictive
FIN SI
Voici le code du déplacement vers le haut avec la contrainte relative au franchissement de mur :
void CharacterController::goUp() { // calcul de la nouvelle position character->goUp(); // récupérer la tuile de la nouvelle position char newTypeOfSprites = mapModel->getTypeOfSprites(character->getNextPos()[0], character->getNextPos()[1]); // si la nouvelle position du personnage est sur la carte et que ce n'est pas un mur if(character->getNextPos()[1] >= 0 && !isWall(newTypeOfSprites)) { // écraser nouvelle position par la tuile du joueur mapModel->setTypeOfSprites(character->getNextPos()[0], character->getNextPos()[1], getPlayerSprites(newTypeOfSprites)); // remplacer ancienne position par la tuile qui était à cette position précédement mapModel->setTypeOfSprites(character->getX(), character->getY(), character->getOldTypeOfSprites()); // stocker la tuile de la nouvelle position character->setOldTypeOfSprites(newTypeOfSprites); // mettre à jour la position character->updatePositions(); } else { // remettre à zéro la position suivante character->resetNextPositions(); } }
Ajouter la contrainte aux autres déplacements et le tour sera joué.
Nous allons maintenant voir le déplacement d'une caisse, sachez que c'est plus complexe que la contrainte précédente, mais je suis là pour vous guider. Et comme la contrainte précédente tout ce joue dans CharacterController.
Commençons par écrire le pseudo code de détection d'une caisse, pensez à la simplification utilisé lors de la détection de mur :
Retourner (aReplacedSprites = caisse) || (aReplacedSprites = caisse sur zone de 'chargement')
Voici le code de la méthode isBox :
const bool CharacterController::isBox(const char aReplacedSprites) const { return (aReplacedSprites == TypeOfSprites::BOX_TYPE) || (aReplacedSprites == TypeOfSprites::BOX_ON_ZONE_TYPE); }
Ecrivons un gros morceau, soit le pseudo code pour déplacer une caisse, il s'agit de la méthode moveBox. Les paramètres de cette méthode sont le sprites à remplacer (aReplacedSprites), les coordonnées X1, Y1 ainsi que les coordonnées X2, Y2 ces dernières représentent le sprite après la caisse. Voici le pseudo code :
Récupérer le sprites ayant pour coordonnéées X2, Y2 Affecter à stopMove la valeur du test suivant : est différent du sol ou différent d'une zone de chargement SI stopMove est faux ALORS SI le sprites de coordonnées X2, Y2 est une zone de chargement ALORS Affecter à replacedSprites2 un sprite de type caisse sur zone de chargement SINON Affecter à replacedSprites2 un sprite de type caisse FIN SI Ecraser la position X2, Y2 par replacedSprites2 SI aReplacedSprites = caisse sur zone de chargement ALORS Retourner sprites de type zone de chargement SINON Retourner sprites de type sol FIN SI FIN SI Retourner aReplacedSprites
Nous pouvons simplifier le code à l'aide d'une condition particulière que l'on appelle condition ternaire. Voyons comment faire sur un exemple de pseudo code :
SI nb > 0 ALORS Affecter à signe la valeur '+' SINON Affecter à signe la valeur '-' FIN SI
Voici le code relatif à cette exemple, utilisant une condition ternaire :
char signe = (nb > 0) ? '+' : '-';
Je vous ai donner cette simplification car nous pouvons l'utiliser à deux reprises dans le code de moveBox que voici :
const char CharacterController::moveBox(const char aReplacedSprites, const int aX1, const int aY1, const int aX2, const int aY2) { // on récupère le sprites en X2, Y2 const char sprites = mapModel->getTypeOfSprites(aX2, aY2); // si c'est le sol ou une zone de chargement alors on déplace la caisse stopMove = !((sprites == TypeOfSprites::FLOOR_TYPE) || (sprites == TypeOfSprites::DESTINATION_TYPE)); if(!stopMove) { // on calcul le sprites X2, Y2 const char replacedSprites2 = (sprites == TypeOfSprites::DESTINATION_TYPE) ? TypeOfSprites::BOX_ON_ZONE_TYPE : TypeOfSprites::BOX_TYPE ; // on affecte le sprites X2, Y2 mapModel->setTypeOfSprites(aX2, aY2, replacedSprites2); return (aReplacedSprites == TypeOfSprites::BOX_ON_ZONE_TYPE) ? TypeOfSprites::DESTINATION_TYPE : TypeOfSprites::FLOOR_TYPE; } return aReplacedSprites; }
Remarque : une optimisation est facultative mais possible, en effet nous n'avons pas besoin du couple de coordonnées X1, Y1, il peut donc être supprimer. Il s'agit d'une erreur de ma part, j'ai oublié de le supprimer dès la partie 1 de ce tutoriel.
Il nous reste plus qu'à connecter les deux méthodes que l'on vient d'écrire au déplacement. Nous allons nous servir du déplacement vers le haut pour notre exemple, voici le pseudo code avec la contrainte de déplacement d'une caisse :
Calculer la position fictive relative à un déplacement vers le haut Récupérer le sprites relatif à la position fictive SI nous sommes toujours sur la carte avec la position fictive ET le sprites où nous voulons aller n'est pas un mur ALORS SI le sprites relatif à la position fictive est une caisse ALORS Faire un appel à la méthode de déplacement d'une caisse et affecter la valeur de retour au sprites relatif à la positioon fictive SINON Affecter à stopMove la valeur false FIN SI SI stopMove est faux ALORS Ecraser la position fictive avec la tuile correspondant au joueur Remplacer l'ancienne position du joueur par le sprites qui s'y trouvait avant Stocker le sprites relatif à la position fictive Mettre à jour la position du personnage SINON Réintialiser la position fictive FIN SI SINON Réintialiser la position fictive FIN SI
Voici le code de la méthode goUp modifier avec la contrainte de déplacement d'une caisse :
void CharacterController::goUp() { // calcul de la nouvelle position character->goUp(); // récupérer la tuile de la nouvelle position char newTypeOfSprites = mapModel->getTypeOfSprites(character->getNextPos()[0], character->getNextPos()[1]); // si la nouvelle position du personnage est sur la carte et que ce n'est pas un mur if(character->getNextPos()[1] >= 0 && !isWall(newTypeOfSprites)) { // déplacer une caisse if(isBox(newTypeOfSprites)) { newTypeOfSprites = moveBox(newTypeOfSprites, character->getNextPos()[0], character->getNextPos()[1], character->getNextPos()[0], character->getNextPos()[1] - 1); } else { stopMove = false; } if(!stopMove) { // écraser nouvelle position par la tuile du joueur mapModel->setTypeOfSprites(character->getNextPos()[0], character->getNextPos()[1], getPlayerSprites(newTypeOfSprites)); // remplacer ancienne position par la tuile qui était à cette position précédement mapModel->setTypeOfSprites(character->getX(), character->getY(), character->getOldTypeOfSprites()); // stocker la tuile de la nouvelle position character->setOldTypeOfSprites(newTypeOfSprites); // mettre à jour la position character->updatePositions(); } else { character->resetNextPositions(); } } else { // remettre à zéro la position suivante character->resetNextPositions(); } }
Le code pour les autres directions est similaire, à l'exception des coordonnées X2, Y2 passé à moveBox qu'il faut adapter, voyons cela.
Aller vers la droite
X2 = character->getNextPos()[0] + 1 Y2 = character->getNextPos()[1]
Aller vers le bas
X2 = character->getNextPos()[0] Y2 = character->getNextPos()[1] + 1
Aller vers la gauche
X2 = character->getNextPos()[0] - 1 Y2 = character->getNextPos()[1]
Une fois les méthodes complétées, amusez vous avec le jeu, en effet vous devriez être en mesure de déplacer les caisses sur les zones de chargement.
Dans ce dernier chapitre du tutoriel nous allons aborder la gestion de la fin de partie. Effectivement il serait bien de féliciter le joueur lorsque celui-ci à déplacer l'ensemble des caisses sur les zones de chargement.
Pour cela il faut parcourir la carte, la méthode isFinish de MapModel nous indique si le jeu est terminée ou non (via isEnd), voici le pseudo code :
Affecter à isEnd la valeur true PARCOURIR la carte sur l'axe Y tant que le jeu est terminé PARCOURIR la carte sur l'axe X tant que le jeu est terminé Affecter à isEnd la valeur de isEnd ET (sprites X, Y différent de zone de chargement ET sprites X, Y différent de caisse) FIN PARCOURIR FIN PARCOURIR Retourner isEnd
Voici le code de la méthode :
bool MapModel::isFinish() const { bool isEnd = true; for(int y=0 ; y < HEIGHT_MAP && isEnd ; y++) { for(int x=0 ; x < WIDTH_MAP && isEnd ; x++) { isEnd = isEnd && !(mapOfGame[y][x] == TypeOfSprites::DESTINATION_TYPE || mapOfGame[y][x] == TypeOfSprites::BOX_TYPE); } } return isEnd; }
Il faut maintenant que le contrôleur ai accès à isFinish, on rend cela possible via la méthode isEndOfGame de MapController que voici:
bool MapController::isEndOfGame() const { return model->isFinish(); }
Modifions la méthode run de MainController pour que lorsque la partie est finie on affiche un écran "Gagné", soit le code suivant :
void MainController::run() { if(! mapController->isEndOfGame()) { characterController->run(); const int* cameraPos = cameraModel->getCameraPositions(characterController->getX(), characterController->getY()); mapController->paint(cameraPos); } else { gb.display.setFontSize(2); gb.display.setColor(BROWN); gb.display.println(""); gb.display.println(""); gb.display.println(" Gagne"); } }
Votre jeu est maintenant complétement jouable, amusez vous bien !
Cette partie était la dernière du tutoriel. Vous pouvez télécharger le code source final. Le jeu est jouable mais également améliorable. En effet il pourrait être intéressant de pouvoir recommencer la partie (sans avoir à quitter le jeu), ou bien avoir plusieurs cartes, etc. Mais le but de ce tutoriel était de proposer une initiation à la programmation orienté objet et au modèle d'architecture Modèle Vue Contrôleur, j'espère que ce tutoriel vous servira dans vos prochaine créations. Le découpage de ce tutoriel n'est pas anodin, effectivement nous avons développer chacune des briques de notre jeu pas à pas, bloc de fonctionnalités après bloc, et c'est comme cela que vous devez concevoir vos jeux. Enfin comme les autres parties n'hésitez pas à me donner votre avis.
Aller plus loin
Avant de partir, et si vous voulez voir une autre approche du MVC, je vous conseille fortement de lire l'excellent tutoriel de steph sur le jeu de la vie disponible ici. Le tutoriel présente le jeu selon différentes approches : une approche fonctionnelle jusqu'au MVC en passant par une version purement objet. De plus, il a ajouté, toujours dans ce tutoriel, des interactions avec les LEDs ainsi que des effets sonores.
NEW il y a 6 ans
Bravo, on est au bout et ça fait un bel exercice ;) Pour se servir de ton code complètement (par exemple pour des ex-nouveaux qui chercheraient à écrire leur premier programme), tu pourrais ajouter un chapitre bonus simple avec la gestion des sons lors des événements (ça c'est simple) et surtout les états du jeu (initialisation, pause, en cours, menu). Sinon, tu pourrais aussi ajouter la partie changement de niveau et dans ce cas, sauvegarder le dernier niveau atteint et proposer au joueur de repartir du dernier niveau franchi au démarrage ou de choisir lui même un niveau de démarrage parmi ceux déjà passé. Pendant la pause, éventuellement, on peut aussi mettre une petite animation, voir sauvegarder l'état du niveau pour proposer un reprendre au démarrage du jeu. Bon bref, à toi de voir si tu rajoutes ces options dans un 6ème tutoriel "bonus", l'avantage serait d'une part d'avoir un joli jeu complet (d'ailleurs tu pourrais faire une création avec le jeu final) et un exemple commenté d'un jeu réalisé de A à Z avec toutes les composantes principales.
chris-scientist
il y a 6 ans
Merci ;)
Je vais y réfléchir, même si j'avoue que l'idée d'avoir plusieurs niveaux me tente et avec pourquoi pas un système de sauvegarde.
Pour les sons je m'y suis jamais frotter encore mais ça pourrait être cool.
Si je dois intégrer ces modifications en particulier le premier lot ça demande une restructuration du code et donc je ferais probablement un nouveau tutoriels. Ce sera bien évidement une suite mais ça implique des modifications du code (et je pense à des nouveaux concepts comme l'héritage).
Je vais voir la demande qu'il y a sur ces améliorations, à suivre dans de prochaines aventures.
Je vais peut-être faire un jeu pour faire un break.
NEW il y a 6 ans
Merci ;)
Je vais y réfléchir, même si j'avoue que l'idée d'avoir plusieurs niveaux me tente et avec pourquoi pas un système de sauvegarde.
Pour les sons je m'y suis jamais frotter encore mais ça pourrait être cool.
Si je dois intégrer ces modifications en particulier le premier lot ça demande une restructuration du code et donc je ferais probablement un nouveau tutoriels. Ce sera bien évidement une suite mais ça implique des modifications du code (et je pense à des nouveaux concepts comme l'héritage).
Je vais voir la demande qu'il y a sur ces améliorations, à suivre dans de prochaines aventures.
Je vais peut-être faire un jeu pour faire un break.
NEW il y a 6 ans
Oui, c'est clair, tu peux faire un break. Tu as atteins l'objectif du tuto qui était d'expliquer la POO (et même plus), de l'illustrer avec des exemples et des exercices et de montrer qu'à la fin ça fonctionne ;)
Le reste, ce ne sera que du bonus et ce n'est en effet plus lié à la POO à proprement parler mais plus sur la structure du programme et sur le jeu par lui même.
NEW il y a 6 ans
Belle série de tutos Chris, merci pour ta contribution ! Je n'ai pas encore eu le temps de me pencher dessus mais ça a l'air bien complet, on pourrait envisager de l'intégrer à l'académie :)
NEW il y a 6 ans
Merci, ce serait un plaisir que de voir le tutoriel dans l’académie ;)
NEW il y a 6 ans
Roooo,
Excellent tutoriel.
J'attends tellement d'en voir un sur un thème grand classique qu'est le jeu de plateforme comme un Mario like. Pour une approche de la gestion du comportement du personnage (saut, gravité, power-up, etc), des ennemis, du début et fin d'un niveau, gestion d'un menu, d'une sauvegarde, d'une bande son, des effets sonores. J'avoue que j'attendais avec impatience ce genres de tutoriels "musclés" dans l'Académie, qui soit à la hauteur d'une gamebuino Meta :)... Arf, si le cœur vous en dit !
chris-scientist
il y a 6 ans
@Max Content d'apprendre que tu aime le tutoriel ! Pour l'instant j'ai un projet qui est de concevoir un framework pour la META afin de réaliser des Sokoban-like... et je dois avouer que je ne suis plus vraiment actif sur ce sujet en ce moment (mais j'aimerai bien le finir)...
NEW il y a 6 ans
Argh, je te dirais bien que j'en ferais bien un mais vu déjà le peu de temps que j'ai et ce que je me suis mis dans la to do liste, je passe mon tour pour le moment. En plus maintenant, on a plusieurs rédacteur de tuto. D'ailleurs Max, même si tu débute, tu peux prendre un sujet qui n'existe pas et te lancer. C'est très formateur. Tu trouves assez facilement des réponses sur le net pour faire les choses. Il faut les adapter et si tu butes sur quelque chose, tu demandes, tu comprends et tu continues l'écriture de ton article pour les autres. Il faut juste ne pas prendre un sujet trop ambitieux au départ.
Tu peux regarder un code à adapter légèrement: https://openclassrooms.com/forum/sujet/gestion-collision-et-deplacement-de-mario et lire des tutos super bien fait et ce tuto: https://jeux.developpez.com/tutoriels/tile-mapping-construction-niveau/simple-personnage/
C'est a adapter mais ça montre les principes. Il y a plein d'autres tutos de ce style en cherchant un peu sur la toile. Le fait d'écrire et d'organiser, je trouve que ça permet de progresser plus vite, mais c'est mon point de vue. Je pense que chris-scientist a éprouvé la même chose et Steph aussi d'après les commentaires que j'ai lu. A toi de voir ou d'attendre qu'on le fasse ;)
Max
il y a 6 ans
Merci pour les liens et les conseils :)
Mais j'avoue qu'au prix et ce pourquoi la console est mise en avant (apprendre à coder du jeu), on s'attend à plus que d'être livré à soi-même et avoir huit tutoriels. Pour moi l'académie telle qu'elle est là, n'est qu'une petite ébauche. Et très franchement j'ai l'impression d'être loin du projet soutenu sur Kickstarter. Si apprendre à programmer du jeu s'arrête au casse-brique, alors je n'ai pas tout saisi...
Chercher, essayer, se planter, recommencer est un bon apprentissage qui, toutefois, a ses limites. Mais prétexter une "méthode" pédagogique pour en faire le moins possible, non... je n'ai pas participé à Kickstarter pour ça...
La goutte d'eau qui fait déborder le vase c'est d'être tombé sur un article qui annonce qu'ils ont en projet une console à monter soi-même pour 2019, et de l'autre côté le dernier tutoriel date de 4 mois pour la META... c'est inachevé.
(c'est un coup de gueule qui n'est pas lancé gratuitement, je le dis parce que ce projet me plait toujours autant qu'à la première heure, et j'écris tout ça comme une critique un peu dure mais dans l'espoir qu'elle soit constructive ;) )
NEW il y a 6 ans
Merci pour les liens et les conseils :)
Mais j'avoue qu'au prix et ce pourquoi la console est mise en avant (apprendre à coder du jeu), on s'attend à plus que d'être livré à soi-même et avoir huit tutoriels. Pour moi l'académie telle qu'elle est là, n'est qu'une petite ébauche. Et très franchement j'ai l'impression d'être loin du projet soutenu sur Kickstarter. Si apprendre à programmer du jeu s'arrête au casse-brique, alors je n'ai pas tout saisi...
Chercher, essayer, se planter, recommencer est un bon apprentissage qui, toutefois, a ses limites. Mais prétexter une "méthode" pédagogique pour en faire le moins possible, non... je n'ai pas participé à Kickstarter pour ça...
La goutte d'eau qui fait déborder le vase c'est d'être tombé sur un article qui annonce qu'ils ont en projet une console à monter soi-même pour 2019, et de l'autre côté le dernier tutoriel date de 4 mois pour la META... c'est inachevé.
(c'est un coup de gueule qui n'est pas lancé gratuitement, je le dis parce que ce projet me plait toujours autant qu'à la première heure, et j'écris tout ça comme une critique un peu dure mais dans l'espoir qu'elle soit constructive ;) )
Steph
il y a 6 ans
Max, je préfère te répondre en ouvrant une discussion plus large sur le sujet que tu évoques, qui sort du cadre de Sokoban vs POO et qui donc n'a rien à faire ici.
NEW il y a 6 ans
Oui, je comprends ton point de vue et je le partage en partie sur la partie Académie que l'on pourrait voir s'enrichir plus rapidement en français et en anglais. Après, on a une petite communauté avec des volontaires prêt à se retrousser les manches et à donner un coup de main et à faire des essais, créer des programmes et pousser la machine un peu comme Sorunome, Aoneil, Steph et on a des programmeurs super mais qui n'ont malheureusement pas assez de temps pour développer plus sur la META comme Eriban, SiegfriedCross ou STUDIOCRAFTapps. Après il y a pas mal d'atelier organisé à Saint-Etienne mais bon ça ne concerne qu'une partie des utilisateurs de la META.
Donc pour ton coup de gueule, je suis partagé en 2: d'une part c'est vrai que par rapport au Kickstarter, on pourrait s'attendre à un enrichissement plus régulier (peut être 2 tutos par mois) et d'autre part, on peut se prendre des sujets et travailler dessus. On se forme et on aide les autres à se former. On est tous bons dans quelque chose et on progresser en cherchant et en se plantant et en s'aidant les uns les autres. C'est vrai que ça marche bien (c'est ce que j'ai fais aussi de mon côté) mais dans ce cas, c'est vrai aussi que l'on peut attendre de l'équipe d'Aurélien qu'elle participe plus dans les réponse ou sur leur capitalisation dans une base de connaissances dans l'Académie avec les problèmes les plus fréquents rencontrés et leur solutions, des tutos, des exemples, qui sait même pourquoi pas des collections de ressources libres faites par l'équipe ou les Gamebuinosiens. Voilà, c'est mon avis et ma réponse à ton coup de gueule ;)
NEW il y a 6 ans
Max, je préfère te répondre en ouvrant une discussion plus large sur le sujet que tu évoques, qui sort du cadre de Sokoban vs POO et qui donc n'a rien à faire ici.
NEW il y a 6 ans
@Max Content d'apprendre que tu aime le tutoriel ! Pour l'instant j'ai un projet qui est de concevoir un framework pour la META afin de réaliser des Sokoban-like... et je dois avouer que je ne suis plus vraiment actif sur ce sujet en ce moment (mais j'aimerai bien le finir)...
NEW il y a 5 ans
Bonjour,
enfin arrivé au bout !
Merci beaucoup pour ce gros travail à travers lequel j'ai vraiment appris beaucoup de choses, des astuces algorithmiques et une belle occasion d'accumuler de la pratique en POO/MVC/C++.
Sur l'ensemble j'ai trouvé qu'il était parfois difficile de maîtriser vraiment le fil du raisonnement. J'ai finalement assez peu réussi à utiliser les guides en pseudo-code pour créer mon propre code. Mais au fil du tutoriel j'ai petit à petit réussi à faire les liens entre les choses et saisir l'intelligence du programme et c'était assez satisfaisant.
J'ai trouvé la première partie de conception très intéressante. Je pense qu'elle gagnerait peut-être à être un peu plus dévoilée. J'imagine qu'a priori tu es passé par des étapes préliminaires avant de pouvoir générer un diagramme de classes (ou alors c'est peut-être possible de l'imaginer directement avec l'expérience...), et je pense que ce serait également bénéfique de profiter du raisonnement de départ qui a permis d'architecturer l'ensemble du programme. Je crois que ça rendrait l'évolution dans la suite du tutoriel plus limpide.
Mais ce n'est qu'une petite critique secondaire. Dans l'ensemble j'ai vraiment beaucoup apprécié le tuto et j'ai appris plein de trucs donc super ;).
chris-scientist
il y a 5 ans
Merci Codnpix pour ton retour.
Pour réaliser ce tutoriels j'ai d'abord écrit tout le code, puis alors j'ai fait le diagramme de classes à partir du code. J'ai utilisé ce support pour montrer une vue d'ensemble du code.
J'aurai pu faire un diagramme de classes dès le départ mais il aurait sûrement évoluer au fur et à mesure de l'avancé du projet.
NEW il y a 5 ans
Codnpix merci pour lui pour le retour. C'et super important. Si tu peux essayes de proposer un bout de tuto à insérer ou pour en remplacer une partie, ça faciliterait le boulot de Chris pour voir s'il l'incorpore et ça permet d'avoir un retour sur ce qui est dur à comprendre (C'est toujours simple quand on sait faire.. ;) et je te rassure perso, j'ai beaucoup de mal pour le moment à réfléchir POO et ton approche / compléments pourront certainement m'être utile ainsi qu'à d'autres.)
Codnpix
il y a 5 ans
Si tu peux essayes de proposer un bout de tuto à insérer ou pour en remplacer une partie
Je ne suis pas sûr de pouvoir prendre la responsabilité d'imaginer moi même le raisonnement qu'il y avait à la base de ce tutoriel là (je m'en suis fait mon idée, mais il reste quelques zones d'ombres)
Par contre je vais me mettre certainement à travailler très bientôt sur un projet de jeu plus personnel qui apriori sera programmé en POO et sur une base de MVC, et à ce moment là je rédigerai avec plaisir un tutoriel pour expliquer ce que j'aurai fait :).