PyMove3D course material¶
Contents:
Introduction¶
You heard about this course and now you are reading course material. Whatever your motivations are, here you will find information about Python and 3D modelling program Blender, but also new ideas how to use computers and software at school or just for fun. Take your time and read the following few chapters to get the best experience.
Legend¶
Objectives¶
![]() |
Some sections apply only to a specific operating system. Icons are used to indicate such special cases, so you can skip the section if it does not apply. |
Instructions¶
Tasks: |
---|
- Remember the operating system and programs you are using and their versions.
- If the marked section is not for your program or operating system, you can skip it.
Legend¶
![]() |
Blender |
![]() |
Python |
![]() |
Linux |
![]() |
MacOS |
![]() |
Windows |
How to use the course¶
Objectives¶
![]() |
How to use this course material? Some advice is given. |
Instructions¶
Tasks: |
---|
- Read the following instructions, they give you the »big picture«.
- Switch to the index und select one interesting topic.
- Select the glossary in the Appendix.
Course structure¶
- every learning unit is named station
- every station is a isolated learning unit, but sometimes learning units depend on each other.
- each station is divided in tree parts
- objectives
- tasks/instructions
- descriptions and samples
How to use the course material?¶
- First read the objectives.
- It this station is your target, secondly read the tasks – read carefully, but only read, do not try to solve the exercises!
- If the goal and the exercises match your needs, you can start reading and master the examples. Repeat the shown examples/demos.
- Now you are ready to solve the tasks and exercises from the instruction section above.
- Don’t forget to create variations of the given tasks.
Looking for solutions¶
If you are looking for a solution, you have additional options:
- global search,
- index,
- glossary
The appendix also includes information on various topics in compressed form, for example, link lists to supplement the material presented here.
About the course¶
Objectives¶
![]() |
What is this course for? The table of contents shows the topics of this course, but gives no explanation of its philosophy. |
Instructions¶
Tasks: |
---|
- Use this course material, have fun!
- If you have an idea to add or improve the material, then we won’t stop you.
- Tell other people about this course material.
At the beginning¶
In 2012 at the »PyCon DE« in Leipzig an proposal to establish a programming contest was discussed. It should teach young people Python, our preferred programming language and one we use in our jobs. Soon, the conference was over but nothing happened!
In march 2013, Peter Koppatz asked Reimar Bauer at the »Linuxtag« in Berlin about the progress with the idea of a programming contest. Reimar answered that nothing had happened since Leipzig!
So Peter presented the idea to combine programming with python and building 3D worlds. Still skeptical, Reimar listened to Peter and he recognized the huge potential of this idea. And so the stone began to roll. Now the first competition is over. And its success is motivation to improve the course material and prepare a version that can easily translated to other languages.
Hall of fame¶
People who help to create and improve this course material will be honored in our list of names (alphabetical order):
- Anderson, Tony – translation
- Babenia, Anatoli – translation, pulishing on read the docs
- Bauer, Reimar – coordinator, author
- Bestwalter, Oliver – translation
- Boscaini, Maurizio – translation
- Fabula. Thomas – community relation
- Jens, Horst – testing, marketing
- Koppatz, Peter – coordinator, author
- Krasnitzky, Marcus – testing
- Meijer, Joroen – development gui
- Pratz, Valentin – testing, autor
- Retel, Joren – testing, author
- Stross-Radschinski, Armin – marketing
- Trabucci, Stefania – Design
- Wais, Alexander – testing
Blender and Python Console¶
In this course we use Python, which conveniently comes with Blender. This introduction explains basics of Blender and the use of its Python console.
Download/Install Blender¶
Objectives¶
![]() |
For the competition you need the software Blender. The installation shouldn’t be a problem. Blender files have the file extension .blend. |
What can we do with Blender?¶
Many things, for example: video production, game development, architecture, art, ... Here’s a little clip which shows what has already been done with Blender:
Arranged by: Mike Pan, Musik: Jan Morgenstern.
Where can I get the program?¶
You can find it here: http://www.blender.org
And here, a little clip about security:
The operation of Blender¶
Objectives¶
Blender is a window-oriented application. Some concepts are different from what you may expect, but it is not difficult. Just follow next videos and experiment a little bit to become familiar with how blender works.
Instructions¶
Tasks: |
---|
- Watch the clips.
- Split the window and close unused windows.
- Change the window type, for example to »File Browser«
- Look at the table in the notes with the most important keyboard shortcuts.
Paneling for Programmers¶
The paneling in Blender is very varied and depends on the tasks which should be done. In this course we want to get to know about Python and we want to use it. Because of that the following classification is very good for the exercises:

Window Management¶
Here a little clip to this topic:
Numpad¶
The views of the 3D-View can changed in all directions. The introduction to this topic is shown by this short video clip.
When there are other special functions of Blender required, the explanation takes place at the given place.
More tutorials about the usage and the operation of Blender should be present on YouTube.
Close and split windows¶
In the video was shown one variant to open and close windows. A second variant is a right mouseclick onto the dividing line between two windows.

Console with Blender/Python¶
Objectives¶
![]() |
Familiarize youself with the console and the interactive Python interpreter in Blender. |
Instructions¶
Tasks: |
---|
- Which version has the system-used Python interpreter?
- Which paths are searched by the Python interpreter?
- Print the sys-modules’s documentation.
- What is the difference between the methods »version« and »version_info«
- Where is your version of Blender located??
- What happens if you type in Python the command: import this? Discuss the output in a team or in twos!
Install the interpreter¶
For the work with Python you have to install software - Python interpreter. In the course we use a special form of Python, because:
- we want to show the results at the same time in a *3D-World*,
- all users should work with the same version,
- operating system-specific questions should stay in the background and Python the focus of attention..
- the 3D-functions of Blender should be of interest only as far as necessary.
Blender is the software which is used in the course/competition. Download the version 2.68 from the website http://www.blender.org/download. Note the installation and start instructions on the Blender website!
Find/start console¶

Download the following blend file:
Blender file with opened »console window«
and open it over the File-Open dialog or a double click, when the file extension .blend is linked with the program Blender.
Alternatively you can switch on to the console directly:

In both cases you get the following result:

System info¶

After the prompt: >>> you can type in instructions/commands. You finish the input with the enter key.
The output looks about this:

You get a list with various names. The list is limited by square brackets and contains entries separated by commas. All names which start and end with »__« are Python system variables. You shouldn’t use this notation for own names.
The sys-module¶

Programs are often very extensive, therefore the programs for special tasks are divided into separate modules or files. Python is modular, too. Additional functionality can be added to your Python program with the import function.
>>>import sys
After the import of sys, dir() shows you a longer list:

Which functions offers the sys-module? Enter the the name of the module into the brackets, to get more information about it. With that you can get a first overview over a module.

Output with print¶

The universal output function is print. Because platform is defined in the module sys, the dot notation is used for a clear call. Like a track connects the train stations, the point connects the single names to a correct path. And now we are already midst in the object-oriented programming.

If the name a function/method, you have to add a pair of brackets to get the return-value. The first call in the picture returns only the method-name in a »strange packaging«. The second call adds a pair of brackets and gets the answer, in our case the description of the operation system that we use.

Everything and more as a video clip¶
Blender Basics¶
This is the main part of the course. It is useful for beginners. If you are a Python beginner too, have a look to the section Python basics. The learning units starts with simple use cases followed by more complicated and complex scenarios.
First Steps¶
One template for all scripts¶
Objectives¶
![]() |
Entering individual commands in the interpreter or the console is tedious and error prone. Therefore it is better to save the instructions to a file and run that file in the interpreter. As a quick start we present and discuss a template. |
Exercises¶
Tasks: |
---|
- Open the editor in Blender, add a new file and copy the template.
- Start customizing the template.
- Replace the default name »Text« with a useful name. The name should have the extension »py«.
- Activate one of the three functions and run the script.
Template for exercises¶
First of all we show the template as a whole. The same template is listed in the appendix, so if you need a new fresh file also have a look there sample code (snippets).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #!bpy
"""
Name: 'Template'
Blender: 2.69
Group: 'Sample'
Tooltip: 'Template for new scripts, copy it and start coding...'
"""
import bpy
def function_1():
""" One line describing the task of this function """
pass
def function_2():
""" One line describing the task of this function """
print(__name__)
print(50 * '*')
def function_3():
""" One line describing the task of this function """
bpy.ops.mesh.primitive_cone_add(location=(1, 2, 1))
if __name__ == '__main__':
# call the function for testing
function_1()
#function_2()
#function_3()
|


