Differences

This shows you the differences between the selected revision and the current
version of the page.


es:kbase:inside_the_brain_and_body_of_your_game 2010/03/17 21:55 es:kbase:inside_the_brain_and_body_of_your_game 2010/03/18 21:38 current
Line 1: Line 1:
====== Dentro del cerebro y el cuerpo de tu juego ====== ====== Dentro del cerebro y el cuerpo de tu juego ======
-Si estás leyendo te preguntarás acerca de los mecanismos que existen bajo WME, o eres Mnemonic comprobando las meteduras de pata que escribo :-).+Si estás leyendo esto te preguntarás acerca de los mecanismos que existen bajo WME, o eres Mnemonic comprobando las meteduras de pata que escribo :-).
Hoy he decidido guiarte a través de los scripts que incluyen los ejemplos de WME y mostrarte cómo funcionan. Pero empecemos, porque hay bastantes cosas que cubrir. Hoy he decidido guiarte a través de los scripts que incluyen los ejemplos de WME y mostrarte cómo funcionan. Pero empecemos, porque hay bastantes cosas que cubrir.
Line 30: Line 30:
</code> </code>
-So when you thing in your game about some possible string manipulation, which will be then translatable, better use this function from the very beginning.+Así que, cuando pienses en manipular cadenas de texto que serán traducidas a otros idiomas, lo mejor es usar esta función al principio.
-Ok, this having off the table, let's move into **scripts** folder. There you will find three include files. These are **base.inc**, **const.inc** and **keys.inc**.+Bien. Ahora nos vamos a ir a la carpeta **scripts**. Aquí encontrarás tres archivos include. Estos son **base.inc**, **const.inc** y **keys.inc**.
-The **base.inc** is by default included to all scripts you create and it should contain global variables for the whole game. I wrote more about that in my Variables and Objects tutorial. **base.inc** already includes the other file which is called **const.inc** which contains constants for the whole game and is wise to be split from variables. Note that they are also variables but will be reinitialized during each script inclusion. So don't fall into that trap initializing some global variable which is not meant to be constant in **base.inc** file. You would make a nice constant out of it. ;-) **keys.inc** is definition of some of more special keycodes. Luckily for us Mnemonic already find the numbers for us and thus saved us some hassle.+**base.inc** está incluído por defecto en todos los scripts que creas, y debe contener las variables globales del juego. He escrito sobre esto en el tutorial [[variables_and_objects|Variables y objetos]]. **base.inc** también incluye el archivo **const.inc**, que tiene las constantes del juego y es mejor mantenerlas separadas de las variables. Ten en cuenta que también son variables, pero son reiniciadas en cada inclusión de script. Así que no caigas en la trampa de crear una variable global (que no va a ser constante) en **base.inc**. De lo contrario, haría una bonita constante con ella. ;-) **keys.inc** es para la definición de algunos códigos de teclado especiales. Afortunadamente, Mnemonic ya encontró estos números y nos ha ahorrado algunos problemas.
-Having our include files resolved, let's move to some more serious topic. When our WME game starts, it initializes the main **Game** object and executes the script which is attached to it. (you can change this script filename in Project Manager on the left side in Game Settings -> Scripts). This is the where we do start so open this file and let's look at it step by step.+Una vez resuelto el tema de los archivos include, vamos a algo más serio. Cuando nuestro juego arranca, WME inicializa el objeto **Game** principal y ejecuta el script que tiene vinculado (puedes cambiar el nombre de este archivo en el Project Manager, en la ventana izquierda, en Game Settings -> Scripts). Aquí es donde comenzamos, así que abre el archivo y vamos a echarle un vistazo línea a línea.
<code script> <code script>
-#include "scripts\base.inc" // just basic stuff+#include "scripts\base.inc" // cosas básicas
#include "scripts\keys.inc" #include "scripts\keys.inc"
Line 46: Line 46:
</code> </code>
-We include also **keys.inc** file, because we will do some keycode comparison and symbolic names are way more easy to cope with than just some numbers.+También incluímos el archivo **keys.inc**, porque vamos a comparar algunos códigos de teclado y los nombres simbólicos son más fáciles de recordar que los números.
-Next two global variables initialization (you should know them from base.inc where there are defined) is there for convenience mainly because WME doesn't support nesting so you can't write //Game.Scene.GetEntity();// for example.+A continuación, inicializamos dos variables globales (debes conocerlas de base.inc, donde están definidas), y lo hacemos así porque WME no soporta anidar funciones, así que no puedes escribir //Game.Scene.GetEntity();// por ejemplo.
<code script> <code script>
-// load the right-click menu+// carga el menú del botón derecho del ratón
global WinMenu = Game.LoadWindow("interface\menu\menu.window"); global WinMenu = Game.LoadWindow("interface\menu\menu.window");
WinMenu.Visible = false; WinMenu.Visible = false;
-// load the "caption" window+// carga el título de la ventana
var win = Game.LoadWindow("interface\system\caption.window"); var win = Game.LoadWindow("interface\system\caption.window");
global WinCaption = win.GetWidget("caption"); global WinCaption = win.GetWidget("caption");
-// load the demo hints+// carga las pistas de la demo
global WinHints = Game.LoadWindow("interface\demo\demo_hints.window"); global WinHints = Game.LoadWindow("interface\demo\demo_hints.window");
WinHints.Visible = true; WinHints.Visible = true;
-// load credits fader+// carga los créditos
global WinCredits = Game.LoadWindow("interface\credits\credits.window"); global WinCredits = Game.LoadWindow("interface\credits\credits.window");
WinCredits.Visible = true; WinCredits.Visible = true;
Line 70: Line 70:
</code> </code>
-Although it's commented already by Mnemonic I will only note that window behavior is defined in window files and don't look for those things in the **game.script**, they are already attached to windows through separate files. Lastly we prepared empty object with what we will deal later. +Además, ya ha sido comentado por Mnemonic, el comportamiento de la ventana se define en los archivos de la ventana, no en **game.script**, y están vinculados a las ventanas a través de archivos separados. Por último, hemos preparado un objeto vacío con el que trabajaremos más tarde.
<code script> <code script>
-// load our main actor+// carga nuestro actor principal
actor = Game.LoadActor("actors\molly\molly.actor"); actor = Game.LoadActor("actors\molly\molly.actor");
Game.MainObject = actor; Game.MainObject = actor;
</code> </code>
-Ok, now we see, that MainObject is our main actor, but we can load as many actors as we wish and then just switch them in the Game.MainObject so we achieve the main actor switching. Also note that for realtime models you need to use //Game.LoadActor3D();// instead.+Ahora vemos que MainObject es nuestro actor principal, pero podemos cargar tantos actores como deseemos y cambiar entre ellos con Game.MainObject, así conseguimos el cambio de actor principal. Ten en cuenta que para los modelos en tiempo real necesitas usar //Game.LoadActor3D();// en su lugar.
-Now we come to the really important line:+Y ahora, vayamos a la línea más importante:
<code script> <code script>
-// run the "daemon" script+// ejecuta el script "daemon"
Game.AttachScript("scripts\game_daemon.script"); Game.AttachScript("scripts\game_daemon.script");
</code> </code>
-As you may know already, if we attach script to Game object, it is valid for the whole game so these are typically scripts which we use during the course of the whole game. We can attach them as many as we wish, but in this demo, there is just one. We'll have a closer look on it soon.+Como debes saber, si vinculamos un script al objeto Game, será válido para todo el juego así que los scripts que definamos aquí serán usados durante toda la aventura. Podemos vincular tantos como deseemos, pero en esta demo sólo hay uno. Ya le echaremos un vistazo de cerca más adelante.
<code script> <code script>
-// initial items+// objetos iniciales
Game.TakeItem("money"); Game.TakeItem("money");
</code> </code>
-Again it's self explanatory, but just remember to have a main actor already attached before trying to give him some money. +De nuevo, está bastante claro. Pero recuerda que debes tener un actor principal vinculado antes de intentar darle dinero ("money").
<code script> <code script>
Line 100: Line 100:
</code> </code>
-Finally we get to something presentable, we load our first scene, which is defined in the Scene Manager. Next part of the **game.script** is some handler definition for the whole game.+Al final conseguimos algo presentable: cargamos nuestra primera escena que está definida en el Scene Manager. La siguiente parte del **game.script** es la definición de los eventos del juego.
<code script> <code script>
on "LeftClick" on "LeftClick"
{ {
-  // what did we click?+  // ¿qué hemos seleccionado?
  var ActObj = Game.ActiveObject;   var ActObj = Game.ActiveObject;
  if(ActObj!=null)   if(ActObj!=null)
  {   {
-    // clicking an inventory item+    // seleccionando un objeto del inventario con el ratón
    if(ActObj.Type=="item" && Game.SelectedItem==null)     if(ActObj.Type=="item" && Game.SelectedItem==null)
    {     {
      Game.SelectedItem = ActObj;       Game.SelectedItem = ActObj;
    }     }
-    // using an inventory item on another object+    // usando un objeto del inventario sobre otro
    else if(Game.SelectedItem != null && Game.SelectedItem!=ActObj)     else if(Game.SelectedItem != null && Game.SelectedItem!=ActObj)
    {     {
Line 123: Line 123:
      else actor.Talk("I can't use these things together.");       else actor.Talk("I can't use these things together.");
    }     }
-    // just a simple click+    // sólo es un click
    else ActObj.ApplyEvent("LeftClick");     else ActObj.ApplyEvent("LeftClick");
  }   }
-  // else propagate the LeftClick event to a scene+  // de lo contrario, envía el evento LeftClik a la escena
  else   else
  {   {
Line 134: Line 134:
</code> </code>
 +La primera comprobación es para el evento del botón izquierdo del ratón. **Game.ActiveObject** devuelve el objeto que hay bajo el cursor del ratón, así que lo asignamos a una variable. Si es null, quiere decir que no hay ningún objeto, así que enviamos el evento a la escena para casos especiales (como el control de regiones en el archivo scene.script). Si, por el contrario, recibimos un objeto, entonces ejecutamos los if's para saber qué hacer con él. Resumiendo: si el objeto está en el inventario, lo asignamos como objeto activo para manipularlo después. Si pinchamos con un objeto del inventario sobre otro objeto de la pantalla, hacemos otras comprobaciones. Primero nos aseguramos de si el objeto sobre el que pinchamos tiene un método con el nombre del objeto definido. Si tuviésemos una manzana en la pantalla, cogemos un cuchillo del inventario y lo usamos sobre la manzana, entonces es de esperar que haya un controlador ** on "cuchillo" {} **.
-Our first handler is for the Left mouse click. **Game.ActiveObject** returns the object which is currently under the mouse cursor, so we assign it to some variable. If it's null which means there is no object under the cursor, we send the event to the Scene for some special cases (like region based handling in scene.script file). If we on the other hand recieve some object we then go through the few if's as what to do with the object, although it's selfexplanatory I just recapitulate: if the object is inventory item inside the inventory box, we assigned it as an active object for further manipulation. If we click with the inventory item on some other item on the screen, we first check some handlers. First one is if the object we clicked on has a method by the name of the item defined. If we had an apple on the screen, took the knife from inventory and use it on apple, it would then expect some ** on "knife" { } ** handler. +La parte del Else If tiene un evento definido como **on "default-use" { } ** (uso por defecto), y será ejecutado (puede ser utilizado para acciones por defecto, como "¡no quiero cortar eso!" o "¡está ATASCADA!") si la acción que queremos hacer no está definida en el objeto. El juego buscará el evento **on "default-use" { } **, si no existe mostrará algún mensaje estándar como //No puedo usar estas cosas juntas.//.
- +
-Else if Item in its script has **on "default-use" { } ** handler defined, it will be executed (It can be used for some default actions, like I don't want to cut that! or It's STUCK!) If this isn't defined for the Item, game looks for  **on "default-use" { } ** handler  of the object we clicked on. If this doesn't exist, it just issue some standard line like //I can't use these things together.// in our case. +
- +
-If we clicked on the object without any inventory item attached, we just send a Left click event to the script attached to the region  +
-(It will then expect on "LeftClick" {} defined for doing anything).+
 +Si pinchamos en un objeto sin haber seleccionado otro objeto del inventario, entonces enviaremos un evento "LeftClick" al script vinculado a la región (es de esperar que tenga definido el evento **on "LeftClick" {}** para poder hacer algo).
<code script> <code script>
on "RightClick" on "RightClick"
{ {
-  // if inventory item selected? deselect it+  // ¿está seleccionado el objeto del menú? deselecciónalo
  if (Game.SelectedItem != null)   if (Game.SelectedItem != null)
  {   {
Line 155: Line 152:
  var ActObj = Game.ActiveObject;   var ActObj = Game.ActiveObject;
-  // is the righ-click menu visible? hide it+  // ¿es visible el menú del botón derecho del ratón? ocúltalo
  if(WinMenu.Visible == true) WinMenu.Visible = false;   if(WinMenu.Visible == true) WinMenu.Visible = false;
  else if(ActObj!=null)   else if(ActObj!=null)
  {   {
-    // if the clicked object can handle any of the "verbs", display the right-click menu+    // si el objeto seleccionado puede manejar alguno de los "verbos", muestra el menú del botón derecho del ratón
    if(ActObj.CanHandleEvent("Take") || ActObj.CanHandleEvent("Talk")     if(ActObj.CanHandleEvent("Take") || ActObj.CanHandleEvent("Talk")
    || ActObj.CanHandleEvent("LookAt"))     || ActObj.CanHandleEvent("LookAt"))
    {     {
-      // store the clicked object in a global variable MenuObject+      // almacena el objeto seleccionado en la variable global MenuObject
      MenuObject = Game.ActiveObject;       MenuObject = Game.ActiveObject;
      var Caption = WinMenu.GetWidget("caption");       var Caption = WinMenu.GetWidget("caption");
      Caption.Text = MenuObject.Caption;       Caption.Text = MenuObject.Caption;
-      // adjust menu's position+      // ajusta la posición del menú
      WinMenu.X = Game.MouseX - WinMenu.Width / 2;       WinMenu.X = Game.MouseX - WinMenu.Width / 2;
      if(WinMenu.X < 0) WinMenu.X = 0;       if(WinMenu.X < 0) WinMenu.X = 0;
Line 179: Line 176:
          WinMenu.Y = Game.ScreenHeight-WinMenu.Height;           WinMenu.Y = Game.ScreenHeight-WinMenu.Height;
-      // and show the right-click menu+      // y muestra el menú del botón derecho del ratón
      WinMenu.Visible = true;       WinMenu.Visible = true;
-      // stop the actor from whatever he was going to do+      // detiene al actor independientemente de lo que fuera a hacer
      actor.Reset();       actor.Reset();
    }     }
Line 190: Line 187:
</code> </code>
-This is so well commented that again I am just stating the obvious. First we deselect potentional Inventory Item when we issue a right click. Then we check if our Right Click  menu is not visible. If it is, it gets hidden. If we didn't click on any assigned regions on screen, we just forward the right click to the scene (as we did with the left click before). The biggest code portion is that if we actually can do anything with the region (it supports some of the handlers like Take, Talk or LookAt) we show the menu. There is some obvious positioning of the menu on the screen and lastly it stops the actor.+El código está comentado y es bastante claro. Primero, deseleccionamos el objeto del inventario cuando pulsamos el botón derecho del ratón. Comprobamos si el menú del botón derecho es visible. Si lo es, lo oculta. Si no hemos pinchado en alguna región asignada, enviamos el evento a la escena (como hicimos con el botón izquierdo). La parte más grande de código comprueba que si hay algo que podamos hacer con la región en la que hemos pinchado (soporta algunas acciones como Coger, Hablar o Mirar a), entonces mostramos el menú. También se posiciona el menú en la pantalla y, por último, detiene al actor.
<code script> <code script>
on "Keypress" on "Keypress"
{ {
-  // on Esc or F1 key+  // pulsando Esc o F1
  if(Keyboard.KeyCode==VK_ESCAPE || Keyboard.KeyCode==VK_F1)   if(Keyboard.KeyCode==VK_ESCAPE || Keyboard.KeyCode==VK_F1)
  {   {
-    // load and display the main menu window+    // carga y muestra la ventana del menú principal
    WinCaption.Visible = false;     WinCaption.Visible = false;
    var WinMainMenu = Game.LoadWindow("interface\system\mainmenu.window");     var WinMainMenu = Game.LoadWindow("interface\system\mainmenu.window");
Line 208: Line 205:
</code> </code>
-Another handler handles all keystrokes (see our handy key symbolic names?). We just (upon escape or F1) load the Main Menu (load, save, exit etc), center it on the screen and switch to exclusive mode which means, that everything else is stopped until this window  ends. When we close the menu window, it gets unloaded again.+Esta función controla las pulsaciones de teclado (¿has visto nuestros útiles nombres para las teclas?). Lo que hacemos (pulsando Escape o F1) es cargar el Menú Principal (cargar, guardar, salir, etc.), centrarlo en la pantalla y cambiar al modo exclusivo. Esto significa que todo se detiene hasta que se cierre la ventana. Cuando se cierra el menú, se descarga de la memoria.
-Last handler (phewwww) of the **game.script** is just handling the quit dialog and game quitting.+La última función de eventos de **game.script** sirve para controlar el menú de salida y cerrar el juego.
<code script> <code script>
on "QuitGame" on "QuitGame"
{ {
-  // on Alt+F4 (window close+  // con Alt+F4 (se cierra la ventana
-  // load and display the quit confirmation window+  // carga y muestra la ventana de confirmación de salida
  WinCaption.Visible = false;   WinCaption.Visible = false;
  var WinQuit = Game.LoadWindow("interface\system\quit.window");   var WinQuit = Game.LoadWindow("interface\system\quit.window");
Line 222: Line 219:
  WinQuit.GoSystemExclusive();   WinQuit.GoSystemExclusive();
-  // and if the user selected Yes+  // y si el usuario elige Sí
  if(WinQuit.xResult)   if(WinQuit.xResult)
  {   {
-    // quit the game+    // sale del juego
    Game.QuitGame();     Game.QuitGame();
  }   }
-  // otherwise just unload the quit window from memory+  // ed lo contrario, borra de la memoria y cierra la ventana
  else Game.UnloadObject(WinQuit);   else Game.UnloadObject(WinQuit);
} }
</code> </code>
-As you can see, it works similary to Main Menu window and when we clicked on yes, it sets xResult to true so **Game.QuitGame();** is called. Not exactly a rocket science.+Como puedes ver, funciona igual que la ventana del Menú Principal. Si seleccionamos Si, xResult se marca como True y llama a **Game.QuitGame();**. No es física cuántica.
---- ----
-Ok... Still don't have enough? In the second part of this tutorial we will have a look at **game_daemon.script** file. +Bien... ¿todavía no tenéis suficiente? En la segunda parte de este tutorial vamos a echarle un vistazo al archivo **game_daemon.script**.
-You can see that after some declaration it starts with infinite loop. It means that it will just go and on until the game is ended or you Detach the script. Funny part about infinite loops is, that you should end them with some little **Sleep();** or it will take the whole control over the game end results in freezing. Not nice experience... +Puedes comprobar que, después de algunas declaraciones, comienza un bucle infinito. Eso quiere decir que se ejecutará hasta que el juego acabe o se desvincule el script. La parte más divertida de los bucles infinitos es que debes detenerlos con la instrucción **Sleep();** o tomarán el control del juego que se acabará colgando. No es una experiencia agradable...
<code script> <code script>
-  // save the active object for later+  // guarda el objeto activo para recuperarlo más tarde
  var ActObj = Game.ActiveObject;   var ActObj = Game.ActiveObject;
-  // handle the standard foating caption+  // maneja el rótulo flotante estándar
  if(Game.Interactive && ActObj!=null)   if(Game.Interactive && ActObj!=null)
  {   {
Line 253: Line 250:
      WinCaption.Text = ActObj.Caption;       WinCaption.Text = ActObj.Caption;
-      // keep the caption on screen+      // mantiene el rótulo en pantalla
      WinCaption.SizeToFit();       WinCaption.SizeToFit();
Line 263: Line 260:
</code> </code>
-First portion of the daemon handles with the Captions when you hover with a mouse over some defined regions with no inventory item attached. It positions it, assign a caption according to caption defined in Scene Edit, scales it and prepares it. +La primera parte del código controla los rótulos que aparecen cuando pasas el ratón sobre algunas regiones sin tener seleccionado un objeto del inventario. Se posiciona, asigna el rótulo que esté definido en Scene Edit, lo escala y lo prepara.
<code script> <code script>
-    // handle the caption when you want to use an object with another+    // maneja los rótulos cuando quieres usar un objeto con otro
    else     else
    {     {
Line 281: Line 278:
</code> </code>
-If you on the other hand have some item assigned, the caption is prepared in a manner of **Use knife with apple**. Again it is pretty obvious from the code itself. Common denominator is that Caption is displayed and gets focus. If we are over empty space with no inventory item in hand we hide the caption with **WinCaption.Visible = false;**. So much for captions.+Si, por otro lado, tienes un objeto asignado, el rótulo es preparado de la siguiente manera: **Usar cuchillo con manzana**. De nuevo, el código es bastante explicativo. El común denominador es que el rótulo es mostrado y consigue el foco. Si estamos sobre un lugar vacío y no tenemos un objeto de inventario en la mano, ocultamos el rótulo con la instrucción **WinCaption.Visible = false;**. Ya es bastante para los rótulos.
-Last portion of the daemon is to handle the inventory behavior. +La última parte controla el inventario.
<code script> <code script>
Line 292: Line 289:
</code> </code>
-If we position mouse into upper part of the screen, we show the inventory (provided the game is in interactive mode, main menu is not visible, and we are not in dialogue mode). When we get out of the inventory box or we are in the dialogue mode or game is not interactive, we hide it. It's a bit crude and you should look at **faq** on some inventory handling tips. +Si movemos el ratón a la parte superior de la pantalla, mostramos el inventario (mientras el juego no esté en modo interactivo, el menú principal no sea visible y no estemos en modo diálogo). Cuando salimos del inventario, entramos en modo diálogo o el juego no es interactivo, lo ocultamos. Es un poco lioso y deberías mirar en [[es:FAQ|Preguntas y respuestas]] para conocer algunos trucos al manejar el inventario.
-Lastly the aformentioned Sleep is issued and we are set.+Finalmente, ejecutamos la instrucción Sleep que mencionamos antes.
-That concludes it for this tutorial and I hope you'll find it at least a bit useful.+El tutorial finaliza aquí y espero que lo encuentres útil.
 
es/kbase/inside_the_brain_and_body_of_your_game.1268859352.txt.gz · Last modified: 2010/03/17 21:55 by saboteur
Recent changes RSS feed Creative Commons License Driven by DokuWiki