Translations of this page:

This is an old revision of the document!
—-

4. Commencer un projet

Juste avant nous avons fait des essais sur une démo pré-compilées, Mais maintenant il est tant de revenir à la racine et de créer un nouveau projet complet comme on a envie. Démarrez le gestionnaire de projet et presser Ctrl+N (sinon cliquez sur l’icône nouveau projet (new project)ou choisissez Nouveau projet (New Project) dans le menu Fichiers (File) ). Nommez votre projet comme vous le souhaitez et laissez WME le créer.

Vous pouvez voir que WME a créé un nouveau projet en y mettant quelques éléments prédéfinis ainsi le démarrage de notre nouveau jeu sera plus simple car nous pouvons dès maintenant lancer ce projet minimaliste et ça marche. Ce que nous allons quand même faire, c'est de porter notre attention sur le point avec lequel le jeu commence réellement. Ce point c'est un simple fichier appelé game.script (Qui se trouve dans data→scripts).

Vous pouvez facilement vérifier dans votre gestionnaire de projet, que le jeu a un script attaché à lui et ça ne sera pas une surprise pour vous, que ce script c'est … game.script. Tout simplement dit, la toute première chose que fait WME après avoir initialisées toutes les fenêtres du système c'est d’exécuter ce fichier. Je parle de ça assez largement, parce que je veut que vous compreniez bien la souplesse de WME. A ce niveau rien n'est décidé, à quoi va ressembler le jeu, comment le jeu se joue, etc…

Essayons de découvrir ce que le script du jeu fait par petit blocs:

#include "scripts\base.inc" 
#include "scripts\keys.inc"

D'abord nous intégrons le fichier base.inc, qui contient 3 variables globales - actor, Scene et Keyboard. Comme ça on a pas besoin, dans chaque script, à déclarer global Scene; avant d'appeler par exemple Scene.GetNode();.
Base.inc à son tour, introduit un autre fichier appelé const.inc qui contient les constantes les directions de l'acteur et les alignement de texte. Au cours de la création de notre jeu nous ajouterons des variables globales et des constantes dans ces fichiers pour garder notre jeu bien rangé. Nous pouvons également séparer nos Includes dans plus de fichiers si on est obligé. Le deuxième fichier contient la définition des codes claviers, nous n'avons donc pas à deviner des chiffres mais tapez simplement leur représentation textuelle comme VK_ESCAPE au lieu de 27 si on veut tester la touche Esc.

Keyboard = Game.Keyboard; 
Scene = Game.Scene;

Comme vous devriez déjà le savoir maintenant, tous les objets de base sont membres de l'objet Game. Mais il y a deux raisons pour lesquelles nous avons besoin de variables pour stocker ces objets imbriqués. Premièrement WME ne permet pas les imbrications donc vous ne pouvez pas utiliser par exemple:

var e = Game.Scene.GetNode("Door");

et deuxièmement ça semble, de toute façon, plus clair si vous écrivez Scene.GetNode("Door");.

Donc, retour à ces lignes - Nous avons créé une variable globale Keyboard qui fait référence à l'objet Game.Keyboard et qui sera utilisé pour interrogé les saisies clavier et une variable globale qui fait référence à l'objet Scene.

Comme petite annotation dans la marge - Cet objet est toujours le même, même si vous décidez de changer des scènes ainsi vous n'avez pas à la réassigner à chaque fois que vous avez changé la scène.

global WinMenu = Game.LoadWindow("interface\menu\menu.window"); 
WinMenu.Visible = false;

Par défaut vous avez un truc prédéfini, que si vous faites un clic droit sur ​​un hot-spot, un petit menu apparait dans lequel vous pouvez choisir entre trois actions. Maintenant, faite moi plaisir et dégommer moi ces 2 lignes. Nous allons essayer de le dépouiller.

Vous devez vous demander, qu'est que window (fenêtre)? Window c'est un groupe d'éléments graphique (boutons, images, champs d’édition pour saisir un texte) ce qui est bien pratique pour concevoir un GUI (Interface Graphique pour l'Utilisateur). Le gros avantage c'est que c'est indépendant de la scène, vous pouvez donc l'avoir à l'écran pour toutes les scènes sans avoir à replacé, expressément, les éléments à chaque fois.

Nous verrons la fabrication des fenêtres plus tard, focalisons nous pour le moment sur ce que veulent dire ses deux lignes. La première ligne charge un fichier .window (qui contient une définition de la fenêtre graphique) et la seconde la rend invisible. Cette fenêtre est attachée à l'objet Game donc le changement de scène ne l'affecte pas. Notez que les fenêtres sont des exceptions. Les entités utilise Active, les fenêtres utilise Visible.

