Python Scripting in Blender
Python Scripting in Blender
Blender
Gordon Erlebacher
Fall 2012
Tuesday, October 2, 12
Audience
• Python classes are for the programmers
• Non-programmers should try to
understand, but will not be required to do
homeworks based on Python
• Non-Programmers and Programmers must
work together to develop the game, not in
isolation
Tuesday, October 2, 12
Python Console
Tuesday, October 2, 12
Python Basics
• From the command line (mac/linux/
windows with cygwin)
• type python
>>> 3+3
6
>>> a = “gor”; b = “fran”
>>> a + b
>>> ‘gorfran‘ # concatenation of strings
Tuesday, October 2, 12
Scripting Language
• Write Python in
• Blender Window
• Editor outside Python
• An interpreter reads each line, checks for errors
and executes the line
• it is somewhat more complex than that
• Allows complex interactions not possible in the
game engine
Tuesday, October 2, 12
Example
print(5+6)
exit() # Stop the program
Tuesday, October 2, 12
Example
print(5+6)
exit() # Stop the program
Tuesday, October 2, 12
When to use Python
• When the logic panel becomes too complex and hard to
understand
• In situations with complex series of states
• When multiple objects should interact with each other
• When one wishes to create actions (animations) on the fly
• Fancy use of random numbers
• Program complex motions
• Handle the mouse
• Handle multiple cameras, multiple players, multiple viewports
• ... whatever your imagination dictates ...
Tuesday, October 2, 12
Everything is an Object
• Actuator, Controller, Sensor
• Mesh
• IPO
• Texture, Material
• Camera
• etc.
Tuesday, October 2, 12
Scenes
Tuesday, October 2, 12
Documentation
• Documentation of 2.63 API
• Code fragments (outside the game engine)
• Thread on scripts (outside the game
engine)
• 2.6 Manual (with section on game engine)
• Blender Basics, 4th Edition
Tuesday, October 2, 12
Interactive Console
Tuesday, October 2, 12
MacOSx/Linux
cd /Applications/blender-2.63a-release-
OSX_10.6_x86_64/blender.app/Contents/
MacOS/
./blender # start blender
Tuesday, October 2, 12
Windows XP/Visa/7
When Blender is started on a Windows operating system, the Console Window is first
created as a separate window on the desktop. Assuming that the right start-up
conditions are met, the main Blender window should also appear and the Console
Window will then be toggled off. This is unlike the 2.4x series where theConsole
Window would remain visible while the main Blender window was open. To display the
console in current versions of Blender, go to Help » Toggle System Console.When
Blender is started on a Windows operating system, the Console Window is first created
as a separate window on the desktop. Assuming that the right start-up conditions are
met, the main Blender window should also appear and the Console Window will then be
toggled off. This is unlike the 2.4x series where theConsole Window would remain
visible while the main Blender window was open. To display the console in current
versions of Blender, go to Help » Toggle System Console.
Tuesday, October 2, 12
Module bge
• bge : Blender Game Engine
• First program:
• import bge
print(dir(bge))
• Output
• Blender Game Engine Started
['__doc__', '__name__', 'constraints', 'events', 'logic', 'render',
'texture', 'types']
['__doc__', '__name__', 'constraints', 'events', 'logic', 'render',
'texture', 'types']
• Blender Game Engine Finished
Tuesday, October 2, 12
Simplest Program
Python script
Tuesday, October 2, 12
How to use the output
import bge
print(dir(bge))
print(dir( bge.events))
Tuesday, October 2, 12
Do not sweat
the details
Tuesday, October 2, 12
Example 1
Tuesday, October 2, 12
bge.logic.getCurrentScene()
['__class__', '__contains__', '__delattr__', '__delitem__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__gt__', '__hash__', '__init__', '__le__', '__lt__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__',
'__subclasshook__', 'active_camera', 'activity_culling',
'activity_culling_radius', 'addObject', 'cameras', 'dbvt_culling',
'drawObstacleSimulation', 'end', 'get', 'invalid', 'lights', 'name',
'objects', 'objectsInactive', 'post_draw', 'pre_draw', 'replace',
'restart', 'resume', 'suspend', 'suspended']
Tuesday, October 2, 12
Scene objects
import bge
control = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()
objs = scene.objects
print(objs)
#Output
[Cube.001, Cube, __default__cam__]
Tuesday, October 2, 12
What are keyboard sensor
properties?
cube = objs[‘Cube.001’]
sensor = cube.sensors[‘mykey’]
print(sensor)
['__class__', '__delattr__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__le__', '__lt__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'events', 'executePriority', 'frequency', 'getKeyStatus',
'hold1', 'hold2', 'invalid', 'invert', 'key', 'level', 'name',
'neg_ticks', 'owner', 'pos_ticks', 'positive', 'reset', 'status',
'tap', 'targetProperty', 'toggleProperty', 'triggered',
'useAllKeys', 'useNegPulseMode', 'usePosPulseMode']
Tuesday, October 2, 12
Tuesday, October 2, 12
Press and release akey
import bge
control =
bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()
objs = scene.objects The printout occurs twice.
cube = objs['Cube.001'] WHY?
sensor = cube.sensors['mykey']
print(dir(sensor))
Tuesday, October 2, 12
Controllers and pulses
• The python controller gets called every time
a pulse hits it
• The keyboard sensor sends a positive pulse
when the key is pressed
• The keyboard sensor sends a negative pulse
when the key is released
• How to prevent the negative pulse from
having an effect?
Tuesday, October 2, 12
Avoid negative pulse
import bge
control = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()
objs = scene.objects
cube = objs['Cube.001'] The printout only occurs
sensor = cube.sensors['mykey'] when the key is pressed
if (sensor.positive):
print(dir(sensor))
Tuesday, October 2, 12
Now, avoid keyboard
sensor
• It is possible to have python capture
keyboard events, without a sensor
• Advantage: you can give the Python code to
your friend
• More complicated, so we will avoid this for
now
• Working with Python sensors/actuators is
faster then writing your own, in most cases
Tuesday, October 2, 12
Two Cameras
• Create a cube and a cone
• camCube and camCone are two cameras,
which point to the cube and to the cone
• “akey” will select the camCube
• “bkey” will select the camCone
• First step: create the scene
(two_cams_python.blend)
Tuesday, October 2, 12
Add two camera actuators, one tracking the cube, one
tracking the cone.
Tracking constraints are not maintained in the game engine
Tuesday, October 2, 12
Object
• bge is an object
• bge has the following variables/subclasses
['__doc__', '__name__', 'constraints',
'events', 'logic', 'render', 'texture', 'types']
• Each subclasses has its own subclasses and
so on
• Check out the API documentation
Tuesday, October 2, 12
Control of the Mouse
Tuesday, October 2, 12
Steps
• Parent a camera to a character object
• The camera is the child of the character
• The character is the parent of the camera
• The character is a dynamic object
• rigid might make the object rotate
• Create flow logic for the camera
• All objects can have any name
• Example on next slide
Tuesday, October 2, 12
Properties that control the
Mouselookup script
The source code is not loaded with Python. If the blender file is
transferred elsewhere, remember to transfer the source files as well
Tuesday, October 2, 12
Try it out!
• http://www.sc.fsu.edu/~gerlebacher/gd/
• mouseCamera.blend
• Activate layer 2 only
• Layer 1 contains the example that comes with mouselook.py
package.
• 0key to see the view from the camera
• pkey to start the game
• use mouse to rotate the view, then ASWD to move the
dynamic object around (and the parented camera will follow)
Tuesday, October 2, 12
Object Properties
Tuesday, October 2, 12
Object Rotation
• Start an object to rotate slowly (keyboard
Rkey)
• Every time the Rkey is pressed, the object
will rotate a little faster
• Without Python, the rotation value in the
motion actuator is a fixed value, which
cannot be changed.
Tuesday, October 2, 12
Constant Rotation
Tuesday, October 2, 12
No Deactivation
Script: rotate_start_nostop
Tuesday, October 2, 12
Properties
Tuesday, October 2, 12
Update Property
Every time the key is pressed,
rotz increases by 0.01
Keeping the key pressed does not
increase the acceleration
Increase the acceleration by keeping a
key pressed: simply use positive
frequency button
Tuesday, October 2, 12
Global Variables
Tuesday, October 2, 12
Method 1
• Choose an object in the game, and give it a property:
‘nb_enemies’
• cube[‘nb_enemies’] = 5
• Another object: hero, needs access to ‘nb_enemies’
• Inside a script for hero,
cube = objects[‘cube’]
nb_en = cube[‘nb_enemies’]
• Disadvantage: Why should this variable be associated with
‘cube’? If all objects need access to this variable, better to have
a more centralized location. Thus the game dictionary.
Tuesday, October 2, 12
Method 2:
Game Dictionary
• bge.logic.gameDict
• Initially, the dictionary is empty
• Initialize variables in the game:
• bge.logic.gameDict[‘nb_enemies’] = 3
• update as needed
• access:
nbe = bge.logic.gameDict[‘nb_enemies’]
Tuesday, October 2, 12
Always sensor: only gets executed once.
Useful for one-time initializations
Tuesday, October 2, 12
Without save/load
Tuesday, October 2, 12
Change Scenes
• Create two scenes
• Scene1: a cube, light, camera
• health [0-100] property
• Scene2: a cone, light, camera
• Same health property
• Store health in globalDict.
• maintained between scenes
Tuesday, October 2, 12
Cube Scene
Change scene
Cube.001
cube.camera
Tuesday, October 2, 12
Cone Scene
Cone.001
cone.camera
Change scene
Tuesday, October 2, 12
Notes
• Camera trackers are required
• A TrackTo contraint outside the game engine is not respected
inside the game engine
• The globalDict is not destroyed when changing scenes,
however,
• Object properties are reset to initial values when changing
scenes. Thus, the advantage of the globalDict
• What about when a game is restarted?
• Object variables can be initialized from the dictionary in an
initialization python script (once per game, or for each object)
Tuesday, October 2, 12
Blender 2.49a
Tuesday, October 2, 12
Anatomy of a program
(blender 2.49b)
• Import GameLogic # not required
• cs = getCurrentScene()
• objs = cs.objects
• gd = GameLogic.globalDict;
• gd[‘house’] = ‘number of bullets’
gd[‘nb_bul’] = 30
• I stored two variables in the Global Dictionary
• Any object can access the global dictionary, from any
script, from any scene
Tuesday, October 2, 12
Anatomy of a program
(blender 2.59)
• Import bge # not required
• cs = bge.logic.getCurrentScene()
• objs = cs.objects # list of all objects in the scene
• gd = bge.logic.globalDict;
• gd[‘house’] = ‘number of bullets’
gd[‘nb_bul’] = 30
• I stored two variables in the Global Dictionary
• Any object can access the global dictionary, from any
script, from any scene
Tuesday, October 2, 12
Tuesday, October 2, 12
Printing variables
• print(objs)
• parenthesis are very important!!! Not necessary in the
past
• printout can be seen on the console
• on Windows, the console is behind the Blender
window
• on the Mac, one must start Blender from the command
line within a window, which becomes the console
• Printing simplifies debugging
Tuesday, October 2, 12
Arrays
• How to store objects and information
• In Python, use lists
• a = [4,5,6] (all the same type)
• b = [73,‘gordon’, -45.34] (different types)
• a[0]+b[2] ==> 4-45.35 = -41.35
• different types, but integer converted to float
• a[0]+b[1] ==> error (different types)
• string ‘gordon’ cannot be converted to integer
Tuesday, October 2, 12
Accessing properties
con = bge.logic.getCurrentController()
sc = bge.logic.getCurrentScene()
print(sc.objects) # prints to console
ob = sc.objects['Cube']
print dir(ob)
Tuesday, October 2, 12
Hash tables
• Special kind of array
• Array index can be any type (object, string, ...)
• a = {} # dictionary creation
• a[‘gordon’] = 3
• a[5] = ‘blender’
• a[6] = 23.5
• a[‘gordon’] + a[6] ==> 26.5
Tuesday, October 2, 12
Dictionary
is a hash table
GameLogic = bge.logic
con = GameLogic.getCurrentController()
sc = GameLogic.getCurrentScene()
print(sc.objects)
ob = sc.objects[‘Cube’]
print(dir(ob))
a = {}
a[ob] = 3 # argument can be list, integer, float, string
a[sc] = ‘gordon‘ # probably will not work
print(a)
Tuesday, October 2, 12
Example
demonstrate_simple_python_script.blend
Tuesday, October 2, 12
Program name: test_program
import bge
GameLogic = bge.logic
con = GameLogic.getCurrentController()
sc = GameLogic.getCurrentScene()
print(sc.objects)
ob = sc.objects['Cube']
print(dir(ob))
a = {}
Tuesday, October 2, 12
Tuesday, October 2, 12
Storing information in
objects
• # ob name is ‘Cube’
ob = objects[‘Cube’]
• # to see this variable, create obj property
ob[‘newvel’] = 3.4
print dir(ob) # ‘newvel’ appears in the list
• To see object in debug mode (blender 2.49b)
• changed in blender 2.59b
• Game menu -> Debug Properties
• Add Property (in property panel)
Tuesday, October 2, 12
Tuesday, October 2, 12