Author: cym
As we all know, the importance of scripts is self-evident, especially in game engine development,
Maybe the physical, artificial intelligence, animation, sound effects, and special effects of a game engine can be implemented using a third-party library, but the script engine cannot be a third-party one. You must write it yourself.
With the script engine, we can easily integrate third-party libraries into our own game engine, making game development easy and fast ..
You may have used a scripting language, but it takes a little time to write a script engine.
In the following example, I will teach you how to write an extremely simple script engine, which is a command-Based Script Engine ..
This script parsing class has the following functions:
Void loadscript (char * filename); // load the script file
Void runscript (); // run the script
Void unloadscript (); // uninstall the script
Void printscript (); // print the basic information of the script for debugging.
There are several private functions:
// Obtain the script commands and parameter functions (these two functions are available now. They are retained for future extension)
Const string getscriptcmd (const string line) const;
Const string getscriptpara (const string line) const;
// Obtain the set of script commands and Parameters
Const vector <string> getscriptcmdpara (const string line) const;
There are several member variables
// Container for loading Script Commands
Boost: array <string, cym_max_source_line> m_strsource;
Int m_iline; // number of rows in the script
You also need to define several macros. Their function is to compare commands.
// The maximum number of lines supported by each script file and the maximum number of characters supported by each script file
# Define cym_max_source_line 4096
# Define cym_max_line_char100
// Define the script command/number of script lines
# Define dnf_pai_printstr "printstr"
# Define dnf_cmd_printstrloop "printstrloop"
# Define dnf_cmd_newline "newline"
# Define dnf_cmd_pressanykey "pressanykey"
// Chinese script command
# Define dnf_cmd_printstr_cn "print"
# Define dnf_cmd_printstrloop_cn "cyclic printing"
# Define dnf_cmd_newline_cn "line feed"
# Define dnf_cmd_pressanykey_cn "press any key"
As you can see, this script parsing class supports both Chinese and English: Isn't it cool?
Note that this script parsing class uses the boost library. If you haven't touched the boost library before, you may need to download the boost library and get familiar with it.
PS: boost library is a C ++ library with industrial strength and is well known as a C ++ quasi-standard library.
1. Load the script from the file:
// Load script/run script/uninstall script
Void ccymscript: loadscript (char * filename)
{
M_iline = 0; // Number of script rows
Int I = 0; // used for Loop
Ifstream infile;
Infile. Open (filename );
If (infile. Good ())
Cout <"script file opened successfully! '"<Endl;
Else if (infile. Bad ())
Cout <"An error occurred while opening the script file! '"<Endl;
// Load the script
While (Getline (infile, m_strsource [I])
{
++ I;
++ M_iline;
}
Infile. Close ();
}
This code is relatively simple:
1. Use the ifstream open () function to open the script file
2. load the content in the script file into an array used to store the script command through the loop and Getline () functions. Note that the array here uses the array manager in the boost library, it is as convenient as an array, and the speed is almost the same as that of the original array, but it is more secure ..
2. Print the basic information of the script.
// Output string
Void ccymscript: printscript ()
{
Int I = 0; // used for loop searching
// Print the basic information of the script, number of rows
Cout <"Number of command lines:" <m_iline <Endl;
// Print all scripts, commands
For (I = 0; I <m_iline; ++ I)
{
Cout <m_strsource [I] <Endl;
}
Cout <"--------------------------------" <Endl;
// Cout <getscriptcmd (m_strsource [0]) <Endl;
// Cout <getscriptpara (m_strsource [0]) <Endl;
// Cout <getscriptcmdpara (m_strsource [0]) [0] <Endl;
}
This Code does not need to be explained.
3. Obtain commands and related parameters:
// Obtain the set of script commands and Parameters
Const vector <string> ccymscript: getscriptcmdpara (const string line) const
{
Vector <string> strvtr;
String Tok;
Stringstream STR (line );
While (Getline (STR, Tok ,''))
{
Strvtr. push_back (Tok );
}
Return strvtr;
}
1. This Code uses a string stream. We use the input string to construct a string stream.
2. Use the Getline () function to separate strings by spaces. Each string is loaded into a string container. Obviously, the first element of the container is always
Command character, and all subsequent elements will be considered as parameters of this command... then we will return this container;
4. Execute the script:
Void ccymscript: runscript ()
{
// Container used to store script commands and Parameters
Vector <string> strvtr;
Int I = 0; // used for Loop
For (I = 0; I <m_iLine-1; ++ I)
{
Strvtr. Clear ();
Strvtr = getscriptpolicpara (m_strsource [I]);
// Compare command
// Print the command
If (0 = strvtr [0]. Compare (dnf_0000_printstr) | 0 = strvtr [0]. Compare (dnf_0000_printstr_cn ))
{
Cout <strvtr [1] <Endl;
}
// Print cyclically
Else if (0 = strvtr [0]. Compare (dnf_cmd_printstrloop) | 0 = strvtr [0]. Compare (dnf_cmd_printstrloop_cn ))
{
For (INT I = 0; I <boost: lexical_cast <int> (strvtr [2]); ++ I)
{
Cout <strvtr [1] <Endl;
}
}
// Line feed command
Else if (0 = strvtr [0]. Compare (dnf_0000_newline) | 0 = strvtr [0]. Compare (dnf_0000_newline_cn ))
{
For (INT I = 0; I <boost: lexical_cast <int> (strvtr [1]); ++ I)
{
Cout <Endl;
}
}
}
}
1. This command is also relatively simple: we first use the vector container to obtain the split string ..
2. Use the if statement to compare each command with the macro we previously defined. If it is the same, execute this command; otherwise, ignore it ..
To add a clear comment statement, you only need to use the starts_with () function in the boost library to judge if an if judgment statement is added to the for loop.
Whether the specified string contains a "//" comment statement. The usage is as follows:
// Annotation statement
If (boost: starts_with (m_strsource [I], "//")
{
Cout <"this is a comment" <Endl;
}
Uninstall script:
Note that I didn't implement the unloadscript () function here, because I used array in the boost library to manage arrays.
The memory is automatically released when it exits the scope. Therefore, the array storing commands is not manually released,
I still keep the unloadscript () function for future extension.
5. Use our script to parse the class
# Include "cymscript. H"
Using namespace boost;
Using namespace STD;
Void main ()
{
Ccymscript * script = new ccymscript ();
Script-> loadscript ("test.txt ");
Script-> printscript ();
Script-> runscript ();
Getchar ();
}
------------------------------------------------ The following is a demonstration ---------------------------------------------------------------------
// This is the script file I wrote. It is very easy to print characters, line breaks, and print cyclically ....
// Note that he supports both Chinese and English, so we can use both Chinese and English.
Print chengyimingvb
Line feed 1
Printstr Chen yiming
Newline 2
Print chenyimin 3 cyclically