Python snippet - using properties to configure scripts

Here is a code snippet (Blender 2.49+) that makes it easy for you to setup params of a GE Python script or module by properties.

Advantages:

  • Optional configuration by properties even by Non-programmers
  • Allows to apply the same script to multiple objects running with different parameters (no more need to make a copy of the script)
  • the default values can still be modified within the script if someone still likes to do that.
    The complete script
    First a complete example for the one who can’t wait. You can copy and paste it to the Blender Text window.
    I will explain it further down.

import GameLogic
# properties
Pprop = "prop" # my convention P<propname> = "propname". This makes it easy to change the property name at one place
# Default values
prop = 10 # used when the property is not defined
 
def getPropValue(obj, propName, default=None):
 try:
  return obj[propName]
 except KeyError:
  return default
 
def usage(cont): 
 value = getPropValue(cont.owner, Pprop, prop)
 print "The used value for",Pprop,"is",value
 
usage(GameLogic.getCurrentController()) # script mode, remove for module mode

Let me know if you have problems or better methods.

I hope it helps

[INDENT][INDENT][INDENT]How does it work?
[/INDENT][/INDENT][/INDENT]Initialization
At the beginning of the script you can configure the property names and the default values.

 
import GameLogic
# properties
Pprop = "prop" # my convention P<propname> = "propname". This makes it easy to change the property name at one place
# Default values
prop = 10 # used when the property is not defined

Property names and default values are optional, as they can be set directly later on.
I recommend to use this method as it makes it easier to change them later if required.
The advantages are:

  • you change them just once even if used multiple times
  • you know it is configured at the beginning of the script (no need to search the whole script)
  • you can easily see what properties the script is using (no need to search the whole script).

The snippet
The function getPropValue returns the value from the property. If the property is not set it returns the default value.


def getPropValue(obj, propName, default=None):
 try:
  return obj[propName]
 except KeyError:
  return default

Looks quite simple, isn’t it?
Why not use the code directly?
Imaging you have this code 3 times for three parameters. This would look really ugly. So better use the function.
Usage example


def usage(cont): 
 value = getPropValue(cont.owner, Pprop, prop)
 print "The used value for",Pprop,"is",value

In script mode you need to call the usage function:


usage(GameLogic.getCurrentController()) # for script mode
 

In module mode you do enter the name of the called function at the controller configuration. No need to call the usage function from script.

Short example
This one is a shorter example without the optional fields, doing exactly the same thing as the above example:


import GameLogic
def getPropValue(obj, propName, default=None):
 try:
  return obj[propName]
 except KeyError:
  return default
 
def usage(cont): 
 print "The used value for",Pprop,"is",getPropValue(cont.owner, "prop", 10)
usage(GameLogic.getCurrentController()) # script mode, remove for module mode

Let me know if you have problems or better methods.

I hope it helps

I really want to understand what this all mean, i need to learn more about python, but, even don t understanding it at all, you are a great teatcher!
Thanks for sheare with us!

Just a short example. This is from the vehicleWrapper from tutorialsforblender3d:

 
def Tire_Radius():
 
  # tire radius
  tire_0_Radius = 0.75   # front driver's tire 
  tire_1_Radius = 0.75   # front passenger's tire 
  tire_2_Radius = 0.75   # rear driver's tire 
  tire_3_Radius = 0.75   # rear passenger's tire 
 
return (tire_0_Radius, tire_1_Radius, tire_2_Radius, tire_3_Radius)
 

The good thing is, the numbers are all defined at one place and not spread all over the script. Finnally … they are.
To change them the user has to load the script, find the above code and replace the 0.75 with e.g. 1.00 (must be float).

A non-programmer will ask in the forum if someone else can do this for him.
A programmer will just change it.

As programmer you can implement it as this (assuming you have getPropValue() in your script):

 
def Tire_Radius():
 
  # tire radius
  own = GameLogic.getCurrentController().owner
  tire_0_Radius = getPropValue(own, "radius_0", 0.75)   # front driver's tire 
  tire_1_Radius = getPropValue(own, "radius_1", 0.75)   # front passenger's tire 
  tire_2_Radius = getPropValue(own, "radius_2", 0.75)   # rear driver's tire 
  tire_3_Radius = getPropValue(own, "radius_3", 0.75)   # rear passenger's tire 
 
return (tire_0_Radius, tire_1_Radius, tire_2_Radius, tire_3_Radius)
 

The user can dafine the radiuses by adding the properties radius_0 with 1.0 and radius_1 with 1.0 etc. to the cars body.
The user can even add another car with different radiuses without even touching the script.

Your getPropValue() function is clever! I’m not familiar with “module mode”, are you referring to specifying a module instead of a script in the python controller logic brick? If so, why remove the call to usage?

Regards,
John

Yes that is what I mean.

In module mode the initial code is executed with the first call to a module member.
In the example you would execute usage() twice:

  • while initialization (because of usage(…))
  • while executing the controller call

In script mode ONLY the intial code is executed. Without the call usage() would not be executed.

This can produce unwanted problems. I haven’t found a solution to make a script usable as script and as module without such a change.

Great info, thanks!

Hi, I am writing a program which runs the game brick. I am only able to use Vpython, and I am stuck. I need to make it so the ball will bounce if different directions when hit, and also bounce off of the bricks. I was wondering if you could look over my code, and help me out. If you could email me at [email protected]


from visual import*

scene.title = 'brick'
scene.range=10

brick1=box(pos=(-5,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick2=box(pos=(-4,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick3=box(pos=(-3,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick4=box(pos=(-2,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick5=box(pos=(-1,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick6=box(pos=(0,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick7=box(pos=(1,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick8=box(pos=(2,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick9=box(pos=(3,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick10=box(pos=(4,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick11=box(pos=(5,9,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick12=box(pos=(-4,8,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick13=box(pos=(-3,8,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick14=box(pos=(-2,8,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick15=box(pos=(-1,8,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick16=box(pos=(0,8,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick17=box(pos=(1,8,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick18=box(pos=(2,8,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick19=box(pos=(3,8,0), length=1, height=1, width=1, color=color.white, material=materials.marble)
brick20=box(pos=(4,8,0), length=1, height=1, width=1, color=color.white, material=materials.marble)




ball=sphere(color=color.cyan, pos=vector(0,0,0), radius=0.2)

ball.velocity = vector(0,-1,0)

delta_t= 0.01

panel=box(pos=(0,-9,0), length=2, height=0.5, width=0, color=color.white)
panel.velocity = vector(1,0,0)
while True:
    rate(300)
    ball.pos= ball.pos + ball.velocity*delta_t

    if ball.y<10:
        ball.velocity.y=-ball.velocity.y
    if ball.y >= panel.y +.5 and ball.x<= panel.x+1 and ball.x >= panel.x-1 :
        ball.velocity.y= -ball.velocity.y


    
    if scene.kb.keys:
        s=scene.kb.getkey()
        if s == 'right':
            panel.pos.x = panel.pos.x + 0.2
        if s == 'left':
            panel.pos.x = panel.pos.x - 0.2
    if ball.y >= 7 and ball.x >.5 and ball.x <.5:
        ball.velocity.y=-ball.velocity.y
     
    if ball.y <= -10:
        break
        print "Game Over"