Autor Wątek: Game Scripting Language  (Przeczytany 5716 razy)

Offline Steel_Eagle

  • Użytkownik

# Sierpień 16, 2006, 22:06:29
Hej mam problem z wyborem jezyka do skryptow. Wybor jest miedzy Pythonem Lua a Ruby z czego ten pierwszy narazie prowadzi ;) Czy ktos probowal juz uzywac ktoregos z wyzej wymienionych do pisania skryptow we wlasnej grze i moglby podzielic sie odczuciami?  Jakie sa plusy i minusy kazdego jakie mozliwosci i ograniczenia i czy wygodnie sie pisze  :)

Najbardziej zalezalby mi na mozliwosci odziedziczenia klasy c++ z silnika (np. CUnitWarrior) i rozwinieciu jej w skrypcie (CUnitPaladin). Silnik komunikowalby sie z obiektami przez interfejs (CUnit). Czy cos takiego jest w ogole mozliwe?  ;D W UnrealScripcie bylo to zrobione tak ze w skrypcie deklarowano klase ktora byla opakowaniem jej odpowiednika z c++ a nastepnie dziedziczono z tej skryptowej klasy.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline mINA87

  • Użytkownik

# Sierpień 16, 2006, 22:32:20
Qmpel implementował ostatnio boost::python'a, który fajnie wrapuje standardowego Pythona i ciężko tak od ręki przerzucić instancję klasy C++ do Pythona. Trzeba uciec się do proxy ze statycznymi składowymi, albo low-levelowo haczyć Pythona. Poza tym z tego co kojażę to ogólnie były problemy z extendingiem Pythona i wychodziło full małych i upierdliwych pierdółek, ale tu juz nie jestem kompetentny żeby coś powiedzieć bo to nie ja walczyłem z tym kodem :p

Offline really

  • Użytkownik

# Sierpień 16, 2006, 22:44:01
Przez chwilę bawiłem się Lua i bardzo mi się spodobało. Tylko chwilkę potestowałem, więc nie będę świrował znawcy i podował jakichś szczegółów, bo ich nie znam. Wiem tylko, że ten język użyto w Far Cry'u :)

st3cus

  • Gość
# Sierpień 16, 2006, 22:48:06
Qmpel implementował ostatnio boost::python'a, który fajnie wrapuje standardowego Pythona i ciężko tak od ręki przerzucić instancję klasy C++ do Pythona. Trzeba uciec się do proxy ze statycznymi składowymi, albo low-levelowo haczyć Pythona. Poza tym z tego co kojażę to ogólnie były problemy z extendingiem Pythona i wychodziło full małych i upierdliwych pierdółek
To mi tylko uswiadamia, ze musze przyspieszyc moje prace nad artami (2 lub 3 czesci) o kompleksej integracji Pythona z C++ przy pomocy Boost.Python ;)

mINA87 - dzialam juz od jakiegos czasu nad integracja, troszke musialem przewalczyc, ale to dziala wysmienicie :). W artach pokaze wszystko.

Cytuj
ajbardziej zalezalby mi na mozliwosci odziedziczenia klasy c++ z silnika (np. CUnitWarrior) i rozwinieciu jej w skrypcie (CUnitPaladin). Silnik komunikowalby sie z obiektami przez interfejs (CUnit). Czy cos takiego jest w ogole mozliwe?
Mozna to a nawet wiecej (uzywajac Pythona). Mozesz zbudowac klase w C++, a te sama klase rozbudowac w Pythonie (tak - ta sama klasa - nie dziedziczenie) o nowe metody. To swobodne przeplatanie metod pure Pythonowych z C++-sowymi.

Power potezny - na tyle ze na 99% stanie sie odpowiednikiem "unreal scripta" w projekciku nad ktorym pracuje.

Jesli ktos ma ochote to zapraszam do moich artkow (jak skoncze ;>)

// Aha - pracowalem nad embedowaniem LUA w moim mikrosilniczku. Masa problemow nad wymuszeniem "pseudo obiektowosci". Przejscie na Boost.Python i Pythona okazalo sie strzalem w dziesiatke. Juz obecnie wiem, ze na 99% bede mogl zakodzic kompletna grę w pelni obiektowo w Pythonku ;).

