User Tools

Site Tools


hpl2:tutorials:script:funcdef

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
hpl2:tutorials:script:funcdef [2011/08/14 10:23]
thegreatcthulhu
hpl2:tutorials:script:funcdef [2011/08/15 01:09] (current)
apjjm [Solving a basic problem with function pointers]
Line 8: Line 8:
  
  
-The [[http://​www.angelcode.com/​angelscript/​sdk/​docs/​manual/​doc_datatypes_funcptr.html|Angelscript documentation]] states that //"A function pointer is a data type that can be dynamically set to point to a global function that has a matching function signature as that defined by the variable declaration."​ // In other words, you're making a "type"  ​- something like //int // or //string // - but instead of this type's variables containing //text// or //​numbers//,​ it contains functions - or more specifically, ​ pointers to functions . \\  To understand better what a function pointer is: Consider a box, and this box contains a note telling you to look in another box somewhere else - this is your function pointer, it just contains information on where to look. The other box, the one //​referenced,​ // contains the actual functional information. We can use these "extra boxes" to create variables that can be called just like functions.+The [[http://​www.angelcode.com/​angelscript/​sdk/​docs/​manual/​doc_datatypes_funcptr.html|Angelscript documentation]] states that //"A function pointer is a data type that can be dynamically set to point to a global function that has a matching function signature as that defined by the variable declaration."​ // In other words, you're making a **type** - something like //int // or //string // - but instead of this type's variables containing //text// or //​numbers//,​ it contains functions - or more specifically, ​ pointers to functions . \\  To understand better what a function pointer is: Consider a box, and this box contains a note telling you to look in another box somewhere else - this is your function pointer, it just contains information on where to look. The other box, the one //​referenced,​ // contains the actual functional information. We can use these "extra boxes" to create variables that can be called just like functions.
  
  
Line 17: Line 17:
 funcdef void fdSimpleFunction();​ // Used for pointers to functions which take no arguments and return no vales  funcdef void fdSimpleFunction();​ // Used for pointers to functions which take no arguments and return no vales 
 funcdef int  fdReturningFunction();​ // Used for pointers to functions which return an int and take no arguments. funcdef int  fdReturningFunction();​ // Used for pointers to functions which return an int and take no arguments.
-funcdef int  fdComplexFunction(int,​ int);  // Used for pointers to functions which of return type int and take two ints as arguments ​ +funcdef int  fdComplexFunction(int,​ int);  // Used for pointers to functions which of return type int and take two ints as arguments
 </​code>​ </​code>​
  
Line 26: Line 26:
 <code cpp>void sfHelloWorld() {    <code cpp>void sfHelloWorld() {   
     AddDebugMessage("​Hello World!",​ false); ​ // Outputs: Hello World!     AddDebugMessage("​Hello World!",​ false); ​ // Outputs: Hello World!
-+}
 </​code>​ </​code>​
  
Line 34: Line 34:
  
 <code cpp> <code cpp>
-fdSimpleFunction@ functionVar; ​+fdSimpleFunction@ functionVar;​
 </​code>​ </​code>​
  
Line 41: Line 41:
 <code cpp>// We know this line declares our functionVar <code cpp>// We know this line declares our functionVar
 fdSimpleFunction@ functionVar;​ fdSimpleFunction@ functionVar;​
-  ​+ 
 // We now will make this point to sfHelloWorld()! // We now will make this point to sfHelloWorld()!
-@functionVar = @sfHelloWorld; ​+@functionVar = @sfHelloWorld;​
 </​code>​ </​code>​
  
  
-This new line is making //​functionVar//​point to the address of //​sfHelloWorld//​ (in other words, we just put a note in our box saying look into the specific other box for //​sfHelloWorld//​). You are actually saying **"set the handle of function var to the handle of sfHelloWorld"​** - this is why //​functionVar // can be called just like the function, even though it is actually a variable:+This new line is making //​functionVar // point to the address of //​sfHelloWorld//​ (in other words, we just put a note in our box saying look into the specific other box for //​sfHelloWorld//​). You are actually saying **"set the handle of function var to the handle of sfHelloWorld"​** - this is why //​functionVar // can be called just like the function, even though it is actually a variable:
 <code cpp>// If all has gone well: <code cpp>// If all has gone well:
 functionVar();​ functionVar();​
    
 // Does exactly the same as: // Does exactly the same as:
-sfHelloWorld(); ​+sfHelloWorld();​
 </​code>​ </​code>​
  
Line 61: Line 61:
 <code cpp>// Make the type "​fdSimpleFunction"​ <code cpp>// Make the type "​fdSimpleFunction"​
 funcdef void fdSimpleFunction();  ​ funcdef void fdSimpleFunction();  ​
-  ​+ 
 // Output hello world // Output hello world
 void sfHelloWorld() { void sfHelloWorld() {
     AddDebugMessage("​Hello World!",​ false);     AddDebugMessage("​Hello World!",​ false);
 } }
-  ​+ 
 void OnStart() {  void OnStart() { 
     // Call the function normally!     // Call the function normally!
     AddDebugMessage("​Calling the function normally!",​ false);     AddDebugMessage("​Calling the function normally!",​ false);
     sfHelloWorld(); ​     sfHelloWorld(); ​
-  ​+ 
     // Call the function using our variable!     // Call the function using our variable!
     AddDebugMessage("​Calling the function using the pointer!",​ false);     AddDebugMessage("​Calling the function using the pointer!",​ false);
Line 77: Line 77:
     @functionVar = @sfHelloWorld;​     @functionVar = @sfHelloWorld;​
     functionVar();​     functionVar();​
-+}
 </​code>​ </​code>​
  
  
 So far, all we have managed to achieve is something we could have done already! Why go through all this hassle, to just call a function we could have called anyway? The next section shows how the variable aspect of the function can be exploited to solve a basic problem. So far, all we have managed to achieve is something we could have done already! Why go through all this hassle, to just call a function we could have called anyway? The next section shows how the variable aspect of the function can be exploited to solve a basic problem.
 +
  
 ==== Solving a basic problem with function pointers ==== ==== Solving a basic problem with function pointers ====
Line 93: Line 94:
 }    }   
 void subFunction() { void subFunction() {
-    // do something... +    //Implementing later... 
-+}
 </​code>​ </​code>​
  
Line 104: Line 105:
 void output2() { void output2() {
     AddDebugMessage("​Dawg!",​ false);     AddDebugMessage("​Dawg!",​ false);
-+}
 </​code>​ </​code>​
  
Line 113: Line 114:
 <code cpp>// Create a function definition (which is actually the same as fdSimpleFunction) <code cpp>// Create a function definition (which is actually the same as fdSimpleFunction)
 // Which will matches the signature of both our output functions // Which will matches the signature of both our output functions
-funcdef void fdOutput(); ​+funcdef void fdOutput();
 </​code>​ </​code>​
  
  
-With the second step creating the variable which shall initially point to //output1 // at the start of //​bigFunction. // Next we call//​subFunction // as before, which will change the function pointer. Finally, we will call the function pointed to by the pointer:+With the second step creating the variable which shall initially point to //output1 // at the start of //​bigFunction. // Next we call //​subFunction // as before, which will change the function pointer. Finally, we will call the function pointed to by the pointer:
 <code cpp> <code cpp>
 fdOutput @outputChoice;​ fdOutput @outputChoice;​
Line 124: Line 125:
     subFunction();​     subFunction();​
     outputChoice();​     outputChoice();​
-+}
 </​code>​ </​code>​
  
  
-The subFunction implementation is as follows: +The //subFunction// implementation is as follows:
- +
 <code cpp>void subFunction() { <code cpp>void subFunction() {
     if(RandInt(0,​ 3) == 1)      if(RandInt(0,​ 3) == 1) 
Line 136: Line 135:
         @outputChoice = @output2; ​ // A 1 in 4 chance of this code being reached         @outputChoice = @output2; ​ // A 1 in 4 chance of this code being reached
     }     }
-+}
 </​code>​ </​code>​
  
Line 147: Line 146:
 funcdef void fdOutput(); funcdef void fdOutput();
    
-// Our output functions ​/////////// ​+// Our output functions ​
 void output1() { void output1() {
     AddDebugMessage("​Yo!",​ false);     AddDebugMessage("​Yo!",​ false);
Line 154: Line 153:
     AddDebugMessage("​Dawg!",​ false);     AddDebugMessage("​Dawg!",​ false);
  
-///////////////////////////////////​ 
    
 // The actual stuff that does the descision making // The actual stuff that does the descision making
 fdOutput @outputChoice;​ fdOutput @outputChoice;​
 void bigFunction() { void bigFunction() {
-    // Initially point to output 1 +    ​@outputChoice = @output1; ​// Initially point to output 1 
-    ​@outputChoice = @output1       // 1 in 4 of output 2... +    ​subFunction()   // Call with 1/chance ​of changing outputChoice ​
-    subFunction();​ +
- +
     outputChoice(); ​  // Call whichever output has been chosen     outputChoice(); ​  // Call whichever output has been chosen
  
Line 169: Line 165:
     if(RandInt(0,​ 3) == 1)      if(RandInt(0,​ 3) == 1) 
     {     {
-        @outputChoice = @output2; ​   // A 1 in 4 chance of this code being reached+        @outputChoice = @output2; ​   // A 1 in 4 chance of changing the function pointer
     }     }
 } }
    
-void OnStart() { +void OnStart() {      
-    for(int i=0; i<20; i++) bigFunction();  ​// Call bigFunction 20 times - 1/4 chance of output2? +    // Call bigFunction 20 times - notice roughly a 1/4 chance of output2? 
-+    for(int i=0; i<20; i++) bigFunction(); ​  
 +}
 </​code>​ </​code>​
  
Line 188: Line 185:
  
 <code cpp>// This creates a signature called "​SimpleFunction"​ <code cpp>// This creates a signature called "​SimpleFunction"​
-// Which matches functions which take no arguments, and return nothing. +// Which matches functions which take no arguments, and return nothing..
-funcdef void fdSimpleFunction(); ​  +funcdef void fdSimpleFunction(); ​    
-// Such as these example ​functions+// ...such ​as the following sample ​functions
 +// This function will output "hello world"
 void sfHelloWorld() { void sfHelloWorld() {
-    AddDebugMessage("​Hello World!",​ false); ​  // Output hello world+    AddDebugMessage("​Hello World!",​ false);
  
 // This function will output how many times it has been called ​ // This function will output how many times it has been called ​
Line 199: Line 197:
     AddDebugMessage("​DisplayTimesCalled,​ called: " + GetLocalVarInt("​DTC_TimesCalled"​) + " times",​ false);     AddDebugMessage("​DisplayTimesCalled,​ called: " + GetLocalVarInt("​DTC_TimesCalled"​) + " times",​ false);
  
 +//This function will play the sound of an angry brute! ​
 void sfPlayScarySound() { void sfPlayScarySound() {
-    PlayGuiSound("​enemy\\brute\\notice.snt",​ 1.0f); ​  // Play the sound of an angry brute!+    PlayGuiSound("​enemy\\brute\\notice.snt",​ 1.0f);
 } }
 </​code>​ </​code>​
Line 241: Line 240:
     functionToCall();  ​     functionToCall();  ​
    
-    AddLocalVarInt("​simpleFunctionIndex",​ 1);        // Increment the index +    AddLocalVarInt("​simpleFunctionIndex",​ 1);        // Increment the index, so the next function is called shortly... 
-    AddTimer(asTimerName,​ 1.0f, "​callEachFunction"​); ​ // Call this function again in 1 second+    AddTimer(asTimerName,​ 1.0f, "​callEachFunction"​); ​ // Call this function again in 1 second, so the next function is called
 } }
 </​code>​ </​code>​
  
  
-One potential extension for use with sequences is making each function return a float, which can then be used as the delay time before calling the next function. ​Below is a sample script file for this section, don't forget to visit the OnStart routine and uncomment one of the two lines - or you won't see anything+One potential extension for use with sequences is making each function return a float, which can then be used as the delay time before calling the next function. ​The  ​sample script file for this section ​is below, don't forget to visit the OnStart routine and uncomment one of the two lines - or you won't see anything, and additional function is added to loop the //​callRandomSimpleFunction//​ with a timer so it's effects can be seen easier:
- +
 <code cpp>// This creates a signature called "​SimpleFunction"​ <code cpp>// This creates a signature called "​SimpleFunction"​
 // Which matches functions which take no arguments, and return nothing. // Which matches functions which take no arguments, and return nothing.
-funcdef void fdSimpleFunction();​ // Such as these example ​functions+funcdef void fdSimpleFunction(); ​ 
 + // Such as these sample ​functions:
 void sfHelloWorld() { void sfHelloWorld() {
     AddDebugMessage("​Hello World!",​ false); ​   // Output hello world     AddDebugMessage("​Hello World!",​ false); ​   // Output hello world
 }    }   
-// This function will output how many times it has been called ​ 
 void sfDisplayTimesCalled() { void sfDisplayTimesCalled() {
-    AddLocalVarInt("​DTC_TimesCalled",​ 1);+    AddLocalVarInt("​DTC_TimesCalled",​ 1); //Display how many times function was called:
     AddDebugMessage("​DisplayTimesCalled,​ called: " + GetLocalVarInt("​DTC_TimesCalled"​) + " times",​ false);     AddDebugMessage("​DisplayTimesCalled,​ called: " + GetLocalVarInt("​DTC_TimesCalled"​) + " times",​ false);
 } }
Line 266: Line 263:
    
 // We now can create an array of these simple functions for further use. // We now can create an array of these simple functions for further use.
-// Note that fdSimpleFunction@ is like a type now - like string, or int! 
 fdSimpleFunction@[] simpleFunctions = { @sfHelloWorld,​ @sfDisplayTimesCalled,​ @sfPlayScarySound };  fdSimpleFunction@[] simpleFunctions = { @sfHelloWorld,​ @sfDisplayTimesCalled,​ @sfPlayScarySound }; 
    
Line 302: Line 298:
 } }
 </​code>​ </​code>​
 +
  
 ==== Closing comments ==== ==== Closing comments ====
  
  
-A quick note on an earlier point - when the function pointer is defined initially, it can point nowhere. This can be tested for with the following code:+A quick note on an earlier point - when the function pointer is defined initially, it points ​nowhere ​(as it does if an assignment fails due to mismatching signatures). This can be tested for with the following code:
  
  
-<code cpp>if( functionPointer is null ) +<code cpp>if( functionPointer is null )
 </​code>​ </​code>​
  
  
-Finally, that state of a function pointer **is not saved when the map is - ** there is no way to save the state of a function pointer - so keep them the same (which is fine in the case of an array - like the last example), or assume they haven'​t changed within the**scope** of one function (as in the second example).+Finally, that state of a function pointer **is not saved when the map is - ** there is no way to save the state of a function pointer - so keep them the same (which is fine in the case of an array - like the last example), or assume they haven'​t changed within the **scope** of the first function (E.g. the second example).
  
  
hpl2/tutorials/script/funcdef.1313317426.txt.gz · Last modified: 2011/08/14 10:23 by thegreatcthulhu