Jak mogę wdrożyć inteligentne skrypty w mojej grze?

18

Tworzę silnik gry. To ma być jednostka / komponenty. Aby rozwinąć moją grę, sam pomyślałem o użyciu języka skryptowego do stworzenia jednostek.

Na przykład, jeśli chcę dodać do gracza rodzaj potwora, który jest agresywny, będzie to istota z kilkoma komponentami; komponenty te zmienią się w zależności od typu potwora, więc jeśli mam sto różnych rodzajów potworów, w mojej grze nie będę musiał tworzyć nowej metody dla każdego z nich bezpośrednio w kodzie gry.

Czy powinienem używać języka skryptowego do opisywania tego elementu pod względem komponentów, czy może jest coś jeszcze, co działałoby lepiej? Mówiąc bardziej ogólnie, jak powinienem używać skryptów w mojej grze?

Natan
źródło
Dla samego opisu encji możesz użyć tylko xml lub czegoś podobnego, bez potrzeby pisania skryptów. Do pisania skryptów
użyłbym
@Kikaimaru C # nie jest językiem skryptowym. Użycie lua byłoby lepszym pomysłem lub innym językiem, który można wbudować w silnik.
JDSweetBeat
@DJMethaneMan „C # nie jest językiem skryptowym” nic nie znaczy, absolutnie nie ma problemu z pisaniem skryptów w C # w grze napisanej w C # i korzystaniem z czegoś takiego jak Roselyn do kompilacji ... Ale po 4 latach użyłbym json a javascript zamiast xml i C # :)
Kikaimaru

Odpowiedzi:

17

Moja gra używa frameworku komponentu encji i skryptów do definiowania encji (to nie definiuje bezpośrednio zachowania, o tym powiem więcej na końcu). Skrypty definiują rzeczywiste komponenty, które zostaną użyte do utworzenia każdego elementu. Używa prostego języka skryptowego, który stworzyłem. Oto uproszczona wersja jednego z moich skryptów:

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
    }
}

Wiele z nich jest samoopisujących się, ale oto kilka najważniejszych informacji:

  • Pierwsza sekcja opisuje wspólne informacje dla encji. Obejmuje to opis i nazwy wyświetlane dla różnych aspektów jednostki.
  • Te baseAttributesodniesienia tag inny skrypt, który określa wspólne elementy, które nie chcą mieć do przedefiniowania wielokrotnie. Zawiera składniki, takie jak position, liferequirementsi tak dalej. Jeśli jakikolwiek komponent zostanie tu zdefiniowany ponownie, zastąpi on ten wspólny.
  • Każdy [NAME] { }zestaw definiuje nowy komponent, który zostanie dodany do tych jednostek.
  • Ten opis nie dotyczy tylko jednego bytu , dotyczy wszystkich stworzonych goblinów. Przekonasz się, że niektóre wartości mają zakresy (tj. 0.01:0.015), Kiedy tworzony jest nowy goblin, zostaje on utworzony ze składnikiem, który ma losową wartość w tym zakresie. Więc każdy goblin będzie miał nieco inne umiejętności i nieco inne prędkości. Ta konfiguracja określa, że ​​wszystkie gobliny zaczną od naprawdę dobrych umiejętności w układaniu kostek i wydobywaniu, co jest naprawdę tylko dla moich własnych celów testowych. Ale jestem pewien, że można się domyślić, że bardzo łatwo jest zmienić wartości na dowolne.

Cała ta sprawa polega na utworzeniu niestandardowego analizatora składni, pewnego rodzaju struktury do przechowywania definicji encji (nazywam mój Leksykon!) I fabryki do pobierania tych definicji encji i generowania nowych encji. Dla mnie ten system jest wciąż w początkowej fazie, ale okazuje się naprawdę, bardzo dobrze. Jest to dość potężny system do szybkiego definiowania encji i pozwala tworzyć dowolne encje za pomocą utworzonych komponentów. Jeśli nie masz ochoty tworzyć własnego parsera, myślę, że XML będzie działał dobrze. Przekształciłem mój z rekurencyjnego parsera wypychanego, który napisałem, dla trochę wymyślonego języka programowania.

Jak widać, definiuje to byt. Wspomniałem, że nie określa bezpośrednio zachowania. Może jednak łatwo zdefiniować takie rzeczy, jak znienawidzeni wrogowie i jak agresywnie reagować na wspomnianych wrogów. Byłoby to tak proste, jak zdefiniowanie dowolnego komponentu używanego do kontrolowania takiego zachowania. Moje byty mają również komponent inteligencji (nie pokazano), który definiuje takie rzeczy jak:

  • Jak znajdują ścieżkę (prosty ruch w linii wzroku, prosty A *, predykcyjny A * itp.)
  • Jak agresywni / defensywni są. Jednostki mogą posiadać strefy domowe, które będą bronione, ale być może nie będą agresywne poza tymi strefami.
  • Świadomość technologiczna (otwieranie drzwi, używanie gadżetów, unikanie pułapek itp.)
  • I więcej...

Jakkolwiek twój jest zdefiniowany, to twój system będzie kierował danymi w tym komponencie, co z kolei wpływa na zachowanie twoich entites.

