10.1 Include files
As programs become bigger and bigger, they need to be more structured.
You learned so far to structure programs in more functions and now,
you will learn how to structure them in more than one file.
Consider you have a set of similar functions that represent a well defined part of your program.
Like some function that work with strings, or do some math calculations.
It is recomended to write them in a separate file and include that file in the main program file.
This way it will be easy for you to replace it with another version,
or to take it and use it in other programs as well.
Create a new file called module.txt in the
console folder and write inside the folowing lines of code:
In the main file, our program.txt write:
The #include directive, followed by the name of the
file to be included, in quotation marks, acts like the whole text from the specified
file would have been written right in that place.
Global variables and functions from other included files will be found even if they are included
after being used. However global code will be executed in the order of inclusion.
A namespace allows you to group together a set of functions and global variables,
based on a name prefix, with the purpose of better organizing large scripts.
Let's consider the folowing example.
In a game, we have more levels, and each has, let's say, an Init function in the game's script.
Since there can be only one function named Init,
we can name these functions InitLevel1, InitLevel2 and so on.
A more elegant approach is to declare for each level a namespace: Level1, Level2, etc.
Then, in each namespace we can safely declare the Init function for that level.
Inside the namespace, the Init function will be simply called by it's "short" name, Init.
But to call it from outside the namespace, the "full" name is required,
composed from the namespace name, the : character, and the function "short" name.
That is Level1:Init, Level2:Init etc.
Let's see an example:
It is possible to declare a namespace inside another namespace.
Then a "full" function name would be like Level1:ZoneA:Init.
From another namespace ZoneB, also inside Level1,
you can access variables from ZoneA namespace
like ZoneA:Init (or using the "full" name).
In GS9 namespaces are resolved at compilation by registering the variables with their "full" names.
It is the job of the compiler to resolve "short" variables names, by searching in the "current"
namespace. Because of that, there's no penalty on performance at runtime.
Another use of namespaces in a game can be to provide specific behaviour for various AI classes.
For example you can associate a particular enemy to a EnemyHunter
or EnemySoldier namespace, each with different implementation of the same
functions. Then you can use direct access, based on the enemy's class name, to call functions from it's namespace.