You are on page 1of 64

Python Scripting in

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

print("x = 6") # line is never executed

Tuesday, October 2, 12
Example
print(5+6)
exit() # Stop the program

a = 3/; # Error (stops program from running)


print("x = 6") # line is never executed

•First, the program is checked for syntactical errors

•Second, the program is executed

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

• One can construct one or more scenes


• Each scene contains a collection of objects
• Objects can be shared between scenes
• Scenes help with level design

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

# errors will be printed out to the window


blender is started in.

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))

#['__doc__', '__name__', 'constraints', 'events', 'logic', 'render', 'texture', 'types']

print(dir( bge.events))

['__doc__', '__name__', 'constraints', 'events', 'logic', 'render', 'texture', 'types']

['ACCENTGRAVEKEY', 'AKEY', 'BACKSLASHKEY', 'BACKSPACEKEY', 'BKEY',


'CAPSLOCKKEY', 'CKEY', 'COMMAKEY', 'DELKEY', 'DKEY', 'DOWNARROWKEY',
'EIGHTKEY', 'EKEY', 'ENDKEY', 'ENTERKEY', 'EQUALKEY', 'ESCKEY', 'EventToCharacter',
'EventToString', 'F10KEY', 'F11KEY', 'F12KEY', 'F13KEY', 'F14KEY', 'F15KEY', 'F16KEY',
'F17KEY', 'F18KEY', 'F19KEY', 'F1KEY', 'F2KEY', 'F3KEY', 'F4KEY', 'F5KEY', 'F6KEY',
'F7KEY', 'F8KEY', 'F9KEY', 'FIVEKEY', 'FKEY', 'FOURKEY', 'GKEY', 'HKEY', 'HOMEKEY',
'IKEY', 'INSERTKEY', 'JKEY', 'KKEY', 'LEFTALTKEY', 'LEFTARROWKEY',
'LEFTBRACKETKEY', 'LEFTCTRLKEY', 'LEFTMOUSE', 'LEFTSHIFTKEY', 'LINEFEEDKEY',
'LKEY', 'MIDDLEMOUSE', 'MINUSKEY', 'MKEY', 'MOUSEX', 'MOUSEY', 'NINEKEY',
'NKEY', 'OKEY', 'ONEKEY', 'PAD0', 'PAD1', 'PAD2', 'PAD3', 'PAD4', 'PAD5', 'PAD6', 'PAD7',
'PAD8', 'PAD9', 'PADASTERKEY', 'PADENTER', 'PADMINUS', 'PADPERIOD',
'PADPLUSKEY', 'PADSLASHKEY', 'PAGEDOWNKEY', 'PAGEUPKEY', 'PAUSEKEY',
'PERIODKEY', 'PKEY', 'QKEY', 'QUOTEKEY', 'RETKEY', 'RIGHTALTKEY',
Tuesday, October 2, 12
print(bge.logic)
['BL_DST_ALPHA', 'BL_DST_COLOR', 'BL_ONE', 'BL_ONE_MINUS_DST_ALPHA',
'BL_ONE_MINUS_DST_COLOR', 'BL_ONE_MINUS_SRC_ALPHA',
'BL_ONE_MINUS_SRC_COLOR', 'BL_SRC_ALPHA', 'BL_SRC_ALPHA_SATURATE',
'BL_SRC_COLOR', 'BL_ZERO', 'CAM_POS', 'CONSTANT_TIMER',
'CONSTRAINT_IK_COPYPOSE', 'CONSTRAINT_IK_DISTANCE',

... many more items ...

EWMATRIX_TRANSPOSE', '__doc__', '__name__', '__package__', 'addScene', 'endGame',


'error', 'expandPath', 'getAverageFrameRate', 'getBlendFileList', 'getCurrentController',
'getCurrentScene', 'getExitKey', 'getLogicTicRate', 'getMaxLogicFrame', 'getMaxPhysicsFrame',
'getPhysicsTicRate', 'getRandomFloat', 'getSceneList', 'getSpectrum', 'globalDict', 'keyboard',
'loadGlobalDict', 'mouse', 'restartGame', 'saveGlobalDict', 'sendMessage', 'setExitKey',
'setGravity', 'setLogicTicRate', 'setMaxLogicFrame', 'setMaxPhysicsFrame', 'setPhysicsTicRate',
'startGame']

Tuesday, October 2, 12
Do not sweat
the details

Tuesday, October 2, 12
Example 1

Make a cube move with the Akey

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))

Notice the “:” in the “if statement”


Also: lines inside “if statement” all have the same indentation
(imposed by Python)

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

• Use the MouseLookup.py module


• Download from class website (Oct.2/Oct.
4)
• How does it work?

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

Code in file: mouselook.py


Execute main function, which is
the entry point:
mouselook.main

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

How are they used from within Python?

Let us do something not possible without Python ...

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

Key ups are ignored

Once the motion actuator is


turned on, motion only stops
when it is deactivated

Tuesday, October 2, 12
No Deactivation
Script: rotate_start_nostop

Better: cube = cont.owner


Usually bad idea to use specific
object names. If the object name
changes, strange things might
happen

The motion actuator is never deactivated

Tuesday, October 2, 12
Properties

Get property ‘acc’


Use default -.01 if non-existent

The property value is always the


same when accessed. How to
change it?

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

• I would like to keep track of the total


number of enemies: nb_enemies
• Multiple objects would like to access this
property
• How is this done?

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

save and load globalDict


Save variables between game restarts
When is game restarted?
- when player gets killed (same level)
- when moving from one level to the next

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

You might also like