JeuWeb - Crée ton jeu par navigateur
Système de gestion d'unités - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Système de gestion d'unités (/showthread.php?tid=4308)

Pages : 1 2


Système de gestion d'unités - Sehsyha - 04-05-2014

Bonjour,


j'ai commencé la conception d'un jeu de stratégie ou vont se battre différentes unités. Seul problème technique, je me demande comment gérer leur caractéristiques. Je pense qu'il est nécessaire de les enregistrer en base de données pour les lier aux joueurs par exemple, mais par la suite dans le code pour savoir quelle unité fait quoi, je pensais utiliser le nom directement. Le problème est que ceci rend le code peu maintenable si le nom est codé en dur quelque part. Je me demande donc si il y a une astuce pour faire cela.


Merci d'avance!


RE: Système de gestion d'unités - Xenos - 05-05-2014

Salut,

Je m'orienterai vers un système POO avec une interface "Unité", représentant une unité quelconque, puis des classes abstraites "UnitéTypeMachin", représentant les unités par type (artillerie, char, fantassins,...), puis une classe par unité "UnitéArtillerieLourde".
A partir de là, les propriétés de l'unité (puissance de feu, cadence de tir, etc) seraient plutôt stockées soit dans la classe de l'unité, soit dans une classe séparée contenant les constantes de l'unité, comme "UnitéArtillerieLourdeCaracteristiques". Dans ce second cas, on pourra instancier une unité (UnitéArtillerieLourde) et associer à cette instance ses caractéristiques (UnitéArtillerieLourdeCaracteristiques), qui pourront alors dépendre de paramètres arbitraires: on allège la classe de l'unité en séparant son état (caractéristiques) de ses possibilités d'action (classe de l'unité). Sinon, on peut envisager d'associer le "UnitéArtillerieLourdeCaracteristiques" à la classe "UnitéArtillerieLourde" (et non à chaque instance) si les unités ont toutes les mêmes caractéristiques, ou bien ne pas faire de classe "caractéristiques" si la classe de l'unité est légère.

En BDD serait stockée l'instance de "UnitéArtillerieLourdeCaracteristiques", soit sous la forme d'un ensemble de paramètres (un par colonne si SQL), soit sous la forme d'une instance d'objet (NoSQL ou linéarisation).

Schéma:

<<Unité (Interface)>>

<UnitéArtillerie (Abstraite)>

UnitéArtillerieLourde (Classe) ← <<Unité (Interface)>>

<UnitéArtillerie (Abstraite)>

UnitéArtillerieLourde (Classe)

UnitéArtillerieLourde (Instance) ← UnitéArtillerieLourdeCaracteristiques (Classe)

UnitéArtillerieLourde (Instance) ← UnitéArtillerieLourdeCaracteristiques (Instance) ← {Stockage BDD}


RE: Système de gestion d'unités - Sehsyha - 05-05-2014

Pourquoi pas, mais étant donné que chaque unité a les mêmes attributs mais juste avec des valeurs différentes, je n'ai pas besoin de classe abstraite. Je pensais définir directement chaque unité dans la base, mais ça poserait un problème pour les utiliser dans le code si il fallait utiliser leur nom pour les rechercher dans le cas de changement de nom.


RE: Système de gestion d'unités - Arnadus - 05-05-2014

On pourrait avoir le schéma de ta base de données stp?


RE: Système de gestion d'unités - Sehsyha - 05-05-2014

Je suis en pleine conception donc je n'ai pas encore de schéma tant que je n'ai pas prévu les fonctionnalités.

Mais il se présenterait sûrement d'une forme similaire à celle ci:
Unité(id_unite, nom_unite, vie_unite, attaque_unite, defense_unite)
Joueur(id_joueur, pseudo_joueur, pass_joueur)
Possede(id_possede, id_unite, id_joueur)


RE: Système de gestion d'unités - Arnadus - 05-05-2014

2 recommandations:

1) externaliser les caractéristiques dans une table à part. De cette façon, tu devras modifier uniquement cette table lorsque tu désireras ajouter/supprimer/renommer une caractéristique.

Caractéristiques(id, vie, attaque, defense)
Unité(id, nom, id_carac)
Joueur(...)
Possede(...)

