I have the feeling have the feeling there is no real understanding of the two Python options the python controller offers. Therefore I added a new page to
I have to say I didn’t liked the module mode at the time it was introduced. After a short time I was able to see all the benefits. Now I really like them and skip the script mode without regret. It is very easy to transform a script into a module. Even a beginner can do that. Blender offers a nice template for new modules.
You have to have cont in the parameter list if You use it in the function body - but not else… But we usually have use for cont so it’s a good habit to add it in the parameter list.
If you think about it should be naturally. You just write “cont”.
This is like shouting “Klaus” into your flat. There is not Klaus to listen to you. First you need to invite him.
You can do that by importing Klaus from somewhere else or by defining what Klaus is.
There are exceptions from this rule: the Python syntax (e.g. if, while, def) and the build-ins (e.h. print(), range(), list, object). They are implicit defined within the namespace of your code.
I hope this helps to understand this bit of Python.
Is there any recommended method for passing variables and constants from the init module to the processing module, and for passing variables from the processing module to itself, to be used in next iteration?
I currently use “globalization”, as in the example below, and it works well, but I’m not sure it is the most efficient solution.
def init():
global const1, const2, X # global definition of constants and variables
const1, const2 = pi/4, 1.41 # define constants
X = 0 # initialize state variable(s)
def processing():
global X # redefine X as global in order to make it available in next call
X = (X + const1)/const2 # update X
I recommend to make each and every entry point (BGE callable function) independent from any other. That is a good idea even in script mode.
The following methods are independent from script or property modes. The examples show the module mode methods only.
An object initialization should initialize the object not the module, bge or whatever.
The interface between the entry points is the object itself (accessible via the controller). If you want to share data you should use this object. The simplest way is to use properties as before.
When you do that always ask yourself:
What happens if this code is called by another object?
What happens when this code is called from another scene (important on level switch and HUD)?
You can set up module initialization that is shared by all objects. In your example:
PI_QUARTER = math.pi / 4 # set up once never change ~ constant
CONST2 = 1.41
def init(cont):
x = <really complicated code> # initialize function local variable(s)
cont.owner.obj["X"] = x
def processing(cont):
obj = cont.owner
x =obj["X"]
x = (x + PI_QUARTER)/CONST2 # update X
obj["X"] = x
You can call init() from any object.
While executing processing() x and it s value always belong to the calling object. Because they are read from the property which belongs to the executing object.
PI_QUARTER is shared by all objects as it is a module variable (per convention used as constant).
For simple property initialization I recommend:
set up the properties in the GUI for individual values
set up default values if the properties are not configured in the GUI
Reason: Never expect a user to change your code!!!
# module constants
PI_QUARTER = math.pi / 4 # set up once never change ~ constant
CONST2 = 1.41
# property default values
DEFAULT_X = 0.0
def processing(cont):
obj = cont.owner
x = obj.get("X", DEFAULT_X)
x = (x + PI_QUARTER)/CONST2
obj["X"] = x
The interfaces for configuration are:
Properties (in 90% of cases)
Object names (should be used very very careful)
Parent relationship (parent and children)
Logic brick owner relationship (the owner of a sensor does not need to be the owner of the controller!)
Group instance relationship (important but not implemented yet)
Very clean indeed, thank you very much.
What surprises me is that constant definition statements are executed only once (at compilation time, may be?) and not at every call of the module, as I thought!
With such premises, in most applications I won’t even need any dedicated initialization module.
One final point: since it is important for me that modules can be ported (back and forth…) to other python development environments with minimum changes, I have in mind to create a dummy object where to store the variables that are updated at every iteration, rather than in the blender-specific “controller owner”. Does this make sense? Are there any simpler methods?
<b># THE FOLLOWING CODE NOT TESTED YET!!!</b>
class EmptyClass: <i># create dummy class</i>
pass
PI_QUARTER = math.pi / 4 <i># set up once</i>
CONST2 = 1.41
VariableCarrierObject = EmptyClass()
VariableCarrierObject.X = 0.0 <i># create and initialize X-property</i>
def processing():
<i># Retrieve variables from previous call:</i>
x = VariableCarrierObject.X <i># replaces x = cont.owner["X"] for portability</i>
<i># Update variables:</i>
x = (x + PI_QUARTER)/CONST2
<i># Store variables for next iteration</i>:
VariableCarrierObject.X = x <i># replaces cont.owner["X"] = x</i>
The module initialization is executed with the first access to the module:
via import statement
or
via calling a function
There is already an object that exist ones only (singleton). It is the module itself.
Sure you can add any data you like. It will be accessible from each active scene. It even survives a scene switch.
If you prefer the class style syntax, you can do what you wrote in your example.
The instance of your class is a module variable (belongs to the module, not to a function). It will survive as long as the module lives (end of the game).
It is recommended to name variables and functions with a beginning lowercase letter and class names with a beginning Uppercase letter. This makes it easier to differentiate between them.
E.g.
It depends. In this case, when writing Python controller modules, you effectively program a Python controller to do something. Chances are, you will use a lot of these programmed controllers.
The word “main” expresses the idea of a unique entry point for some program. So you can name your Python controller functions “main” if you organize your code in such a way that 1 Python file = code for 1 Python controller.
If you happen to write multiple functions for multiple controllers into one single file, then surely you’ll need to find better names than “main1”, “main2”, “main3”, etc.
TL;DR: Python modules allow you to program a Python controller, so “main” seems too broad.
‘main’ does not say anything at all beside that is is an main function for something. If it for example get the distance and returns that, then i would call the function ‘get_distance’ or something like that.