Comment puis-je implémenter un script intelligent dans mon jeu?

18

Je développe un moteur de jeu. Il est censé être basé sur une entité / composants. Pour développer mon jeu lui-même, j'ai pensé à utiliser un langage de script pour réellement créer les entités.

Par exemple, si je veux ajouter une sorte de monstre agressif pour le joueur, ce sera une entité à plusieurs composants; ces composants changeront avec le type de monstre, donc si j'ai cent types de monstres différents, dans mon jeu, je n'aurai pas à créer une nouvelle méthode pour chacun d'eux directement dans mon code de jeu.

Dois-je utiliser un langage de script pour décrire cette entité, en termes de composants ou existe-t-il autre chose qui fonctionnerait mieux? Plus généralement, comment utiliser les scripts dans mon jeu?

nathan
la source
Pour une description d'entité juste, vous pouvez utiliser uniquement xml ou quelque chose de similaire, pas besoin de script. Pour les scripts, j'utiliserais C #, mais seulement si votre moteur est en .NET ...
Kikaimaru
@Kikaimaru C # n'est pas un langage de script. Utiliser lua serait une meilleure idée, ou un autre langage pouvant être intégré à votre moteur.
JDSweetBeat
@DJMethaneMan "C # n'est pas un langage de script" ne veut rien dire, il n'y a absolument aucun problème à écrire des scripts en C # dans un jeu écrit en C # et à utiliser quelque chose comme Roselyn pour la compilation ... Mais après 4 ans, j'utiliserais json a javascript au lieu de xml et C # :)
Kikaimaru

Réponses:

17

Mon jeu utilise un framework de composants d'entité et utilise des scripts pour définir des entités (cela ne définit pas directement le comportement, j'en parlerai plus à la fin). Les scripts définissent les composants réels à utiliser pour créer chaque entité. Il utilise un langage de script simple que j'ai créé. Voici une version simplifiée d'un de mes scripts:

ENTITY:"Goblin"
{
    description="It's currently their age."
    commonname="goblin"
    pluralCommonName="goblins"
    childname="gob'in"
    pluralChildName="gob'ins"
    active=Nocturnal
    tags=Mobile
    baseAttributes="OrganicMobileCreature"

    [Model]{
            meshname="Goblin"
            texturename="GoblinTexture"
    }

    [Motion]{
            maxvelocity=0.01:0.015
            locomotion=Walk,Swim
    }

    [Skills]{
            ALL=0.01:0.05,Mine=8.3:8.8,PlaceCube=8.3:8.8
    }

    [Inventory]{
            maxItems=2
            Allow=ALL
            Disallow=NONE
    }
}

Une grande partie de cela est auto-décrivant, mais voici quelques points saillants:

  • La première section décrit les informations communes à l'entité. Cela inclut une description et des noms d'affichage pour divers aspects de l'entité.
  • La baseAttributesbalise fait référence à un autre fichier de script qui définit des composants communs que je ne veux pas avoir à redéfinir plusieurs fois. Il contient des composants tels que position, liferequirementsetc. Si un composant est défini ici à nouveau, ce composant remplacera le composant commun.
  • Chaque [NAME] { }ensemble définit un nouveau composant qui sera ajouté à ces entités.
  • Cette description n'est pas seulement pour une seule entité , c'est pour tous les gobelins créés. Vous verrez que certaines valeurs ont des plages (c'est-à-dire 0.01:0.015), lorsqu'un nouveau gobelin est créé, il est créé avec un composant qui a une valeur aléatoire dans cette plage. Ainsi, chaque gobelin aura des compétences légèrement différentes et des vitesses légèrement différentes. Cette configuration définit que tous les gobelins commenceront avec de très bonnes compétences pour placer des cubes et extraire, ce qui est vraiment juste pour mes propres tests. Mais comme je suis sûr que vous pouvez le deviner, il est très facile de changer les valeurs en ce que je veux.

Tout cela implique de créer un analyseur personnalisé, une sorte de structure pour contenir les définitions d'entités (j'appelle le mien le Lexique!) Et une usine pour prendre ces définitions d'entités et générer de nouvelles entités. Pour moi, ce système est encore à ses débuts, mais il se révèle vraiment, vraiment bien. C'est un système assez puissant pour définir rapidement des entités et vous permet de créer n'importe quelle entité que vous souhaitez en utilisant les composants que vous avez créés. Si vous n'êtes pas à l'aise de créer votre propre analyseur, je pense que XML fonctionnera très bien. J'ai converti le mien à partir d'un analyseur récursif pushback que j'ai écrit pour un langage de programmation un peu inventé.

Comme vous pouvez le voir, cela définit l'entité. J'ai mentionné qu'il ne définit pas directement le comportement. Il peut, cependant, définir facilement des choses comme des ennemis détestés et comment réagir agressivement à ces ennemis. Ce serait aussi simple que de définir le composant que vous utilisez pour contrôler un tel comportement. Mes entités ont également un composant de renseignement (non illustré) qui définit des choses comme:

  • Comment ils trouvent leur chemin (simple mouvement en ligne de visée, A * simple, A * prédictif, etc.)
  • Comme ils sont agressifs / défensifs. Les entités peuvent avoir des zones d'origine qui seront défendues, mais peut-être pas agressives en dehors de ces zones.
  • Sensibilisation à la technologie (ouvrir les portes, utiliser des gadgets, éviter les pièges, etc.)
  • Et plus...

Quelle que soit la vôtre, c'est votre système qui pilotera les données de ce composant, ce qui affectera à son tour le comportement de vos entités.