Comments and documentation¶
If you count the lines in the template (31) and the lines used as comments (10) you can see that documentation is important. If your code is not documented, it is broken!
Read the following tips for a good programming style:
- Filenames: use a name that describes what the file is used for. Just open the file if you want to see what it does.
- Comments are used to automatically generate the documentation of a project.
- You have a better understanding what other authors have written.
- With comments you can describe algorithms and use cases.
Two kinds of comments are possible:
'''
This one liner says all about a module (file) in one sentence.
After an empty line, more text as documentation is possible.
Instead triples of »'«, also »"« can be used.
'''
In our template the lines 2-7, 12, 17 and 23 are comments. In big projects often a style guide is used. Most of them follow the guidelines in PEP-0257 und PEP-0008.
http://www.python.org/peps/pep-0008.html
http://www.python.org/peps/pep-0257.html
The second type of comments starts with a hash or number sign (#). In our template lines 28, 30 and 31 are examples for these kinds of comments. Line 28 is a real comment. On lines 30 and 31 the code is commented out, which prevents its execution.
Functions¶
Functions group code together to help organize it. A function has a name by which it can be called to execute the containing code. Not every task can be completed in one line and a function with a good name can make code easier to understand by describing what a specific piece of code does.
Three functions are defined in the template, each starts with the keyword def followed by the name of the function.
After the name of the function a list of parameters in braces is possible, if left empty (like in our template), the definition of the function ends with a pair of empty braces. The colon at the end of the line starts a new code block - this is not only true for functions - all kinds of blocks can be started with a colon.
All following lines (but at least one line) are indented with four spaces. If you want to end the block (in this case the function) you do that by unindenting the code that should not be part of the block anymore.
With this cool indentation trick it is not necessary to use curly braces or other constructs to define code blocks.
Have a look to the lines 10 to 13:
def function_1():
""" One line describing the task of this function """
pass
This function consists of two lines. The first is a so called »docstring« followed by the command pass. Because of the rule: every block needs at least one line, we use the keyword pass and it does what it should do: nothing, but the block building rule is satisfied.
Calling a function¶
A function is called by writing its name followed by a pair of braces like in line 29-31. The last two lines thought are commented out and won’t be executed. If you remove the number signs (#) at the beginning of the line, those functions will also be executed.
function_1()
#function_2()
#function_3()
Function print¶
In the function named »function_2« we use the function print. The result is visible in a console.
print(__name__)
print(50 * '*')
The first print gives us the name of our script, the second returns fifty stars.
Two ways to use a script¶
Line number 27 contains a little bit of magic! In the if-statement we check the content of a variable named »__name__«. This variable is set automatically by the Python interpreter depending on how the file is run. Two values are possible:
- the name of the file
- the name »__main__«
If the value is »__main__«, all indented commands after the colon are executed - so the colon starts a new block here. If the value is different the commands in the block are not executed. With this trick you are able to run your file as a script that calls the functions directly and reuse the functions defined in your script from a different file by importing it.
Module specific functions¶
In the function »function_3«. we call a special Blender function. its name is »primitive_cone_add« and part of an object hierarchy. The path to the function is constructed with dots as delimiters. functions which are part of objects are called method. The method »primitive_cone_add« needs one parameter to place the result of the method call in our 3D-World. Have a look in the 3D Window after execution.
bpy.ops.mesh.primitive_cone_add(location=(1, 2, 1))
Import modules¶
You can use elements from other files by importing them. This helps you to organize your code in several files and makes code reusable. This also gives you the possibility to use e.g. the function of Blender in your modules by importing them:
import bpy
Run a script¶
Objectives¶
![]() |
Now that you learned about the basic structure of a script, we will save, load and run the script to check if it does exactly what the programmer (i.e. you) has thought. |
Instructions¶
Tasks: |
---|
- Create a project folder for all scripts.
- Check and run the script discussed in the last station.
- Activate all functions from the template.
- Replace pass in function_1 with a print function.
- Add a fourth function that is creating a new sphere in the 3D World at location (1,1,3)





Start with console on MacOS¶

If you start Blender with a double click, no output will be shown. As a workaround start Blender within a console. Everybody who is familiar with a terminal, moves to the folder of blender.app and starts the application in the background with the following command:
./blender.app/Contents/MacOS/blender &
A second way to start Blender, search Blender with Finder and open the package with a right mouse click:


Blender is starting and a terminal window is opened. Do not close this window until you want to quit Blender. Errors and print output is now visible in the terminal window.
Parameter and functions¶
Objectives¶
![]() |
You learned about the structure of a script and how to run it. Now we define a new function with a parameter. This increases the flexibility of our own code and programms. |
Instructions¶
Tasks: |
---|
Create a new scrtipt and save it as bprint.py in your project folder.
Run the script and check the output in the 3D View.
Rewrite the script, the output function should set the text on a given position in the 3D-View. Use a second parameter for this task.
How is the function call for the mascot of Blender, the monkey named »Suzanne«?
bprint – output into the 3D view¶
How can you create text in a 3D world? With our own function we can add new functionality. A new function named bprint (b stands for Blender) will be created and used. Have a look at the complete script.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #!bpy
"""
Name: 'bprint.py'
Blender: 2.69
Group: 'Experiment'
Tooltip: 'Output of text in a scene'
"""
import bpy
def bprint(print_text):
"""Places a given text in the 3D view """
bpy.ops.object.text_add(location=(0, 0, 0), rotation=(0, 0, 0))
bpy.ops.object.editmode_toggle()
bpy.ops.font.delete()
bpy.ops.font.text_insert(text=print_text)
bpy.ops.object.editmode_toggle()
if __name__ == '__main__':
# Stop edit mode
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# delete all mesh objects from a scene
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
# delete all text objects from a scene
bpy.ops.object.select_by_type(type='FONT')
bpy.ops.object.delete()
# call the new function
bprint("If in doubt, just do it")
|
Defining parameters¶
In our template we used a parameter with the function print:
print(__name__)
The definition of the new funktion bprint defines a parameter as well. The parameter is named »print_text« - the name of the parameter(s) can be choosen freely.
#!bpy
"""
Name: 'bprint.py'
Blender: 2.69
Group: 'Experiment'
Tooltip: 'Output of text in a scene'
"""
import bpy
def bprint(print_text):
"""Places a given text in the 3D view """
bpy.ops.object.text_add(location=(0, 0, 0), rotation=(0, 0, 0))
bpy.ops.object.editmode_toggle()
bpy.ops.font.delete()
bpy.ops.font.text_insert(text=print_text)
bpy.ops.object.editmode_toggle()
if __name__ == '__main__':
# Stop edit mode
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# delete all mesh objects from a scene
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
# delete all text objects from a scene
bpy.ops.object.select_by_type(type='FONT')
bpy.ops.object.delete()
# call the new function
bprint("If in doubt, just do it")
Note: | Parameters are placed between the rounded braces behind the name of the function. |
---|
Optional parameters¶
If you define a function like in the example above, you can not call the function without passing an argument into the function. If you want to make the parameter optional you can give the parameter a default value. If that parameter does not get fed an argument when the function is called, the default value is used instead. This is useful if many parameters are possible but not all are mandatory. Examples for optional parameters:
def my_functions(location=(0,0,0))
def my_function(rotation=(0,1,1))
def my_function(text="hello, world")
note: | An optional parameter is defined as a key-value-pair, as shown in the examples above. |
---|
Blender showcase for parameters¶
Now let’s have a look at an example in Blender. First of all enlarge the info window in Blender:


For better readability of this »ASCII-tapeworm« all parameters are broken up to separate lines:
bpy.ops.mesh.primitive_cylinder_add(vertices=32,
radius=1,
depth=2,
end_fill_type='NGON',
view_align=False,
enter_editmode=False,
location=(-4.93998, -5.74176, 4.41665),
rotation=(0, 0, 0),
layers=(True,
False, False, False, False,
False, False, False, False,
False, False, False, False,
False, False, False, False,
False, False, False))
Most of the lines are optional. The shortest version is:
bpy.ops.mesh.primitive_cylinder_add(location=(-4.93998, -5.74176, 4.41665))
And with some better readable parameter values:
bpy.ops.mesh.primitive_cylinder_add(location=(2, 2, 2))
API¶
Search the API¶
Objectives¶
![]() |
Creating objects from a menu as with Add » Mesh » ... is easy. The same gaol is also achievable within a Python script. The API is important to get the necessary informations. |
Instructions¶
Tasks: |
---|
- Create an new Python script.
- Create a function that lists all methods available in Blender who create a mesh objects (primitive) .
- Create one instance from each object in your scene. No object should touch an other.
- Create a figure as a composition from a cone and a sphere (UV_Sphere). There are two possible solutions. Maybe you will find a third version.
Structure of the API¶
All available functionality is grouped by different modules. Only the first two are required in the beginning.
Application Modules
- Data Access (bpy.data)
- Operators (bpy.ops)
- Types (bpy.types)
- Utilities (bpy.utils)
- Path Utilities (bpy.path)
- Application Data (bpy.app)
- Property Definitions (bpy.props)
Standalone Modules
- Math Types & Utilities (mathutils)
- Font Drawing (blf)
- Audio System (aud)
Game Engine Modules
- Game Engine bge.types Module
- Game Engine bge.logic Module
- Game Engine bge.render Module
- Game Engine bge.events module
Which »primitives« are available?¶
If you start creating a complex world in 3D/Blender, often a good starting point is to create simple objects. Lets create the available mesh objects. But which objects are available?
First and easiest solution: have a look at the menu Add » Mesh » ... and look at the tooltip at the mouse pointer.
RTFM (read the fine manuals)
- Online documentation, search for »mesh primitive« on Blenderdocs
- Search the file »OperatorList.txt«.You can open it in the Blender editor using the menu sequence:Help » Operator Sheet Sheet.A copy is also included in the appendix: OperatorList.txt
If you are familiar with the structures in Blender, the console is a good starting point to discover the API.
If your are not successful searching the API, ask the community. A linklist is available in the appendix.
Note: | It is essential to work with the API, nobody is able to remember all possibilities! |
---|
Finding the right method(s)¶
Add mesh objects with Python instead using the menu is shown in a screenshot where the console is used. This is error prone, using a script is a good alternative.

Create the objects¶
Now that we know how to create new objects lets create a script for this task. Where to place the new object, is controlled by the parameter location, a tuple (values in rounded braces) with tree Values for the x-, y- und z-aches.
Here is a fragment...
bpy.ops.mesh.primitive_cube_add(location=(2, 2, 0))
bpy.ops.mesh.primitive_cylinder_add(location=(-2, -2, 0))
And so the final solution might look like:

Short video about using the API¶
Showcase¶
Try to recreate the following construct unsing only cubes and the menu Add » Mesh » ...!
Todo
create a script...
Search the scene¶
Objectives¶
![]() |
If the objects are created, in a second step further manipulations are necessary. The next question is: Which objects are available or exists in a scene? |
Instructions¶
Tasks: |
---|
- What is possible with lists? If in doubt, have a look at Python basics: lists
- Create a script that executes the code from this station.
- Add a new object to the scene and run the script again.
Show all objects¶
In an new Blender file, in a scene some objects are placed by default. How to get a list of available objects is shown with the following script:
#!bpy
"""
Name: 'object-list.py'
Blender: 2.69
Group: 'Discover'
Tooltip: 'Find objects in a scene'
"""
import bpy
def get_list_of_objects():
""" Print list of objects in a scene """
for i in bpy.data.objects:
print(i)
if __name__ == '__main__':
# call the new function
get_list_of_objects()
The modul bpy.data contains as structure objects. From this you can get a list of objects of the context, the scene. A for loop is used to print all objects:
Result:
<bpy_struct, Object("Camera")>
<bpy_struct, Object("Cube")>
<bpy_struct, Object("Lamp")>

This is the output on a command line on windows.

Compositions¶
Composite pieces¶
Objectives¶
![]() |
In this station a figure for the halma game will be created. It is a composition from mesh objects (primitives). |
Instructions¶
Tasks: |
---|
- Create a composite pice as shown in this learning unit.
- Move the new object with the mouse.
- Join the parts and name the object »halma_figure«.
- Move the new object again.
- Duplicate the object and have a look at the counter in the header of the info window.
First version¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #! bpy
"""
Name: 'halma_figure.py'
Blender: 269
Group: 'Example composit piece'
Tooltip: 'Crate and add a halma figure'
"""
import bpy
def halma_figure():
'''Crate a halma figure from a ball and a cone'''
# get the context
scn = bpy.context.scene
# names of the parts
parts = ['head', 'body', 'halma_figure']
# crate the head
bpy.ops.mesh.primitive_uv_sphere_add(location=(2, 2, .9))
obj = bpy.context.object
obj.scale[0] = .6
obj.scale[1] = .6
obj.scale[2] = .6
obj.name = parts[0]
scn.objects.active = scn.objects[parts[0]]
# create the body
bpy.ops.mesh.primitive_cone_add(location=(2, 2, 0))
obj = bpy.context.object
obj.scale[0] = .8
obj.scale[1] = .8
obj.name = parts[1]
scn.objects.active = scn.objects[parts[1]]
if __name__ == '__main__':
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
halma_figur()
|
Select the context¶
Selecting the context is the first step. Next step is creating and positioning objects. The context is assigned to a variable named scn.
# get the context
scn = bpy.context.scene
Name it¶
If you name the objects, later on it is easier to select one of them.
# names of the parts
parts = ['head', 'body', 'halma_figure']
First part of the composite pice¶
The sphere is the first part. We also scale the object afterwards and name it »head«.
# crate the head
bpy.ops.mesh.primitive_uv_sphere_add(location=(2, 2, .9))
obj = bpy.context.object
obj.scale[0] = .6
obj.scale[1] = .6
obj.scale[2] = .6
obj.name = parts[0]
Second part of the composite pice¶
Same procedure as with the first part.
# create the body
bpy.ops.mesh.primitive_cone_add(location=(2, 2, 0))
obj = bpy.context.object
obj.scale[0] = .8
obj.scale[1] = .8
obj.name = parts[1]
scn.objects.active = scn.objects[parts[1]]
Call the function¶
Let’s have a look to the final version. Are all pieces on the right place and have the right dimension? The old objects are deleted, so a frech and empty scene is used. You can check the info window. There are also statistics about the number of objects.
if __name__ == '__main__':
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
halma_figur()

How many objects are selected/available?¶

How to connect the parts to one?¶
Add the following lines of code to glue together the two pieces to a new one.
# connect parts to a new one
scn.objects[parts[0]].select = True
scn.objects[parts[1]].select = True
bpy.ops.object.join()
obj.name = parts[2]
Rotate/move/assemble¶
Objectives¶
![]() |
Creating new Objects is easy, afterwards we have to scale and move the pieces to a new location. How this can achieved is shown and explained in this station. |
Instructions¶
Tasks: |
---|
Move the pieces of the example to a different place.
Join the pieces to a single one and name it »marsmobil«.
Create the following object, shown in this picture:
- Create your own object.
Creating objects¶
The complete script, parts of the script are explained afterwards.
#!bpy
"""
Name: 'mars_mobile.py'
Blender: 2.69
Group: 'Composition'
Tooltip: 'Rotate, locate and scale objects assembled to a futuristic prototype'
"""
import bpy
def create_objects():
"""Create objects from a list of attributes
List values:
object name -- string
object type -- string
location -- tupel of integers
"""
objectlist = [('cu1', 'cube', (-6, 1, 1)),
('cu2', 'cube', (-3, 1, 1)),
('cy1', 'cylinder', (0, 1, 1)),
('cy2', 'cylinder', (3, 1, 1)),
('uv1', 'uv_sphere', (6, 1, 1)),
('uv2', 'uv_sphere', (9, 1, 1))]
for element in objectlist:
if element[1] == 'cube':
bpy.ops.mesh.primitive_cube_add(location=element[2])
if element[1] == 'cylinder':
bpy.ops.mesh.primitive_cylinder_add(location=element[2])
if element[1] == 'uv_sphere':
bpy.ops.mesh.primitive_uv_sphere_add(location=element[2])
# give it a name
obj = bpy.context.object
obj.name = element[0]
def select_cubes():
"""Sample: select two objects by name """
bpy.ops.object.select_pattern(pattern="cu2")
bpy.ops.object.select_pattern(pattern="cu1")
def activate_object():
"""Sample: activate an object by name"""
bpy.context.scene.objects.active = bpy.data.objects["cu2"]
def scale_cu2():
"""Select, scale and move cube 2"""
bpy.context.scene.objects.active = bpy.data.objects["cu2"]
obj = bpy.context.scene.objects.active
obj.scale = (1, 1, 3)
obj.location = (-3, 1, 3)
def scale_cy():
"""Select cylinders, scale and move"""
bpy.context.scene.objects.active = bpy.data.objects["cy1"]
obj = bpy.context.scene.objects.active
obj.scale = (1, 1, .2)
obj.location = (0, 1, .2)
bpy.context.scene.objects.active = bpy.data.objects["cy2"]
obj = bpy.context.scene.objects.active
obj.scale = (1, 1, .2)
obj.location = (3, 1, .2)
def assemble_mars_mobile():
"""Create a composite piece """
pi_half = 3.141592/2
# body
bpy.context.scene.objects.active = bpy.data.objects["cu2"]
obj = bpy.context.scene.objects.active
obj.location = (-3, 1, 1.5)
# rotation
obj.rotation_euler = [pi_half, 0, 0]
# wheel (right)
bpy.context.scene.objects.active = bpy.data.objects["cy1"]
obj = bpy.context.scene.objects.active
obj.location = (-4, 2, 1)
obj.rotation_euler = [0, pi_half, 0]
# wheel (left)
bpy.context.scene.objects.active = bpy.data.objects["cy2"]
obj = bpy.context.scene.objects.active
obj.location = (-2, 2, 1)
obj.rotation_euler = [0, pi_half, 0]
# wheel (front)
bpy.context.scene.objects.active = bpy.data.objects["uv1"]
obj = bpy.context.scene.objects.active
obj.location = (-3, -1, 1)
# cabin
bpy.context.scene.objects.active = bpy.data.objects["cu1"]
obj = bpy.context.scene.objects.active
obj.location = (-3, 2, 3)
bpy.context.scene.objects.active = bpy.data.objects["uv2"]
obj = bpy.context.scene.objects.active
obj.location = (-3, 2, 4)
if __name__ == '__main__':
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# delete all meshes from a szene
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
create_objects()
## comment and uncomment the lines as you like
# select_cubes()
# aktivate_object()
# scale_cu2()
# scale_cy()
# assemble_mars_mobile()
How it works¶
Every function is solving a particular problem. You can test the different functions if you comment or uncomment the function calls at the end of the script.
The first step is creating all objects. It is important to name the objects.

Many objects can be selected, but only one at the time can be the active one


Select objects¶
def select_cubes():
"""Sample: select two objects by name """
bpy.ops.object.select_pattern(pattern="cu2")
bpy.ops.object.select_pattern(pattern="cu1")
Activate an object¶
Manipulations are only possible with the active object.
def activate_object():
"""Sample: activate an object by name"""
bpy.context.scene.objects.active = bpy.data.objects["cu2"]
Scale objectes¶
Scaling an object is possible in tree dimensions. If no scaling should happened, the scaling factor is 1. In our example only the z-achs is scaled. Afterwards we move the center of the objects, therefore they are positioned on the ground again.
def scale_cu2():
"""Select, scale and move cube 2"""
bpy.context.scene.objects.active = bpy.data.objects["cu2"]
obj = bpy.context.scene.objects.active
obj.scale = (1, 1, 3)
obj.location = (-3, 1, 3)
Both cylinders are minimized.
def scale_cy():
"""Select cylinders, scale and move"""
bpy.context.scene.objects.active = bpy.data.objects["cy1"]
obj = bpy.context.scene.objects.active
obj.scale = (1, 1, .2)
obj.location = (0, 1, .2)
bpy.context.scene.objects.active = bpy.data.objects["cy2"]
obj = bpy.context.scene.objects.active
obj.scale = (1, 1, .2)
obj.location = (3, 1, .2)
Rotation with Euler¶
All objects are scaled and in the next step they can be assembled. Some parts have to be rotated. We calculate the value once:
pi_half = 3.141592/2
and use it as often as needed and pi_half. It is always a rotation of 90°.
obj.rotation_euler = [pi_half, 0, 0]
More about calculating a rotation is explained at Rotating an object
Now we have finished our prototype and the next car race at the mars can start :-)

Todo
translate station eurlerrotaton linked from here...
Labyrinth/maze¶
Objectives¶
![]() |
This station is a repetition of techniques already shown. But wait, it is also the starting point for a game that we build in the End of these course. It is named »Sokoban«. If you don’t know this game you can read more about it at Game Sokoban |
Labyrinth¶
Our starting point is a maze build out of cubes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #! bpy
"""
Name: 'labyrinth.py'
Blender: 269
Group: 'Example'
Tooltip: 'Creating a maze'
"""
import bpy
level_00 = ["###################",
"#. #",
"# $ #",
"# #",
"# #",
"# @ #",
"# #",
"# #",
"# #",
"# #",
"###################"]
level_01 = [" ##### ",
" # # ",
" #$ # ",
" ### $## ",
" # $ $ # ",
"### # ## # ###### ",
"# # ## ##### ..# ",
"# $ $ ..# ",
"##### ### #@## ..# ",
" # ######### ",
" ####### "]
def sokobanLevel(level):
"""Create a maze by adding cube objects"""
cols = len(level[0])
rows = len(level)
for row in range(rows):
for i in range(cols):
if level[row][i] == '#':
bpy.ops.mesh.primitive_cube_add(location=(row*2, i*2, 0))
if __name__ == '__main__':
sokobanLevel(level_00)
|
Iterate with for¶
The function len gives us the number to iterate in a for loop through the lists.
cols = len(level[0])
rows = len(level)
Comparison¶
With each comparison we decide to generate a new object otherwise nothing happened.
for row in range(rows):
for i in range(cols):
if level[row][i] == '#':
bpy.ops.mesh.primitive_cube_add(location=(row*2, i*2, 0))
Function call with parameter¶
The function is now called with one of the available levels (level_00, level_01,level_02...).
if __name__ == '__main__':
sokobanLevel(level_00)
Material¶
Material – colored labyrinth¶
Objectives¶
![]() |
So far, our objects are unique grey. Now lets make the new world a little bit colorful. Therefor we are using materials and/or textures. |
Instructions¶
Tasks: |
---|
- Construct your own new level as shown in the last station.
- Create new types of objects for the character $ and @ (ie. cone, cylinder).
- Add different colors for every type of object.
Das Labyrinth¶
Creating the labyrinth is the same procedure as before but in addition we add a material.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #! bpy
"""
Name: 'colored_labyrinth.py'
Blender: 269
Group: 'Materials'
Tooltip: 'Generates colorful objects by materials'
"""
import bpy
level_00 = ["###################",
"#. #",
"# $ #",
"# #",
"# #",
"# @ #",
"# #",
"# #",
"# #",
"# #",
"###################"]
level_01 = [" ##### ",
" # # ",
" #$ # ",
" ### $## ",
" # $ $ # ",
"### # ## # ###### ",
"# # ## ##### ..# ",
"# $ $ ..# ",
"##### ### #@## ..# ",
" # ######### ",
" ####### "]
MATERIAL_RED = bpy.data.materials.new('Red Material')
def sokobanLevel(level):
"""Generating a labyrinth with colored cubes"""
cols = len(level[0])
rows = len(level)
for row in range(rows):
for i in range(cols):
if level[row][i] == '#':
bpy.ops.mesh.primitive_cube_add(location=(row*2, i*2, 0))
obj = bpy.context.object
setColor(obj, MATERIAL_RED, (1, 0, 0))
def setColor(obj, material, color):
material.diffuse_color = color
material.specular_hardness = 200
obj.data.materials.append(material)
if __name__ == '__main__':
sokobanLevel(level_00)
|
Create a new material¶
Materials in Blender are distinguished by name and exists independent from objects. Therefor it is possible to put one material to different objects.
MATERIAL_RED = bpy.data.materials.new('Red Material')
Save object¶
The new object is allocated to a variable named »obj«.
for row in range(rows):
for i in range(cols):
if level[row][i] == '#':
bpy.ops.mesh.primitive_cube_add(location=(row*2, i*2, 0))
obj = bpy.context.object
setColor(obj, MATERIAL_RED, (1, 0, 0))
Function: setColor¶
The function setColor needs tree parameters: object, material and color.
setColor(obj, MATERIAL_RED, (1, 0, 0))
Allocate material¶
Within setColor the parameters are used to change the given object.
def setColor(obj, material, color):
material.diffuse_color = color
material.specular_hardness = 200
obj.data.materials.append(material)
Result¶

Material – colored faces¶
Objectives¶
![]() |
In the last station we applied the material to the hole object. Now we select a few faces to color only parts of the object surface. |
Instructions¶
Tasks: |
---|
Create a cylinder and change the color of the top and bottom base.
Create a chessboard like in this image:
- Create an set of tokens for the game draughts (or checkers) an the board.Louis-Léopold Boilly (1761–1845)Painting of a family game of checkers(»jeu des dames«)
A colored cube¶
To be able to color of one or more faces, select them. At first the script:
#!bpy
"""
Name: 'colored_cube.py'
Blender: 2.69
Group: 'Material'
Tooltip: 'Colored faces'
"""
import bpy
red = bpy.data.materials.new('Red')
blue = bpy.data.materials.new('Blue')
yellow = bpy.data.materials.new('Yellow')
def setColor(obj, material, color):
material.diffuse_color = color
material.specular_hardness = 200
obj.data.materials.append(material)
def colored_cube():
""" A three colored cube """
bpy.ops.mesh.primitive_cube_add(location=(0,0,0))
ob = bpy.context.object
ob.name = 'three'
setColor(ob, red, (1, 0, 0))
setColor(ob, yellow, (1, 1, 0))
setColor(ob, blue, (0, 0, 1))
# apply the colors
for face in ob.data.polygons:
face.material_index = face.index % 3
if __name__ == '__main__':
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
colored_cube()
Name the colors¶
Every color should have a name. This is the first Step.
red = bpy.data.materials.new('Red')
blue = bpy.data.materials.new('Blue')
yellow = bpy.data.materials.new('Yellow')
Add the materials¶
This is little bit tricky, to add a color for each face. Step by step:
- All faces of an object (a cube has six) are saved in a list of polygons.
- In a for loop wie iterate over this list.
- The index number from the list is divided by three with the modulo operator. So we get three possible results 0, 1 or 2.
- Each number is connected with a color.
- Finally the color number is assigned to the material index, because materials are also managed with an index.
# apply the colors
for face in ob.data.polygons:
face.material_index = face.index % 3
hint: | In old tutorials before 2.68 faces are selected from a list named faces. Now the new list and name is polygons. |
---|
Find faces¶
Objectives¶
![]() |
Often an object is collection of huge number of polygons, it is not easy to find the index values for a spezific area or number of polygons. A little script helps you to find the polygones of interest. |
Instructions¶
Tasks: |
---|
- Test the script and discover how the functions work.
- Change the color of eyes from »Suzanne«.
- Try to colorize the mouth of »Suzanne«.
- Try colorize a part of a figure that you created yourself.
The script¶
#!bpy
"""
Name: 'show_faces.py'
Blender: 2.68
Group: 'Material'
Tooltip: 'Materialien an einzelne Flächen zuweisen'
"""
import bpy
red = bpy.data.materials.new('Red')
blue = bpy.data.materials.new('Blue')
yellow = bpy.data.materials.new('Yellow')
def setColor(obj, material, color):
material.diffuse_color = color
material.specular_hardness = 200
obj.data.materials.append(material)
def monkey():
""" a new monkey """
bpy.ops.mesh.primitive_monkey_add(location=(0, 0, 1), rotation=(0, 0, .5))
ob = bpy.context.object
ob.name = 'Suzanne'
setColor(ob, red, (1, 0, 0))
setColor(ob, yellow, (1, 1, 0))
setColor(ob, blue, (0, 0, 1))
# colorize the whole object
for poly in ob.data.polygons:
poly.material_index = 1
def coloredEyes(name):
bpy.context.scene.objects.active = bpy.data.objects[name]
me = bpy.context.object
# changes are visible after switch to the edit mode
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')
polygons_augen = [48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63]
# blue Eyes
for poly in me.data.polygons:
if poly.index in polygons_augen:
poly.material_index = 2
print(poly.index, polygons_augen)
def getIndexOfFaces(name):
""" Print the index of faces to the console
- Switch to the edit-Mode
- select faces
- the output ist shown in the console
"""
bpy.context.scene.objects.active = bpy.data.objects[name]
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')
me = bpy.context.object.data
for poly in me.polygons:
if poly.select:
print("Polygon index: %d, length: %d" % (poly.index,
poly.loop_total))
bpy.ops.object.mode_set(mode='EDIT')
if __name__ == '__main__':
# collect the object names
obj_names = []
for obj in bpy.context.scene.objects:
obj_names.append(obj.name)
# if no Suzanne is in the list, create one
if not obj_names.count("Suzanne"):
monkey()
# switch in the edit mode (3D View) and selct one ore more faces
# selected index nummers can be found on the command line
getIndexOfFaces('Suzanne')
# If you put the printed index values in a function
# the process is repeatable
coloredEyes('Suzanne')
Materials/Textures – procedural¶
Objectives¶
![]() |
Procedural textures are explained in this station. It is only the starting point to this complex topic. |
Instructions¶
Tasks: |
---|
- Run the script and check the functionality of the functions.
- Change the parameters of a texture.
- Set material and texture to a new object.
All types in one image – the mapping types will be shown in a separate station. On the picture you can see the names of the textures and how the rendered objects looks like.

Code used to render the image¶
#!bpy
"""
Name: 'material_procedural.py'
Blender: 2.69
Group: 'Materials and Textures'
Tooltip: 'Texturen procedurale'
"""
import bpy
def materialcheck(obj, materialtype):
""" Put a procedural textur on a object."""
# used names
matname = "mat" + materialart
texname = "tex" + materialart
# new material
material = bpy.data.materials.new(matname)
material.diffuse_color = (0, .5, 0)
obj.data.materials.append(material)
# new texture
textur = bpy.data.textures.new(texname, type=materialart)
# lits all properties and methods of a texture
# print(dir(textur))
# connect texture with material
bpy.data.materials[matname].texture_slots.add()
bpy.data.materials[matname].active_texture = textur
if __name__ == '__main__':
# switch to object mode if edit mode is activ
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# clear the scene
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
# all names of procedurale texturen, without IMAGE and LANDSCAPE
materials = ['BLEND',
'CLOUDS',
'DISTORTED_NOISE',
'MAGIC',
'MARBLE',
'MUSGRAVE',
'NOISE',
'OCEAN',
'POINT_DENSITY',
'STUCCI',
'VORONOI',
'VOXEL_DATA',
'WOOD']
x, y, z = 1, 0, 1
for i in materials:
# new line in the middle of the list
if z % 7 == 0:
y = 4
x = 1
bpy.ops.mesh.primitive_cylinder_add(location=(x, y, 0))
obj = bpy.context.scene.objects.active
obj.name = 'obj-%0.2d' % (z)
obj = bpy.context.scene.objects['obj-%0.2d' % (z)]
x += 3
z += 1
materialcheck(obj, materialtype=i)
hint: | Run the script, set the camera on the right position and start the menu sequence: Render » Render Image. |
---|
print(dir(textur))
Output example for the texture »WOOD«:
['__doc__', '__module__', '__slots__', 'animation_data',
'animation_data_clear', 'animation_data_create', 'bl_rna',
'color_ramp', 'contrast', 'copy', 'evaluate', 'factor_blue',
'factor_green', 'factor_red', 'intensity', 'is_library_indirect',
'is_updated', 'is_updated_data', 'library', 'nabla', 'name',
'node_tree', 'noise_basis', 'noise_basis_2', 'noise_scale',
'noise_type', 'rna_type', 'saturation', 'tag', 'turbulence',
'type', 'update_tag', 'use_color_ramp', 'use_fake_user',
'use_nodes', 'use_preview_alpha', 'user_clear', 'users',
'wood_type']
Materials/Textures – mapping¶
Objectives¶
![]() |
Mapping is a common method to put pictures on objects. With simple objects it is possible to use a script. This is demonstrated in this station. Move the final cube to see all pictures applied. How to animate the cube is shown in an other station. |
Instructions¶
Tasks: |
---|
- Start the functions and have a look to the resulting output.
- Replace the images with your own.
- Alter the code, let one face empty.
Sample images¶
Download (pictures_uv_mapping.zip)
Putting images (2D) on a body (3D) is named UV-Mapping. The letters U and V are used, because X, Y and Z always used for positioning an object in a 3D-World. Like materials textures are managed independent form any object. Textures are also never directly connected to an object, instead a material is used. So wie have a chain: texture » material » body.
In our first example a picture is placed on one site of a cube:

The second example is showing different images on all faces of a cube:

Have I heard the term »Mindcraft« (hava a look at exercise tree):

One image on all faces¶
#!bpy
"""
Name: 'mat1.py'
Blender: 2.69
Group: 'Sample'
Tooltip: 'Put one image on each site of a cube'
"""
import bpy
import os
def uvMapperCube(obj):
""" Put image to an object"""
# used names
matname = "matUVMapping"
texname = "texUVMapping"
# new material
if not matname in bpy.data.materials:
material = bpy.data.materials.new(matname)
material.diffuse_color = (0, .5, .4)
obj.data.materials.append(material)
# new texture
texUV = bpy.data.textures.new(texname, type="IMAGE")
image_path = os.path.expanduser("//wuerfelbilder/blume.jpg")
image = bpy.data.images.load(image_path)
texUV.image = image
# connect textur with material
bpy.data.materials[matname].texture_slots.add()
bpy.data.materials[matname].active_texture = texUV
bpy.data.materials[matname].texture_slots[0].texture_coords = "GLOBAL"
bpy.data.materials[matname].texture_slots[0].mapping = "CUBE"
def delete_old_stuff():
# escape edit mode
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# delete all mesh objects
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
# delete all materials
for i in bpy.data.materials.values():
bpy.data.materials.remove(i)
# delete all textures
for i in bpy.data.textures.values():
bpy.data.textures.remove(i)
# delete all images
for i in bpy.data.images.values():
# delete image path, this is only possible without a user
i.user_clear()
# delete all, except »Render Result«
if i.name != "Render Result":
bpy.data.images.remove(i)
if __name__ == "__main__":
delete_old_stuff()
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0))
obj = bpy.context.scene.objects.active
obj.name = 'image-as-uvmapping'
obj = bpy.context.scene.objects['image-as-uvmapping']
uvMapperCube(obj)
One image on each Face¶
#!bpy
"""
Name: 'mat2.py'
Blender: 2.69
Group: 'Sample'
Tooltip: 'Put six different images to cube'
"""
import bpy
import os
def uvMapperCube(obj):
""" Put images to an object"""
# used names
namen = {'blume.jpg': ('mat01', 'tex01'),
'boot.jpg': ('mat02', ' tex02'),
'jueterbog.jpg': ('mat03', 'tex03'),
'kopf.jpg': ('mat04', 'tex04'),
'moster.jpg': ('mat05', 'tex05'),
'telefon.jpg': ('mat06', 'tex06'),
#'warnung.jpg': ('mat07', 'tex07')
}
for i in namen.keys():
# new material
matname = namen[i][0]
if not matname in bpy.data.materials:
material = bpy.data.materials.new(matname)
material.diffuse_color = (0, .5, .4)
obj.data.materials.append(material)
# new texture
texUV = bpy.data.textures.new(namen[i][1], type="IMAGE")
image_path = os.path.expanduser("//wuerfelbilder/{}".format(i))
image = bpy.data.images.load(image_path)
texUV.image = image
# connect texture with material
bpy.data.materials[matname].texture_slots.add()
bpy.data.materials[matname].active_texture = texUV
bpy.data.materials[matname].texture_slots[0].texture_coords = "ORCO"
bpy.data.materials[matname].texture_slots[0].mapping = "CUBE"
# apply one material to one face
for face in obj.data.polygons:
face.material_index = face.index
def delete_old_stuff():
# escape edit mode
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# delete all mesh objects
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
# delete all materials
for i in bpy.data.materials.values():
bpy.data.materials.remove(i)
# delete all textures
for i in bpy.data.textures.values():
bpy.data.textures.remove(i)
# delete all images
for i in bpy.data.images.values():
# delete image path, this is only possible without a user
i.user_clear()
# delete all, except »Render Result«
if i.name != "Render Result":
bpy.data.images.remove(i)
if __name__ == "__main__":
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
delete_old_stuff()
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0))
obj = bpy.context.scene.objects.active
obj.name = 'image-as-uvmapping'
obj = bpy.context.scene.objects['image-as-uvmapping']
uvMapperCube(obj)
Effects¶
Text: Bevel & Extrude¶
Objectives¶
![]() |
Text is often used in opening and closing credits of a film. In this station we create a 3D Version from plain text. |
Instructions¶
Tasks: |
---|
- Create your own text.
- Configure the environment (camera, lightning, ... see also »Configure your world«
- Add a material to the text.
- Render the final image.
3D-Effekt¶
#!bpy
"""
Name: 'text.py'
Blender: 2.69
Group: 'Text'
Tooltip: 'Text with 3D-Effekt'
"""
import bpy
def add_a_text(text="hallo"):
""" Add text """
if not 'Text' in bpy.data.objects:
bpy.ops.object.text_add()
bpy.data.objects['Text'].data.body = text
def extrudeText():
""" Text: extrude """
bpy.context.object.data.extrude = 0.04
def bevelText():
""" Text: bevel """
bpy.context.object.data.bevel_depth = 0.02
bpy.context.object.data.bevel_resolution = 8
def text2mesh():
""" Text: transform to a mesh """
# ATTENTION: Characters are not editable any more!
bpy.ops.object.convert(target='MESH', keep_original=False)
if __name__ == "__main__":
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
add_a_text("Hallo Du Pappnase")
bpy.context.scene.objects.active = bpy.data.objects['Text']
extrudeText()
bevelText()
#text2mesh()
Example¶
This is one version, experiment with the control elements in the property window of Blender.

Blender Extended¶
If a project grows up, you need technics to manage objects and files. Two of them are shown in the next stations. Modules are useful to split the code in smaller units. Classes are useful to follow an object oriented paradigm while programming applications.
Modules¶
Module I¶
Objectives¶
![]() |
Large projects can no longer manage them in a file. The source code will quickly become confusing. Therefore, there is, as in other languages also, for Python a solution that is shown here. |
Instructions¶
Tasks: |
---|
- Move parts of the source code in a second file (levels.py) from.
- Import the outsourced parts.
- Check whether the program behaves, as previously working.
- Add a third level in the file levels.py.
One module for levels¶
To separate level definitions from the code that creates the maze we create two files. The first one is named levels.py. From now on, a game designer could create new levels, while a programmer cares about the game logic.
#! bpy
"""
Name: 'levels.py'
Blender: 269
Group: 'Modules'
Tooltip: 'Maze definitions'
"""
level_00 = ["###################",
"#. #",
"# $ #",
"# #",
"# #",
"# @ #",
"# #",
"# #",
"# #",
"# #",
"###################"]
level_01 = [" ##### ",
" # # ",
" #$ # ",
" ### $## ",
" # $ $ # ",
"### # ## # ###### ",
"# # ## ##### ..# ",
"# $ $ ..# ",
"##### ### #@## ..# ",
" # ######### ",
" ####### "]
The main module¶
Reusing code from other files (other authors/programmers) is achieved with the import statement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #! bpy
"""
Name: 'sokoban.py'
Blender: 269
Group: 'Modules'
Tooltip: 'Creating a game called Sokoban and using modules'
"""
import bpy
from levels import level_00
from levels import level_01
def sokobanLevel(level):
"""Create a maze with cubes"""
cols = len(level[0])
rows = len(level)
for row in range(rows):
for i in range(cols):
if level[row][i] == '#':
bpy.ops.mesh.primitive_cube_add(location=(row*2, i*2, 0))
if __name__ == '__main__':
sokobanLevel(level_00)
sokobanLevel(level_01)
|
Errors¶
Again and again, errors occur and it is important to find the cause. For example a small typo occurred. The errors are always shown as a traceback in the console.
Traceback (most recent call last):
File "/Users/.../sokoban.py", line 10, in <module>
ImportError: cannot import name Level_01
Error: Python script fail, look in the console for now...
The file path in this Traceback is shorten. Important is the line number, often indicating the main cause of the error. Also important is the type of error, in this case the ImportError, because Python is case-sensitive. So the Error will disappear, if you replace L with l.
Connecting Python scripts with a Blender file¶
The classical way to find modules in Python is limited in Blender. The easiest workaround is to include the Python scripts into the Blender file.
Step by step¶
- Create a new blend file.
- Load every Python script.
- For each file call the menu: Text | Make internal.

Save the Blender file and all modules are available.
External Editors¶
The internal Editor is not so bad, but if you like to use your prefered Editor, for example emacs, vi on Linux or PyCharm on Windows, you can edit the external Python scripts. A small icon is indicating, that you have altered the content of the file and you are forced to reload the script, starting with a right click on this icon.

Module II¶
Objectives¶
![]() |
Now we connect tree Python script to build a complete szene |
Instructions¶
Tasks: |
---|
What are the differences to the modules, used before.
Create your own scene and manage the objects in separate modules (files).
- Add a module for the ground. Let it look like a chessboard.See also learning station: materials
Module: checker.py¶
#! bpy
"""
Name: 'checker.py'
Blender: 269
Group: 'Modules'
Tooltip: 'Create a checker'
"""
import bpy
def checker(location=(0, 0, 0)):
'''Checker build from a cone and a sphere'''
# save the context
scn = bpy.context.scene
# list of names
parts = ['head', 'body', 'checker']
# head
bpy.ops.mesh.primitive_uv_sphere_add(location=(2, 2, .9))
obj = bpy.context.object
obj.scale[0] = .6
obj.scale[1] = .6
obj.scale[2] = .6
obj.name = parts[0]
scn.objects.active = scn.objects[parts[0]]
# body
bpy.ops.mesh.primitive_cone_add(location=(2, 2, 0))
obj = bpy.context.object
obj.scale[0] = .8
obj.scale[1] = .8
obj.name = parts[1]
scn.objects.active = scn.objects[parts[1]]
# connecting the parts
scn.objects[parts[0]].select = True
scn.objects[parts[1]].select = True
bpy.ops.object.join()
obj.name = parts[2]
obj.location = location
if __name__ == '__main__':
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
checker(location=(2, 2, 2))
Module: levels.py¶
#! bpy
"""
Name: 'levels.py'
Blender: 269
Group: 'Modules'
Tooltip: 'Maze definitions'
"""
level_00 = ["###################",
"#. #",
"# $ #",
"# #",
"# #",
"# @ #",
"# #",
"# #",
"# #",
"# #",
"###################"]
level_01 = [" ##### ",
" # # ",
" #$ # ",
" ### $## ",
" # $ $ # ",
"### # ## # ###### ",
"# # ## ##### ..# ",
"# $ $ ..# ",
"##### ### #@## ..# ",
" # ######### ",
" ####### "]
Main programm: sokoban.py¶
#! bpy
"""
Name: 'sokoban_m2.py'
Blender: 269
Group: 'Modules'
Tooltip: 'Create a maze'
"""
import bpy
import levels
from checker import checker
def sokobanLevel(level):
"""Create a level managed by modules"""
cols = len(level[0])
rows = len(level)
for row in range(rows):
for i in range(cols):
coords = (row*2, i*2, 0)
if level[row][i] == '#':
bpy.ops.mesh.primitive_cube_add(location=coords)
elif level[row][i] == '@':
checker(location=coords)
elif level[row][i] == '$':
bpy.ops.mesh.primitive_cone_add(location=coords)
if __name__ == '__main__':
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
sokobanLevel(levels.level_00)
Result¶

Classes¶
Class: Simple¶
Objectives¶
![]() |
Classes are part of a programming paradigma. We use Python which is a object oriented programming language, With this knowledge it is possible to build and add new functionality to Blender and your projects. Let’s see how it works. |
Instructions¶
Tasks: |
---|
- Read the text about objectoriented programming on wikipedia.
- Build and test the class shown in this station.
- Replace the text with your own.
- Mix the concept of a class with positioning a Text in the 3D-View (Text in 3D).
Simple class¶
This example is taken from: Blender API.
The code:
import bpy
class HelloWorldOperator(bpy.types.Operator):
bl_idname = "wm.hello_world"
bl_label = "Minimal Operator"
def execute(self, context):
print("Hello World")
return {'FINISHED'}
bpy.utils.register_class(HelloWorldOperator)
# test call to the newly defined operator
bpy.ops.wm.hello_world()
Notes about the code (step by step)¶
A class definition is introduced by the keyword class, followed by a self-selected name and finally a pair of parentheses. As in our case, the class can also inherit properties of another class, in our example bpy.types.Operator. A colon marks the start of the block, the next line(s) must be indented.
class HelloWorldOperator(bpy.types.Operator):
Two variables are defined that. This ist necessary for the integration of our class in the Blender system.
bl_idname = "wm.hello_world"
bl_label = "Minimal Operator"
No class without methods. A method is introduced by the keyword def and the first parameter used, is self. With self the connection between function and class is defined. In our example, the second parameter context is mandatory and used by Blender. The function does not really do much. Finally a typical blender statement, gives the value {‘FINISHED’} back.
def execute(self, context):
print("Hello World")
return {'FINISHED'}
Finally, the new class is registered in the Blender system and also a trial statement is called. The result can be seen in the console. There, the Hello World should be printed as expected.
bpy.utils.register_class(HelloWorldOperator)
# test call to the newly defined operator
bpy.ops.wm.hello_world()
Class: Mesh I¶
Objectives¶
![]() |
In an object-oriented world, parts of the model are mapped into classes. This has many advantages and the most important rules are shown here. Here is a complex example of how to create a basic shape, which does not exist in Blender. It is a pyramid. |
Instructions¶
Tasks: |
---|
- Repeat the sub-steps shown here to create a class until you have a working version.
- Create a class of its own »primitive«, eg. a wedge or the base form of a hex key.
- Add a material to the class, which is given to the new object.
Design data for a mesh¶
We start with the ground of a pyramid. The first step is defining the vertices an there location in a 3D scene. After that, then for each area, the index values of each surface section summarizes (a face is defined). The latter determines whether an area is closed or remains open, if it is not defined.
def pyramid_values():
"""
This function takes inputs and returns vertex and face arrays.
no actual mesh data creation is done here.
"""
verts = [(-1, +1, 0),
(+1, +1, 0),
(+1, -1, 0),
(-1, -1, 0)]
faces = [(0, 1, 2, 3),]
return verts, faces
The coordinates of each point are given by the focus of our future pyramid. The whole thing still possible in a clockwise sense.
Todo
Picture with coordinats
Class: AddPyramid¶
After the keyword class follows a self-selected class name AddPyramid.
As in the example with the simple class, our class inherits from a class in Blender: bpy.types.Operator. We need tree variable, for the correkt integration of our new class into Blender, its menues or lists for selection.
class AddPyramid(bpy.types.Operator):
"""Add a simple pyramid mesh"""
bl_idname = "mesh.primitive_pyramid_add"
bl_label = "Add Pyramid"
bl_options = {'REGISTER', 'UNDO'}
Properties¶
Also tree parameters are nessesary to place a new pyramid in a 3D-World.
"""Add a simple pyramid mesh"""
bl_idname = "mesh.primitive_pyramid_add"
bl_label = "Add Pyramid"
bl_options = {'REGISTER', 'UNDO'}
Method: execute¶
The methode execute is using the coordintate given by the function pyramid_values(). The values are transfered to locale variables: verts_loc and faces.
Now two new objects are created mit the operator new().
- one Mesh for the coordinates
- one bmesh for ...
Todo
bmash description
def execute(self, context):
verts_loc, faces = pyramid_values()
mesh = bpy.data.meshes.new("Pyramid")
bm = bmesh.new()
Coordinates second part¶
With two for loops the coordintes are added to the new objects.
for v_co in verts_loc:
bm.verts.new(v_co)
for f_idx in faces:
bm.faces.new([bm.verts[i] for i in f_idx])
Create objects¶
Afte the preparation, a new object can be created and placed on a given location.
bm.to_mesh(mesh)
mesh.update()
self.location = (0, 0, 0)
Display the object¶
With object_utils the object gets visible in a szene. If all works fine, the return value {‘FINISHED’} is given back.
# set the new object into the szene
from bpy_extras import object_utils
object_utils.object_data_add(context, mesh, operator=self)
return {'FINISHED'}
Register/Unregister¶
Blender needs a registration and unregristreation command for the new class.
def register():
bpy.utils.register_class(AddPyramid)
def unregister():
bpy.utils.unregister_class(AddPyramid)
Test run¶
Lets test the creation of a new pyramid, so far we only have the base.
if __name__ == "__main__":
register()
# create a instanz of a pyramid
bpy.ops.mesh.primitive_pyramid_add()
With the next step, we will finish the pyramid.
The code for the class¶
import bpy
import bmesh
from bpy.props import BoolProperty, FloatVectorProperty
def pyramid_values():
"""
This function takes inputs and returns vertex and face arrays.
no actual mesh data creation is done here.
"""
verts = [(-1, +1, 0),
(+1, +1, 0),
(+1, -1, 0),
(-1, -1, 0)]
faces = [(0, 1, 2, 3), ]
return verts, faces
class AddPyramid(bpy.types.Operator):
"""Add a simple pyramid mesh"""
bl_idname = "mesh.primitive_pyramid_add"
bl_label = "Add Pyramid"
bl_options = {'REGISTER', 'UNDO'}
# generic transform props
view_align = BoolProperty(name="Align to View",
default=False)
location = FloatVectorProperty(name="Location",
subtype='TRANSLATION')
rotation = FloatVectorProperty(name="Rotation",
subtype='EULER')
def execute(self, context):
verts_loc, faces = pyramid_values()
mesh = bpy.data.meshes.new("Pyramid")
bm = bmesh.new()
for v_co in verts_loc:
bm.verts.new(v_co)
for f_idx in faces:
bm.faces.new([bm.verts[i] for i in f_idx])
bm.to_mesh(mesh)
mesh.update()
self.location = (0, 0, 0)
# set the new object into the szene
from bpy_extras import object_utils
object_utils.object_data_add(context, mesh, operator=self)
return {'FINISHED'}
def register():
bpy.utils.register_class(AddPyramid)
def unregister():
bpy.utils.unregister_class(AddPyramid)
if __name__ == "__main__":
register()
# create a instanz of a pyramid
bpy.ops.mesh.primitive_pyramid_add()
Class: Mesh II¶
Objectives¶
![]() |
Now we will finish the pyramid class |
Instructions¶
Tasks: |
---|
- Repeat the sub-steps shown here to create a class until you have a working version.
- Create a class of its own »primitive«, eg. a wedge or the base form of a hex key.
- Add a material to the class, which is given to the new object.
Design data for a mesh¶
Define the tip of the pyramid and defining the faces, is the last step.
def pyramid_values():
"""
This function takes inputs and returns vertex and face arrays.
no actual mesh data creation is done here.
"""
verts = [(-1, +1, 0),
(+1, +1, 0),
(+1, -1, 0),
(-1, -1, 0),
(0, 0, +2)]
faces = [(0, 1, 2, 3),
(0,1,4),
(1,2,4),
(2,3,4),
(3,0,4)]
return verts, faces
Defining the faces is done clockwise and remember the indes starts with 0.
The final version of the class¶
import bpy
import bmesh
from bpy.props import BoolProperty, FloatVectorProperty
def pyramid_values():
"""
This function takes inputs and returns vertex and face arrays.
no actual mesh data creation is done here.
"""
verts = [(-1, +1, 0),
(+1, +1, 0),
(+1, -1, 0),
(-1, -1, 0),
(0, 0, +2)]
faces = [(0, 1, 2, 3),
(0, 1, 4),
(1, 2, 4),
(2, 3, 4),
(3, 0, 4)]
return verts, faces
class AddPyramid(bpy.types.Operator):
"""Add a simple pyramid mesh"""
bl_idname = "mesh.primitive_pyramid_add"
bl_label = "Add Pyramid"
bl_options = {'REGISTER', 'UNDO'}
# generic transform props
view_align = BoolProperty(name="Align to View",
default=False)
location = FloatVectorProperty(name="Location",
subtype='TRANSLATION')
def execute(self, context):
verts_loc, faces = pyramid_values()
mesh = bpy.data.meshes.new("Pyramid")
bm = bmesh.new()
for v_co in verts_loc:
bm.verts.new(v_co)
for f_idx in faces:
bm.faces.new([bm.verts[i] for i in f_idx])
bm.to_mesh(mesh)
mesh.update()
self.location = (0, 0, 0)
# neues Objekt in die Szene setzen
from bpy_extras import object_utils
object_utils.object_data_add(context, mesh, operator=self)
return {'FINISHED'}
def register():
bpy.utils.register_class(AddPyramid)
def unregister():
bpy.utils.unregister_class(AddPyramid)
if __name__ == "__main__":
register()
# create a instanz of a pyramid
bpy.ops.mesh.primitive_pyramid_add()
Blender at School¶
The lessons should be exciting, informative and challenging. Is Blender the right choice? The interplay between a 3D world and the training at school will be shown. Have a look at some examples.
Blender & Python at school¶
Objectives¶
![]() |
Each of the following lessons takes a topic from the school curriculum and uses a 3D world visualization to make it easier to to understand and more exciting. There are lessons from many subjects such as mathematics, physics, chemistry and art, but there is room for many additional lessons from these and other subjects such as astronomy, computer science which are suitable for representation in a 3D world.. |
Instructions¶
Tasks: |
---|
- Have a look at the learning units in this section.
- Do you have a new idea?
- Start with Python and Blender if you are not familiar with programming and/or the Python programming language.
- Use the available examples.
- Create your own exercises.
Ideas¶
- Representation of molecules (chemistry) [finished/available]
- Laws of geometry (mathematics) [idea]
- Examples of plants (biology) [idea]
- Free fall (physics) [idea]
- Inclined plane (physics) [idea]
- Programming constructs like object oriented programming, control flow, modules (informatics) [finished, look at section Blender and Python basics]
Combination of two and more subjects
- language and informatics [idea]
- Your own ideas ...
Examples/Links¶
Adriana Mikolaskova – Blender at School – Art and Design (in german)
Video-Link: http://youtu.be/RQH1tnzD9rQ
Chris Wilmer produced a video about fuel storage - how filling fuel tanks with sand and other types of crystals can vastly increase the amount of storage inside for gaseous fuels. This video has won a prize in the 2011 International Science & Engineering Visualization Challenge.
Chemestry: molecules¶
Author(s): | Joren Retel & Peter Koppatz |
---|---|
Tags: | Chemestry, molecules |
Objectives¶
![]() |
Atoms and molecules – an exiting use case for 3D. With this material it is possible to create molecules, other experiments outside of chemistry and just for fun. A script is guiding you to create molecules or other objects. |
Instructions¶
Tasks: |
---|
- Download:
Zipfile with example data (PDB)
- Open the blend file and have a look at the examples.
- Add new molecules to the collection.
- Let students construct a molecule from a given set of atoms.
- Working with atoms should be fun, how about constructing a name from a set of atoms.

If a real molecule is intergrated in the name, as student can earn some extra points.
Hint: | All mentioned files are available as a collection within the blend-file. |
---|
PDB-Format¶
We use the structure of a PDB-File. The documentation about the PDB format is available at:
or the short version in the following table:
COLUMNS | DATA TYPE | CONTENTS |
---|---|---|
1 - 6 | Record name | “ATOM” |
7 - 11 | Integer | Atom serial number. |
13 - 16 | Atom | Atom name. |
17 | Character | Alternate location indicator. |
18 - 20 | Residue name | Residue name. |
22 | Character | Chain identifier. |
23 - 26 | Integer | Residue sequence number. |
27 | AChar | Code for insertion of residues. |
31 - 38 | Real(8.3) | Orthogonal coordinates for X in Angstroms. |
39 - 46 | Real(8.3) | Orthogonal coordinates for Y in Angstroms. |
47 - 54 | Real(8.3) | Orthogonal coordinates for Z in Angstroms. |
55 - 60 | Real(6.2) | Occupancy. |
61 - 66 | Real(6.2) | Temperature factor (Default = 0.0). |
73 - 76 | LString(4) | Segment identifier, left-justified. |
77 - 78 | LString(2) | Element symbol, right-justified. |
79 - 80 | LString(2) | Charge on the atom. |
Part of a PDB file:
1 2 3 4 5 6 7 8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
ATOM 145 N VAL A 25 32.433 16.336 57.540 1.00 11.92 A1 N
ATOM 146 CA VAL A 25 31.132 16.439 58.160 1.00 11.85 A1 C
ATOM 147 C VAL A 25 30.447 15.105 58.363 1.00 12.34 A1 C
ATOM 148 O VAL A 25 29.520 15.059 59.174 1.00 15.65 A1 O
Simple version or teaching¶
To experiment with this file format we only need the coordinates an the type of atom. So the following simpler structure remains (a water molecule in this example):
########## PDB-Struktur(vereinfacht) ##########
# H20 (Wasser, Water)
ATOM -0.544 -0.257 -0.228 H
ATOM 0.391 0.456 0.228 H
ATOM -0.332 0.44 -0.016 O
Important for the representation is the use of different diameters and colors for each type of atom:
Atom | Diameter | Color |
---|---|---|
Hydrogen | 0,32 | blue |
Carbon | 0,91 | green |
Knitted fabric | 0,75 | blue |
Phospor | 1,06 | red |
Oxygen | 0,73 | red |
unknown Atom | 1,0 | black |
Content of the Blender file¶

- 01 Introduction (listing of all possibilities)
- 02 PDB data structure (with examples, used by the standard)
- 03 Tasks
- export_data.py (save the coordinates for a new structure to a file)
- moleculeExample.py (Hydrogen, part of a DNA, methanol ...)
- new_struktur.py (a template with one unit of each type of atom)
More informations about this topic¶
A extension for Blender, with more possibilities as in this station shown...
http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Import-Export/PDB
Blender Game Engine¶
There are two ways to create games with Blender and Python. Firstly the object-oriented way, wherein every object has it’s own script, which is executed every frame. Secondly the way, wherein the game runs in a mainloop, which calls the different funcions of the objects (like in pygame). Both use cases are shown in the following sections.
Starting the Blender Game Engine (BGE)¶
Objectives¶
The bge module¶
The bge module contains nearly all you need to write a game in Python. But if you write
import bge
in the interactive interpreter or a script, which you start with »Run Script«, you’ll get the Error:
ImportError: No module named 'bge'
Start BGE the right way¶
Change the Render Type from »Blender Render« to »Blender Game«
You can start the Blender Game Engine now by clicking »P« while the cursor is over the »3D-View« or by clicking »Start« in the Render Properties.
Game I¶
Mainloop¶
Objectives¶
![]() |
In this part you learn how to write a little program for the game engine which uses a mainloop. |
Preparations¶
- Open a new blend-file
- Change the render engine from »Blender Render« to »Blender Game«
- Change to the scripting area and create the file main.py in the text editor
- Click now in the scene settings in the menu item Custom Properties on »add«

- Click on »edit« set Property Name to »__main__« and Property Value to »main.py«

The script¶
First import the module of the Blender Game Engine, bge.
import bge
ATTENTION: | You can’t run the script with Run Script now, because the module bge can only be imported, if the Game Enigne is active. You can start the program now by clicking »P« while the cursor is over the »3D-View«. |
---|
#! bpy
import bge
import time
import timeit
# active scene cube
scene = bge.logic.getCurrentScene()
# the object "Cube"
scene.objects["Cube"]
keyboard = bge.logic.keyboard
LOOP = True
FPS = 60 # Frames per Second
last_time = timeit.default_timer()
while LOOP:
# mainloop
# wait until next frame
current_time = timeit.default_timer()
# sleep time until next frame
sleep_time = 1 / FPS - (current_time - last_time)
if sleep_time > 0:
time.sleep(sleep_time)
last_time = current_time
# change scene
# read keyboard input
k_events = bge.logic.KX_INPUT_ACTIVE
# uparrow key pressed
if keyboard.events[bge.events.UPARROWKEY] == k_events:
# move up cube .005 Blender-Units
cube.position[2] += .01
# downarrow key pressed
if keyboard.events[bge.events.DOWNARROWKEY] == k_events:
# move down cube .005 Blender-Units
cube.position[2] -= .01
# escape key pressed
if keyboard.events[bge.events.ESCKEY] == k_events:
# Stop mainloop -> exit program
LOOP = False
# render next frame
bge.logic.NextFrame()
You can find the keys under Blender Game Engine – events.
More about Blender and the Game Enigne under Blender Game Engine – API
Object Oriented¶
Objectives¶
![]() |
In this part you learn how to write a little game for the game engine which is splitted in many scripts, which are executed every frame. |
Running scripts for an object¶
If you want to run a script for a Blender-Object, you can use the logic bricks to do that. First you have to add an »Always« sensor. Click to the left ‘’‘, for executing the script every frame.

Then add an »Python« controller and set the Script Property to your script.

Then connect them.
The scripts¶
The script for our Player (The monkey named »Player«).
#! bpy
import bge
import timeit
import aud
import os
def main():
"""Contains all changes"""
# get scene
scene = bge.logic.getCurrentScene()
# get contoller
con = bge.logic.getCurrentController()
# get player
player = con.owner
# get keyboard
keyboard = bge.logic.keyboard
# get the text object
text = scene.objects["Text"]
# check if start has already been run
if "lives" not in player:
start(player)
# check for collisions
for object in scene.objects:
# does object collide
# the distance is from origin to origin, so we subtract a bit
if player.getDistanceTo(object) - 2 <= 0:
# Is object an enemy ...
if object.name.startswith("Enemy"):
if player["can_collide"]:
player["lives"] -= 1
# play enemy hit sound
aud.device().play(player["enemy_sound"])
# Set that player can't collide
player["can_collide"] = False
# register time of collision
player["last_col"] = timeit.default_timer()
# ... or is object a coin?
elif object.name.startswith("Coin"):
player["coins"] += 1
# play collecting sound with the aud module
aud.device().play(player["coin_sound"])
# remove the coin from the scene
object.endObject()
# player hasn't got lives?
if player["lives"] <= 0:
print("lost")
# remove player from scene
player.endObject()
# stop game
bge.logic.endGame()
# player got all coins?
if player["coins"] >= 10:
print("Win")
bge.logic.endGame()
# player can collide again?
if not player["can_collide"]:
if (timeit.default_timer() - player["last_col"]) >= 1:
player["can_collide"] = True
# move player
# keyboard events
k_events = bge.logic.KX_INPUT_ACTIVE
# up arrow pressed?
if keyboard.events[bge.events.UPARROWKEY] == k_events:
# move player forwards on its local y axis
player.applyMovement((0, 0, .2), True)
# down arrow pressed
if keyboard.events[bge.events.DOWNARROWKEY] == k_events:
# move player backwards on its local y axis
player.applyMovement((0, 0, -.2), True)
# left arrow pressed
if keyboard.events[bge.events.LEFTARROWKEY] == k_events:
# rotate to the left
player.applyRotation((0, 0, .05))
# right arrow pressed
if keyboard.events[bge.events.RIGHTARROWKEY] == k_events:
# rotate to the right
player.applyRotation((0, 0, -.05))
# Set the text
text.text = "Lives: {}; Coins: {}".format(player["lives"], player["coins"])
def start(player):
"""Setup the player"""
player["lives"] = 3
player["coins"] = 0
player["can_collide"] = True
# sound with the aud module
# coin collect sound
path = bge.logic.expandPath("//snd/coin.wav")
player["coin_sound"] = aud.Factory.file(path)
# enemy hit sound
path = bge.logic.expandPath("//snd/enemy.wav")
player["enemy_sound"] = aud.Factory.file(path)
main()
And the Script for our Enemys:
#! bpy
import bge
from random import randint
def main():
"""Contains all changes"""
# get scene
scene = bge.logic.getCurrentScene()
# get contoller
con = bge.logic.getCurrentController()
# get player
enemy = con.owner
# check, if enemy is outside the field
if abs(enemy.position[0]) >= 20 or abs(enemy.position[1]) >= 20:
# reverse direction
enemy.applyRotation((0, 0, 180))
# change direction in ca. 1% of the calls
if randint(1, 100) == 1:
# change direction
enemy.applyRotation((0, 0, randint(1, 360)))
# check for collisions
for object in scene.objects:
# does object collide
# the distance is from origin to origin, so we subtract a bit
if enemy.getDistanceTo(object) - 2 <= 0 and object != enemy:
# Is object an enemy ...
if object.name.startswith("Enemy"):
# reverse direction
enemy.applyRotation((0, 0, 180))
# move
enemy.applyMovement((0, 0, .15), True)
main()
The camera¶
Connecting the camera to the player: 1. Deselect all (»A« toggles selection) 2. Select the camera (with a right click) 3. Press shift while selecting the player, so you selected both and the player is active 4. Press »Ctrl« + »P« and click on »Object«

- Select the camera again and enable »Slow Parent« in the Relations Extras
- Set the Offset to »11.5«

More about Blender and the Game Enigne under Blender Game Engine – API
Game II¶
Sokoban - the idea¶
Objectives¶
(All information are taken form http://en.wikipedia.org/wiki/Sokoban)
![]() |
Sokoban (warehouse keeper) is a type of transport puzzle, in which the player pushes boxes or crates around in a warehouse, trying to get them to storage locations. |
Instructions¶
Tasks: |
---|
- Download the
blend-file
- Read the code explanation in the next station
- Start the game.
- Create a new level.
History¶
Sokoban was created in 1981 by Hiroyuki Imabayashi, and published in 1982 by Thinking Rabbit, a software house based in Takarazuka, Japan.
Rules¶
The game is played on a board of squares, where each square is a floor or a wall. Some floor squares are marked as storage locations, and some of them have boxes.
The player is confined to the board, and may move horizontally or vertically onto empty squares (never through walls or boxes). The player can also move into a box, which pushes it into the square beyond. Boxes may not be pushed into other boxes or walls, and they cannot be pulled. The puzzle is solved when all boxes are at storage locations.
Sokoban - the code¶
Objectives¶
![]() |
This part shows the code for a basic sokoban game implemented with Blender and Python. |
Instructions¶
Tasks: |
---|
- If you haven’t done it so far, download the
blend-file
- Read the code, improve it and try to understand it
- Add materials and textures to the objects
- Create own levels
- Save highscores to a file
The blend-file¶
Blender has a System with 20 Layers, which can switched on and off. You can do that with the keyboard or with the GUI.
- Keyboard:
Change the layer: Press a (not numpad) number from 1 - 20
Activate a layer: Press Shift + a (not numpad) number from 1 - 20
- GUI:
Change the layer: Klick on an layer
Activate a layer: Shift + klick on a layer
Note: The layer of the selected object includes a yellow point. Active layers are darker than unactivated. If you want to change the layer of the selected object, click M + the layers number.
If you start the game, only the 1st layer is allowed to be active. The 2nd layer with your objects must be inactive or you’ll get an error.
The 1st layer¶
On the first layer are laying only 5 Objects:
- Two cameras, one for the game view and one for displaying different screens
- Two emptys, one for adding game objects and one for adding screens
- One lamp
The 2nd layer¶
All the other objects, which are needed for the game, are laying on the 2nd layer and the programm will add them to the game:
- player
- static/moveable box
- about, help and info screen
- end point
- ground
The Script¶
The Script is called every frame (that makes an always sensor which calls the script), so we can’t store global variables in our script. So we need an object which exists all the time to store our variables there. I used the »add_empty« to do this and applied the always sensor to it, too. So we can save variables like this:
a["state"] = "intro"
»a« is our »add_empty« and we store our state, which says if the player is in the intro or playing a level. Now we are on the second point: We execute always the same script, but we want to do different actions - displaying the intro and playing levels. So we must save what we did last and where we want to continue. So we need states, in our case in named them »intro« and »play«. Each state has an own loop method, which is called when it’s active. If the state changes, another method is called and adds the object for the state. This all happens in the method main():
def main():
scene = bge.logic.getCurrentScene()
# we use the empty to store variables
a = scene.objects["add_empty"]
if "state" not in a:
# first method call, set state to intro and setup intro scene
a["state"] = "intro"
a["level_index"] = 0
add_intro_objects()
if a["state"] == "intro":
# intro is active
get = intro_loop()
if get == "end":
bge.logic.endGame()
elif get == "start":
# play first level
a["state"] = "play"
create_level(data.levels[a["level_index"]])
a["level_index"] += 1
elif a["state"] == "play":
get = play_loop()
if get == "end":
# go back to intro
a["state"] = "intro"
add_intro_objects()
a["level_index"] = 0
elif get == "next":
if a["level_index"] > len(data.levels) - 1:
# all levels are played, go back to intro
a["state"] = "intro"
add_intro_objects()
a["level_index"] = 0
else:
# play next level
create_level(data.levels[a["level_index"]])
a["level_index"] += 1
The Splash Screen (intro state)¶
Before starting the game, the player will see a splash screen. There he can call help and about. First, we have to set the camera active:
camera = scene.objects["screen_cam"]
scene.active_camera = camera
On keyboard input can show help, about or start the game. Here we look if »h« was pressed and if true, we hide intro and about screen and display the help screen.
elif keyboard.events[bge.events.HKEY] == k_events:
# display the help
scene.objects["help"].setVisible(True)
scene.objects["intro"].setVisible(False)
scene.objects["about"].setVisible(False)
Adding objects¶
For adding an object, you need an object in the scene which is active yet. In our case we have the empty »add_empty« for adding objects and »screen_empty« for adding screens. The new objects will be added on the empty’s position with it’s rotation and scale.
I’ll show you here some parts of the code, you can find the whole code at the end of the page. Before you setup a new scene, you have to clear the old one. That can be done with the following lines:
for object in scene.objects:
if object.name not in ['Camera', 'Lamp', 'screen_empty',
'add_empty', 'screen_cam']:
object.endObject()
After that, we can add new objets, for example a static box:
# the static box object
static_box_obj = scene.objectsInactive["static_box"]
# add static box to scene
scene.addObject(static_box_obj, a)
The variable »a« is in this case an empty on the place where the object will be added.
The Game (play state)¶
After adding the objects and setting up the new camera, we convert the level in an easier format without end points. We do this because the end points could be overwritten if player or box is on it.
# make copy that can be changed and store it
a["field"] = [list(string.replace(".", " ").replace("*", "$").
replace("+", "@")) for string in level[:]]
We don’t need them because we check by the positions if a box is over an end point, for example to set other colors.
def update_box_color(objects):
"""Gives the box another color, if it is over an end point"""
# get all end points by name
end_points = [object for object in objects if
object.name.startswith("end_point")]
# get all moveable boxes by name
moveable_boxes = [object for object in objects if
object.name.startswith("moveable_box")]
for box in moveable_boxes:
for point in end_points:
# check if positions are the same
if (int(box.position[0]), int(box.position[1])) \
== (int(point.position[0]), int(point.position[1])):
# change box color (red, green, blue, alpha)
box.color = (.281, .232, .106, 1)
break
else:
box.color = (.9, .872, .134, 1)
For more details read the comments in the code.
#! bpy
import aud # for audio
import bge
import data
import timeit
import time
import os
from random import randint
from random import choice
from math import radians # from degrees to radians
from math import degrees # from radians to degrees
def play_loop():
"""Creates a new player and controls the game"""
# our scene
scene = bge.logic.getCurrentScene()
# the object with the variables
a = scene.objects["add_empty"]
keyboard = bge.logic.keyboard
# set box colors
update_box_color(scene.objects)
player = scene.objects["player"]
# change the scene
# read keyboard input
k_events = bge.logic.KX_INPUT_JUST_ACTIVATED
# uparrow key pressed
if keyboard.events[bge.events.UPARROWKEY] == k_events:
# move player forwards if he can
move = can_move_player(player, a["field"], scene)
if move:
# player can move
if move == 1:
# move only the player
move_forwards_player(player, a["field"])
else:
# move the player and the moveable box in front of him
box = get_front_box(a["field"], player, scene.objects, scene)
move_forwards_player(player, a["field"], box)
# set box colors
update_box_color(scene.objects)
# check, if level is won
if is_level_won(a["level"], a["field"]):
# end level
print("Won")
# play next level
return "next"
elif keyboard.events[bge.events.LEFTARROWKEY] == k_events:
rotate_left(player)
elif keyboard.events[bge.events.RIGHTARROWKEY] == k_events:
rotate_right(player)
if keyboard.events[bge.events.QKEY] == k_events:
# end level, go back to intro
return "end"
def create_level(level):
"""Add the objects for a sobokan level"""
# our active scene
scene = bge.logic.getCurrentScene()
# clear scene
for object in scene.objects:
if object.name not in ['Camera', 'Lamp', 'screen_empty',
'add_empty', 'screen_cam']:
object.endObject()
# our empty for adding
a = scene.objects["add_empty"]
# store the level variable
a["level"] = level
# our columns
cols = len(level[0])
# our rows
rows = len(level)
# the names of our created objects
# add ground
ground_pos = (rows - 1, cols - 1, -1)
# the ground object
ground_obj = scene.objectsInactive["ground"]
# setup ground's adding position
a.worldPosition = ground_pos
# add the ground object to the scene
ground = scene.addObject(ground_obj, a)
# scale the ground
ground.localScale[0] = rows
ground.localScale[1] = cols
# setup the camera
camera = scene.objects["Camera"]
scene.active_camera = camera
# add the othe objects
for row in range(rows):
for i in range(cols):
coords = (row * 2, i * 2, 0)
# change adding position to coords
a.worldPosition = coords
if level[row][i] == "#":
# the static box object
static_box_obj = scene.objectsInactive["static_box"]
# add static box to scene
scene.addObject(static_box_obj, a)
elif level[row][i] == "@":
# the player object
player_obj = scene.objectsInactive["player"]
# Add the player
player = scene.addObject(player_obj, a)
player.applyRotation((radians(90), 0, 0))
elif level[row][i] == "$":
# the moveable box object
moveable_box_obj = scene.objectsInactive["moveable_box"]
# add a moveable box
scene.addObject(moveable_box_obj, a)
elif level[row][i] == ".":
# the end point object
end_point_obj = scene.objectsInactive["end_point"]
# set the adding position to ground height
a.worldPosition[2] = -.99
# Add an end point
scene.addObject(end_point_obj, a)
elif level[row][i] == "*":
# moveable box and end point on one field
# the moveable box object
moveable_box_obj = scene.objectsInactive["moveable_box"]
# add a moveable box
scene.addObject(moveable_box_obj, a)
# the end point object
end_point_obj = scene.objectsInactive["end_point"]
# set the adding position to ground height
a.worldPosition[2] = -.99
# Add an end point
scene.addObject(end_point_obj, a)
elif level[row][i] == "+":
# player and end point on one field
# the player object
player_obj = scene.objectsInactive["player"]
# Add the player
player = scene.addObject(player_obj, a)
player.applyRotation((radians(90), 0, 0))
# the end point object
end_point_obj = scene.objectsInactive["end_point"]
# set the adding position to ground height
a.worldPosition[2] = -.99
# Add an end point
scene.addObject(end_point_obj, a)
# make copy that can be changed and store it
a["field"] = [list(string.replace(".", " ").replace("*", "$").
replace("+", "@")) for string in level[:]]
def move_forwards_player(game_object, field, box=None):
"""Moves the object (and a box, if given) one step forwards"""
if box is not None:
# update field
field[int(box.worldPosition[0] / 2)][int(box.worldPosition[1] / 2)]\
= " "
# move the box in the »3D-View«
box.orientation = game_object.orientation
move(box, 2)
# update field
field[int(game_object.worldPosition[0] / 2)][int(
game_object.worldPosition[1] / 2)] = " "
# move the player in the »3D-View«
move(game_object, 2)
# update »3D-View«
bge.logic.NextFrame()
# update field
if box:
field[int(box.worldPosition[0] / 2)][int(box.worldPosition[1] / 2)]\
= "$"
field[int(game_object.worldPosition[0] / 2)][int(
game_object.worldPosition[1] / 2)] = "@"
def move(game_object, distance):
"""Moves the object"""
# get the objects orientation and move to the right direction
if int(degrees(game_object.orientation.to_euler().z)) % 360 == 0:
game_object.position[1] -= distance
elif int(degrees(game_object.orientation.to_euler().z)) % 360 == 90:
game_object.position[0] += distance
elif int(degrees(game_object.orientation.to_euler().z)) % 360 == 180:
game_object.position[1] += distance
else:
game_object.position[0] -= distance
def rotate(game_object, degrees):
"""Rotates the object around z axis"""
game_object.applyRotation((0, 0, radians(degrees)))
def rotate_left(game_object):
"""Rotates the object 90 degrees to the left"""
rotate(game_object, 90)
def rotate_right(game_object):
"""Rotates the object 90 degrees to the right"""
rotate(game_object, -90)
def can_move_player(game_object, field, scene):
"""Check, if the player can be moved"""
def check_for_obstruction(object_forwards, object_d_forwards):
"""Check, if object_forwards/object_d_forwards is an obstruction"""
# place in front of the player is free
if object_forwards == " " or object_forwards == ".":
return 1
# an obstruction is in front of the player
elif object_forwards == "#":
return 0
# a movable box is in front of the player
else:
# there is nothing behind the box
if object_d_forwards == " " or object_d_forwards == ".":
return 2
# there is something behind the box
return 0
# players position in the field
player_position = (int(game_object.worldPosition[0] / 2),
int(game_object.worldPosition[1] / 2))
try:
# the object's orientation
if int(degrees(game_object.orientation.to_euler().z)) % 360 == 0:
# the object in front of the player
object_forwards = field[player_position[0]][player_position[1] - 1]
# the object after the object in front of he player
object_d_forwards = field[player_position[0]][player_position[1]
- 2]
return check_for_obstruction(object_forwards, object_d_forwards)
elif int(degrees(game_object.orientation.to_euler().z)) % 360 == 90:
object_forwards = field[player_position[0] + 1][player_position[1]]
object_d_forwards = field[player_position[0]
+ 2][player_position[1]]
return check_for_obstruction(object_forwards, object_d_forwards)
elif int(degrees(game_object.orientation.to_euler().z)) % 360 == 180:
object_forwards = field[player_position[0]][player_position[1] + 1]
object_d_forwards = field[player_position[0]
][player_position[1] + 2]
return check_for_obstruction(object_forwards, object_d_forwards)
else:
object_forwards = field[player_position[0] - 1][player_position[1]]
object_d_forwards = field[player_position[0]
- 2][player_position[1]]
return check_for_obstruction(object_forwards, object_d_forwards)
except IndexError:
# object_d_forwards not in field so object_forwards must be static cube
return 0
def get_front_box(field, player, objects, scene):
"""Returns the Blender object of the box in front of the player"""
# players position in the field
player_position = (int(player.worldPosition[0] / 2),
int(player.worldPosition[1] / 2))
box = None
# get player's orientation and check for a box
if int(degrees(player.orientation.to_euler().z)) % 360 == 0:
object_forwards = (player_position[0], player_position[1] - 1)
elif int(degrees(player.orientation.to_euler().z)) % 360 == 90:
object_forwards = (player_position[0] + 1, player_position[1])
elif int(degrees(player.orientation.to_euler().z)) % 360 == 180:
object_forwards = (player_position[0], player_position[1] + 1)
else:
object_forwards = (player_position[0] - 1, player_position[1])
box = get_object_from_position(object_forwards,
[object for object in scene.objects if
object.name.startswith("moveable_box")])
return box
def get_object_from_position(position, objects):
"""Get the object on position *position*"""
for object in objects:
if (int(object.position[0] / 2),
int(object.position[1] / 2)) == position:
return object
def is_level_won(level, field):
"""Look, if all moveable boxes are on an end point"""
cols = len(level[0])
rows = len(level)
for row in range(rows):
for i in range(cols):
# is moveable box on an end point
if field[row][i] == "$" and not (level[row][i] == "." or
level[row][i] == "+" or
level[row][i] == "*"):
return False
return True
def update_box_color(objects):
"""Gives the box another color, if it is over an end point"""
# get all end points by name
end_points = [object for object in objects if
object.name.startswith("end_point")]
# get all moveable boxes by name
moveable_boxes = [object for object in objects if
object.name.startswith("moveable_box")]
for box in moveable_boxes:
for point in end_points:
# check if positions are the same
if (int(box.position[0]), int(box.position[1])) \
== (int(point.position[0]), int(point.position[1])):
# change box color (red, green, blue, alpha)
box.color = (.281, .232, .106, 1)
break
else:
box.color = (.9, .872, .134, 1)
def intro_loop():
"""The intro before the first level is starting"""
# our active scene
scene = bge.logic.getCurrentScene()
keyboard = bge.logic.keyboard
# look if a key was pressed
k_events = bge.logic.KX_INPUT_JUST_ACTIVATED
# uparrow key pressed
if keyboard.events[bge.events.SPACEKEY] == k_events:
# start level
return "start"
elif keyboard.events[bge.events.HKEY] == k_events:
# display the help
scene.objects["help"].setVisible(True)
scene.objects["intro"].setVisible(False)
scene.objects["about"].setVisible(False)
elif keyboard.events[bge.events.AKEY] == k_events:
# show the about on the screen
scene.objects["help"].setVisible(False)
scene.objects["intro"].setVisible(False)
scene.objects["about"].setVisible(True)
if keyboard.events[bge.events.QKEY] == k_events:
# if intro screen is shown, quit program
return "end"
return "ok"
def add_intro_objects():
"""Adds the objects which are needed for the intro"""
# the active scene
scene = bge.logic.getCurrentScene()
# clear scene
for object in scene.objects:
if object.name not in ['Camera', 'Lamp', 'screen_empty',
'add_empty', 'screen_cam']:
object.endObject()
# the add_empty for adding objects
a = scene.objects["add_empty"]
# the screen_empty for adding screens
s = scene.objects["screen_empty"]
# set active camera
camera = scene.objects["screen_cam"]
scene.active_camera = camera
# the intro screen object
intro_screen_obj = scene.objectsInactive["intro"]
# add intro screen
scene.addObject(intro_screen_obj, s)
# the help screen object
help_obj = scene.objectsInactive["help"]
# add the help screen
help = scene.addObject(help_obj, s)
# hide help screen
help.setVisible(False)
# the about screen object
about_obj = scene.objectsInactive["about"]
# add the about screen
about = scene.addObject(about_obj, s)
# hide about screen
about.setVisible(False)
def main():
scene = bge.logic.getCurrentScene()
# we use the empty to store variables
a = scene.objects["add_empty"]
if "state" not in a:
# first method call, set state to intro and setup intro scene
a["state"] = "intro"
a["level_index"] = 0
add_intro_objects()
if a["state"] == "intro":
# intro is active
get = intro_loop()
if get == "end":
bge.logic.endGame()
elif get == "start":
# play first level
a["state"] = "play"
create_level(data.levels[a["level_index"]])
a["level_index"] += 1
elif a["state"] == "play":
get = play_loop()
if get == "end":
# go back to intro
a["state"] = "intro"
add_intro_objects()
a["level_index"] = 0
elif get == "next":
if a["level_index"] > len(data.levels) - 1:
# all levels are played, go back to intro
a["state"] = "intro"
add_intro_objects()
a["level_index"] = 0
else:
# play next level
create_level(data.levels[a["level_index"]])
a["level_index"] += 1
main()
Python Basics¶
There are many Python courses available. We only discuss some special corner cases. Have also a look at the linklist below.
Data types: Overview¶
Objectives¶
![]() |
Python provides a set of data types. As a supplement and for a quick entry, a brief introduction to each data type, and some other topics will be provided. |
Instructions¶
Tasks: |
---|
- Have a look to the standard documentation in addition to the given examples.
- Execute the example in the next chapters. Do not forget to create variations.
Numbers¶
- Integer
- Float
- Long
- Complex
Mappings/Collections¶
- Dictionary
- Set
Tecniques useful for different data types¶
Data type: string¶
Objectives¶
![]() |
Every programming language is using strings as a data type. The Python way to handle strings, is shown in this station. |
Instructions¶
Tasks: |
---|
- Save the following text, line by line into variables:
"Shall I compare thee to a summer's day?
Thou art more lovely and more temperate..."
Lines from Shakespeare's Sonnet 18.
- Return the values of all variables with the print-Function. Don’t forget the empty line.
Properties and rules¶
- A string is enclosed in the following characters: single quotation, double quotation and triples of the quotation signs.
- Strings are immutable, if you change a string, the computer has to reserve new memory and afterward release the old memory.
- Each character is callable with an index. The index counting starts at zero.
More hints about strings kann be found at:
Assign strings¶
Each variable get’s own value.
todo: find a good equivalent to the german version...
Concatenate strings¶
Building longer Strings from substrings, is an often used technique.
Hint: | The same result can be achieved with other data types tuple and list. |
---|
Data type: tuple & for loop¶
Objectives¶
![]() |
The specifics of the tuple data type, short and sweet. |
Instructions¶
Tasks: |
---|
- Create a second file: tuple_and_lists.py (Note: files must not be named for reserved words, because it can lead to name conflicts!)
- Save your address in a tuple.
- Enter the address of the tuple.
- Use a for loop to output the tuple.
Content¶
Properties ...¶
- Immutable like strings
- External characteristic in the source code are the parentheses
- Can take any object
- Parts of a tuple can be extract. The index starts with 0.
- Attempt to change the value of a tuple entry is not possible!
Example:¶
In these examples, the for loop is used for the control flow.
T1 = () # an empty tupel (considered unusual and purely academic)
t2 = ('The', 'quick', 'brown', 'fox', 'jumps', 'over', 7, 'stones')
print(t2[0], t2[1], t2[2], t2[3], t2[4], t2[5], t2[6], t2[7])
for i in t2:
print(i, )
print()
print(t3)
t2[4] = 9 # Will that work?
As you can extract parts of a tuple is in the station slicing shown.
Data type: Lists & while¶
Objectives¶
![]() |
Introduction to the datatype list. |
Instructions¶
Tasks: |
---|
- Discover the methods a list supports. Use the command dir([]) at the command line.
- Create a list with things available in your environment.
- Print some elements or all from your list.
Properties¶
The essential properties of a list are:
- Square brackets - the external indicator if parts of list are used.
- A list can accommodate a wide variety of object types, for example, Strings, numbers ...
- She has a variety of methods to manage the list items.
For more information about lists, have a look at: Built-in Types
Repetition with while¶
With a while loop, you can reach the same results as with the for loop! A termination condition leads to the end of the loop or to a premature demolition.
L1 = [] # empty List
L2 = ['The', 'brave', 'tailor', 'hit', 7, 'on', 'a', 'string']
print(L2[0], L2[1], L2[2], L2[3], L2[4], L2[5], L2[6], L2[7])
i = 0
while i < len(L2):
print(L2[i])
i = i + 1 # The variable i must Modify the value,
# Otherwise it will loop indefinitely !!
L2.reverse()
print(L2)
With the slicing operator further sub output can be realized.
See also: Slicing
Data type: dictionary & if¶
Objectives¶
![]() |
In other programming langauges a dictionary is named »Associative array«, in Python it is named »Dictionary«. Some useful methods and scenarios are demonstrated. |
Instructions¶
Tasks: |
---|
- Create a script: dictionaries.py
- Create a second version of the refrigerator example according to the station for data type lists.
- Expand the mushroom example and generate a complete HTML page with print function.
Properties of a dictionary¶
- Dictionaries are called mapping-type.
- They are similar to the associative array of other programming languages.
- They are represented by a pair of curly brackets {} and always contain name/value pairs that are separated by a colon. Names are also called keys
- The order of the key values in the dictionary is random.
Examples¶
cars = {'BMW':'Germany', 'Renault':'France', 'Volvo':'Sweden'}
# other stucture...
cars = {'BMW':'Germany',
'Renault':'France',
'Volvo':'Sweden'}
Method | Note | Example, comment |
---|---|---|
clear() | removes all entries from a dictionary | cars.clear() the result os an empty dictionary {} |
copy() | copy all entries af a give dictionary | copy_of_cars = cars.copy() |
has_key() | returns the value 1 if the key exists if not 0 | cars.has_key(‘Volvo’) |
items() | returns all name/value pairs each as a tuple | cars.items() |
keys() | returns a list of all keys | cars.keys() | |
update() | add a new name/value, if the key exists the value will be replaced | cars[‘Skoda’] = ‘Czech Republic’ |
get() | return the value to a give name | cars.get(‘Volvo’) cars.get(‘xyz’,’???’) |
Second Example¶
# create a dictionary...
mushrooms = {} # empty dictionary
mushrooms['cep'] = ['eatable x times', "mixed forest", "Boletus edulis"]
mushrooms['fly amanita'] = ["eatable once", "coniferous forest", "Amanita muscaria"]
mushrooms['bay bolete'] = ["eatable x times", "mixed forest", "Boletus badius"]
mushrooms['Coprinus'] = ['eatable x times', "meadow", "Coprinus"]
# print the content:
print('''Pretty print dictionary of mushrooms:\n ''')
for i in mushrooms.keys():
print("""kind = {}, eatable = {}, be found = {}; """.format(i,
mushrooms[i][0],
mushrooms[i][1]))
In this example some other data types are used or created.
- Dictionary = mushrooms
- List = as result of the mehtod call keys()
- Tupel = as parameter of the format method
Many more variations are possible eg. combined with a Slicing -operator.
Module: Formating not calculating¶
Objectives¶
![]() |
If all calculations are finished, print is often used to present all values as a string. Beside the old %s-Operator in Python 3.x a new function is available. Examples are showing some nice solutions. |
Instructions¶
Tasks: |
---|
Change the examples presented in the old as in the new notation.
Print a list, as it is listed on a sales slip.
- Look at the examples in the Python documentation at:
http://docs.python.org/2/library/string.html#format-examples
String formating with the Moduluo-Operator %¶
Principles to the old version¶
- The % sign is a wildcard, followed by a letter indicating the data type.
- Examples: %s, %d, %f, %2d, %2.3f
- The number after the percent sign specifies the precision to be used for output.
- The last % sign initiates the handover of parmaeter(s) to be used for the placeholder.
- The number of parameters (list, tuple) must match the number of placeholders.
Special case: Dictionary as parameter¶
- If the parameter is a dictionary, then the wildcard must matching the names (keys) of the dictinary.
Example 1¶
for i in range(1,11):
print("%s * %s = %s" % (i,10,i*10))
Example 2¶
print("The %s f%sx j%ss" % ("brown","o","ump"))
Example 3¶
# create a dictionary...
mushrooms = {} # empty dictionary
mushrooms['cep'] = ['eatable x times', "mixed forest", "Boletus edulis"]
mushrooms['fly amanita'] = ["eatable once", "coniferous forest", "Amanita muscaria"]
mushrooms['bay bolete'] = ["eatable x times", "mixed forest", "Boletus badius"]
mushrooms['Coprinus'] = ['eatable x times', "meadow", "Coprinus"]
# print the content:
print('''Pretty print dictionary of mushrooms:\n ''')
for i in mushrooms.keys():
print("""kind = %s, eatable = %s, be found = %s; """.format(i,
mushrooms[i][0],
mushrooms[i][1]))
Example 4¶
adress = {"firstnamename": "Robin",
"lastname": "Hood",
"location": "Sharewood Forest",
"mark": "Bow & Arrow"}
print("""
Wanted %(lastname)s, %(firstname)s
special mark %(mark)s
lives in %(location)s
""" % (adress)
String formating with format()¶
This new method was discussed in PEP 3101 and is available since Python version 2.7.
Principles to the new version¶
- placehoder is a pair of curly braces
- the parameter are placed in the format method
The following examples repeat the old examples above and should the cause the same result.
Example 1¶
for i in range(1,11):
print('{} * {} = {}'.format(i,10,i*10))
The same example, but more table like:
for i in range(1,11):
print('{:2d} * {:2d} = {:3d}'.format(i,10,i*10))
x = 10
print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
print("The {} f{}x j{}s".format("brown","o","ump"))
Example 3¶
# create a dictionary...
mushrooms = {} # empty dictionary
mushrooms['cep'] = ['eatable x times', "mixed forest", "Boletus edulis"]
mushrooms['fly amanita'] = ["eatable once", "coniferous forest", "Amanita muscaria"]
mushrooms['bay bolete'] = ["eatable x times", "mixed forest", "Boletus badius"]
mushrooms['Coprinus'] = ['eatable x times', "meadow", "Coprinus"]
# print the content:
print('''Pretty print dictionary of mushrooms:\n ''')
for i in mushrooms.keys():
print("""kind = {}, eatable = {}, be found = {}; """.format(i,
mushrooms[i][0],
mushrooms[i][1]))
Excample 4¶
adress = {"firstnamename": "Robin",
"lastname": "Hood",
"location": "Sharewood Forest",
"mark": "Bow & Arrow"}
print("""
Wanted {lastname}, {firstname}
special mark {mark}
lives in {location}
""" % (**adress)
Example 5¶
A little collection fo exotic versions...
>>> name ="Peter"
>>> "{!r:>10}".format(name)
" 'Peter'"
>>> '{:x>42}'.format(name)
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxPeter'
Modulo: the rest is important¶
Objectives¶
![]() |
The modulus operator is used twice in Python. Once for the formatted output of texts and secondly for the calculation of the remainder, after a integer division. What this operator can be used, is shown here. |
Instructions¶
Tasks: |
---|
- What is the result if the calculation of the number 3 is performed?
- Search for some aother examples you can find on the internet.
Calculating with the modulo operator %¶
This example is using a for loop:
for i in range(1,11):
print('{} divided by {} is {} and the reminder is {}'.format(i, 2, i/2, i % 2))
The result:
1 divided by 2 is 0 and the reminder is 1
2 divided by 2 is 1 and the reminder is 0
3 divided by 2 is 1 and the reminder is 1
4 divided by 2 is 2 and the reminder is 0
5 divided by 2 is 2 and the reminder is 1
6 divided by 2 is 3 and the reminder is 0
7 divided by 2 is 3 and the reminder is 1
8 divided by 2 is 4 and the reminder is 0
9 divided by 2 is 4 and the reminder is 1
10 divided by 2 is 5 and the reminder is 0
Question: What can you achieve?
- Answer: It is clear which number is even (rest = 0) and that number
- is odd (residual = 1).
Question: Where do I need this?
- Answer: For example, the different coloring of the table rows.
- No matter how long the table is, the color is always exchanged in the exchange, and thus the table more readable.

Other examples can be found under http://en.wikipedia.org/wiki/Euclidean_division
Slicing¶
Objectives¶
![]() |
Slicing is a useful technique to operate on all sequenz data types. Helpful examples are given in this station. |
Instructions¶
Tasks: |
---|
- Create a tuple or a list with the following sentence and store each word as a value: “Simple is better than complex”
- Return the last value of the tuple or list.
- Create a dictionary with ten concept pairs <first language> – <second language>.
- Print the content of the dictionare in order.
- Construct a data structure which stores the position of a chess game.
- Return the position as ASCII art.
What is slicing?¶
It is the selection of a subset of a sequence of values. This works with strings, tuples and lists alike.
Cut part range from - to:
s = "Big Bug Bunny"
part = s[8:10]
print(s, part)
Cut the last part:
s = "Big Bug Bunny"
part = s[-1:]
print(s, part)
Cut first element:
s = "Big Bug Bunny"
part = s[0]
print(s, part)
Cut all elements:
s = "Big Bug Bunny"
part = s[:] # same as s without braces
print(s, part)
Nested Views¶
What applies to the strings, can also be applied to tuples and lists. If the element is a character string, it can also partly cut again:
t1 = ('The', 'quick', 'brown fox', 'jumps', 'over', 'the', 'lazy', 'dog')
t2 = t1[2][3:8]
print(t2)
Dictionaries and slicing¶
For the data type * dictionary * there is no slicing operator! Various methods returns a list as a result. If the result is a list, slicing is possible again.
# create a dictionary...
mushrooms = {} # empty dictionary
mushrooms['cep'] = ['eatable x times', "mixed forest", "Boletus edulis"]
mushrooms['fly amanita'] = ["eatable once", "coniferous forest", "Amanita muscaria"]
mushrooms['bay bolete'] = ["eatable x times", "mixed forest", "Boletus badius"]
mushrooms['Coprinus'] = ['eatable x times', "meadow", "Coprinus"]
# print the content:
print('''Pretty print dictionary of mushrooms:\n ''')
for i in mushrooms.keys():
print("""kind = {}, eatable = {}, be found = {}; """.format(i,
mushrooms[i][0],
mushrooms[i][1]))
Other Python courses¶
Python Specials¶
Appendix¶
Blender: often used commands¶
Table of contents
Template: section blender basics¶
#!bpy
"""
Name: 'Template'
Blender: 2.69
Group: 'Sample'
Tooltip: 'Template for new scripts, copy it and start coding...'
"""
import bpy
def function_1():
""" One line describing the task of this function """
pass
def function_2():
""" One line describing the task of this function """
print(__name__)
print(50 * '*')
def function_3():
""" One line describing the task of this function """
bpy.ops.mesh.primitive_cone_add(location=(1, 2, 1))
if __name__ == '__main__':
# call the function for testing
function_1()
#function_2()
#function_3()
Template: simple sample¶
#!bpy
"""
Name: '???'
Blender: 2.69
Group: 'Experiment'
Tooltip: 'Try...'
"""
import bpy
def test():
""" One line describing the task of this function """
pass
if __name__ == '__main__':
# Stop edit mode
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# delete all mesh objects from a scene
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
# call the new function
test()
Find Objects by name¶
All objecte as list of names ...
Version I
all = [item.name for item in bpy.data.objects]
for name in all:
print(name)
Version II
# collect all names
obj_names = []
for obj in bpy.context.scene.objects:
obj_names.append(obj.name)
Selection by type ...
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.select_by_type(type='CURVE')
Selection by pattern...
bpy.ops.object.select_pattern(pattern="Mein Auto")
Deaktivate all objects¶
for obj in bpy.context.selectable_objects:
obj.select = False
Switch between edit- and object mode¶
Works only if a object is selected.
bpy.ops.object.editmode_toggle()
bpy.ops.object.mode_set(mode = 'OBJECT')
bpy.ops.object.mode_set(mode = 'EDIT')
Delete objects¶
Works only, if objects are selected ...
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
Activate object¶
bpy.context.scene.objects.active = bpy.data.objects["Cube"]
Todo
check all variants, to set a path ...
Detect the index of a face¶
def getIndexOfFaces(name):
""" Print the index of faces to the console
- Switch to the edit-Mode
- select faces
- the output ist shown in the console
"""
bpy.context.scene.objects.active = bpy.data.objects[name]
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')
me = bpy.context.object.data
for poly in me.polygons:
if poly.select:
print("Polygon index: %d, length: %d" % (poly.index,
poly.loop_total))
bpy.ops.object.mode_set(mode='EDIT')
Operator list¶
Objectives¶
![]() |
This is a copy from the file OperatorList.txt. It is also available with the menu sequence Help » Operator Cheat Sheet. |
Instructions¶
Tasks: |
---|
- Select the menu Help » Operator Cheat Sheet
- Switch the text file and search for » mesh.primitive_ «
List of operators¶
Start searching in most browsers (Ctrl+f), more information are available in the API.
http://www.blender.org/documentation/blender_python_api_2_69_1/
Contests¶
Programming contest 2013¶
![]() |
![]() |
Two winners of a beginners programming competition showed their results in the opening keynote of the German Python conference in Cologne. They have to use Python to program Blender. Both showed slides and also their animation movie.
A 15 year old girl visualized Conway’s “Game of life” and a boy, 13 years showed a card game “skat” having good software design skills.
The conference and also the competition is driven by the german Python Software Verband. This is a national equivalent to the Python Software Foundation. The contest will continue and likely start again in november and been celebrated at the next EuroPython in Berlin 21.7 – 27.7.2014.
Programming contest 2014¶
The contest will continue and likely start again in november and been celebrated at the next EuroPython in Berlin 21.7 – 27.7.2014.
Incubator¶
Please insert new learning units (stations) here, as long as it is not clear where to place the new content. If you have an proposal, enhancement or bug use the ticket system at bitbucket.org.