var win = Game.LoadWindow("interface\system\caption.window"); 
global WinCaption = win.GetWidget("caption");

Et encore un chargement de fenêtre! Celle-ci est destinée au légendes (infos-bulles) chaque fois que vous passez votre souris sur le hot-spot. De plus, nous introduisons une toute nouvelle méthode pour faire référence à une partie spécifique de la fenêtre. Celui-ci est le champ réel qui contient le texte. Maintenant pour me faire plaisir - GetWidget est l'ancienne manière d'obtenir le contrôle. Maintenant nous utilisons plus facilement GetControl , donc réécrivez moi la seconde ligne en :

global WinCaption = win.GetControl("caption"); //Vous pouvez également constater la similitude Scene.GetNode(name); Window.GetControl(name);

vient ensuite:

global MenuObject = null;


Nous stockons un null dans MenuObject qui sera utilisé plus tard pour voir ce qui est cliqué. Null est une valeur speciale, qui indique qui n'y a absolument rien. Et vous pouvez, aussi bien, effacer cette ligne.

actor = Game.LoadActor("actors\molly\molly.actor"); 
Game.MainObject = actor;

Maintenant ces lignes sont importantes. La variable "actor" est une variable globale dans base.inc qui sera remplis, maintenant, avec la définition de notre fichier .actor. Encore plus tard nous verrons comment les fichiers d'acteur sont construit. Pour le moment vivons avec le fait que nous avons Molly et qu'elle peut faire tout ce qu'on veut.

Aussi en note dans la marge, nous pouvons une deuxième fonction Scene.LoadActor(actor); qui charge l'acteur mais l'attache à la scène courante et l'acteur est détruit quand vous quittez la scène.

La dernière ligne, nous plaçons notre acteur fraichement chargé dans l'attribut MainObject, ce qui fait la seul chose - lorsque l'acteur se déplace et que la scène est censée défiler, le défilement s'oriente vers l'acteur. Au cas ou il y aurait plusieurs acteurs échangeables (Comme par exemple dans Day of the Tentacle) Cet attribut permettra d'avoir un défilement correct quelque soit le personnage sélectionné. Vous pouvez régler Null dans cet attribut.

Game.AttachScript("scripts\game_loop.script"); //anciennement connu comme game_daemon.script

Nous allons fixer le processus clés, qui s'occupe de l'affichage des légendes et de l'apparition de l'inventaire quand vous glissé votre souris en haut. Ce sera notre second fichier que nous allons examiner dans une minute. Là encore vous pouvez voir, que ce fichier est globalement attaché au jeu entier.

Et voici quelque chose autrefois extrêmement important - désormais paramétrable à partir du gestionnaire de projet:

Game.ChangeScene("scenes\Room\Room.scene");

C'est le point où vous définissez à quel scène commence votre jeu. Habituellement ça sera un genre d’écran menu sauf si vous démarrez par une intro. ou du genre. Maintenant vient la partie principale de nettoyage. Comme nous sommes en plein épuration de notre jeu, nous allons maintenant virer toutes les interactions avec l'inventaire seulement pour les ajouter plus tard lorsque nous serons plus qualifiés.

Donc modifiez simplement les événements dans “LeftClick” pour avoir:

on "LeftClick" 
{ 
  var ActObj = Game.ActiveObject; 
  if(ActObj!=null) 
  { 
     ActObj.ApplyEvent("LeftClick"); 
  } 
  else 
  { 
    Scene.ApplyEvent("LeftClick"); 
  } 
}

——————————————
EN COURS DE TRADUCTION
——————————————-

When we left click in the scene, we first look if the click was in the hotspot. WME knows if there is a hotspot under our mouse cursor and fills attribute ActiveObject accordingly.
Now we simplified our logic to two states. If we clicked on an object, we’ll call his “LeftClick” event. This brings us back to our experiments in the last chapter where we assigned the “LeftClick” event to door. This is the reason why that event got called in the first place. ApplyEvent is a method which is used for running events manually.

If we clicked elsewhere (no hotspot under cursor), scene “LeftClick” event is fired. I almost hear you scream now: “Wait a minute. What is a scene “LeftClick” event?!".