LUA do Pythona to jak maluch do ferrari
« Ostatnia zmiana: Sierpień 16, 2006, 22:50:44 wysłana przez st3cus »

Offline DarkJarek

  • Użytkownik
    • DarkJarek HomePage

# Sierpień 16, 2006, 23:12:27
Ja mam w planach stworzyć własną bibliotekę - składnia raczej ta z c++. Dodatkowo języm ma mieć możliwości bardzo zbliżone do c++. Czeka mnie DUŻO pisania :D ale mam nadzieję, że się opłaci no i, że skończe.

Offline fofoo

  • Użytkownik
    • WebLog

# Sierpień 17, 2006, 00:26:07
Najszybszym z tych języków jest lua, potem python a na końcu ruby. Co do możliwości (jeśli chodzi o sam język, 'możliwości' _nie_ oznaczają tu ilości i jakości dostępnych bibliotek) jest dokladnie odwrotnie. Ruby jest bardzo elastyczny (otawarte klasy), python jest już troche mniej elastyczny ale nadal jest językiem obiektowym.
Pozatym istaniej coś takiego jak pyrex http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/czyli mieszanka pythona i c.
Może Ci się też przydać http://www.swig.org/links.html
lub http://www.riverbankcomputing.com/Docs/sip4/sipref.html

Myśle że python jest najlepszym wyborem w tym przypadku :)

Offline Steel_Eagle

  • Użytkownik

# Sierpień 17, 2006, 00:35:48
St3tc byloby bardzo milo gdybys opublikowal te arty  ;) Powodzenia przy pisaniu.

A co do szybkosci to i tak bardziej zlozone funkcje beda spisane w c++ wiec nie widze problemu  :)

Offline dx0ne

  • Użytkownik
    • Pierdoły od dx0ne'a

# Sierpień 17, 2006, 03:25:52
LUA do Pythona to jak maluch do ferrari

ale najwyraźniej na potrzeby gier wystarcza (mam na myśli jego popularność). tak samo jak i maluchem można pojechać w wiele miejsc nie wspominając już że ferrari jeśli idze o np. polskie warunki nie poszalejesz prawie wcale :) no chyba że masz ferrari jenorazowego użytku :D

Offline Reg

  • Administrator
    • Adam Sawicki - Home Page

# Sierpień 17, 2006, 04:04:06
Się rozumie, że Python to zupełnie inny kaliber niż Lua, ale co z wydajnością? Czy tu czasem nie jest odwrotnie, i Python do Lua jest jak maluch do ferrari? :)

Arta już nie możemy się doczekać.

BTW: st3cus: Ja rozumiem, że to skromne forum nie jest godne, żeby gościć tak wielką osobistość jak Ty jako zarejestrowanego użytkownika, ale naprawdę chce Ci się za każdym razem tutaj rejestrować tylko żeby coś napisać?
« Ostatnia zmiana: Sierpień 17, 2006, 04:08:18 wysłana przez Regedit »

Offline mINA87

  • Użytkownik

# Sierpień 17, 2006, 10:44:14
No to pochwal się st3cus jak rozwiązałeś przezkazywanie istniejącej instancji obiektu C++ do Pythona :] Nie mowię że jest to niemożliwe, bo działa, ale mogłoby ładniej wyglądać :p Są chyba 3 drogi:
1. korzystanie z proxy
2. low-levelowe ustawianie Pythona (tutaj bym się najchętniej pobawił, ale jak zwykle brak czasu :p)
3. zablokowanie przez no_copy i stworzenie customowych konwerterów to_python (czy jakoś tak).
Z tym że na necie gdzie by nie spojrzał na taki problem to ludzie korzystają z rozwiązania 1szego i mówią że inne rozwiązania są hardcorowe, złe (pure evil ^^) itp itd.

st3cus

  • Gość
# Sierpień 17, 2006, 11:46:14
Ok - Za dużo nie powiem, bo nie chce sobie niszczyć artów już na starcie ;). Kto chce ten poczeka na nie, kto nie - to nie =]


