User Tools

Site Tools


hpl3:community:scripting:angelscript_tutorial

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
hpl3:community:scripting:angelscript_tutorial [2017/06/20 12:47]
abion47 [Inheritance]
hpl3:community:scripting:angelscript_tutorial [2018/04/15 16:37] (current)
abion47 [Variable Types]
Line 379: Line 379:
 Let's start with the //​integral//​ types of AngelScript. These types are meant to hold numbers without decimal points. Let's start with the //​integral//​ types of AngelScript. These types are meant to hold numbers without decimal points.
  
-^ Type Name ^ Value Range ^ Default ​^ +^Type Name ^Value Range ^Default ​| 
-| int8 | -128 to 127 | 0 | +|int8 |-128 to 127 |0 | 
-| int16 | -32,768 to 32,767 | 0 | +|int16 |-32,768 to 32,767 |0 | 
-| int | -2,​147,​483,​648 to 2,​147,​483,​647 | 0 | +|int |-2,​147,​483,​648 to 2,​147,​483,​647 |0 | 
-| int64 | -9,​223,​372,​036,​854,​775,​808 to 9,​223,​372,​036,​854,​775,​807 | 0 | +|int64 |-9,​223,​372,​036,​854,​775,​808 to 9,​223,​372,​036,​854,​775,​807 |0 | 
-| uint8 | 0 to 255 | 0 | +|uint8 |0 to 255 |0 | 
-| uint16 | 0 to 65,535 | 0 | +|uint16 |0 to 65,535 |0 | 
-| uint | 0 to 4,​294,​967,​295 | 0 | +|uint |0 to 4,​294,​967,​295 |0 | 
-| uint64 | 0 to 18,​446,​744,​073,​709,​551,​615 | 0 |+|uint64 |0 to 18,​446,​744,​073,​709,​551,​615 |0 |
  
-These types are categorized based on two factors - size, and signedness. ​+These types are categorized based on two factors - size, and signedness.
  
 The //size// of a type is how much memory it takes up in the program. This size is generally measured in bits. An <​html>​int8</​html>,​ for example, uses 8 bits to store its value, whereas an <​html>​int64</​html>​ uses 64 bits. (The <​html>​int</​html>​ and <​html>​uint</​html>​ types use 32 bits, but as 32 bit the most frequently used size, the "​32"​ part of the names have been chopped off for the sake of convenience.) The //size// of a type is how much memory it takes up in the program. This size is generally measured in bits. An <​html>​int8</​html>,​ for example, uses 8 bits to store its value, whereas an <​html>​int64</​html>​ uses 64 bits. (The <​html>​int</​html>​ and <​html>​uint</​html>​ types use 32 bits, but as 32 bit the most frequently used size, the "​32"​ part of the names have been chopped off for the sake of convenience.)
  