2) Si ta question porte uniquement sur le mapping entre le nom de ton champ en bdd et le nom de la caractéristique qui sera affiché à l'utilisateur, il n'existe pas vraiment d'astuces. En général, les frameworks arrivent à deviner la valeur à afficher à l'écran en s'aidant du nom de la propriété/du champ mais ça pose problème dès lors qu'il faut afficher des noms avec accents etc... Tu peux à la limite te faire une petite table de mapping.
Ou tout simplement externaliser ces noms de caractéristiques dans un fichier de configuration/constantes. Au moins, lorsque tu décideras de modifier ce nom, tu ne devras le faire qu'à un seul endroit. c'est toujours le même principe: DRY (Don't Repeat Yourself) .


RE: Système de gestion d'unités - Xenos - 05-05-2014

N'utilise pas des noms (textes) pour faire des références entre BDD et code serveur (PHP, ruby, python, java...), préfère les identifiants numériques (id_type_unite au lieu d'un nom_unite). Déjà, il y a moins de raison d'en changer, ensuite tu y gagneras en place dans la BDD et en perfs, enfin tu pourras placer des contraintes dessus plus facilement.
En cas de changement de nom, seul le nom affiché (stocké dans un PHP par exemple, ou dans un XML comme j'aime à le faire) sera impacté: l'identifiant numérique n'aura pas de raison d'être modifié.

La classe abstraite (UnitéArtillerie) peut être utile simplement pour regrouper les unités par type, même si leurs caractéristiques sont les mêmes d'un type à l'autre. A toi de voir Wink Tu peux aussi choisir une approche à interface, et créer une interface par "possibilité" (TireDesObus, TireDesBalles, TirDeZone, PossedeFumigenes,...) puis implémenter les interfaces nécessaires dans la classe de l'unité, même si ces interfaces sont vides, c'est juste un indice sur les capacités de l'unité. Cela servira peut-être plus tard, soit en y ajoutant du code, soit en testant $unite instanceof TirDesObus pour savoir quels textes d'aide afficher.

Dernier élément: les clefs primaires peuvent porter sur plusieurs colonnes, je ne sais pas si "id_possede" est vraiment utile. Si tu ne l'utilises pas, tu peux t'en passer, et le remplacer par une PRIMARY KEY (id_joueur, id_unite) (attention à l'ordre des colonnes: l'index n'est utilisé que si la 1ere colonne est utilisée dans la clause WHERE, pour simplifier; donc un WHERE id_unite=11 n'utilisera pas la clef, alors que WHERE id_joueur=42 l'utilisera, de même que WHERE id_joueur=42 AND id_unite=11).

Je ne pense pas qu'externaliser les caractéristiques dans une table à part soit nécessaire, ou utile, étant donné qu'ici, l'unité n'est composée que de ces caractéristiques. Cela va rajouter une couche pour par grand chose. Ce serait pertinent si la table "Unité" pouvait être modifiée soit pour changer les caractéristiques, soit pour changer autre chose, mais là, n'ayant pas de "autre chose", cela me semble superflu de créer une jointure de plus.


RE: Système de gestion d'unités - Sehsyha - 05-05-2014

Oui je pense donc faire un fichier de constantes où je référencerais les clés primaires et caractéristiques de chaque unités et qui sera ensuite traité pour l'introduction dans la base. Quant au id_possede, il est utile car j'utilise de l'active record et l'objet a obligatoirement une clé primaire de ce genre. Par contre je peux ajouter un index de type arbre-b sur les champs id_joueur et id_unite pour des recherches plus rapides, telle que le 'WHERE id_unite = 11' qui iront aussi vite que si c'était une clé primaire.

Mon fichier de constante sera relu quand je relance le serveur pour avoir une base à jour par rapport à cela, ce ne sera pas difficile de faire un script pour ça.


RE: Système de gestion d'unités - Arkhanz - 06-05-2014

Salut,

En regardant ton problème je me demande si l'organisation de ta base ne va pas te poser des problèmes. A ce que j'ai compris dans ton organisation, dans ta table Possede tu listera chaque unité de chaque joueur avec donc son joueur et ses caractéristiques. Je ne sais pas si tu prévois que les joueurs aient beaucoup d'unité ou non, mais si plusieurs joueurs ont des milliers d'unités, cette table risque de devenir bordélique. La solution peut être d'avoir une entrée dans la table Possede par joueur et non par unité et ensuite selon la façon dont tu veux t'organiser (et si tu aime découper) regrouper des listes texte, je m'explique :

Schéma 1 : Possede(id_joueur, liste_unites)
Dans liste_unites tu pourrais avoir une liste du style "id_unite,id_carac,nombre;id_unite,id_carac,nombre;..." et ensuite dans ton code, avec un explode et un foreach tu obtiens toutes les infos.

Schéma 2 : Possede(id_joueur, unite_1, unite_2, unite_3, ...)
C'est le même schéma à ceci près que plutôt d'avoir une grande liste qui contient toutes les unités, tu en as une par type d'unité puisqu'à ce que j'ai compris, les type d'unités ne changent pas mais leurs caractéristiques oui, donc dans les champs unite_X la liste serait de même format ("id_unite,id_carac,nombre;") mais chaque champ listerait uniquement une unité donc tu pourrais avoir par exemple un champ du style : "8,15,9658;8,18,658;8,25,98;".

En espérant t'aider,


RE: Système de gestion d'unités - Xenos - 06-05-2014

Je n'abonde clairement pas dans ton sens, Arkhanz, car la méthode du "je stocke une chaine sérialisant les données" (exemple: liste d'id d'unités "1,2,5,25,81,46,32") supprime tout l'intérêt d'un SQL (ou même d'un SGDB en général).
→ Il serait alors impossible de cherche une unité avec un id précis, ou avec des caractéristiques précises
→ Impossible de mettre à jour une unité sans charger, désérialiser, modifier, resérialiser et updater toute la liste des unités
→ Hermétique à l'évolution, puisqu'il faudra bousculer tout le schéma de sérialisation quand on voudra ajouter des nouveautés.

Si le jeu a 1.000 joueurs, chacun avec 10.000 unités, et bien une table de 10.000.000 de lignes (une par unité) est tout à fait adaptée. Le SGDB est là pour gérer ces cas (recherche de données dans des tables à nombreuses lignes), alors ne coupons pas son système (optimal en plus!) de recherche et de fonctionnement avec des bricolages Smile