Weźmy taka funkcje Python-a:
def ChangeArgs( bf2engine_SVECT3D, bf2engine_CPolygon ):
bf2engine_SVECT3D *= 10.123
bf2engine_CPolygon.Resize(1)
bf2engine_CPolygon.SetVertex( 0, bf2engine_SVECT3D )

Jej zadanie to pobranie wskaźników na C++-sowe obiekty SVECT3D i CPolygon. SVECT3D zostanie pomnożony przez 10.123 (zostanie użyty C++ sowy operator *= do tego celu) , a następnie wrzucony (już jako const &) do wielokąta. Zadaniem samplesa jest pokazanie łatwości przekazania parametru nie przez wartość, ale przez wskaźnik/referencje i swobodne operowanie na nim (przez wartość naturalnie również można – o czym będzie dalej)

Poniższy kod jest kodem do weryfikacji: tworzymy dwa wskaźniki, wektorek inicjujemy, wywołujemy Python-owa funkcje i logujemy wyniczki:

SVECT3D *svect_ptr = new SVECT3D( 1, 2, 3);
CPolygon *poly_ptr  = new CPolygon();

bf2::engine::python::CallFunction2P( "ChangeArgs", context_namespace, svect_ptr, poly_ptr );

bf2::engine::core::Log( "SVECT3D[pointer] = %.3f, %.3f, %.3f\n", svect_ptr->x, svect_ptr->y, svect_ptr->z );
bf2::engine::core::Log( "CPolygon.GetNumberOfVertices() = %d\n", poly_ptr->GetNumberOfVertices() );

if( poly_ptr->GetVertex(0) == *svect_ptr )
bf2::engine::core::Log( "Wektorki te same\n" );
else
bf2::engine::core::Log( "Wektorki rozne\n" );

delete svect_ptr;
delete poly_ptr;

A oto co dostałem w wydruczku:

Cytuj
SVECT3D[pointer] = 10.123, 20.246, 30.369
CPolygon.GetNumberOfVertices() = 1
Wektorki te same

Jak widać działa doskonale ;). Funkcja operowała na wskaźniku do obiektu C++.

Co do skomplikowania CallFunction2P - kod "aktywny" to 4 linijki (dosłownie) + 2 na obsługę błędów
Parametrami mogą być dowolne typy – również zarejestrowane przez programistę (czyli wyeksponowane do Python-a).

OK

Zróbmy to samo, ale SVECT3D będzie lokalna zmienna - nie przekazujemy ja przez wskaźnik, tylko przez wartość ;) :

Kod testowy w C++:

SVECT3D svect_local( 5, 21, -2);
CPolygon *poly_ptr  = new CPolygon();

bf2::engine::python::CallFunction2P( "ChangeArgs", context_namespace, svect_local, poly_ptr );

bf2::engine::core::Log( "SVECT3D[local] = %.3f, %.3f, %.3f\n", svect_local.x, svect_local.y, svect_local.z );
bf2::engine::core::Log( "CPolygon.GetNumberOfVertices() = %d\n", poly_ptr->GetNumberOfVertices() );

if( poly_ptr->GetVertex(0) == svect_local )
bf2::engine::core::Log( "Wektorki te same\n" );
else
bf2::engine::core::Log( "Wektorki rozne\n" );

delete poly_ptr;

A oto wyniczek:

Cytuj
SVECT3D[local] = 5.000, 21.000, -2.000
CPolygon.GetNumberOfVertices() = 1
Wektorki rozne
Działa poprawnie. SVECT3D został przekazany przez wartość, tam przemnożony i dodany do wielokąta. W związku z tym wektorki są różne.

Jeśli w wywołaniu CallFunction2P podamy svect_local jako referencje - &svect_local, to znów będziemy mogli w Pythonie operować na oryginalnym obiekcie a nie na jego duplikacie.

Więcej info – arty ;) (a postaram się opisać sporo fajnych rzeczy)

PS - nie wiem o co chodzi z tym Proxy, ale tak czy siak - ta metoda przedstawiona, przynajmniej dla mnie, jest całkiem wygodna i przyjemna ;). Naturalnie mogę równiez operować na metodach z obiektów

PS2 - Regedit dorabiasz sobie jakaś dziwna ideologie na mój temat. Jeśli nie wiesz czemu sie skasowałem (a powód kompletnie nie miał związku ze tą społecznościa ani z warsztatem jako takim) to daruj sobie takie  komentarze ok ?.