-<​note>​In computer memory, one bit is one switch in the computer'​s memory that can either be on or off. This is considered to have a value of 1 (on) or 0 (off). ​ Stringing these bits together, you can use different combinations of bits to refer to larger and larger values. This is known as the binary system. You can learn more about the binary system [[https://​www.mathsisfun.com/​binary-number-system.html|here]].</​note>​+<​note>​In computer memory, one bit is one switch in the computer'​s memory that can either be on or off. This is considered to have a value of 1 (on) or 0 (off). Stringing these bits together, you can use different combinations of bits to refer to larger and larger values. This is known as the binary system. You can learn more about the binary system [[https://​www.mathsisfun.com/​binary-number-system.html|here]].</​note>​
  
 The //​signedness//​ of a type is whether or not the values in the type can have a sign, or, in other words, whether or not the type supports negative numbers. If you compare <​html>​int8</​html>​ and <​html>​uint8</​html>,​ you'll see that the range of <​html>​int8</​html>​ is -128 to 127, whereas the range of "​uint8"​ is 0 to 255. The number of possible values in both cases is still the same (256 possible values), but the "​signed"​ type has been shifted over so that 0 is in the middle of the range instead of the beginning. The //​signedness//​ of a type is whether or not the values in the type can have a sign, or, in other words, whether or not the type supports negative numbers. If you compare <​html>​int8</​html>​ and <​html>​uint8</​html>,​ you'll see that the range of <​html>​int8</​html>​ is -128 to 127, whereas the range of "​uint8"​ is 0 to 255. The number of possible values in both cases is still the same (256 possible values), but the "​signed"​ type has been shifted over so that 0 is in the middle of the range instead of the beginning.
Line 399: Line 399:
 Next, we have what are known as the //​floating-point//​ types. These types are for representing numbers with decimal points. Next, we have what are known as the //​floating-point//​ types. These types are for representing numbers with decimal points.
  
-^ Type Name ^ Value Range ^ Smallest Positive Value ^ Maximum Number of Digits ^ Default ​^ +^Type Name ^Value Range ^Smallest Positive Value ^Maximum Number of Digits ^Default ​| 
-| float | +/- 3.402823466e+38 | 1.175494351e-38 | 6 | 0.0 | +|float |+/- 3.402823466e+38 |1.175494351e-38 |6 |0.0 | 
-| double | +/- 1.79769313486231e+308 | 2.22507385850720e-308 | 15 | 0.0 |+|double |+/- 1.79769313486231e+308 |2.22507385850720e-308 |15 |0.0 |
  
 You can see from the table that the floating-point types aren't quite as straight-forward as the integral types. Instead of a nice clean minimum and maximum value, we have a bunch of decimal numbers in scientific notation. This has to do with how floating-point types are stored in memory. That topic is fairly advanced, so I won't go over it here, but if you're curious, the process is described [[https://​www3.ntu.edu.sg/​home/​ehchua/​programming/​java/​datarepresentation.html#​zz-4.|here]]. You can see from the table that the floating-point types aren't quite as straight-forward as the integral types. Instead of a nice clean minimum and maximum value, we have a bunch of decimal numbers in scientific notation. This has to do with how floating-point types are stored in memory. That topic is fairly advanced, so I won't go over it here, but if you're curious, the process is described [[https://​www3.ntu.edu.sg/​home/​ehchua/​programming/​java/​datarepresentation.html#​zz-4.|here]].
Line 411: Line 411:
 There is one more built-in type for AngelScript,​ and it has nothing to do with numbers: There is one more built-in type for AngelScript,​ and it has nothing to do with numbers:
  
-^ Type Name ^ Possible Values ​^ Default ​^ +^Type Name ^Possible Values ^Default ​| 
-| bool | true, false | false |+|bool |true, false |false |
  
 The <​html>​bool</​html>​ type name is short for //​boolean//​. Boolean values are restricted to one of two values: //true// or //false//. Booleans have to do with whether something is or is not. For example, some boolean variables you might store could be: The <​html>​bool</​html>​ type name is short for //​boolean//​. Boolean values are restricted to one of two values: //true// or //false//. Booleans have to do with whether something is or is not. For example, some boolean variables you might store could be:
- +<code =c++>
-<​code=c++>​+
 bool IsLightOn = true; bool IsLightOn = true;
 bool HasPlayerEnteredArea = false; bool HasPlayerEnteredArea = false;
Line 424: Line 423:
 === Special Types === === Special Types ===
  
-Beyond the built-in types of AngelScript,​ there are a number of other types that are specific to HPL3. If you were to go to another game that uses AngelScript (such as Overgrowth),​ chances are that game's modding system won't have these types available (though ​chances are they will have equivalents).+Beyond the built-in types of AngelScript,​ there are a number of other types that are specific to HPL3. If you were to go to another game that uses AngelScript (such as Wolfire'​s ​Overgrowth),​ chances are that that game's modding system won't have these types available (though ​it's possible ​they will have equivalents).
  
-^ Type Name ^ Possible Values ^ Default ​^ +^Type Name ^Possible Values ^Default ​| 
-| [[hpl3/community/scripting/Classes/tString]] | "Hello SOMA" | ""​ | +|[[:hpl3:community:scripting:​classes:​tstring|tString]] |"​Hello SOMA" |<font inherit/inherit;;#​FF0000;;​inherit><​Empty><​/font> ​ |
-| [[hpl3/community/scripting/​Classes/​tID]] | //(See below)// | N/A | +
-| [[hpl3/​community/​scripting/​Classes/​cVector2f]] | (2.0, 3.5) | //All members are 0.0// | +
-| [[hpl3/​community/​scripting/​Classes/​cVector3f]] | (2.0, 3.5, -1.2) | //All members are 0.0// | +
-| [[hpl3/​community/​scripting/​Classes/​cVector4f]] | (2.0, 3.5, -1.2, 6.6) | //All members are 0.0// | +
-| [[hpl3/​community/​scripting/​Classes/​cMatrixf]] | [ 1.0,  2.0,  3.0,  4.0],[ 5.0,  6.0,  7.0,  8.0],[-1.0, -2.0, -3.0, -4.0],​[-5..0,​ -6.0, -7.0, -8.0] | //All members are 0.0// | +
-| [[hpl3/​community/​scripting/​Classes/​cColor]] | cColor_Red | //All members are 0.0// |+
  
-First, we have HPL3'​s ​string typethe <​html>​tString</​html>​. A string ​in programming means a sequence of characters, ​such as letters ​or numbers. ​Together, they may form word or phrase that you can use for your various purposes. (You may remember in the introduction lesson where we used string ​to print words onto the screen.)+In HPL3'​s ​AngelScripta `tString` is a specific flavor of a string, which is a sequence of characters, letters, and numbers. ​It doesn'​t have fixed length, so it can be anything from `"a"​` ​to `"​Greetings,​ sirs, my what a lovely fine evening we have here. Might you fancy a cup of tea?"`.
  
-Next is the <​html>​tID</​html>​ type. This type is used by the HPL3 engine ​to refer to different objects or entities in the game. Each entity is guaranteed a unique ID that points to them(That being said, there are various helper methods with which to refer to entities by their names rather than IDs, so it's unlikely ​that you will have to deal with this type very often.)+The most common way to use a `tString` ​is to store some kind of word or label, such as when you want to display a message on the screen ​that the player will readThere are some handy functions ​that you can use with a `tString`:
  
-There are a number of vector types as well, and each one has to do with how many dimensions it represents<​html>​cVector2f</​html>,​ for example, only deals with two dimensions, similar to if you were working on a 2D graph with X and Y coordinatesSimilarly, the <​html>​cVector3f</​html> ​deals in three dimensions, so it adds a Z coordinate on top of the X and Y of the 2D vector. And as you might expect, the <​html>​cVector4f</​html>​ deals in four dimensions, so it adds a corresponding W coordinate. +^Function Name ^Description ^Example Usage | 
- +|length |Gets the number of characters represented by the string<​html>​int stringLength = tStringValue.length();</​html> ​| 
-Similar to the vector types, there is a matrix type as well, known as <​html>​cMatrixf</​html>​. In theory, a matrix value can have any number of arbitrary rows and columns, but it is optimized ​to be 2x2, 3x3, or 4x4. There are a number of helper methods that work with interactions between matrices and vectors as well, so the linear algebra aficionados out there can do some crazy stuff with them. +|resize |Resizes ​the string ​to be the specified length. (Removes characters ​or adds "null" ​characters ​as necessary.) | <html>tString resizedString ​originalString.resize(5);</html|
- +
-And lastly, there is a color type, <​html>​cColor</​html>​. This type stores its information in four color channels: red, green, blue, and alpha (opacity). Color variables can come in handy when dealing with stuff that uses color, such as working with terminals ​or GUI applications. +
- +
-<​note>​The ​"t" ​in the above types stands for "​type",​ where the "​c"​ stands for "​class"​. The "​t"​ types can generally be used as is, but the "​c"​ types might require you to access the value'​s //members//I go into class members more in Lesson 7, but for now, you can know that you access them using //​dot-notation//​. This means you use the variable name, followed by a period and the name of the member you want to get. These members can be like the following:​ +
- +
-<code=c++> +
-    cVector4f vector; +
-    float x vector.x; +
-    float y = vector.y; +
-    float z = vector.z; +
-    float w = vector.w; +
-     +
-    cColor color; +
-    float red = color.r; +
-    float green = color.g; +
-    float blue = color.b; +
-    float alpha = color.a; +
-</code> +
-  +
-To see the full list of a type's members, go to that type's reference page on this wiki under "​Community -> Scripting -> Classes"​ or by clicking the links in the type table.</​note>+
  
 === Arrays === === Arrays ===
  
-All the types we've been talking about so far have been single-value types - an <​html>​int</​html>​ will store 5 or 3but not both at the same timeThere are occasions where you want to store more than one value at a time, thoughFor example, if you had 10 lights that you wanted to store the brightness levels for, you might do it like this:+In addition to variables that store a single value, ​there is also a type of variable that holds ''​many''​ valuesThese variables ​are called '''​arrays'''​.
  
-<​code=c++>​ +Some languages allow you to create arrays ​that can store anythingbut in AngelScriptarrays can only hold a single ​type. This type is chosen when the array is first declared:
-    float LightLevel0;​ +
-    float LightLevel1;​ +
-    float LightLevel2;​ +
-    float LightLevel3;​ +
-    float LightLevel4;​ +
-    float LightLevel5;​ +
-    float LightLevel6;​ +
-    float LightLevel7;​ +
-    float LightLevel8;​ +
-    float LightLevel9;​ +
-</​code>​ +
- +
-But that looks tediousdoesn'​t it? You would have to look at each variable individuallyand they aren't stored in any way that packages them together for a single ​purposeWhat's more, if you changed the number of lights you had, you would have to then add or delete variables, making sure that you also add or delete where the variables are used. +
- +
-This is where [[hpl3/​community/​scripting/​classes/​array|arrays]] come in. Where other types store a single value, arrays store a collection of values that you can reference by index. For example, take a look at how the above code might be simplified with the use of an array:+
  
 <​code=c++>​ <​code=c++>​
-    ​array<floatlightLevels;+array<intintArray; 
 +array<​bool>​ boolArray;​ 
 +array<​tString>​ stringArray;
 </​code>​ </​code>​
  
-That's it. The 10 lines of code (or 20, or 100, depending on how many lights there are) just got turned into a single line of code. Let's go ahead and look at that code. +In the above example, the type name inside ​the angled ​brackets is the type of value that array can storeFor example, ​the `intArray` can only store integers, and the `stringArray` can only hold string ​values.
- +
-Firstyou have the type name <​html>​array</​html>​. No surprise there, that's how we've been declaring variables ​the whole time up until now. But notice how alongside the "​array"​ there'​s another type name between angle brackets ​<​html><​float></​html>​. This is part of the declaration ​of array typesIt tells the program what type of values are stored in the array. In this case, we have an array that stores <​html>​float</​html> ​values. ​You can have arrays of other types too: +
- +
-<​code=c++>​ +
-    array<​int>​ intValues;​ +
-    array<​bool>​ booleanValues;​ +
-    array<​tString>​ stringValues;​ +
-    array<​cVector3f>​ vectorValues;​ +
-</​code>​+
  
 That's all well and good, but how do you get at the values in the array? That is done using something called //indexer notation//. Let me show you how it works: That's all well and good, but how do you get at the values in the array? That is done using something called //indexer notation//. Let me show you how it works:
Line 514: Line 465:
 In addition to adding a value at a specific index, there are also different ways you can more dynamically access an array. These ways use the array'​s functions, which we will get into in Appendix 2. For now, these are the more useful functions of an array and how they are used: In addition to adding a value at a specific index, there are also different ways you can more dynamically access an array. These ways use the array'​s functions, which we will get into in Appendix 2. For now, these are the more useful functions of an array and how they are used:
  
-^ Function Name ^ Description ^ Example Usage ^ +^Function Name ^Description ^Example Usage | 
-| length | Gets the number of values stored in the array. | <​code=c++>​int length = lightLevels.length();</​code> ​+|length |Gets the number of values stored in the array. |  
-| push_back | Adds a value to the end of the array. (If indices 0-4 are used, the value is stored at index 5.) | <​code=c++>​lightLevels.push_back(1.0);</​code> ​+|push_back |Adds a value to the end of the array. (If indices 0-4 contain values, the new value is stored at index 5.) |  
-| resize | Resizes the array to the specified length, adding or removing values as necessary. ​<​code=c++>​lightLevels.resize(10);</​code> ​|+|resize |Resizes the array to  |
  
 ---- ----
 +
 +\\
  
 ===== Lesson Three: Operators and Expressions ===== ===== Lesson Three: Operators and Expressions =====
Line 2421: Line 2374:
  
 <​note>​The <​html>​TryX</​html>​ technique is a popular one when dealing with situations that need to be specially handled to prevent potential errors from happening. In a situation where a string needs to be converted (aka //parsed//) to a numeric value, for example, the string might not be a valid number (it could contain letters or something). Trying to convert such a string would result in one of two things - success or an error. If the <​html>​TryParse</​html>​ approach was implemented instead, however, then the function would return a boolean value showing whether or not a parsing could be performed and, if so, the result of the parsing is handed back to the caller through an <​html>&​out</​html>​ parameter.</​note>​ <​note>​The <​html>​TryX</​html>​ technique is a popular one when dealing with situations that need to be specially handled to prevent potential errors from happening. In a situation where a string needs to be converted (aka //parsed//) to a numeric value, for example, the string might not be a valid number (it could contain letters or something). Trying to convert such a string would result in one of two things - success or an error. If the <​html>​TryParse</​html>​ approach was implemented instead, however, then the function would return a boolean value showing whether or not a parsing could be performed and, if so, the result of the parsing is handed back to the caller through an <​html>&​out</​html>​ parameter.</​note>​
 +
 +----
 +
 +==== Object Handles ====
  
 ---- ----
Line 2743: Line 2700:
 </​code></​note>​ </​code></​note>​
  
-The power of interfaces comes from the fact that while a class may only inherit from one base class at the most, it may implement as many interfaces as it wants. This comes in handy when you have a class with a large number of traits. If for example, you had a custom array class, you might want to implement a number of interfaces that define what it can do:+The power of interfaces comes from the fact that while a class may only inherit from one base class at the most, it may implement as many interfaces as it wants. ​You can do this by separating the interface names in the class declaration with a comma. Similarly, if a class is inheriting from a base class //and// wants to implement an interface, the class name is given first, followed by the names of the interfaces:​ 
 + 
 +<​code=c++>​ 
 +    class cComplexClass : cBaseClass, iInterfaceA,​ iInterfaceB {} 
 +</​code>​ 
 + 
 +This comes in handy when you have a class with a large number of traits. If for example, you had a custom array class, you might want to implement a number of interfaces that define what it can do:
  
 <​code=c++>​ <​code=c++>​
Line 2774: Line 2737:
 ---- ----
  
 +==== Mixin Classes ====
 +
 +Sometimes, rather than exploiting the benefits of inheritance or interfaces, you merely want to segment some code into pieces in order to maximize code reuse and efficiency. In these cases, AngelScript provides a somewhat unique feature called a //mixin class//. Where inheritance and interfaces are intended to extend a class'​s capabilities or allow for flexibility in cases of variable types, a mixin class is merely intended to provide a class with a pre-defined set of fields and functions.
 +
 +A mixin class is defined with the <​html>​mixin</​html>​ keyword:
 +
 +<​code=c++>​
 +    mixin class MyMixinClass
 +    {
 +        void DoSomething()
 +        {
 +            // Do something
 +        }
 +    }
 +</​code>​
 +
 +This mixin class can now be used in the definition of other classes, which is done in the same way as declaring a base class or interface:
 +
 +<​code=c++>​
 +    class cMyClass : MyMixinClass {}
 +</​code>​
 +
 +Now, as far as other places in your code are concerned, the <​html>​cMyClass</​html>​ has the functions in it that were originally declared in <​html>​MyMixinClass</​html>:​
 +
 +<​code=c++>​
 +    cMyClass obj;
 +    obj.DoSomething();​
 +</​code>​
 +
 +Keep in mind that this is not the same thing as inheritance. With inheritance,​ the derived class //is// the base class (i.e. a "​Circle"​ //is// a "​Shape"​). However, <​html>​cMyClass</​html>​ is not a <​html>​MyMixinClass</​html>​. It is merely taking on the fields and functions of <​html>​MyMixinClass</​html>​ as if they were its own. To illustrate this, see what happens if you try to instantiate a <​html>​MyMixinClass</​html>​ variable with an instance of <​html>​cMyClass</​html>:​
 +
 +<​code=c++>​
 +    MyMixinClass obj = new cMyClass(); // Error
 +</​code>​
 +
 +This code would result in an error because <​html>​cMyClass</​html>​ and <​html>​MyMixinClass</​html>​ are not compatible types. In fact, <​html>​MyMixinClass</​html>​ is not a type at all. It cannot be instantiated,​ nor can variables be declared with it as their type. The only reason it exists is to provide <​html>​cMyClass</​html>​ with its contents. ​
 +
 +This concept is known in programming as //syntactic sugar//, which describes a programming feature that only exists to make life easier for the programmer in their code. Once the code is compiled, the syntactic sugar is specially processed in a way that, if you were to inspect the machine code after the script is compiled, no trace of the sugar would remain.
 +
 +<​note>​I included this section for the sake of completeness,​ but in my opinion, mixin classes are not good to use. When you define code in one place and it gets used in another, that would be better handled with either inheritance or interfaces. If a class is meant to have a set of functions that relate to a behavior, that is what interfaces are for. 
 +
 +The only time I would recommend using a mixin class is for when you are dealing with a particularly massive class and want to break it into pieces for organizational purposes. C# hosts a feature for this express purpose called "​partial classes",​ and I recommend anyone interested in mixin classes to [[https://​www.codeproject.com/​Articles/​709273/​Partial-Classes-in-Csharp-With-Real-Example|read about C#'s partial classes]] to get a feeling for what I think is the best and only legitimate use case for mixin classes.</​note>​
 +
 +----
 ==== Delegates ==== ==== Delegates ====
 +
 +Up until now, you've been using variables to store data of types. These types could be primitive types, such as <​html>​int</​html>​ or <​html>​bool</​html>,​ or they could be object types like <​html>​cVector3f</​html>​ or <​html>​cMatrixf</​html>​. They could be arrays or even names of classes or interfaces that you came up with yourself. What if I told you, though, that you could also use a variable to store a //​function?//​
 +
 +A //​delegate//​ is, in a nutshell, just that - a variable that stores a pointer to a function. The variable can be used to call that function just as though as you were calling it by name directly.
 +
 +=== Funcdef ===
 +
 +Before you can learn how to use delegates, you need to understand what a Funcdef is. Funcdef is short for "​function definition",​ and the basic explanation is that it defines a function "​type"​. Appropriately,​ it is declared using the <​html>​funcdef</​html>​ keyword:
 +
 +<​code=c++>​
 +    funcdef bool FunctionType(int,​ int);
 +</​code>​
 +
 +From this code, you can see that after the <​html>​funcdef</​html>​ keyword, the rest looks like a typical function declaration. One major exception is that the parameters don't have parameter names. That's because the Funcdef only concerns itself with the types of the parameters, and doesn'​t care about their names.
 +
 +After this, <​html>​FunctionType</​html>​ can be used to describe the "​type"​ of any function that shares an identical function signature with it:
 +
 +<​code=c++>​
 +    // This function takes two int parameters and returns a bool, so it matches FunctionType
 +    bool DoSomething(int a, int b)
 +    {
 +        return true;
 +    }
 +</​code>​
 +
 +<​note>​As a general rule, Funcdefs should be declared at the global scope, although there'​s no rule against declaring them in the class scope.</​note>​
 +
 +=== Using Delegates ===
 +
 +Now that we have a Funcdef, we can use it to declare and instantiate a delegate. When declaring a delegate, you use the Funcdef just as you would use a type for a regular variable:
 +
 +<​code=c++>​
 +    funcdef void MyDelegateType(int);​
 +    ​
 +    // ...
 +    // Elsewhere in your code
 +    ​
 +    MyDelegateType @delegate;
 +</​code>​
 +
 +A delegate is a pointer to a function, so it is necessary to declare it as a pointer object (see [[hpl3/​community/​scripting/​angelscript_tutorial#​object_handles|Object Handles]]). From here, you can use the function name of a function to "​assign"​ the function to the delegate:
 +
 +<​code=c++>​
 +    void DoSomething(int a) {}
 +    ​
 +    // ... 
 +    // Elsewhere in your code
 +    ​
 +    delegate = @DoSomething;​
 +</​code>​
 +
 +Similarly to the declaration,​ you must use the handle operator to get the pointer to the function and assign it to the delegate.
 +
 +Now that the delegate has been assigned a function pointer, you can use it as though you were calling the function directly:
 +
 +<​code=c++>​
 +    delegate(5);​ // Calls the DoSomething function that was assigned before
 +</​code>​
 +
 +When creating a delegate for a class function, a slightly different approach is required. Because the function is bound to the instance object of the class, you need to create the delegate using the Funcdef constructor,​ passing a reference to the object'​s function as a parameter:
 +
 +<​code=c++>​
 +    class A 
 +    {
 +        void DoSomething(int a) {}
 +    }
 +
 +    // ...
 +    // Elsewhere in your code
 +    ​
 +    A a;
 +    delegate = MyDelegateType(a.DoSomething);​
 +</​code>​
 +
 +Now that you know how to declare, assign, and use delegates, let me explain why they are useful. Imagine you have a situation where you have a number of functions, and you want to conditionally call one of them based on a value. You could use <​html>​if</​html>​s,​ of course:
 +
 +<​code=c++>​
 +    if (value == 1)
 +    {
 +        Function1():​
 +    }
 +    else if (value == 2)
 +    {
 +        Function2():​
 +    }
 +    // ...
 +    else if (value == 99)
 +    {
 +        Function99():​
 +    }
 +</​code>​
 +
 +That immediately throws red flags, so let's do the sane thing and replace it with a <​html>​switch</​html>:​
 +
 +<​code=c++>​
 +    switch (value)
 +    {
 +        case 1:
 +            Function1();​
 +            break;
 +        case 2:
 +            Function2();​
 +            break;
 +        // ...
 +        case 99:
 +            Function99();​
 +            break;
 +    }
 +</​code>​
 +
 +This code is much more efficient, but we run into another problem. I clipped the code in the example, but imagine if I had actually typed out all 99 cases of that <​html>​if</​html>​ or <​html>​switch</​html>​ code. It would be unsustainably long, to the point that if you had to find any particular case it would be nontrivially cumbersome to do. Not to mention if you later needed to add one, twenty, or a thousand more.
 +
 +In this case, you can instead use a delegate to store the function you want to call:
 +
 +<​code=c++>​
 +    funcdef void StateFunction();​
 +    StateFunction @state;
 +    ​
 +    // ...
 +    // Elsewhere in your code
 +    ​
 +    state = @Function99;​
 +    state();
 +</​code>​
 +
 +<​note>​This approach is commonly used when designing game engines. Because each level of each map of each mode of the game's operation needs to be handled differently,​ using a <​html>​switch</​html>​ block could require thousands of different cases, so it isn't really an option. Instead, the game stores a delegate that points to a function that handles that particular state (such as the main menu, or the pause screen, or level 2-A). 
 +
 +When something happens in the game that changes its state (for example, when the player presses the pause button), the game performs the corresponding assignment to the state delegate. Then when the next time the game refreshes itself, it will automatically call the new function, making a seamless transition into the new state.</​note>​
  
 ---- ----
hpl3/community/scripting/angelscript_tutorial.1497962831.txt.gz · Last modified: 2017/06/20 12:47 by abion47