====== Variables and Objects ====== Started by: metamorphium Date: 21. 8. 2005 Prerequisities: WME development kit installed Welcome to my first tutorial. It will be focused on working with variables and objects in WME scripting language. Since the topic is theoretical I will start with some theory to be sure that I won't loose you later down the road. First let's recap some obvious things. Think of variable as of some form of **container** used to store some information. What information you store into it is entirely up to you. WME script is very forgiving, giving you a universal variable into which you can store anything you like (it is dynamically typed, in computer science terms). So let's look at this closer. Fire up your WME Project Manager and create a new project there. Mine is called **ObjectsTutorial**. You will see that in //Scenes// there is a new scene called Room. Try to run your project with **F5** and it should show you green screen with Molly in the middle. Alt+F4 to end it quickly and let's get to work. Go to your project directory and open file scene_init.script located in **data/scenes/Room/scr/scene_init.script** for writing. A Variable is declared using the keyword **var** or **global**, which determines the scope in which the variable will be valid. We will come to that later. For now ignore what is in the file. Add the following code immediately under the line **#include "base.inc"**: var my_variable; //First local variable created Since I was speaking about the single variable type in the sense that you can feed whatever you want into your script, we can easily test it. From now on append all examples below so your scene_init.script file will grow larger and larger. It will make you a nice reference in case you forget anything later. my_variable = 1; // First we assign a number to our variable my_variable = my_variable * 500; // Perform some numeric operation on it Game.Msg(my_variable); // Prints out the value (a number) assigned to our variable my_variable = "Hello World"; // Now we assign a string to our variable Game.Msg(my_variable); // Prints out the string we just assigned If you run your test now you will see that it works and that a variable can hold whatever type you assign it. Additionally, you can change what type of value is stored in your variable at any time. Since most of you already knew this part I am moving to something more interesting: **Arrays**. Basically, an Array is a field of variables which can help us in access automation. We will again use our nice variable to do that job for you so let's look at the quick (non object) way how to create simple array: // Each variable in array is indexed by number and it starts from 0. //This you must remember otherwise other coders will hate you. my_variable[0] = "Today is Wednesday"; my_variable[1] = "Tomorrow is Wednesday as well"; my_variable[2] = "Everyday is Wednesday"; Now we can print these texts either using the Game.Msg(my_variable[0]); etc. or we can use more elegant way through the loop: for (var a = 0; a < 3 ; a = a+1) { Game.Msg(my_variable[a]); //variable a will get the value of numbers from 0 //to 2 thanks to **for** loop construct } Again you can test it by running WME project and when you get back, we will move to some more complicated things. ...(tm) Ok. I presume that you're back and know how all these necessary things works so we will now start with something more interesting. I was speaking at the begining about using keyword **var** and **global**. This is one of the key things to understand for successful scripting. Basically by using these keywords, you declare the scope in which the variable is **unique**. The local variable is valid in **one script file** -> the one you defined it in. The global variable is valid for the whole game. So if you want your game to remember what was going even after script ended, you should use global variable. We will again look at it using example. Open your script called **game.script** located in data/scripts and just below the include lines enter the following: global my_global = "Hi, I am your global variable!"; Now go back to your **scene_init.script** and append the following: global my_global; Game.Msg(my_global); **!!This is important!! If you use global variables they MUST be declared using the global keyword in every script you are using them. Otherwise it won't work and you will end up with script compiler errors. I will present my own solution to keeping this easy later.** So just for the record - we created global variable in game.script and set some value into it. Than we printed the value on screen in scene_init.script file. Using globals is the only way how to achieve this. On the other hand the global variable name must be unique for the whole game. If you use **var** you can have variable called for example //test// in every single file. Don't do that if you have global variable of this name. I was debugging a few WME projects and this bug was present there: global variable overridden by some local variable of the same name. Try to keep your code clean as much as possible and chances that your project will be finished will rapidly grow. Ok. I promised you, that I will say you my way how I keep globals organized in my project. It's some sort of love or hate thing so either it can help you or you'll never use it. It's entirely up to you. So here goes: In the folder **data/scripts** you will find file called **base.inc**. This file is included into every single script file of your game. What I am doing myself is creating bunch of well named inc files and put all globals there. Then I (again using the include command) put these files into base.inc and I am sure I won't run into problems with searching for variables later on. So let's adjust our simple global variable to this new scheme. In **data/scripts** create a new file called for example **test.inc** put only one line there: global my_global; //Never ever initialize this in the included file. it will //result in your variable resetting with each single script load and it will //cause you a headache. Now in the **base.inc** file add line which will read #include "scripts\test.inc" In game.script, **remove** the keyword **global** from the line which reads **''global my_global = "Hi, I am your global variable!";''**. Next, remove the line which reads **''global my_global;''** from scene_init.script, otherwise your game will crash on script compiler error (It will cause double definition). And that concludes my way of dealing with globals which lets me easily keep things well organized and traceable. Also I can never override my variable since if I try to define it in some script it gets me script compiler error since the original variable has been already included. But ... we are not done yet. We will move onto the really great field of WME variables - **objects**. Let's start with a simple example as we are used to: Imagine you have a scene with a nice butterfly. This butterfly has some X and Y position on the screen, some name and for example flag which indicates if it's visible or not. Using the traditional way, we should create 4 separate variables we would have need to keep track of. Not with WME! We can use object for it. So let's look at our first simple object. Go back to **scene_init.script** and better start some more appending: var butterfly; // we know this already //now the fun begins: butterfly.X = 100; butterfly.Y = 200; butterfly.Name = "beautiful butterfly"; butterfly.Active = false; If we try our favorite ''Game.Msg(butterfly);'' It will write on the screen word "[object]". This is a sign that our endeavor was successful and that we have our neat object done. If we need to access the values we simply print them using Game.Msg(butterfly.X); Game.Msg(butterfly.Y); Game.Msg(butterfly.Name); Game.Msg(butterfly.Active); //Just note that booleans True / False are in Game.Msg() interpreted as yes / no, but you can still ask about them using traditional if ( butterfly.Active ) or if (! butterfly.Active ) constructs. // Trust me that this object organization will help you with better orientation when you will try hard to read five months old scripts and find some particularly nasty bugs in them. Last thing and the most advanced at the same time is the full object as you can use it. WME doesn't support calling functions from one script in another. But it supports calling object functions. These functions are called **methods** and are parts of some script file. We will now put our butterfly example on way higher level. :-) First of all create in the **scr** folder of your room scene file called butterfly.script into this file write the following: method HelloButterfly() { Game.Msg(this.Name); } Then get back to your **scene_init.script** and change the **''var butterfly;''** to var butterfly = new Object("scenes/Room/scr/butterfly.script"); This will cause all methods declared in butterfly.script file to be associated with our variable (now object) and finally we can test the brand new functionality by appending after our butterfly block the following: butterfly.HelloButterfly(); Upon running our tutorial project we will see that objects are a real fun to work with and sooner or later you will learn to love them. They help to keep your project tidy and if you learn to use them properly, you will save yourself lots of stress. I hope that you liked this tutorial aimed at beginners and that it helped you at least a bit with understanding the very basics of WME script.