This is another trick by WME which comes out of Scene template. If you create a new scene, or open your room scene in scene edit and switch to the Properties tab and click on the "Scripts…" button, you’ll see that there are two scripts attached. Your favorite scene_init.script and scripts/scene.script. And since this is the template every single scene uses, let’s uncover what dark mysteries this file holds?

#include "scripts\base.inc" 
 
on "LeftClick" 
{ 
  actor.GoTo(Scene.MouseX, Scene.MouseY); 
}

HA! That’s it. if this event is fired, our actor goes to the current mouse position in the scene. So it boils down to the simple thing: If we click on a hotspot it’s left click is fired else our actor walks to the current mouse position. And that’s about the LeftClicks for now.

Let’s move on to the next event “RightClick” and erase the whole block. We don’t need it now and it would only make our head spin.

Last two events (“Keypress” and “QuitGame”) deals with menu displaying and handling the alt+f4 combo. We don’t have to bother ourselves with it for now, but rest assured, that we’ll look into them soon too.

Let’s recap new methods and attributes we learned so far in this chapter:

var window = Game.LoadWindow(window filename); - Loads a window definition, attaches it to the Game object and optionally returns a reference to it (in this case to window variable)
window.Visible = true / false; - Makes the loaded window visible/invisible on the screen
window.GetContro(controlname); - Returns a reference to a control stored in the window
Game.LoadActor(actor filename); - Loads an actor from file and attaches it to a game object.
Scene.LoadActor(actor filename); - Loads an actor from file and attaches it to a scene object destroying it after the scene is left.
Game.MainObject = actor; Sets the actor to whom the scene scrolling is synchronized.
Game.ActiveObject; - stores the reference to an object your mouse cursor is currently over.
Game.ApplyEvent(eventName); - is a method which fires the event associated to the Game object
Scene.ApplyEvent(eventName); - is a method which fires the event associated to the Scene object
Node.ApplyEvent(eventName); - is a method which fires the event associated to the node stored in the object in question.

For better understanding the last command, we could easily run in our last chapter the “LeftClick” event of the door elsewhere like this:

var door = Scene.GetNode("Door"); 
door.ApplyEvent("LeftClick");

I hope you got my point now… Let’s also look if you have the same *game.script* file as I do before we proceed:

#include "scripts\base.inc" 
#include "scripts\keys.inc" 
 
// store some of the game's attributes in global variables for convenience 
Keyboard = Game.Keyboard; 
Scene = Game.Scene; 
 
// load the "caption" window 
var win = Game.LoadWindow("interface\system\caption.window"); 
global WinCaption = win.GetControl("caption"); 
 
// load our main actor 
actor = Game.LoadActor("actors\molly\molly.actor"); 
Game.MainObject = actor; 
 
// run the "daemon" script 
Game.AttachScript("scripts\game_daemon.script"); 
 
// which scene to load? 
Game.ChangeScene("scenes\Room\Room.scene"); 
 
 
 
on "LeftClick" 
{ 
  var ActObj = Game.ActiveObject; 
  if(ActObj!=null) 
  { 
     ActObj.ApplyEvent("LeftClick"); 
  } 
  else 
  { 
    Scene.ApplyEvent("LeftClick"); 
  } 
} 
 
on "Keypress" 
{ 
  // on Esc or F1 key 
  if(Keyboard.KeyCode==VK_ESCAPE || Keyboard.KeyCode==VK_F1) 
  { 
    // load and display the main menu window 
    WinCaption.Visible = false; 
    var WinMainMenu = Game.LoadWindow("interface\system\mainmenu.window"); 
    WinMainMenu.Center(); 
    WinMainMenu.GoSystemExclusive(); 
    Game.UnloadObject(WinMainMenu); 
  } 
} 
 
on "QuitGame" 
{ 
  // on Alt+F4 (window close) 
  // load and display the quit confirmation window 
  WinCaption.Visible = false; 
  var WinQuit = Game.LoadWindow("interface\system\quit.window"); 
  WinQuit.Center(); 
  WinQuit.GoSystemExclusive(); 
  // and if the user selected Yes 
  if(WinQuit.xResult) 
  { 
    // quit the game 
    Game.QuitGame(); 
  } 
  // otherwise just unload the quit window from memory 
  else Game.UnloadObject(WinQuit); 
}

Now test the game and you’ll see that it’s still running although we made quite some changes to it. And as we want to continue boiling our example game down to the necessary minimum, we need to look at the game_loop.script (formerly named game_daemon.script) as well.

#include "scripts\base.inc" 
 
global WinCaption; 
global WinMenu;

We can easily delete the line global WinMenu; because we’ve already dropped the idea of right click menu.

