Même logique de jeu sur deux bibliothèques graphiques distinctes

11

Quelle philosophie de code / structure d'abstraction / conception de programme permettrait d'utiliser un jeu avec des graphiques 2D et 3D (séparément) SANS avoir à recoder la logique du jeu?

Nous parlons de prendre le même code, de changer un minimum de choses (par exemple, échanger des noms de fichiers pour des actifs 2D avec des noms de fichiers pour des actifs 3D), et peut-être de brancher quelques spécialisations d'une classe de base par génériques / modèles.

Pour le mettre dans un contexte réel où cela a du sens: imaginez un jeu multijoueur LAN où il y a un client 3D haut de gamme et gourmand en performances pour les joueurs avec de très bonnes plates-formes de joueurs, et un client 2D plus humble pour les anciens. des boîtes poussiéreuses que quelqu'un a trouvées dans leur grenier. Mais c'est toujours le même jeu - les mêmes événements sont enregistrés (quelqu'un a ramassé une pièce), le même protocole réseau est utilisé, les mondes sont proportionnels, etc.

Pour le mettre dans un contexte MVC: les contrôleurs sont exactement les mêmes (en appuyant sur la touche "Haut", l'accélération des joueurs sera réglée à 3,5 unités / seconde), les vues sont totalement différentes (2D par rapport à 3D) et le modèle est le même. sauf pour tout ce qui est directement lié aux graphiques (un contrôle de collision pour l'environnement est effectué toutes les 5 secondes, et il utilise le même algorithme. Notez que cela signifierait qu'il y a une coordonnée Z pour tous les objets de jeu dans la version 2D, mais c'est simplement ignoré ou affiché à l'utilisateur d'une autre manière, par exemple par une ombre qui est affichée plus à gauche lorsque le joueur est en l'air).

Ce qui rend ce sujet si fascinant, c'est qu'il obligerait le développeur à avoir une idée très claire de la façon dont ses données sont structurées et comment les flux de contrôle. Notez que cela n'implique pas d'utiliser autre chose qu'une bibliothèque graphique comme SDL, D3DX ou OpenGL. Aucun moteur de jeu!

Puisqu'il s'agit d'une question principalement théorique, je vais laisser les langages de programmation hors de lui, mais si vous voulez donner un exemple, vous pouvez utiliser n'importe quel langage que vous aimez, C ++ si vous voulez aller tout le porc, ou même Brainfuck si vous vous sentez à la hauteur du défi (Toute réponse concrète sera appréciée, ainsi que toute réponse abstraite!).

Toby
la source
Je ne suis pas sûr que ce soit pratique. Tant de logique de jeu utilise les mathématiques vectorielles, vous devez soit tout faire en 3D avant de convertir en 2D ou autre pour le rendu, soit vous devez complètement résumer votre bibliothèque de vecteurs - ce qui serait sûrement peu pratique?
tenpn
Recherchez le terme «couche d'abstraction» et familiarisez-vous avec lui, car vous allez travailler ensemble pendant un certain temps.
zaratustra

Réponses:

8

Je pense que tout ce dont vous auriez besoin serait d'une couche d'abstraction enveloppant votre bibliothèque graphique; vous en auriez besoin d'une nouvelle pour chaque bibliothèque que vous utiliseriez, et chacune devrait avoir exactement la même API externe.

Pensez à la localisation des chaînes: au lieu de coder en dur la chaîne "Inventaire" dans votre jeu, vous appelleriez plutôt votre bibliothèque de localisation (éventuellement personnalisée), qui effectuerait certains processus et retournerait une chaîne appropriée, selon le contexte de le jeu.

De la même manière, tous les appels à votre moteur graphique seraient effectués via votre wrapper autour de celui-ci.

Ce faisant, vous limitez / limitez les commandes que vous pouvez donner à votre moteur graphique. En voici quelques-uns essentiels:

  1. Dessiner (objet graphique) à (emplacement)
  2. Modifier la propriété (alpha, rotation, etc.) de (objet graphique)
  3. Déplacer (objet graphique) vers (emplacement)
  4. Construire une carte de (nom de niveau / structure de données)

Et quelques autres, que vous trouverez en travaillant sur votre projet.

Si vous utilisez un langage orienté objet de type strict, vous appellerez les commandes ci-dessus l' interface que vos wrappers implémenteront tous. De préférence, ce seront les seules méthodes non protégées / publiques.

Maintenant, créez un nouveau wrapper pour chacune de vos bibliothèques graphiques et implémentez l'API . Lorsqu'une commande pour dessiner __ à __ vous est donnée, vous devez utiliser du code pour créer l'image-objet ou le modèle, et le dessiner dans votre environnement. Cela peut nécessiter une astuce, comme le stockage de chaque image-objet dans un hachage pour être à nouveau accessible à un autre moment par un symbole donné.

En ce qui concerne la création de cartes, le moyen le plus efficace serait de pré-construire chaque carte pour chaque moteur graphique au préalable et de faire une recherche. Vous pouvez également stocker la carte dans votre propre structure de données personnalisée, puis utiliser votre wrapper pour créer une carte à partir de cette structure de données.

J'espère que cela vous aidera à démarrer =]

Justin L.
la source
2

Construire l'architecture de votre jeu avec un paradigme assez proche de MVC pour permettre une abstraction complète du code d'affichage serait probablement assez difficile pour tout grand projet. Cependant, il semble que le plus grand obstacle à la création d'un jeu prenant en charge à la fois un client 2D et 3D serait de concevoir un jeu dans lequel les deux clients sont également capables.

Il serait nécessaire de commencer la conception de votre jeu avec la pleine intention de créer et de prendre en charge les deux clients, et il serait probablement plus sûr de limiter toutes les fonctionnalités du jeu à ce qui est logique pour le client 2D.

À titre d'exemple, si vous ne conceviez pas un ensemble de fonctionnalités restreint, vous pourriez créer des niveaux dans lesquels des informations ou des objets importants n'étaient visibles que sous des angles spécifiques. Bien que ce soit bien pour les clients 3D qui ont une liberté de vision à 360 degrés, à moins que votre client 2D ne prenne explicitement en charge un angle de vue qui avait une visibilité sur chacun de ces objets importants, vous gêneriez les utilisateurs du client.

Il serait préférable de définir un nombre spécifique d'angles de vision pour le client 2D (8 ou 16 ou autres) et de développer tout le contenu pour s'adapter à ces contraintes. Malheureusement, si vous avez des niveaux et des objets conçus pour être visibles uniquement à partir d'un ensemble d'angles spécifiques, cela peut sembler assez étrange dans un client 3D.

À mon avis, ce serait une mauvaise tentative de choix d'une conception de jeu permettant aux clients 2D et 3D d'avoir des capacités égales. Je pense que ce serait une meilleure utilisation des ressources pour concevoir des options de gameplay asymétriques, et permettre à chaque client de jouer à ses forces. Par exemple, si le client 2D était principalement concentré sur une perspective de niveau stratégique sur le monde du jeu, le client 3D étant utilisé pour un gameplay de niveau tactique.

Charles Ellis
la source
0

Je pense que vous avez à peu près répondu à votre propre question:

Pour le mettre dans un contexte MVC: Les contrôleurs sont exactement les mêmes (en appuyant sur la touche "Haut", l'accellération des joueurs sera réglée à 3,5 unités / seconde), les vues sont totalement différentes (2D par rapport à 3D), et le modèle est le même sauf pour tout ce qui est directement lié aux graphiques.

Ainsi, en fournissant une abstraction adéquate entre l'entrée, la logique de jeu, etc. et les graphiques, vous aurez résolu le problème.

C'est essentiellement le but du modèle MVC, en particulier en ce qui concerne les applications de bureau et Web: il peut y avoir plusieurs clients accédant et manipulant les mêmes données (une interface Web, un client mobile et un client de bureau pour le courrier électronique, par exemple).

Sean James
la source
0

Restez simple si vous le voulez simple: - Écrivez la logique du jeu pour déplacer les objets. Ne stockez aucune donnée sur eux liée au rendu. - Écrivez des moteurs de rendu qui ont la possibilité d'examiner l'état des données du jeu et de les dessiner.

Vous pouvez utiliser des techniques de programmation plus ou moins compliquées pour cela. La seule chose dont vous avez besoin est un moyen d'obtenir des données "supplémentaires" que vous devez rendre pour chaque objet de jeu. Le moyen le plus simple est de ne nécessiter aucune donnée supplémentaire! Si l'objet du jeu est un "Assistant", dessinez un Assistant.

Si vous avez besoin de méthodes plus compliquées, envisagez le polymorphisme, le modèle de mémento, les tables de hachage, les pointeurs void *, etc.

Vincent Scheib
la source