« Ostatnia zmiana: Sierpień 17, 2006, 17:43:00 wysłana przez st3cus »

Offline mINA87

  • Użytkownik

# Sierpień 17, 2006, 12:26:45
troszkę obszedłeś problem :p Stworzyłeś właśnie swego rodzaju proxy :] Ciężko mi to dokładnie opisać, bo mówię że tylko troszkę gadałem jak to było kodowane i nie wgryzałem się w kod, ale chodzi o problem stworzenia instancji obiektu Pythona z instancji obiektu C++. Właśnie najprościej w ten sposób - proxy. Ale nie jest to zbyt ładne i psuje parę konwencji interakcji systemu skryptów z kodem natywnym. Przekazujesz gołe wskaźniczki do Python'a ?

st3cus

  • Gość
# Sierpień 17, 2006, 12:35:19
To jest samples. Smart pointerki tez mozna uzyć. Proxy nie proxy - chodzi o wygodę ;). O psuciu czego mówisz ?. Jakis przykład co to popsuje :)
Jak dasz samplesa czy problem to obczaje co mozna z tym zrobic. Niskopoziomowe "hackowanie" pythona jak to nazwales moze byc niebezpieczne (jesli to to co mysle).

//Edit - robilem sobie testy. Oczywiscie powstaja obiekty PyObject (bo mają powstac) - i sa przekazywane jako argumenty (chyba o tym mowisz), ale imo to jak najbardziej jest OK. Jedyne co sie martwilem, to to czy gdzies "po drodze" nie beda sie klonowaly obiekty C++ (co moze spowodowac mala "eksplozje" zuzycia pamieci :)). Ale wszystko jest ok - jest tak jak z reszta zmiennych w pythonie - to referencje. Jak dla mnie to bardzo dobre rozwiazanie.  Python widzi obiekty jako Python-owe, C++ jako C++-owe. Nie wiem czemu miało by to być złe ;). Jest w pełni zgodne z wytycznymi API Pythona, a przy tym banalnie proste w użyciu w app C++. 
« Ostatnia zmiana: Sierpień 17, 2006, 13:54:15 wysłana przez st3cus »

Offline mINA87

  • Użytkownik

# Sierpień 17, 2006, 14:32:51
nie zrozumieliśmy się :p chodzi mi o to że często jak tworzysz PyObject przez boost::python (samo PyObject jest OK) to tworzona jest kopia obiektu. Właśnie zbyt często :] Cięzko mi w 100% opisać problem bo ja dotknąłem go jakby tylko przez szybkę :p A spróbuj jeszcze sam z siebie utworzyć object z instancji obiektu C++ w którym masz zablokowane konstruuktor domyślny i kopiujący :] Próbowałem operowac flagą no_copy (czy jak ona się tam nazywa), ale właśnie ciągle nie uzyskiwałem pozytywnych efektów. Mówiąc o low-levelowym haczeniu Pythona mówię o ręcznym/półręcznym stworzeniu tej struktury :] Tam jakoś tworzyło się parę deskryptorów, używało kilku funkcji, jakoś tam można pomieszać, ale sioę w to nie zagłębiałem z braku czasu.

st3cus

  • Gość
# Sierpień 17, 2006, 14:37:36
Ah to wszystko jasne ;). Otóż ja to chyba obszedłem - nic mi się nie tworzy :).  Zrobiłem sobie test - z samplesa wcześniej (tylko, ze usunąłem wskaźnik - CPolygon jest zmienna lokalna). Dałem wielokącikowi Resize na ok. 1milion wierzchołków, na TaskManagerku obserwowałem VM size.  Przy tworzeniu PyObject-a poprzez boosta nie miałem zduplikowania obiektu (powinno być wykazane zwiększenie zaalokowania pamięci przy powstaniu kopii):).  Jeśli ten cały problem to tylko to, to wydaje mi się, że mam rozwiązanie (choć będę to badał dokładnie - ale wychodzi na to, ze jest ok. ) :)

« Ostatnia zmiana: Sierpień 17, 2006, 14:41:51 wysłana przez st3cus »