MichaelHouse
źródło
Dzięki za udostępnienie. Myślę, że spróbuję to zrobić w formacie XML. Dużo o tym myślę (dzięki AbstractChaos btw) i powinno zaspokoić moje potrzeby (przynajmniej w przypadku opisów bytów).
nathan
1
@nathan Zgadzam się, że powinieneś używać XML. Powodem mojego postu było więcej danych, które należy zawrzeć w pliku XML i sposób ich wykorzystania. Format danych może być dowolny. Dane, które wybierzesz, i sposób ich wykorzystania są o wiele ważniejsze.
MichaelHouse
@ Byte56 Wiem, że ten post jest stary, ale jak poradzić sobie z relacjami rodziców z dziećmi? Załóżmy, że mamy drzewko umiejętności i potrzebujesz 10 punktów umiejętności A [0], aby umożliwić A [1], i 10 punktów w tym, aby umożliwić A [2] itp. Czy powinienem je zagnieździć, czy spłaszczyć i wcisnąć ID rodzica? Oczywiście są one logicznie równoważne, ale miałem nadzieję, że masz wgląd w rzeczywistość.
Superstringcheese,
@ Superstringcheese if player.hasPoints(10) then i++ end skillTree[i]byłby jakimś pseudokodem. Nie mam jednak pojęcia, jak ważne jest to pytanie dla tego postu.
JDSweetBeat 26.04.16
4

Jeśli wszystko, czego naprawdę potrzebujesz, to sposób definiowania składników Potwora, to XML działałby dobrze zarówno w języku C #, jak i java błyskawicznie go implementuje.

Twój xml może być

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

Wtedy mogłaby wyglądać twoja klasa mafijna. (Jawa)

public class Mob {
  private IPersonality personality;
  private Integer intelligence

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

Gdzie IPersonality jest interfejsem.

Następnie możesz załadować swój plik XML i przeanalizować każdą wartość w fabryce.

na przykład Parsuj wartość osobowości do PersonalityFactory, który jest po prostu:

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; 
  }
}

Następnie możesz ustawić taki tłum

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

Kluczem jest to, że silnik zna format xml i ma fabrykę dla wszystkich potrzeb.

Jedną z zalet xml jest to, że możesz zdefiniować własny schemat, aby mieć pewność, że format jest zawsze poprawny, zobacz tutaj .

Mam nadzieję że to pomoże

AbstractChaos
źródło
Właściwie muszę znaleźć sposób, aby łatwo stworzyć nowy byt w trakcie procesu tworzenia gry. Czy xml będzie wystarczająco elastyczny? I tak muszę dodać skrypt dla wewnętrznej logiki gry.
nathan
Jeśli czytasz klasę Mob jako Entity, wówczas tworzysz nową Enitity (Mob) za pomocą XML z różnymi składnikami (IPersonality, Intelligence [przykład danych dla tego moba]). I niestety nie mogę odpowiedzieć, czy będzie wystarczająco elastyczny, ponieważ nie wiem, co więcej chcesz robić, niż to, co określiłeś, jednak XML jest formatem, w którym jedynym ograniczeniem jest sposób interpretacji każdej sekcji. Zaktualizuj swoje pytanie szczegółowym przykładem, a pokażę plik XML, który sobie z tym poradzi. Wewnętrzna logika gry brzmi jak powinna być wewnętrzna?
AbstractChaos
0

Myślę, że Python jest w porządku. Często LUA jest również dobrą alternatywą, jeśli chcesz dodać możliwości skryptowe do swoich programów.

Możesz albo użyć XML do opisania zachowania swoich potworów, wymagałoby to trochę kodowania w rzeczywistym kodzie gry, ponieważ zapisujesz tylko „nazwę” lub niektóre atrybuty zgodnie z zachowaniem (prędkość, rodzaj broni, której używa potwór, itp.) zachowania, które należy zastosować w kodzie gry.

Jeśli używasz Scriptengine (np. LUA), możesz przenieść ten kod ze wstępnie skompilowanego programu do plików skryptowych, które są ładowane w czasie wykonywania. Aby to zrobić, musisz udostępnić interfejs API swoich „potworów” silnikowi skryptowemu. Pozwala to wywoływać metody kodu potwora z zewnątrz.

Aron_dc
źródło
API mojego potwora? To znaczy, będę musiał móc tworzyć nowe komponenty ze skryptu (instanacja). Czy to możliwe?
nathan
Afaik, to powinno być możliwe. Możesz także zastosować mieszane podejście do pamięci zewnętrznej (jak wspomniane przez abstractchaos lub byte56) i języka skryptowego (LUA, Python ...). Główną zaletą np. LUA jest to, że możesz zmienić kod w czasie wykonywania i jest on natychmiast dostępny w uruchomionej grze / silniku
Aron_dc
Ho na poważnie? To naprawdę ogromna zaleta. Mam też LUA (lub inny język skryptowy) dla „osi czasu gry”. Mam na myśli, aby stworzyć scenariusz scenariuszy, w których gracz musi zostać zablokowany, ten duszek musi się tu przenieść, zapalić tu i tam ... Więc może mógłbym również użyć języka skryptowego do ładowania encji? Zamierzam również opublikować kolejne pytanie, aby ujawnić mój obecny sposób zarządzania bytem / komponentami w stosunku do tego, co nazywam „menedżerem”, aby sprawdzić, czy mam się dobrze.
nathan