while(true){

This will be always true. This way we are looking at the infinite loop. To end this loop, one would have to call Game.DetachScript("scripts\game_loop.script");

var ActObj = Game.ActiveObject;


We’ve seen exactly the same line before in the game script.

 if(Game.Interactive && ActObj!=null) 
 {

So first we test if the game is interactive and our mouse cursor is over some active object. But we’ll make this condition a bit simpler so we’ll put away all inventory items logic and it’ll look like this:

if(Game.Interactive && ActObj!=null) 
{ 
      WinCaption.X = Game.MouseX; 
      WinCaption.Y = Game.MouseY + 20; 
      WinCaption.TextAlign = TAL_LEFT; 
      WinCaption.Text = ActObj.Caption; 
 
      WinCaption.SizeToFit(); 
      if(WinCaption.X + WinCaption.Width > Game.ScreenWidth) WinCaption.X = Game.ScreenWidth - WinCaption.Width; 
      if(WinCaption.Y + WinCaption.Height > Game.ScreenHeight) WinCaption.Y = Game.ScreenHeight - WinCaption.Height; 
 
     WinCaption.Visible = true; 
     WinCaption.Focus(); 
} 
else WinCaption.Visible = false;

So what happens if we have our mouse over the object?

WinCaption.X = Game.MouseX; 
WinCaption.Y = Game.MouseY + 20;

WinCaption contains the reference to the text field inside of the caption window loaded in the game script. We set its position to the same coordinates as our mouse X-position and Mouse Y-position + 20 so it’ll be 20 pixels below.

WinCaption.TextAlign = TAL_LEFT; 
WinCaption.Text = ActObj.Caption;

Then we set text aligning to left and set the text of the caption to the node caption as defined in the scene editor.

WinCaption.SizeToFit();

We resize the caption so its size is the same as the size of the displayed text.

if(WinCaption.X + WinCaption.Width > Game.ScreenWidth) WinCaption.X = Game.ScreenWidth - WinCaption.Width;

If the caption width however extends out of the screen, we set our caption X-position to end exactly with the screen border (based on the resolution).

if(WinCaption.Y + WinCaption.Height > Game.ScreenHeight) WinCaption.Y = Game.ScreenHeight - WinCaption.Height;

We do the same with the height and the bottom border.

WinCaption.Visible = true; 
WinCaption.Focus();

We display our caption by making it visible and give it focus, which is in this case not necessary, because we don’t interact with it. So we can simply delete this line too.

} 
else WinCaption.Visible = false;

The rest means that either the game went into non interactive mode or we moved our mouse out of any active hotspots. In both cases we simply hide the caption.

 if(Game.Interactive && Game.MouseY < 45 && !Game.ResponsesVisible && !WinMenu.Visible) Game.InventoryVisible = true; 
  else if(Game.MouseY > 100 || Game.ResponsesVisible || !Game.Interactive) Game.InventoryVisible = false;

Those two lines deal with inventory showing / disappearing and so we simply delete them.

Sleep(20);

Remember what I’ve told you about infinite loops and hanging computers? Enough said.
So let’s look at our revised game_daemon.script

#include "scripts\base.inc" 
 
global WinCaption; 
 
// infinite loop 
while(true){ 
  var ActObj = Game.ActiveObject; 
 
  if(Game.Interactive && ActObj!=null) 
  { 
      WinCaption.X = Game.MouseX; 
      WinCaption.Y = Game.MouseY + 20; 
      WinCaption.TextAlign = TAL_LEFT; 
      WinCaption.Text = ActObj.Caption; 
      WinCaption.SizeToFit(); 
      if(WinCaption.X + WinCaption.Width > Game.ScreenWidth) WinCaption.X = Game.ScreenWidth - WinCaption.Width; 
      if(WinCaption.Y + WinCaption.Height > Game.ScreenHeight) WinCaption.Y = Game.ScreenHeight - WinCaption.Height; 
     WinCaption.Visible = true; 
  } 
  else WinCaption.Visible = false; 
  Sleep(20); 
}

As you can see, those are the barebones of our starting project. No inventory, no menus, simple point and click game. Moreover you understand now, what’s the brain behind the game and as we build upon it, you’ll feel more comfortable knowing that you have the rock solid background. Next step: the actor!

 
fr/wmebook/ch4.1319032813.txt.gz · Last modified: 2011/10/19 16:00 by Anto0085
Recent changes RSS feed Creative Commons License Driven by DokuWiki