El siguiente paso sería añadir todos los zombies que deseemos y desde el código ir asignado el comportamiento que hemos creado.
Pero esta tarea es muy tediosa. Sería más sencillo usar el editor y asignar la clase, que define su comportamiento, a cada sprite.
Esto es posible creando un componente propio.
Para “exponer” las propiedades que queremos tener accesibles desde el editor, se deben declarar en la sección published de la clase. Nos interesan exponer las propiedades que le asignábamos valores cuando creábamos el zombie por código. Estas son la dirección, la velocidad, y además vamos a añadir la distancia que recorre el zombie.
|
1 2 3 4 5 |
published property Distancia: single read FDistancia write SetDistancia default DefaultDistancia; property DireccionPersistent: TCastleVector3Persistent read FDireccionPersistent; property VelocidadPersistent: TCastleVector3Persistent read FVelocidadPersistent; |
Observa el código anterior. Declaramos una propiedad llamada Distancia, que es de tipo Single con un valor por defecto contenido en la variable DefaultDistancia declaramos en el parte pública de la clase.
|
1 2 3 4 5 |
public const DefaultDistancia :single = 50; property Direccion: TVector3 read Fdireccion write Setdireccion; property Velocidad: TVector3 read Fvelocidad write Setvelocidad; |
Cualquier tipo de variable simple (integer, single, string , etc.) se puede declarar directamente. Pero las variables que son una estructura como Tvector, no se puede declarar como Published ya que no lo permite pascal. Para ello, CGE, solucionó el problema creando un “clase intermedia”, en este caso para TVector3, se creó TCastleVector3Persistent.
La gestión de esta clase la debemos realizar en la propiedad create, así que añadimos, en la sección Public de la clase los métodos create y destroy. Recuerda que todo lo que creemos debemos destruirlo.
|
1 2 |
constructor Create(AOwner: TComponent); override; destructor Destroy; override; |
Dentro de Create, escribimos el código para gestionar estas clases.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
constructor TZombieBehavior.Create(AOwner: TComponent); begin inherited Create(AOwner); Distancia := DefaultDistancia; Fdireccion := Vector3(-1, 0, 0); FDireccionPersistent := TCastleVector3Persistent.Create(nil); FdireccionPersistent.SetSubComponent(True); {$IFDEF FPC} FDireccionPersistent.InternalGetValue := @GetDireccionForPersistent; FDireccionPersistent.InternalSetValue := @SetDireccionForPersistent; {$ELSE} FDireccionPersistent.InternalGetValue := GetDireccionForPersistent; FDireccionPersistent.InternalSetValue := SetDireccionForPersistent; {$ENDIF} FDireccionPersistent.InternalDefaultValue := Direccion; Fvelocidad := Vector3(10, 0, 0); FVelocidadPersistent := TCastleVector3Persistent.Create(nil); FVelocidadPersistent.SetSubComponent(True); {$IFDEF FPC} FVelocidadPersistent.InternalGetValue := @GetVelociadForPersistent; FVelocidadPersistent.InternalSetValue := @SetVelocidadForPersistent; {$ELSE} FVelocidadPersistent.InternalGetValue := GetVelociadForPersistent; FVelocidadPersistent.InternalSetValue := SetVelocidadForPersistent; {$ENDIF} FVelocidadPersistent.InternalDefaultValue := Velocidad; end; |
Lo primero que hacemos es asignar a la propiedad Distancia su valor por defecto. Lo siguiente es a la propiedad Fdireccion es asignarle un valor, este valor será el que se muestre en el editor, como valor por defecto. Ahora inicializamos la variable FdireccionPersistent creando la clase correspondiente. Tras ello indicamos que es un subcomponente pasando el valor true al procedimiento SetSubCoomponent.
Ya por último, a su propiedad InternalGetValue le asignamos el método GetDireccionForPersistent que será usado para obtener el valor del vector de dirección. Del mismo modo, le asignamos el método SetDireccionForPersistent para asignar valores al vector de dirección.
Los métodos son muy sencillos.
|
1 2 3 4 5 6 7 8 9 |
function TZombieBehavior.GetDireccionForPersistent: TVector3; begin Result := Direccion; end; procedure TZombieBehavior.SetDireccionForPersistent(const Value: TVector3); begin Direccion := Value; end; |
Repetiremos los misma idea para el resto de propiedades TVector3.
Si queremos aprovechar, e incluir algunas de las propiedades el categoría Basic, debemos declarar la siguiente función en la sección Public de la clase.
|
1 |
function PropertySections(const PropertyName: string): TPropertySections; override; |
Este función contendrá el siguiente código.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function TZombieBehavior.PropertySections(const PropertyName: string): TPropertySections; begin WritelnLog('Property: ' + PropertyName); if ArrayContainsString(PropertyName, ['VelocidadPersistent', 'DireccionPersistent']) then begin Result := [psBasic]; end else begin Result := inherited PropertySections(PropertyName); end; end; |
Preparando el editor
Por último debemos indicar el editor que hago uso de nuestro componente. Para ello abre el archivo CastleEngineManifest.xml que esta en la carpeta del proyecto. Añade, sino existe, la entrada editor_units, tal como parece en el código más abajo y guárdalo.Observa el código. Si el propiedad se llama igual que algún elemento de la lista que hemos indicado entre corchetes, devuelve psBasic de lo contrario devuelve lo indique la clase padre.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<project name="Ghost1" standalone_source="Ghost1_standalone.dpr" game_units="GameInitialize" qualified_name="com.mycompany.Ghost1" caption="Ghost and Goblins " editor_units="gamezombiesbehavior" > <compiler_options> <search_paths> <path value="code/" /> <path value="code/enemigos" /> </search_paths> </compiler_options> </project> |
Si quisieras añadir más componentes, ponlos dentro de las comillas separados por comas.
Ahora desde el editor, en el menú Project, selecciona Restart Editor (With Custom Components)

Con ello, el editor de volverá a compilar y se abrirá de nuevo. Tras ello, pulsa con el botón derecho sobre el zombie y selecciona Add Behaivor (Extense Parente Transform), y después selecciona Zombie(TZombieBehaivor)

Y si lo seleccionas, a la derecha podrás ver sus propiedades, que hemos definido anteriormente.

Probando.
Ahora solo queda borrar las líneas de código dónde definíamos el zombie y lo inicializabamos. Bórralo de la sección Published dentro de la unidad GameViewMain.

Y dentro del procedimiento Start de la unidad GameViewMain.
Ahora solo queda añadir los sprites zombie que queramos, desde el editor, añadirles el comportamiento que hemos creado, ajustar su valores y compilar.
Conclusiones
En este capítulo hemos visto como podemos integrar el comportamiento (behavior) que hemos creado, en el editor. Esto nos abre muchas posibilidades, ya que se pueden ampliar la clase con múltiples propiedades y configurarlas desde el editor, evitando en trabajo tedioso de tener que programar la asignación de este comportamiento a todos y cada uno de los sprites que desemos.
Tienes el código disponible en el github.
Saludos
