{"id":1237,"date":"2026-04-20T08:00:00","date_gmt":"2026-04-20T07:00:00","guid":{"rendered":"https:\/\/jorgeturiel.es\/?p=1237"},"modified":"2026-04-17T19:22:29","modified_gmt":"2026-04-17T18:22:29","slug":"ghosts-n-goblins-y-cge-parte-8","status":"publish","type":"post","link":"https:\/\/jorgeturiel.es\/?p=1237","title":{"rendered":"Ghosts \u2018n Goblins y CGE. Parte 8"},"content":{"rendered":"\n<p>El siguiente paso ser\u00eda a\u00f1adir todos los zombies que deseemos y desde el c\u00f3digo ir asignado el comportamiento que hemos creado.<\/p>\n\n\n\n<p>Pero esta tarea es muy tediosa. Ser\u00eda m\u00e1s sencillo usar el editor y asignar la clase, que define su comportamiento, a cada sprite.<\/p>\n\n\n\n<p>Esto es posible creando un componente propio.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p><br>Para \u201cexponer\u201d las propiedades que queremos tener accesibles desde el editor, se deben declarar en la secci\u00f3n <em>published<\/em> de la clase. Nos interesan exponer las propiedades que le asign\u00e1bamos valores cuando cre\u00e1bamos el zombie por c\u00f3digo. Estas son la direcci\u00f3n, la velocidad, y adem\u00e1s vamos a a\u00f1adir la distancia que recorre el zombie.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >  published\n    property Distancia: single read FDistancia write SetDistancia default\n      DefaultDistancia;\n    property DireccionPersistent: TCastleVector3Persistent read FDireccionPersistent;\n    property VelocidadPersistent: TCastleVector3Persistent read FVelocidadPersistent; <\/pre><\/div>\n\n\n\n<p><br>Observa el c\u00f3digo anterior. Declaramos una propiedad llamada <em>Distancia<\/em>, que es de tipo <em>Single <\/em>con un valor por defecto contenido en la variable <em>DefaultDistancia<\/em> declaramos en el parte p\u00fablica de la clase.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >public\n  const\n    DefaultDistancia :single = 50;\n    property Direccion: TVector3 read Fdireccion write Setdireccion;\n    property Velocidad: TVector3 read Fvelocidad write Setvelocidad;<\/pre><\/div>\n\n\n\n<p>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 <em>Published<\/em> ya que no lo permite pascal. Para ello, <em>CGE, <\/em>solucion\u00f3 el problema creando un \u201cclase intermedia\u201d, en este caso para <em>TVector3<\/em>, se cre\u00f3 <em>TCastleVector3Persistent<\/em>.<\/p>\n\n\n\n<p>La gesti\u00f3n de esta clase la debemos realizar en la propiedad create, as\u00ed que a\u00f1adimos, en la secci\u00f3n <em>Public<\/em> de la clase los m\u00e9todos <em>create<\/em> y <em>destroy<\/em>. Recuerda que todo lo que creemos debemos destruirlo.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >   constructor Create(AOwner: TComponent); override;\n   destructor Destroy; override; <\/pre><\/div>\n\n\n\n<p>Dentro de Create, escribimos el c\u00f3digo para gestionar estas clases.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >constructor TZombieBehavior.Create(AOwner: TComponent);\nbegin\n  inherited Create(AOwner);\n  Distancia := DefaultDistancia;\n  Fdireccion := Vector3(-1, 0, 0);\n  FDireccionPersistent := TCastleVector3Persistent.Create(nil);\n  FdireccionPersistent.SetSubComponent(True);\n\n  {$IFDEF FPC}\n  FDireccionPersistent.InternalGetValue := @GetDireccionForPersistent;\n  FDireccionPersistent.InternalSetValue := @SetDireccionForPersistent;\n  {$ELSE}\n  FDireccionPersistent.InternalGetValue := GetDireccionForPersistent;\n  FDireccionPersistent.InternalSetValue := SetDireccionForPersistent;\n  {$ENDIF}\n  FDireccionPersistent.InternalDefaultValue := Direccion;\n\n  Fvelocidad := Vector3(10, 0, 0);\n  FVelocidadPersistent := TCastleVector3Persistent.Create(nil);\n  FVelocidadPersistent.SetSubComponent(True);\n  {$IFDEF FPC}\n  FVelocidadPersistent.InternalGetValue := @GetVelociadForPersistent;\n  FVelocidadPersistent.InternalSetValue := @SetVelocidadForPersistent;\n  {$ELSE}\n  FVelocidadPersistent.InternalGetValue := GetVelociadForPersistent;\n  FVelocidadPersistent.InternalSetValue := SetVelocidadForPersistent;\n  {$ENDIF}\n  FVelocidadPersistent.InternalDefaultValue := Velocidad;\n\nend;               <\/pre><\/div>\n\n\n\n<p>Lo primero que hacemos es asignar a la propiedad <em>Distancia<\/em> su valor por defecto. Lo siguiente es a la propiedad <em>Fdireccion<\/em> es asignarle un valor, este valor ser\u00e1 el que se muestre en el editor, como valor por defecto. Ahora inicializamos la variable<em> FdireccionPersistent<\/em> creando la clase correspondiente. Tras ello indicamos que es un subcomponente pasando el valor <em>true<\/em> al procedimiento <em>SetSubCoomponent<\/em>.<\/p>\n\n\n\n<p>Ya por \u00faltimo, a su propiedad <em>InternalGetValue <\/em>le asignamos el m\u00e9todo <em>GetDireccionForPersistent<\/em> que ser\u00e1 usado para obtener el valor del vector de direcci\u00f3n. Del mismo modo, le asignamos el m\u00e9todo <em>SetDireccionForPersistent<\/em> para asignar valores al vector de direcci\u00f3n.<\/p>\n\n\n\n<p>Los m\u00e9todos son muy sencillos.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >function TZombieBehavior.GetDireccionForPersistent: TVector3;\nbegin\n  Result := Direccion;\nend;  \n\nprocedure TZombieBehavior.SetDireccionForPersistent(const Value: TVector3);\nbegin\n  Direccion := Value;\nend;     \n<\/pre><\/div>\n\n\n\n<p>Repetiremos los misma idea para el resto de propiedades <em>T<\/em><em>V<\/em><em>ector<\/em><em>3<\/em>.<\/p>\n\n\n\n<p>Si queremos aprovechar, e incluir algunas de las propiedades el categor\u00eda <em>Basic<\/em>, debemos declarar la siguiente funci\u00f3n en la secci\u00f3n <em>Public<\/em> de la clase.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >function PropertySections(const PropertyName: string): TPropertySections; override;  \n<\/pre><\/div>\n\n\n\n<p>Este funci\u00f3n contendr\u00e1 el siguiente c\u00f3digo.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >function TZombieBehavior.PropertySections(const PropertyName: string): TPropertySections;\nbegin\n  WritelnLog('Property: ' + PropertyName);\n  if ArrayContainsString(PropertyName, ['VelocidadPersistent',\n    'DireccionPersistent']) then\n  begin\n    Result := [psBasic];\n  end\n  else\n  begin\n    Result := inherited PropertySections(PropertyName);    \n  end;\n\nend; <\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"> Preparando el editor<\/h2>\n\n\n\n<p>Por \u00faltimo debemos indicar el editor que hago uso de nuestro componente. Para ello abre el archivo <em>CastleEngineManifest.xml<\/em> que esta en la carpeta del proyecto. A\u00f1ade, sino existe, la entrada <em>editor_units<\/em>, tal como parece en el c\u00f3digo m\u00e1s abajo y gu\u00e1rdalo.Observa el c\u00f3digo. Si el propiedad se llama igual que alg\u00fan elemento de la lista que hemos indicado entre corchetes, devuelve <em>psBasic<\/em> de lo contrario devuelve lo indique la clase padre.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:xhtml decode:true \" >&lt;project name=\"Ghost1\"\nstandalone_source=\"Ghost1_standalone.dpr\"\ngame_units=\"GameInitialize\"\nqualified_name=\"com.mycompany.Ghost1\"\ncaption=\"Ghost and Goblins \"\neditor_units=\"gamezombiesbehavior\"\n&gt;\n&lt;compiler_options&gt;\n&lt;search_paths&gt;\n&lt;path value=\"code\/\" \/&gt;\n&lt;path value=\"code\/enemigos\" \/&gt;\n&lt;\/search_paths&gt;\n&lt;\/compiler_options&gt;\n&lt;\/project&gt;<\/pre><\/div>\n\n\n\n<p>Si quisieras a\u00f1adir m\u00e1s componentes, ponlos dentro de las comillas separados por comas.<\/p>\n\n\n\n<p>Ahora desde el editor, en el men\u00fa <em>Project<\/em>, selecciona <em>Restart Editor (With Custom Components)<\/em><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"317\" height=\"166\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image.png\" alt=\"\" class=\"wp-image-1240\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image.png 317w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-300x157.png 300w\" sizes=\"auto, (max-width: 317px) 100vw, 317px\" \/><\/figure>\n<\/div>\n\n\n<p><br>Con ello, el editor de volver\u00e1 a compilar y se abrir\u00e1 de nuevo. Tras ello, pulsa con el bot\u00f3n derecho sobre el zombie y selecciona <em>Add Behaivor (Extense Parente <\/em>Transform)<em>,<\/em> y despu\u00e9s selecciona <em>Zombie(TZombieBehaivor)<\/em><br><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"711\" height=\"453\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-1.png\" alt=\"\" class=\"wp-image-1241\" style=\"width:711px;height:auto\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-1.png 711w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-1-300x191.png 300w\" sizes=\"auto, (max-width: 711px) 100vw, 711px\" \/><\/figure>\n<\/div>\n\n\n<p>Y si lo seleccionas, a la derecha podr\u00e1s ver sus propiedades, que hemos definido anteriormente.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"312\" height=\"217\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-2.png\" alt=\"\" class=\"wp-image-1242\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-2.png 312w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-2-300x209.png 300w\" sizes=\"auto, (max-width: 312px) 100vw, 312px\" \/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\"><a><\/a> Probando.<\/h2>\n\n\n\n<p>Ahora solo queda borrar las l\u00edneas de c\u00f3digo d\u00f3nde defin\u00edamos el zombie y lo inicializabamos. B\u00f3rralo de la secci\u00f3n <em>Published<\/em> dentro de la unidad <em>GameViewMain<\/em>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"530\" height=\"198\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-3.png\" alt=\"\" class=\"wp-image-1243\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-3.png 530w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2026\/04\/image-3-300x112.png 300w\" sizes=\"auto, (max-width: 530px) 100vw, 530px\" \/><\/figure>\n<\/div>\n\n\n<p>Y dentro del procedimiento <em>Start<\/em> de la unidad <em>GameViewMain<\/em>.<\/p>\n\n\n\n<p>Ahora solo queda a\u00f1adir los sprites zombie que queramos, desde el editor, a\u00f1adirles el comportamiento que hemos creado, ajustar su valores y compilar.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusiones<\/h2>\n\n\n\n<p>En este cap\u00edtulo 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\u00faltiples propiedades y configurarlas desde el editor, evitando en trabajo tedioso de tener que programar la asignaci\u00f3n de este comportamiento a todos y cada uno de los sprites que desemos.<\/p>\n\n\n\n<p>Tienes el c\u00f3digo disponible en el <a href=\"https:\/\/github.com\/Blueicaro\/GhostAndGoblins_CGE-.git\">github<\/a>.<br>Saludos<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>El siguiente paso ser\u00eda a\u00f1adir todos los zombies que deseemos y desde el c\u00f3digo ir asignado el comportamiento que hemos creado.<br \/>\nPero esta tarea es muy tediosa. Ser\u00eda m\u00e1s sencillo usar el editor y asignar la clase, que define su comportamiento, a cada sprite.<br \/>\nEsto es posible creando un componente propio.<\/p>\n","protected":false},"author":2,"featured_media":1232,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[57,56,61,26,48],"tags":[49,32,23,21,24],"class_list":["post-1237","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-castle-game-engine","category-cge","category-free-pascal","category-programacion","category-videojuegos","tag-castle-game-engine","tag-free-pascal","tag-lazarus","tag-pascal","tag-programacion"],"_links":{"self":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/1237","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1237"}],"version-history":[{"count":5,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/1237\/revisions"}],"predecessor-version":[{"id":1246,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/1237\/revisions\/1246"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/media\/1232"}],"wp:attachment":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1237"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1237"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1237"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}