JeuWeb - Crée ton jeu par navigateur
Maui - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Général (https://jeuweb.org/forumdisplay.php?fid=36)
+--- Forum : Présentez-vous (https://jeuweb.org/forumdisplay.php?fid=41)
+--- Sujet : Maui (/showthread.php?tid=7881)

Pages : 1 2


RE: Maui - Xenos - 09-10-2017

Citation :En fait en php, avec les session tu as l'instanciation, ce qui fait qu'avec le sessions, tu as tout ce qu'il te faut pour faire un jeu.
Ca, cela mérite du détail car je ne vois pas le lien entre les sessions PHP, et l'instanciation de classes... Ni avec le fait que les sessions sont "requises" pour faire un jeu?! J'ai blinde de minis-jeux sans aucune notion de session, et les jeux où j'ai recours aux sessions, je n'y ai recours que pour ce à quoi elle servent: l'Authentication (traduire le terme risque de me faire dire une connerie, donc, vous m'excuserez de l'anglicisme! Smile ).

Citation :la présenter comme la seule manière correcte d'organiser son code
Perso, je pense que le problème vient de l'enseignement de la POO: elle ne sert en pratique qu'à éviter de mélanger des données et des comportements, et à permettre d'interchanger des comportements (ainsi que d'encapsuler les choses dans des classes et d'attribuer une visibilité aux composantes [propriétés, méthodes etc] mais ça, ce n'est pas ce que j'entends par "POO": c'est juste un namespacing des choses, et on peut faire de même en procédural en évitant juste les variables globales). Quand le but d'un jeu web n'est que de manipuler des data (ou quand un site a juste des data à manipuler), le surcoût amené par cette architecture POO n'est pas toujours compensé par l'atout de l'encapsulation. D'autant plus quand chaque entité (chaque classe) n'a qu'un seul comportement. Bref, c'est souvent présenté comme un saint graal, mal amené en cours sous la forme de "1 Interface => 1 Classe => 1 instance", ce qui enlève toute l'intérêt de la chose.

Attention après à ne pas sur-pousser le "DRY" (cf le copier/coller n'est pas malsain): les choses se répètent parfois, et les factorer pour les centraliser n'est pas toujours une bonne idée. Deux choses de même sémantiques (même sens; même signification) doivent être centralisées, mais parfois, des choses identiques n'ont pas forcément le même but, ni la même évolution, et là, DRY va pousser à les centraliser ce qui va abstraire le code et le rendre chiant à faire évoluer. Faut pas oublier que, parfois, un bête Ctrl+F/Ctrl+H dans le projet est plus efficace qu'une énorme abstraction pour tout centraliser Wink

Pour ma part, je te conseillerai plutôt le pragmatisme absolu: tout le temps passé dans de l'archi et dans de l'écriture de code n'est pas du temps passé dans la vie du jeu (gamedesign, management de la communauté, brainstorming pour trouver les idées d'amélioration, etc). Il faut donc passer le moins de temps possible dans son code. Cela ne veut pas dire de ne rien abstraire du tout et de copier/coller tout n'importe comment, ni de faire une sur-abstraction en centralisant tous les mots du dictionnaire dans une liste de constantes à réutiliser ensuite. L'essentiel pour bien tenir sur le long terme est surtout d'avoir un périmètre bien délimité pour chaque composant du projet. Cela permet de faire sauter une feature sans exploser tout le projet. En PRAWD, je peux virer un points d'entrée (une page) sans défoncer les autres. Je peux virer un composant du gameplay de la BDD, et savoir partout où il est utilisé (je regarde dans quelles procédures les tables apparaissent, et je sais quels points d'entrée s'en servent).

PS: et le pragmatisme absolu passe aussi souvent par le simple fait de virer 80% des features inutiles du projet Wink


RE: Maui - incodewetrust - 10-10-2017

(09-10-2017, 06:32 PM)Xenos a écrit :
Citation :En fait en php, avec les session tu as l'instanciation, ce qui fait qu'avec le sessions, tu as tout ce qu'il te faut pour faire un jeu.
Ca, cela mérite du détail car je ne vois pas le lien entre les sessions PHP, et l'instanciation de classes... Ni avec le fait que les sessions sont "requises" pour faire un jeu?! J'ai blinde de minis-jeux sans aucune notion de session, et les jeux où j'ai recours aux sessions, je n'y ai recours que pour ce à quoi elle servent: l'Authentication (traduire le terme risque de me faire dire une connerie, donc, vous m'excuserez de l'anglicisme! Smile ).

Tu as raison cela mérite des explications. A chaque fois que je discute avec un adepte de la POO autour de la création de jeu multijoueurs au tour par tour, il pense sincèrement qu'il est impossible de faire autrement qu'en instanciant un objet "personnage" de la classe personnage lors de la connexion. Mais au final tu obtiens les mêmes données entre un objet sortant du moule de sa classe avec des attribut définie par le constructeur de classe et une récupération de données structurée tout à fait classique que tu stocke dans des variables de sessions. Au final la structure des données devant être récupérés sera la même et produira, dans un cas comme dans l'autre, ce qui définit l'instanciation c'est à dire qu'un "objet" (classe) ou en l'occurence "tableau multidimensionnel" pour la session, qui pourra partager des attributs similaires avec un autre objet sans être le même. Du coup pour moi les variables de sessions peuvent parfaitement se substituer à l'instanciation des classes pour définir les attributs/états du personnages ou tout autre type de données.

Par contre je n'ai jamais prétendu que les sessions étaient requises pour faire un jeu, j'ai dit qu'avec on avait tout ce qu'il fallait pour en faire un (avec la persistance des données tant que la session reste ouverte). Pour des jeux multis je m'en sert pour éviter un grand nombre de requêtes READ d'affichage (pour READ de contrôle je m'abstiens) et dans tout les cas je les utilise pour stocker des options de jeu/ d'affichage/ des messages de confirmation/ erreur ou stocker n'importe quelle donnée devant survivre à un changement/rechargement de page. Je les trouve du coup extrêmement pratique et elles sont même devenues pour moi indispensables.

Mais on peut tout à fait obtenir le même résultat en stockant systématiquement tout via des requêtes (bof en terme de perf), en utilisant des Cookie (mais cocorico il y'a toujours les petits messages gênants), et même en stockant ces états dans des attributs de classes (si on aime utiliser des procédés complexes pour faire des choses simples).

Citation :Attention après à ne pas sur-pousser le "DRY" (cf le copier/coller n'est pas malsain): les choses se répètent parfois, et les factorer pour les centraliser n'est pas toujours une bonne idée. Deux choses de même sémantiques (même sens; même signification) doivent être centralisées, mais parfois, des choses identiques n'ont pas forcément le même but, ni la même évolution, et là, DRY va pousser à les centraliser ce qui va abstraire le code et le rendre chiant à faire évoluer. Faut pas oublier que, parfois, un bête Ctrl+F/Ctrl+H dans le projet est plus efficace qu'une énorme abstraction pour tout centraliser Wink

Pour ma part, je te conseillerai plutôt le pragmatisme absolu: tout le temps passé dans de l'archi et dans de l'écriture de code n'est pas du temps passé dans la vie du jeu (gamedesign, management de la communauté, brainstorming pour trouver les idées d'amélioration, etc). Il faut donc passer le moins de temps possible dans son code. Cela ne veut pas dire de ne rien abstraire du tout et de copier/coller tout n'importe comment, ni de faire une sur-abstraction en centralisant tous les mots du dictionnaire dans une liste de constantes à réutiliser ensuite. L'essentiel pour bien tenir sur le long terme est surtout d'avoir un périmètre bien délimité pour chaque composant du projet. Cela permet de faire sauter une feature sans exploser tout le projet. En PRAWD, je peux virer un points d'entrée (une page) sans défoncer les autres. Je peux virer un composant du gameplay de la BDD, et savoir partout où il est utilisé (je regarde dans quelles procédures les tables apparaissent, et je sais quels points d'entrée s'en servent).

PS: et le pragmatisme absolu passe aussi souvent par le simple fait de virer 80% des features inutiles du projet Wink

Pour moi tu pose clairement les enjeux, mais je ne suis pas d'accord avec ta conclusion, j'y reviendrais.

Il y'a certes une "perte de temps" immédiate et sèche, le refactoring prends beaucoup de temps (que ce soit lié à du DRY ou non). Si le gain en terme de maintenabilité  est réel, il est parfois difficile à estimer surtout sur le long terme. Il ne faut pas le négliger car le pur copier-coller ne marche pas toujours, selon les circonstance, tu dois souvent tu dois adapter une partie plus ou moins importante ce qui fait qu'un processus unique issue du DRY sera de plus en plus intéressant sur des projets menés à long terme.

J'en ai fait l’expérience en refaisant mon système de combat. J'avais un processus d'attaque pour les joueurs, un autre pour l'IA arachnide car les données et les processus entre un joueur/arachnide étaient radicalement différents et même un troisième pour des construction de type tourelles, géré par un crontask, qui possédait la encore une structure complètement différente (puisqu'une tourelle n'a que peu de points communs avec un joueur).

J'ai passé une dizaine d'heure sur le seul formatage des données préliminaire à mon processus unique. Mais au final en maintenant 3 versions différentes, je devais, à chaque modification du moteur de combat adapter les nouvelles règles sur ces trois processus qui différaient sur 50% des étapes environ et devait être adaptés sur les 50% du tronc commun. Du coup dans le nouveau processus unique les fonctions traitent les exceptions et permettent surtout d'intégrer automatiquement tout les effets du tronc commun à tout ces acteurs grâce au formatage des données.

J'aurais pu continuer à copier-coller en adaptant, mais au final cela aurait été une petite perte de temps à chaque modification et une source potentielle d'erreur multipliée par 3 (lors de chaque adaptation).

En faisant des efforts pour rester DRY sur ces derniers 6-8 mois, mon fichier de fonction est passé de 300 à plus de 3000 lignes. Il n'est évidemment pas sur et même fortement improbable que je récupère un jour le temps investis dans ce refactoring total du processus. Mais au final et c'est la ou je ne suis pas d'accord avec toi, ce refactoring, pour moi doit être fait même s'il n'est pas rentabilisé en terme de temps ou autre, pour deux raisons :

- Cela oblige à repenser sa manière d'organiser le code, à automatiser tout ce qui peut l'être, bref le refactoring en terme de compétence et d'évolution de sa manière de programmer ne peut amener à mes yeux que du positif. Il amène à produire du code de qualité.

- La maintenabilité ne doit pas être négligée. Je parle du refacto en général pas seulement celui lié au DRY. Combien de développeur, pas forcément mauvais au demeurant, vont, par paresse ou par contrainte, face à une "pyramide of doom", encapsuler le tout dans un if supplémentaire. Au final en procédant ainsi ils ont parfaitement conscience de rajouter une couche de caca supplémentaire sur le monticule, et de déléguer le problème au suivant.... c'est sans doute efficace d'un point "make it run" mais adieux le "make it right". Le client ne sera généralement pas apte à juger et s'en moquera probablement. Mais le dév a généralement conscience d'avoir fait de la merde et même si c'est très pragmatique ce n'est pas forcément très gratifiant .

Et un jour ou l'autre tout cela se paye lorsqu'il faudra relire et modifier le code, bref en terme de maintenabilité. Effectivement il est impossible de prédire dire à l'avance que tout le temps passé sera récupéré, mais le principe reste valable et autant le mettre en pratique sur un code susceptible d'être modifié.

Bref de mon point de vue, au contraire, sur son propre projet, son propre jeu, je pense qu'il est important d'essayer de bien faire, car dans le monde pro avec les contraintes clients/temps on ne peut pas forcément mettre en application ces deux points du fait c'est un travail "invisible" qui ne produit pas de fonctionnalité supplémentaire (et donc n'a aucune chance d'intéresser le client, sauf si le client est dév évidemment).


RE: Maui - Xenos - 10-10-2017

[ P***, il m'a battu sur la longueur de post! :O ]

Je suis d'accord sur le fait que l'instance de "Personnage" n'a aucun sens vu que tous les persos, dans ces jeux, ont les mêmes comportements (c'est un mélange entre comportements différents, qui appelle plutôt de la POO en effet, et manipulation de données, qui devient d'une simplicité déconcertante et d'une fiabilité à tout épreuve quand on se passe de POO). En revanche, dans les deux cas, il n'y a rien à stocker en session, ce serait même malsain car cela mélange les rôles de la session (Authentication) et de la BDD (Data storage).

Oui, tu peux te servir de la session pour du Data Storage, à la condition qu'il n'y ait pas besoin d'interaction entre les sessions. Mais si t'as besoin d'interaction, et c'est souvent le cas, je trouve que c'est une très mauvaise pratique (niveau accès concurrents, fiabilité du stockage, et mises à jour des structures, c'est se faire chier pour rien).

Hum... T'es pas le premier à dire "en terme de perf, bof" dès qu'on parle de SQL (ou autre stockage, mais je prendrai celui-là). Temps de connexion OVH: 1ms. Temps d'execution d'une requête renvoyant 2000 lignes de data (id, x, y, z, caseType de mémoire): 3ms. Donc, non, c'est pas "lent". C'est juste fiable et propre, et c'est ce qu'il faut utiliser. On ne se sert pas des sessions comme d'un "cache qui économise les requêtes SQL". Si tu veux du caches, tu prends un composant de cache client (ie: un cache "côté PHP") séparé de la session (POO ou pas).

Ton exemple de tourelle est, là, un cas typique de POO en revanche.

La factorisation ne sert qu'à fusionner les éléments de même sémantique. S'il est logique que deux entités aient (et auront "toujours") le même comportement, alors oui, tu factorises. En revanche, s'il n'y a pas fondamentalement de logique à ce que les deux entités aient le même fonctionnement, là, tu "copies/colles" (et souvent, t'y verras des variations). Sinon, à tout merger, tu ne pourras plus rien toucher tant les ramifications du moindre truc partiront dans tous les sens. On retombe surtout sur le point essentiel du propos: un périmètre bien délimité pour chaque composant du projet. C/C ou factorisation deviennent mauvais quand ils cassent cette règle.

"Make it work", c'est la 1ere règle. Après, "Make it right". Après "Make it fast". Le but est bien de remplir le besoin en premier lieu, et après, de s'amuser au peaufinage et fignolage interne (qui se fait très bien si, justement, tu respecte la notion de "périmètre hermétique pour chaque feature").

Nombre de créateurs sont passés ici, voulant faire du "bien et joli et propre parce que c'est mon projet perso et j'suis pas au boulot"... Je ne suis pas sûr que beaucoup d'entre eux aient sorti quelque chose (et encore moins le tenir dans le temps).

Je brefise donc moi aussi: le plus important pour moi est d'avoir des périmètres bien délimités pour chaque feature, et d'éviter les codes qui traversent toute la stack. Cela permet une maintenance simple et un refactoring simple en limitant les ramifications des modifs (qu'on soit POO ou pas).


RE: Maui - incodewetrust - 10-10-2017

Tu peux factoriser les éléments communs de plusieurs entités distinctes et traiter les différence dans un processus unique. Pour le moment, je gagne un temps précieux à chaque modification (et j'ai même pu intégrer très facilement et uniformiser des mécanismes annexes qui ne s'appliquait alors que sur certains processus grâce au travail de formatage des données en amont). Je pense qu'à ce stade seul le créateur peut réellement savoir, pour son projet, si cela est opportun ou non de le faire en essayant d'estimer la part des modifications à venir qui sera factorisable et donc intégrable une seule fois sans gestion d’exceptions.

Citation :Nombre de créateurs sont passés ici, voulant faire du "bien et joli et propre parce que c'est mon projet perso et j'suis pas au boulot"... Je ne suis pas sûr que beaucoup d'entre eux aient sorti quelque chose (et encore moins le tenir dans le temps).

Aucune antinomie, le "make it right" viens de toute manière après le "make it run" donc il faut déjà le faire en premier lieu, nous sommes d'accord sur ce point, mais, une fois que c'est fait, mon opinion est qu'il faut continuer de manière permanente à retravailler son code pour gagner en maintenabilité vis à vis d'ajouts ultérieurs. Cela n'est évidemment valable que si l'on veut souhaite poursuivre son projet sur le long terme. Moi en tout cas je le fais, je sais ce que cela me coûte en temps mais aussi les bénéfices, qu'ils soient directement visibles ou non, que j'en retire et surtout que j'en retirerais aussi dans l'avenir car le refactoring c'est aussi un investissement en quelque sorte.

Sinon j'étais sur que tu réagirais sur le sql et j'ai même hésité à mettre "je sais d'avance que tu ne sera pas d'accord mais" Wink.


RE: Maui - Maui - 20-10-2017

C'était super intéressant de vous lire et j'ai remarqué que j'ai fait des choses qui sont pas forcement "Make it Right".
Comme exemple j'utilise des Sessions pas que pour un soucis d'authentification (comme dans les combat ).
D'un point de vue général je choisi les Sessions quand c'est une info qu'il n'est pas nécessaire de garder en cas de déconnexion du joueur.

Mais sinon je suis bien d'accord qu'il faut réfléchir long terme et avoir un code lisible... Pour le procédural j'use ( et peut être j'abuse du include ) mais ça me donne une page php = une fonction (ou une fonction de fonction ^^) du jeu.
Après j’indente et je commente beaucoup même si des choses me semble obvious sur le coup je sais que certains jours je suis un peu à l'ouest et que les commentaires me sauveront !
Bon après le truc c'est que je suis autodidacte et que j'ai jamais eu à travailler en équipe donc du coup mon Make it Right est un peu passé à la trappe Sad

En tout cas vous m'avez appris pleins de choses tous les deux et je vous en remercie Smile


RE: Maui - Xenos - 20-10-2017

De rien. Quelles infos rentrent dans ce cas de "jetable en cas de déconnexion" (hors cache)?
Note que c'est pas du include, mais du require.

En revanche, je n'ai pas compris ton "une page php = une fonction/une fonction de fonctions du jeu"?! Quel lien entre la page web et les fonctions [de fonction] du jeu?


RE: Maui - Ter Rowan - 21-10-2017

une page php = un fichier php, pas une page web, aucune empathie technologique le xenos


RE: Maui - Xenos - 21-10-2017

Désolé, mais j'ai tellement vu de trucs partir en cou*lles pour ce genre de "détail"... Smile

Tiens, un exemple récent (à plusieurs milliers d'€): un projet de centrale électrique est découpé en "morceaux", appelés "units" (disons, unit A, B, C). On veut modifier le logiciel de gestion pour sa construction, et on demande au développeur que le logiciel puisse gérer plusieurs "units" de la centrale. Le développeur rajoute alors les mm, les cm, les yards, les gallons, etc... bref, il rajoute la gestion de plusieurs unités métriques différentes Smile

Bref, tout cela pour illustrer que même si cela peut paraitre être une "petite différence" (antipathique!), cela peut vite déboucher sur de l'incompréhension voire de la mécompréhension, et flinguer un projet. D'où ma tendance à laisser l'autre développer ce qu'il entend éventuellement par "page php" plutôt que d'inférer silencieusement qu'il s'agit en fait de "fichier php".


RE: Maui - Air - 22-10-2017

C'est la richesse de notre langue qui permet autant d'incompréhension :-)


RE: Maui - Xenos - 22-10-2017

"Unit" est un terme anglais, et non Français...

oui, je sais: "aucune empathie linguistique le xenos" Big Grin