MichaelHouse
la source
Merci d'avoir partagé. En fait, je pense que je vais essayer de le faire en utilisant le format XML. J'ai beaucoup réfléchi à cela (grâce à AbstractChaos btw) et cela devrait répondre à mes besoins (au moins pour les descriptions d'entités).
nathan
1
@nathan Je suis d'accord que vous devriez opter pour XML. La raison de mon message était davantage les données à inclure dans votre XML et comment les utiliser. Le format des données peut être celui que vous souhaitez. Les données que vous choisissez d'inclure et la façon dont vous implémentez leur utilisation sont bien plus importantes.
MichaelHouse
@ Byte56 Je sais que ce message est ancien, mais comment pourriez-vous gérer les relations parents-enfants? Disons que nous avons un arbre de compétences et que vous avez besoin de 10 points dans la compétence A [0] pour activer A [1], et 10 points dans celui pour activer A [2], etc. Dois-je les imbriquer, ou les aplatir et saisir un ParentId? Évidemment, ils sont logiquement équivalents, mais j'espérais que vous aviez une idée du monde réel.
Superstringcheese
@Superstringcheese if player.hasPoints(10) then i++ end skillTree[i]serait un pseudocode. Cependant, je n'ai aucune idée de la pertinence de cette question pour le poste.
JDSweetBeat
4

Si tout ce dont vous avez vraiment besoin est un moyen de définir les composants d'un Monster, alors XML fonctionnerait bien, C # et java en ont une implémentation rapide comme l'éclair.

Votre xml pourrait être

<?xml version="1.0" encoding="UTF-8"?>
<mobs>
  <mob>
    <personality>Aggressive</personality>
    <intelligence>20</intelligence>
  </mob>
</mobs>

Ensuite, votre classe Mob pourrait ressembler. (Java)

public class Mob {
  private IPersonality personality;
  private Integer intelligence

  //**  Getters & Setters **//
}

Où IPersonality est une interface.

Vous pouvez ensuite charger votre xml et analyser chaque valeur via une usine.

par exemple, analyser la valeur de personnalité dans la personnalité de l'usine qui est simplement:

public IPersonality getPersonality(String personalityName) {
  if(personalityName.equals("Aggressive")) {
    return new AggressivePersonality();
  }
  else if(personalityName.equals("Passive")) {
    return new PassivePersonality();
  }
  else {
     //Maybe allow for no personality (We all know monster like that ;) )
     return null; 
  }
}

Ensuite, vous pouvez mettre en place une foule comme ça

Mob mob = new Mob();
mob.setPersonality(getPersonality(xmlValue));
mobList.add(mob);

La clé est que votre moteur connaît le format du XML et dispose d'une usine pour tout ce dont il a besoin.

Un avantage de xml est que vous pouvez définir votre propre schéma pour vous assurer que le format est toujours correct, voir ici .

J'espère que cela t'aides

AbstractChaos
la source
En fait, je dois trouver un moyen de créer facilement une nouvelle entité sur le jeu lors du processus de développement du jeu. Est-ce que xml sera suffisamment flexible? Je devrai quand même ajouter des scripts pour la logique de jeu interne.
nathan
Si vous lisez la classe Mob en tant qu'entité, vous créez une nouvelle entité (Mob) en utilisant XML avec différents composants (IPersonality, Intelligence [exemple de données pour ce mob]). Et malheureusement, je ne peux pas répondre s'il sera suffisamment flexible car je ne sais pas quoi faire de plus que ce que vous avez spécifié, mais XML est un format où les seules limites sont la façon dont vous interprétez chaque section. Mettez à jour votre question avec un exemple détaillé et je vais montrer un fichier XML qui peut gérer cela. La logique de jeu interne sonne comme si elle devait être interne?
AbstractChaos
0

Python va bien je pense. Souvent, LUA est également une bonne alternative si vous souhaitez ajouter des capacités de script à vos programmes.

Vous pouvez soit utiliser XML pour décrire le comportement de vos monstres, cela impliquerait un certain codage dans le code du jeu, car vous n'enregistrerez que le "nom" ou certains attributs en fonction du comportement (vitesse, type d'arme que le monstre utilise, etc.) du comportement à utiliser dans votre code de jeu.

Si vous utilisez un Scriptengine (par exemple LUA), vous pouvez transférer ce code depuis votre programme précompilé vers des fichiers de script qui sont chargés pendant l'exécution. Pour ce faire, vous devez exposer l'API de vos "monstres" au scriptengine. Cela vous permet d'appeler les méthodes du code du jeu monstre de l'extérieur.

Aron_dc
la source
L'API de mon monstre? Je veux dire, je devrai pouvoir créer de nouveaux composants à partir du script (instanciation). C'est possible?
nathan
Afaik, cela devrait être possible. Vous pouvez également utiliser une approche mixte de stockage externe (comme mentionné par abstractchaos ou byte56) et de langage de script (LUA, Python ...). Le principal avantage de LUA, par exemple, est que vous pouvez changer votre code au moment de l'exécution et qu'il est instantanément disponible dans votre jeu / moteur de
course
Ho sérieusement? C'est un énorme avantage en effet. J'ai aussi bien de LUA (ou autre langage de script) pour "chronologie de jeu". Je veux dire, pour créer des scènes scénarisées où le joueur doit être bloqué, ce sprite doit se déplacer ici, s'allumer ici et là ... Alors peut-être que je pourrais aussi utiliser un langage de script pour le chargement d'entité? Je vais aussi poster une autre question pour exposer ma façon actuelle de gérer les entités / composants sur ce que j'appelle "manager" pour voir si je vais bien.
nathan