Je fais donc un jeu où vous pouvez envoyer des navires à des emplacements pour vendre ou acheter des ressources comme le bois, le fer, l'or, etc.
Maintenant, je me demandais comment les ressources devraient être créées dans le jeu. Je suis venu avec 2 options
Créez une classe pour chaque ressource:
public class ResourceBase { private int value; // other base properties } public class Gold : ResourceBase { public Gold { this.value = 40 // or whatever } }
Créer des instances d'une classe de ressources
public class Resource { string name; int value; public Resource(string name, int value) { this.name = name; this.value = value; } } // later on... Resource gold = new Resource("Gold",40);
Avec la deuxième option, il est possible de remplir les ressources du jeu à partir d'un fichier resources.json, j'aime un peu cette structure.
De nouvelles idées / modèles de conception / structures sont toujours les bienvenus!
EDIT: C'est un peu comme l'application compagnon d'Assassins Creed Black Flag. Voir la barre de ressources sur l'image ci-dessous
EDIT 2: J'ai fait quelques recherches supplémentaires sur le "chargement des éléments / ressources du fichier JSON" et j'ai trouvé ce blog: Power of JSON in Game Development - Items . Il montre le meilleur de l'option 1 et de l'option 2. Vous pouvez toujours ajouter des fonctionnalités à chaque ressource :)
la source
enum
plutôt un .Réponses:
Optez pour la deuxième approche, simplement parce que vous pouvez introduire de nouveaux types de ressources ou éléments à tout moment sans avoir à réécrire ou mettre à jour le code ( développement piloté par les données ).
Modifier:
Pour en savoir un peu plus sur les raisons pour lesquelles il s'agit d'une bonne pratique générale, même si vous êtes sûr à 100% qu'une valeur ne changera jamais.
Prenons l'exemple du jeu sur console mentionné dans les commentaires, car cela fournit une très bonne raison pour laquelle vous ne devriez rien coder en dur, sauf si vous en avez vraiment (ou voulez), par exemple des clés de cryptage, votre propre nom, etc.
Lors de la sortie d'un jeu sur des consoles, celles-ci doivent généralement passer par un processus d'examen, où le propre AQ du fabricant de la console testera le jeu, le jouera, recherchera les problèmes, etc. Ceci est obligatoire et coûte de l'argent, beaucoup d'argent. Je pense avoir lu une fois qu'une version pourrait coûter entre 30 000 et 50 000 $ rien que pour la certification.
Imaginez maintenant que vous poussiez votre jeu à sortir, en payant les 30 000 $ et attendez. Et soudain, vous remarquez que certaines de vos valeurs de jeu sont littéralement brisées. Disons que vous pouvez acheter des barres de fer pour 50 pièces d'or et les vendre pour 55 pièces d'or.
Que faire? Si vous avez codé en dur ce genre de choses, vous devrez créer une nouvelle version de mise à jour / version, qui devra être revue une fois de plus, alors dans le pire des cas, vous paierez à nouveau pour la recertification! Je parie qu'Ubisoft ne m'en voudra pas, mais pour votre propre poche de développeur de jeux indépendants… aïe!
Mais imaginez que le jeu vérifie occasionnellement les définitions de jeu mises à jour (par exemple sous la forme d'un fichier JSON). Votre jeu peut télécharger et utiliser la dernière version à tout moment sans nécessiter de nouvelle mise à jour. Vous pouvez corriger ce déséquilibre / exploiter / bug à tout moment sans exiger de recertification ou tout autre argent payé. Juste une petite décision de conception, vous ne pensiez pas que cela en valait la peine, vous avez simplement économisé une somme d'argent à 5 chiffres! N'est-ce pas génial? :)
Ne vous méprenez pas. Cela s'applique également à d'autres types de logiciels et de plates-formes. Le téléchargement de fichiers de données mis à jour est en général beaucoup plus facile et réalisable pour l'utilisateur standard, qu'il s'agisse d'un jeu ou d'une sorte d'application / d'outil. Imaginez un jeu installé sous Program Files dans Windows. Votre programme de mise à jour a besoin de droits d'administrateur pour modifier quoi que ce soit et vous ne pouvez pas modifier les programmes en cours d'exécution. Avec DDD, votre programme télécharge simplement les données et les utilise. Le joueur pourrait même ne pas remarquer qu'il y a eu une mise à jour.
la source
En règle générale, vous utilisez différentes classes lorsque les objets nécessitent un code différent et des instances de la même classe lorsque les objets ne nécessitent que des valeurs différentes.
Lorsque les ressources ont des mécanismes de jeu différents qui leur sont propres, il peut être judicieux de les représenter avec des classes. Par exemple, lorsque vous avez du Plutonium qui a une durée de demi-vie et des lapins qui procréent selon la séquence des fibonacci , alors il pourrait être judicieux d'avoir une classe de base
Resource
avec une méthodeUpdate
implémentée en tant que no-op et deux classes dérivéesHalfLifeResource
etSelfGrowingResource
qui remplacer cette méthode pour diminuer / augmenter la valeur (et peut-être aussi inclure une logique pour gouverner ce qui se passe lorsque vous stockez les deux côte à côte).Mais lorsque vos ressources ne sont en réalité que des nombres stupides, il est inutile de les implémenter avec quelque chose de plus sophistiqué qu'une simple variable.
la source
Je voudrais ajouter qu'il y a deux options supplémentaires:
Interface: vous pouvez le considérer si la classe de ressources ne serait qu'un "stockage" pour 5 entiers et chaque autre entité aurait une logique différente concernant les ressources (par exemple, dépenses / butin du joueur, production de la ville Ressource). Dans ce cas, vous ne voudrez peut-être pas du tout une classe - vous vouliez simplement exposer qu'une entité a une variable avec laquelle d'autres peuvent interagir:
en outre, cela a l'avantage que vous pouvez piller une ville avec exactement le même code que vous pilleriez la flotte ennemie, ce qui favorise la réutilisation du code.
L'inconvénient est que l'implémentation d'une telle interface peut s'avérer fastidieuse si de nombreuses classes l'implémentent, vous pourriez donc finir par utiliser des interfaces mais pas pour le problème d'origine, en le résolvant avec l'option 1 ou 2:
Instances (avec enum): dans certains cas, il serait souhaitable d'utiliser enum au lieu de chaîne lors de la définition du type de ressource:
cela fournira un peu de "sécurité", car votre IDE vous donnera la liste de toutes les ressources valides lors de l'affectation après avoir écrit le point
ResourceType = Resource.
, en plus il y a plus de "trucs" avec des énumérations dont vous pourriez avoir besoin, comme Type explicite ou composition / drapeaux que je peux imaginer être utile lors de l'élaboration:Quant à ce qui est le mieux - il n'y a pas de solution miracle, mais personnellement, je pencherais pour toute forme d'instances, elles ne sont peut-être pas aussi sophistiquées que l'interface, mais elles sont simples, n'encombrent pas l'arbre d'héritage et sont largement comprises.
la source
my-great-enum
) à une représentation C # de l'énum (MyGreatEnum
).Vous devez utiliser l'option 1, qui présente 3 avantages:
new Gold(50)
resource instanceof Gold
la source
Si vos ressources n'ont pas de logique métier propre, ou des scénarios de cas particuliers avec la façon dont elles interagissent avec l'environnement, d'autres ressources (en plus du commerce que vous avez couvert) ou le joueur, alors l'option deux facilite l'ajout de nouvelles.
Si vous devez considérer des situations comme ce qui se passerait si vous mélangez deux ressources pour l'artisanat, si les ressources peuvent avoir des propriétés très différentes (un seau d'eau est très différent d'un morceau de charbon) ou d'autres interactions économiques complexes, alors l'approche 1 est beaucoup plus flexible pour le moteur, mais pas les données.
la source