Pour le plaisir, j'essaye d'écrire un des jeux de société préférés de mon fils sous forme de logiciel. Finalement, je prévois de créer une interface utilisateur WPF dessus, mais en ce moment, je construis la machine qui modélise les jeux et ses règles.
En faisant cela, je continue à voir des problèmes que je pense communs à de nombreux jeux de société, et peut-être que d'autres les ont déjà résolus mieux que moi.
(Notez que l'IA pour jouer au jeu et les modèles autour de hautes performances ne m'intéressent pas.)
Jusqu'à présent, mes modèles sont:
Plusieurs types immuables représentant des entités dans la boîte de jeu, par exemple des dés, des pions, des cartes, un plateau, des espaces sur le plateau, de l'argent, etc.
Un objet pour chaque joueur, qui contient les ressources des joueurs (ex: argent, score), leur nom, etc.
Un objet qui représente l'état du jeu: les joueurs, à qui c'est le tour, la disposition des pièces sur le plateau, etc.
Une machine d'état qui gère la séquence des tours. Par exemple, de nombreux jeux ont un petit pré-jeu où chaque joueur lance pour voir qui joue en premier; c'est l'état de départ. Quand le tour d'un joueur commence, il roule d'abord, puis il bouge, puis il doit danser sur place, puis les autres joueurs devinent de quelle race de poulet ils sont, puis ils reçoivent des points.
Y a-t-il un état de la technique dont je peux profiter?
EDIT: Une chose que j'ai réalisé récemment est que l'état du jeu peut être divisé en deux catégories:
État de l'artefact du jeu . «J'ai 10 $» ou «ma main gauche est en bleu».
État de la séquence de jeu . "J'ai roulé deux fois en double; le suivant me met en prison". Une machine à états peut avoir un sens ici.
EDIT: Ce que je recherche vraiment ici, c'est la meilleure façon de mettre en œuvre des jeux multijoueurs au tour par tour comme Chess ou Scrabble ou Monopoly. Je suis sûr que je pourrais créer un tel jeu en travaillant simplement du début à la fin, mais, comme d'autres modèles de conception, il existe probablement des moyens de rendre les choses beaucoup plus fluides qui ne sont pas évidentes sans une étude approfondie. C'est ce que j'espère.
la source
Réponses:
il semble que ce soit un fil de 2 mois que je viens de remarquer maintenant, mais que diable. J'ai déjà conçu et développé le cadre de jeu pour un jeu de société commercial en réseau. Nous avons eu une expérience très agréable en travaillant avec.
Votre jeu peut probablement être dans un nombre (presque) infini d'états en raison des permutations de choses comme combien d'argent le joueur A a, combien d'argent le joueur B a, etc. Par conséquent, je suis à peu près sûr que vous voulez pour rester à l'écart des machines d'État.
L'idée derrière notre cadre était de représenter l'état du jeu comme une structure avec tous les champs de données qui, ensemble, fournissent l'état complet du jeu (c'est-à-dire: si vous vouliez sauvegarder le jeu sur le disque, vous écrivez cette structure).
Nous avons utilisé le modèle de commande pour représenter toutes les actions de jeu valides qu'un joueur pouvait effectuer. Voici un exemple d'action:
Ainsi, vous voyez que pour décider si un mouvement est valide, vous pouvez construire cette action et appeler sa fonction IsLegal, en passant l'état actuel du jeu. S'il est valide et que le joueur confirme l'action, vous pouvez appeler la fonction Apply pour modifier réellement l'état du jeu. En vous assurant que votre code de jeu ne peut modifier l'état du jeu qu'en créant et en soumettant des actions légales (en d'autres termes, la famille de méthodes Action :: Apply est la seule chose qui modifie directement l'état du jeu), alors vous vous assurez que votre jeu l'état ne sera jamais invalide. De plus, en utilisant le modèle de commande, vous permettez de sérialiser les mouvements souhaités de votre joueur et de les envoyer sur un réseau pour être exécutés sur les états de jeu des autres joueurs.
Il a fini par y avoir un piège avec ce système qui s'est avéré être une solution assez élégante. Parfois, les actions comportaient deux phases ou plus. Par exemple, le joueur peut atterrir sur une propriété en monopole et doit maintenant prendre une nouvelle décision. Quel est l'état du jeu entre le moment où le joueur a lancé les dés et avant qu'il ne décide d'acheter une propriété ou non? Nous avons géré des situations comme celle-ci en présentant un membre "Action Context" de notre état de jeu. Le contexte de l'action serait normalement nul, indiquant que le jeu n'est actuellement dans aucun état spécial. Lorsque le joueur lance les dés et que l'action de lancer des dés est appliquée à l'état du jeu, il se rend compte que le joueur a atterri sur une propriété qui ne lui appartient pas et peut créer un nouveau "PlayerDecideToPurchaseProperty" contexte d'action contenant l'index du joueur dont nous attendons une décision. Au moment où l'action RollDice est terminée, notre état de jeu indique qu'il attend actuellement que le joueur spécifié décide s'il achète ou non une propriété. Il est désormais facile pour toutes les autres actions de la méthode IsLegal de renvoyer false, à l'exception des actions "BuyProperty" et "PassPropertyPurchaseOpportunity", qui ne sont légales que lorsque l'état du jeu a le contexte d'action "PlayerDecideToPurchaseProperty".
Grâce à l'utilisation de contextes d'action, il n'y a jamais un seul moment dans la durée de vie du jeu de société où la structure de l'état du jeu ne représente pas complètement exactement ce qui se passe dans le jeu à ce moment-là. C'est une propriété très souhaitable de votre système de jeu de société. Il vous sera beaucoup plus facile d'écrire du code lorsque vous pourrez trouver tout ce que vous voulez savoir sur ce qui se passe dans le jeu en examinant une seule structure.
En outre, il s'étend très bien aux environnements en réseau, où les clients peuvent soumettre leurs actions sur un réseau à une machine hôte, qui peut appliquer l'action à l'état de jeu "officiel" de l'hôte, puis renvoyer cette action à tous les autres clients pour demandez-leur de l'appliquer à leurs états de jeu répliqués.
J'espère que cela a été concis et utile.
la source
La structure de base de votre moteur de jeu utilise le modèle d'état . Les objets de votre boîte de jeu sont des singletons de différentes classes. La structure de chaque état peut utiliser un modèle de stratégie ou la méthode de modèle .
Une Factory permet de créer les joueurs qui sont insérés dans une liste de joueurs, un autre singleton. L'interface graphique surveillera le moteur de jeu en utilisant le modèle Observer et interagira avec celui-ci en utilisant l'un des nombreux objets Command créés à l'aide du modèle de commande . L'utilisation d'Observer et de Command peut être utilisée dans le contexte d'une vue passive Mais à peu près n'importe quel modèle MVP / MVC peut être utilisé en fonction de vos préférences. Lorsque vous enregistrez le jeu, vous devez récupérer un souvenir de son état actuel
Je recommande de regarder certains des modèles sur ce site et de voir si l'un d'entre eux vous saisit comme point de départ. Encore une fois, le cœur de votre plateau de jeu sera une machine à états. La plupart des jeux seront représentés par deux états avant le jeu / configuration et le jeu réel. Mais vous pouvez avoir plus d'états si le jeu que vous modélisez a plusieurs modes de jeu distincts. Les états n'ont pas besoin d'être séquentiels, par exemple le wargame Axis & Battles a un plateau de bataille que les joueurs peuvent utiliser pour résoudre des batailles. Il y a donc trois états avant le jeu, le plateau principal, le plateau de bataille, le jeu basculant continuellement entre le plateau principal et le plateau de combat. Bien entendu, la séquence de tours peut également être représentée par une machine à états.
la source
Je viens de terminer la conception et l'implémentation d'un jeu basé sur l'état utilisant le polymorphisme.
Utilisation d'une classe abstraite de base appelée
GamePhase
qui a une méthode importanteCela signifie que chaque
GamePhase
objet contient l'état actuel du jeu, et un appel àturn()
regarde son état actuel et renvoie le suivantGamePhase
.Chaque béton
GamePhase
a des constructeurs qui détiennent l' état du jeu entier . Chaqueturn()
méthode contient un peu des règles du jeu. Bien que cela répartisse les règles, cela permet de rapprocher les règles connexes. Le résultat final de chacunturn()
est simplement de créer le suivantGamePhase
et de passer à l'état complet à la phase suivante.Ceci permet
turn()
d'être très flexible. En fonction de votre jeu, un état donné peut se ramener à de nombreux types de phases. Cela forme un graphique de toutes les phases du jeu.Au plus haut niveau, le code à piloter est très simple:
Ceci est extrêmement utile car je peux maintenant facilement créer n'importe quel état / phase du jeu pour le test
Maintenant, pour répondre à la deuxième partie de votre question, comment cela fonctionne-t-il en multijoueur? Dans certains
GamePhase
s qui nécessitent une entrée de l'utilisateur, un appel deturn()
demanderait le courant dePlayer
leurStrategy
état / phase actuel.Strategy
est juste une interface de toutes les décisions possibles qu'unPlayer
peut prendre. Cette configuration permet égalementStrategy
d'être implémentée avec l'IA!Andrew Top a également déclaré:
Je pense que cette déclaration est très trompeuse, alors qu'il est vrai qu'il y a beaucoup d'états de jeu différents, il n'y a que quelques phases de jeu. Pour gérer son exemple, il ne s'agirait que d'un paramètre entier pour les constructeurs de mes concrets
GamePhase
.Monopole
Un exemple de certains
GamePhase
serait:Et certains états de la base
GamePhase
sont:Et puis certaines phases enregistreraient leur propre état si nécessaire, par exemple PlayerRolls enregistrerait le nombre de fois qu'un joueur a lancé des doubles consécutifs. Une fois que nous quittons la phase PlayerRolls, nous ne nous soucions plus des lancers consécutifs.
De nombreuses phases peuvent être réutilisées et liées entre elles. Par exemple, le
GamePhase
CommunityChestAdvanceToGo
créerait la phase suivantePlayerLandsOnGo
avec l'état actuel et le renverrait. Dans le constructeur duPlayerLandsOnGo
joueur actuel serait déplacé vers Go et leur argent serait incrémenté de 200 $.la source
Bien sûr, il existe de nombreuses, nombreuses, nombreuses, nombreuses, nombreuses, nombreuses, nombreuses ressources sur ce sujet. Mais je pense que vous êtes sur la bonne voie en divisant les objets et en les laissant gérer ses propres événements / données, etc.
Lorsque vous faites des jeux de société basés sur des tuiles, vous trouverez agréable d'avoir des routines à mapper entre le tableau de bord et les lignes / colonnes et inversement, ainsi que d'autres fonctionnalités. Je me souviens de mon premier jeu de société (il y a longtemps) lorsque je me suis demandé comment obtenir des rangées / colonnes à partir de boardarray 5.
Nostalgie. ;)
Quoi qu'il en soit, http://www.gamedev.net/ est un bon endroit pour obtenir des informations. http://www.gamedev.net/reference/
la source
La plupart des documents que je peux trouver en ligne sont des listes de références publiées. La section Publications de Game Design Patterns contient des liens vers des versions PDF des articles et des thèses. Beaucoup d'entre eux ressemblent à des articles académiques tels que Design Patterns for Games . Il existe également au moins un livre disponible sur Amazon, Patterns in Game Design .
la source
Three Rings propose des bibliothèques Java LGPL. Nenya et Vilya sont les bibliothèques pour les choses liées au jeu.
Bien sûr, cela aiderait si votre question mentionnait des restrictions de plate-forme et / ou de langue que vous pourriez avoir.
la source
Je suis d'accord avec la réponse de Pyrolistical et je préfère sa façon de faire les choses (je viens de parcourir les autres réponses cependant).
Par coïncidence, j'ai également utilisé sa dénomination "GamePhase". Fondamentalement, ce que je ferais dans le cas d'un jeu de société au tour par tour, c'est que votre classe GameState contienne un objet de la GamePhase abstraite comme mentionné par Pyrolistical.
Disons que les états du jeu sont:
Vous pourriez avoir des classes dérivées concrètes pour chaque état. Avoir des fonctions virtuelles au moins pour:
Dans la fonction StartPhase (), vous pouvez définir toutes les valeurs initiales d'un état, par exemple en désactivant l'entrée de l'autre joueur et ainsi de suite.
Lorsque roll.EndPhase () est appelé, assurez-vous que le pointeur GamePhase est défini sur l'état suivant.
Dans ce MovePhase :: StartPhase (), vous définiriez par exemple les mouvements restants du joueur actif au montant obtenu lors de la phase précédente.
Maintenant, avec cette conception en place, vous pouvez régler votre problème "3 x double = prison" à l'intérieur de la phase Roll. La classe RollPhase peut gérer son propre état. Par exemple
Je diffère de Pyrolistical en ce qu'il devrait y avoir une phase pour tout, y compris lorsque le joueur atterrit sur un coffre communautaire ou quelque chose comme ça. Je gérerais tout cela dans le MovePhase. En effet, si vous avez trop de phases séquentielles, le joueur se sentira très probablement trop «guidé». Par exemple, s'il y a une phase où le joueur peut UNIQUEMENT acheter des propriétés et ensuite SEULEMENT acheter des hôtels et ensuite SEULEMENT acheter des maisons, c'est comme s'il n'y avait pas de liberté. Il suffit de regrouper toutes ces pièces en une seule BuyPhase et de donner au joueur la liberté d'acheter tout ce qu'il veut. La classe BuyPhase peut gérer assez facilement les achats légaux.
Enfin, abordons le plateau de jeu. Bien qu'un tableau 2D convienne, je recommanderais d'avoir un graphique de tuiles (où une tuile est une position sur le plateau). Dans le cas du monopole, il s'agirait plutôt d'une liste à double lien. Ensuite, chaque tuile aurait un:
Il serait donc beaucoup plus facile de faire quelque chose comme:
La fonction AdvanceTo peut gérer vos animations étape par étape ou ce que vous voulez. Et aussi décrémenter les mouvements restants bien sûr.
Les conseils de RS Conley sur le modèle d'observateur pour l'interface graphique sont bons.
Je n'ai pas beaucoup posté auparavant. J'espère que cela aide quelqu'un.
la source
Si votre question n'est pas spécifique à la langue ou à la plate-forme. alors je vous recommande de considérer les modèles AOP pour l'état, le souvenir, la commande, etc.
Quelle est la réponse .NET à AOP ???
Essayez également de trouver des sites Web intéressants tels que http://www.chessbin.com
la source