Je suis un étudiant de première année à l'université pour mon diplôme en informatique ... J'ai beaucoup programmé ces dernières années, mais récemment, je me suis davantage intéressé aux idées théoriques sur l'organisation du code, les modèles de conception, les différences de langues, etc.
J'ai une classe Java, donc j'ai abandonné ma recherche/développement C++ et je suis passé à Java et JOGL (Java OpenGL)). C'est merveilleux! Mais c'est sans rapport.
Je veux faire un petit jeu de rôle, mais cette question s'applique vraiment à tout type de jeu. Comment organisez-vous les objets du jeu de manière structurée, comme le modèle Modèle-Vue-Contrôleur? Cela semble être un modèle incroyable, très largement utilisé et qui a beaucoup de sens, mais j'ai du mal à comprendre comment le mettre en œuvre.
Par exemple, je dois garder une trace d'un objet GL pour dessiner à l'écran. Je dois avoir des classes qui implémentent MouseListener, MouseMotionListener, MouseWheelListener et KeyListener (ou une classe, un tout- et je dois placer mes données de jeu quelque part où toutes ces différentes classes peuvent y accéder et les modifier; si quelqu'un appuie sur un bouton du clavier, la classe de gestion des entrées doit en quelque sorte effectuer l'action que la clé est mappé à; lorsqu'un cadre doit être dessiné, la classe graphique doit trouver un moyen de parcourir toutes les différentes "choses" et de les dessiner toutes.
Et mon plus gros problème, l'interface graphique; où est-ce lié à tout cela? C'est quelque chose comme l'entrée, mais pas tout à fait, et il faut à la fois définir et obtenir des éléments de données de la simulation de jeu réelle ... Et le compliquer encore PLUS est si je décide d'essayer d'ajouter un réseau, qui (similaire à l'interface graphique ) doit également avoir accès à un grand nombre de données pour modifier et lire ...
Oh, je suis tout simplement confus. Je ne sais pas comment faire fonctionner tout cela ensemble de manière orientée objet ... C'est assez facile d'écrire des choses qui correspondent clairement aux modèles, mais quand vous avez des tonnes de choses qui se passent, toutes liées à une boucle de jeu, se modifiant mutuellement et les données du jeu et ainsi de suite, ... je n'en sais même plus. Peut-être que je fais juste une affaire plus importante qu'elle ne l'est en réalité.
Quelqu'un d'autre a-t-il ressenti cela? Veuillez clarifier ma situation afin que je puisse passer moins de temps à m'inquiéter et à ne pas savoir par où commencer!
-Ricket
Edit: J'ai trouvé un joli diagramme qui pourrait m'aider à comprendre tout cela ... Source: (attention, fichier PS!) http://www.tucs.fi/publications/attachment.php?fname=TR553. ps.gz
http://img10.imageshack.us/img10/6278/mvcdiagramgamesbl5.png
Edit2: J'aime aussi l'explication de ce gars sur la façon dont il a planifié son jeu MVC: http://interactivesection.wordpress.com/2007/11/19/dum-de-dum-drum-my-first-mvc- développement de jeu /
Edit3: Un autre excellent article! http://dewitters.koonsolo.com/gamemvc.html
Cela pourrait vous aider à considérer le modèle comme une sorte d'API de jeu. À quoi votre jeu serait-il réduit s'il n'y avait aucune interface utilisateur pour le jeu ordonné depuis le début? Vous mentionnez que ce que vous avez en tête est un RPG, donc dans ce cas, vous pouvez imaginer que le personnage du joueur, son inventaire, ses sorts, ses capacités, ses PNJ et même des choses comme la carte et les règles de combat font tous partie du modèle. . C'est comme les règles et les éléments du Monopoly sans les détails de la façon dont le jeu final affiche cela ou de la façon dont l'utilisateur va interagir avec lui. C'est comme Quake en tant qu'ensemble abstrait d'objets 3D se déplaçant à travers un niveau avec des éléments tels que l'intersection et la collision calculés mais sans rendu, ombres ou effets sonores.
En mettant tout cela dans le modèle, le jeu lui-même est désormais indépendant de l'interface utilisateur. Il pourrait être connecté à une interface de texte ASCII comme les jeux Rogue ont, ou une interface utilisateur de ligne de commande semblable à Zork, ou une interface utilisateur Web ou 3D. Certaines de ces interfaces utilisateur peuvent être un ajustement terrible. selon les mécanismes du jeu, mais ils seraient tous possibles.
La couche View est la couche dépendante de l'interface utilisateur. Il reflète le choix spécifique de l'interface utilisateur que vous avez choisi et sera très dédié à cette technologie. Il peut être chargé de lire l'état du modèle et de le dessiner en 3D, ASCII ou images et HTML pour une page Web. Il est également chargé d'afficher tous les mécanismes de contrôle que le joueur doit utiliser pour interagir avec le jeu.
La couche Controller est le lien entre les deux. Il ne devrait jamais contenir aucune logique de jeu réelle, ni être responsable du pilotage de la couche View. Au lieu de cela, il doit traduire les actions prises dans le calque Vue (en cliquant sur des boutons, en cliquant sur des zones de l'écran, des actions du joystick, etc.) en actions effectuées sur le modèle. Par exemple, laisser tomber un objet, attaquer un PNJ, peu importe. Il est également responsable de la collecte des données et de toute conversion ou traitement pour faciliter l'affichage de la couche View.
Maintenant, la façon dont je l'ai décrit ci-dessus est comme s'il y avait une séquence d'événements très distincte conduisant le jeu qui n'est probablement vraiment appropriée que pour un jeu Web. C'est parce que c'est ce sur quoi j'ai passé mon temps ces derniers temps. Dans un jeu qui n'est pas piloté par la demande d'un utilisateur et la réponse d'un serveur comme le Web (par exemple, un jeu fonctionnant sur la machine de l'utilisateur), vous voudrez probablement vous assurer que la couche Modèle a bien implémenté le modèle Observer. Par exemple, si des actions ont lieu dans le modèle parce que le temps passe, vous ne voudrez peut-être pas que la couche View interroge constamment le modèle pour les mises à jour. Au lieu de cela, en utilisant le modèle Observer, le modèle peut informer les observateurs des modifications apportées aux objets du modèle au fur et à mesure qu'elles se produisent. Cela pourrait à son tour être utilisé pour demander une mise à jour immédiate de la vue afin de refléter le changement.
Ensuite, si 60 secondes qui s'écoulaient entraînaient des réparations pour la base du joueur, la base pourrait effectuer les réparations et informer immédiatement tous les observateurs qui y sont attachés que la base a été mise à jour. La vue peut être attachée en tant qu'observateur et noter qu'elle doit réafficher la base car son état a changé. La notification elle-même peut avoir inclus suffisamment d'informations pour mettre à jour la vue ou elle devra peut-être faire demi-tour et consulter le modèle pour mettre à jour, mais le résultat sera le même.
Vous vous entendez là-bas. en gros, posez-vous la question "quel code changerait si je devais changer une partie du programme?"
Si cela change son apparence sans changer les données de base, alors c'est dans la vue. Si ce sont des données qui peuvent être visualisées de plusieurs manières, c'est bien le modèle. Et si c'est comme ça que vous jouez, alors c'est le contrôle.
Donc, si c'est si vous dessinez une "hache" avec deux lames ou une, c'est la vue. Si c'est le nombre de points de vie que vous infligez avec une hache, c'est une figurine. Et si c'est si vous balancez la hache en tapant "s" ou en faisant un clic droit, c'est le contrôle.
Je sens avec vous que je me souviens quand j'ai découvert MVC pour la première fois, j'ai essayé de tout y mettre. J'ai en effet créé un jeu utilisant le modèle MVC. Ce que j'ai découvert plus tard, c'est que ce que j'ai fait était exagéré. J'ai essayé d'intégrer à peu près toutes les classes que j'ai faites dans une seule catégorie dans MVC.
Ce que je suggère, c'est de lire "Design Patterns" par la bande de quatre. Il existe de nombreux modèles utiles en plus de MVC. Parfois, cela n'a aucun sens d'utiliser MVC. Surtout pour les jeux, je ne suis pas sûr que MVC soit une si bonne idée. La raison est que vous ne souhaitez pas afficher un objet de jeu de différentes manières (vues), mais que vous souhaitez réutiliser un code de dessin pour de nombreux types d'objets de jeu différents.
Pour mon propre moteur de jeu 2D, j'ai utilisé le modèle stratégie assez activement. Les objets du jeu, comme le joueur et les monstres que j'ai appelés un Sprite. Je laisse le dessin du Sprite être géré par un modèle de stratégie . C'est alors que j'ai appelé Sprite.draw () je ferais quelque chose comme ceci:
class Sprite {
void draw() {
this.view.draw(this.currentPosition, this.currentOrientation);
}
Point currentPosition; // Current position of this Sprite
double currentOrientation; // Facing angle of Sprite
};
L'avantage de cette approche est que vous pouvez partager un objet de vue entre plusieurs sprites. Parce que généralement, il y aura beaucoup de p. des monstres qui se ressembleront mais qui auront des positions différentes et qui se comporteront éventuellement différemment.
Donc, comportement J'utiliserais également un modèle de stratégie qui serait un objet contenant du code décrivant le comportement. De cette façon, je peux appliquer le même comportement à plusieurs monstres à différents endroits. Donc, chaque image, j'appellerais une fonction pdate () pour mettre à jour l'orientation de la position et ce que fait le monstre.
class Sprite {
void setUpdateAction(Action action) {
this.updateAction = action;
}
void update(double start_time, double delta_time)
{
this.prevPosition = position();
advance(delta_time); // Advance to next position based on current speed and orientation
this.updateAction.execute(this, start_time, delta_time);
}
Action updateAction;
};
Il existe de nombreuses variantes de cela. Dans mon implémentation actuelle, j'ai même séparé currentPosition, speed, orientation et advance () dans un objet séparé appelé MotionState. C'est ainsi que je peux construire des arbres de recherche des positions et orientations possibles lors de la recherche d'algorithmes de recherche de chemin. Ensuite, je ne veux pas emporter avec moi d'informations sur la manière de se comporter de chaque mise à jour ou sur la façon dont Sprite doit être dessiné.
Le concept MVC de centralisation de la logique d'interaction utilisateur est un bon modèle pour le développement de jeux.
J'ai fait un petit travail avec le développement de jeux Flash. Ici est un article sur les pools d'objets dans Flash. Le concept est multiplateforme et peut vous donner quelques idées.
Vous avez raison de vous préoccuper de tout ce qui se passe en même temps. En fonction de la conception de votre jeu, votre boucle de jeu peut avoir beaucoup à gérer. C'est là que vous apprendrez toutes les astuces d'optimisation sales, souvent à la dure :)
Il existe de nombreuses façons d'organiser votre code - une option peut être d'écrire une classe GameManager en tant que Singleton. Tous les objets du jeu y sont liés pour la gestion et l'interaction de l'utilisateur. Le GameManager gère toutes les entrées utilisateur et distribue les messages à son pool d'objets. Vous pouvez utiliser des interfaces pour définir des modèles de communication communs entre les objets du jeu et le GameManager.
En ce qui concerne l'optimisation des performances, le threading est très puissant. Un fonctionnement asynchrone peut garantir que vous ne gaspillez pas ces précieux cycles.
Tous vos écouteurs et gestionnaires doivent entrer dans la classe Controller, l'état des objets à l'écran (par exemple, la position, la couleur, etc.) doit faire partie de vos classes Model et quel que soit le code qui dessine des choses à l'écran fera partie de la vue.
Ma façon de penser MVC est comme MDUC
Modèle
Afficher
Contrôleur d'entrée utilisateur
Le modèle contient les objets du modèle de domaine
L'écran affiche l'état actuel et le comportement des objets du modèle de domaine à l'écran.
Le contrôleur d'entrée utilisateur gère toutes les entrées utilisateur.
C'est exactement le même modèle, mais les noms sont juste un peu plus descriptifs, donc je trouve que les responsabilités de chaque partie du modèle sont plus claires, et donc la signification du modèle est plus mémorable.
Une fois que vous voyez que vous séparez les données et les opérations de modèle de l'affichage, à partir des entrées de l'utilisateur, il est plus facile de voir où regrouper quoi dans votre propre code.