I must say that I am a convert to subclassing game objects. It allows some really neat things to be done quite simply, such as making lots of identical (or nearly so) setups on objects.
/ / / / / CAUTION / / / / / /
Subclassing is a relatively advanced python programming skill. This resource assumes some programming knowledge. If you don’t have it, here are some great resources about subclassing:
- subclassing in general
-
subclassing in bge
There are also a whole heap of threads I wrote about this fairly recently
Create a basic sub-class:
To create a subclass in blender, you simply create a class subclassing bge.types.KX_GameObject, and pass the object to it when you initialize it:
import bge
def make_projectile(cont):
Projectile(cont.owner)
cont.script = __name__ + '.execute'
def execute(cont):
cont.owner.run()
class Projectile(bge.types.KX_GameObject):
def __init__(self, old):
print('subclassing1')
def run(self):
print('running')
Simply creating an always linked to a python controller running the function ‘make_projectile’ will mutate the game object into a projectile object.
Sub-sub-class in blender:
Yes, it works like it should. I thought I’d just point this out for the people who don’t know about it:
import bge
def make_homingprojectile(cont):
HomingProjectile(cont.owner)
cont.script = 'subclasstest.run'
def execute(cont):
cont.owner.run()
class Projectile(bge.types.KX_GameObject):
def __init__(self, old):
print('subclassing1')
def run(self):
print('running')
def other(self):
print('other')
class HomingProjectile(Projectile):
def __init__(self, old):
super().__init__(old)
print('subclassing2')
def run(self):
print('running2')
self.other()
This will subclass the game object with HomingProjectile, and will execute the ‘run’ function from Homing Projectile, and the ‘other’ function from Projectile.
Auto-make subclassing functions:
To subclass an object in bge, you have to create a function to mutate the object. So let’s say I have a class called ‘HomingWeapon’. To mutate a game object into one of these ‘homing weapons’ I have to create a function, something like ‘make_homing_weapon.’
But if I have a large script with 10-20 different object types defined in it, it get’s cumbersome to have all of these functions separately defined.
So let me present to you, the auto-subclass-function-generator:
# This is a solution to create a million nearly identical
# functions, one for each object type/class. It is only necessary because
# blender's logic has an odd way of handling subclassing of game_objects
def execute(cont):
cont.owner.run(cont)
globals_class_list = [c for c in globals() if type(globals()[c]) == type]
exec_str = ''
for class_type in globals_class_list:
function_name = 'make_'+class_type.lower()
function_contents = '''
def {0}(cont):
{1}(cont.owner)
cont.script = '{2}.execute'
cont.owner.run()
'''.format(function_name, class_type, __name__)
exec_str += function_contents
exec(exec_str)
Put this at the end of your script, and when the module is run, for each class defined within, it will create the function:
def make_{classname}(cont):
ClassName(cont.owner)
cont.script = 'module_name.execute'
cont.owner.run()
If you have a bit of coding knowledge, it is easy enough to see that this will mutate your object, and then change the controllers script to run a function in the same file called ‘execute’ which is also defined in the codeblock I posted above. This simply calls a function internal to the class. I tend to use ‘run’ but you can use whatever you like.
A simple demo module for this would be:
class HomingProjectile(bge.types.KX_GameObject):
def __init__(self, old_object):
print('Making Homing Projectile')
def run(self, cont):
print('boo')
# This is a solution to create a million nearly identical # functions, one for each object type. It is only necessary because
# blender has an odd way of handling subclassing of game_objects
def execute(cont):
cont.owner.run(cont)
globals_class_list = [c for c in globals() if type(globals()[c]) == type]
exec_str = ''
for class_type in globals_class_list:
function_name = 'make_'+class_type.lower()
function_contents = '''
def {0}(cont):
{1}(cont.owner)
cont.script = '{2}.execute'
cont.owner.run()
'''.format(function_name, class_type, __name__)
exec_str += function_contents
exec(exec_str)
Then in logic bricks, create:
Always -> python controller: ‘modulename.make_homingprojectile’
The console will spam you with ‘boo’ which comes from the ‘run’ function inside the class. This also works fine with the sub-sub-class like I described earlier.