Introducci贸n a la integraci贸n de scripts en un motor de juegos

Integraci贸n con AngelScript

Las ventajas diferenciativas de AngelScript en relaci贸n a Lua y Python son principalmente dos:

. Su sintaxis es similar a C++
. No requiere de funciones proxy

Veamos como realizar la integraci贸n en sus pasos b谩sicos:

1. Ejecutar un script desde C++

Como primer paso deberemos incluir la cabecera correspondiente para poder acceder al API de integraci贸n del sistema de script con nuestro programa C++:

[c贸digo C++]

| #include "angelscript.h"

Por otro lado, el enlace con la librer铆a podemos hacerlo del siguiente modo:

[c贸digo C++]

| #ifdef _DEBUG
| #pragma comment(lib, "angelscriptd.lib")
| #else
| #pragma comment(lib, "angelscript.lib")

El paso siguiente ser谩 cargar el script en un buffer, para luego poder indicarle al motor de script que trabaje con 茅l:

[c贸digo C++]

| FILE * fp = fopen("../../scripts/script1.as", "rb");
| int iLength = _filelength(_fileno(fp));
| char * pScriptBuffer = new char[iLength];
| fread(pScriptBuffer, iLength, 1, fp);
| fclose(fp);

Hasta aqu铆 nada fuera de lo com煤n, la 煤nica funci贸n que no solemos utilizar es _filelength que retorna el tama帽o en bytes de un archivo (su prototipo se encuentra en io.h).

Ahora, obtendremos un puntero al motor de scripting con la siguiente l铆nea:

[c贸digo C++]

| asIScriptEngine * engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

Ahora, le pasaremos el buffer donde cargamos el script al motor, junto con dos strings descriptivos del m贸dulo al cual pertenece y la secci贸n:

[c贸digo C++]

| engine->AddScriptSection("module", "section", pScriptBuffer, iLength);

Ahora, intentaremos compilar el script:

[c贸digo C++]

| int res = engine->Build("module");
| if (res == -1)
| {
| // ...
| }

El siguiente paso ser谩 obtener un identificador de la funci贸n que deseamos ejecutar dentro del script:

[c贸digo C++]

| asIScriptContext *context = 0;
| engine->CreateContext(&context);
| int functionID = engine->GetFunctionIDByDecl("module", "void DoSomething()");
|
| context->Prepare(functionID);

Ahora s铆, podremos ejecutar la funci贸n dentro del script:

[c贸digo C++]

| int r = context->Execute();
| if(r == asEXECUTION_EXCEPTION)
| {
| // ...
| }

Por 煤ltimo, liberamos el contexto que creamos con la funci贸n CreateContext l铆neas atr谩s:

[c贸digo C++]

| context->Release();

El script que llamamos script1.as posee el siguiente c贸digo:

[c贸digo AngelScript]

| void DoSomething()
| {
| }

2. Ejecutar una funci贸n de un script desde C++ pasando un par谩metro

Veamos como interactuar con un script. Es posible con el API de AngelScript registrar una variable global desde C++ para que luego un script pueda utilizarla como si la hubiese declarado 茅l mismo.

Si quisi茅ramos, por ejemplo, declarar una variable global entera deber铆amos escribir:

[c贸digo C++]

| int iContador = 0;
| engine->RegisterGlobalProperty("int iContador", &iContador);

Estas l铆neas debemos introducirlas luego de obtener el puntero al motor de scripting pero antes de compilar el script (de otro modo existir谩 un error de compilaci贸n).

El script podr铆a poseer el siguiente c贸digo relacionado:

[c贸digo AngelScript]

| void DoSomething()
| {
| iContador = 10;
| }

Ahora, podremos recuperar el valor fijado por el script accediendo directamente a dicha variable (recordemos que la declaramos en C++):
cout << “el valor de counter es: ” << iContador << endl;

3. Ejecutar una funci贸n C++ desde un script

Hasta el momento pudimos apreciar que ejecutar un simple script lleva un poco m谩s de c贸digo (debido a la creaci贸n del contexto, preparaci贸n y compilaci贸n) que con Lua o Python pero ac谩 empieza lo bueno. Para ejecutar una funci贸n desde angelscript no debemos estar creando funciones proxy, simplemente registramos nuestra funci贸n real :)

Supongamos que deseamos ejecutar la siguiente funci贸n:

[c贸digo C++]

| void Print(int value)
| {
| printf("%d", value);
| }

Deberemos registrar la funci贸n de la siguiente manera:

[c贸digo C++]

| engine->RegisterGlobalFunction("void Print(int)", asFUNCTION(Print), asCALL_CDECL);

Si en cambio nuestra funci贸n es:

[c贸digo C++]

| void Foo(int value, float value2, float value3)
| {
| }

Entonces deberemos registrarla del siguiente modo:

[c贸digo C++]

| engine->RegisterGlobalFunction("void Foo(int, float, float)", asFUNCTION(Foo), asCALL_CDECL);

Un script puede, ahora, hacer uso de cualquier de las funciones registradas del siguiente modo:

[c贸digo AngelScript]

| void DoSomething()
| {
| Print(43240);
| }

4. Ejecutar el m茅todo de una clase desde un script

Registrar propiedades de clases o m茅todos tambi茅n se hace de manera directa. S贸lo debemos tener en cuenta ciertas restricciones en el uso de m茅todo virtuales.

Partiendo de la siguiente clase:

[c贸digo C++]

| class ClaseFoo
| {
| public:
| int valor;
|
| void SetValor(int iVal)
| {
| valor = iVal;
| }
| };

Para registrar la propiedad valor y el m茅todo SetValor deberemos escribir:

[c贸digo C++]

| // Registro la clase
| engine->RegisterObjectType("ClaseFoo", sizeof(ClaseFoo), asOBJ_CLASS);
| // Registro la propiedad
| engine->RegisterObjectProperty("ClaseFoo", "int valor", offsetof(ClaseFoo, valor));
| // Registro el m茅todo
| engine->RegisterObjectMethod("ClaseFoo", "void SetValor(int)", asMETHOD(ClaseFoo, SetValor), asCALL_THISCALL);

A partir de all铆 un script podr谩 acceder a esta clase del siguiente modo:

[c贸digo C++]

| void DoSomething()
| {
| ClaseFoo foo;
|
| foo.valor = 10;
| foo.SetValor(20);
| }

Conclusi贸n

El objetivo de este documento fue introducir el uso de los sistemas de scripts mas populares del momento, ejemplificar su uso b谩sico e introducir al uso de herramientas complementarias para su integraci贸n.

Integrar cualquier sistema de scripts a nuestro motor de juegos o a un programa C++ puede ser muy beneficioso pero decidir cu谩l o de que forma integrarlo es la decisi贸n dif铆cil.

En la parte 2 de este tutorial veremos que herramientas existen en la red para ayudarnos a integrar estos motores de scripts en nuestro c贸digo que suele ser la parte mas trabajosa.

Compartir:
  • Twitter
  • Facebook
  • MySpace
  • BarraPunto
  • del.icio.us

Pages: 1 2 3 4 5 6

Comments

  1. Novack
    December 1st, 2007 | 2:05

    Hehe, flor de articulo. Todavia no lo termine de leer, pero muy buen tema!

  2. Ni7ram
    December 1st, 2007 | 12:53

    Epa! Crei que tenias abandonada la pagina pero no, estabas haciendo un super articulo. Buenisimo!

  3. December 7th, 2007 | 22:24

    [...] Este art铆culo completa el que publiqu茅 la semana pasada y que puede acceder haciendo click aqu铆. [...]