Search Results

Sunday, January 23, 2011

Using Python in the Blender Game Engine - Part 1

Hey, there. So, we'll be learning about using Python in the Blender Game Engine today.
Perhaps you've never heard of the Blender Game Engine; If so, then look at this previous entry explaining what the BGE is. Now,since I believe that the best way to learn is by doing, we'll be making... A Maze-type game! No, not one like Pacman, but one like the oldschool Atari game Adventure, or Berzerk. So, then, first you'll start up Blender. Since we'll be making a game, it would be wise to configure your window setup to be efficient for making games, and if you plan to make many games, then you should go into the File > User Preferences menu and select "Make Default". This will make it so that the windows you have set up in Blender will carry over each time you want to create a new .blend file or restart Blender.

The Basic Window Setup for Game Development (for me)

Now, then, you should have a Cube to start off with, as usual, like so. What we'll be doing is using Python for most everything in our game, including to move the cube, which will become our Player, so go ahead and rename the Cube to "Player". Open up a Logic Window (if there isn't one already; there is one built-in to the Game Logic screen on the default build of Blender 2.5), and plug an Always sensor into a Python controller. The Python controller will be running our player's Python script.

There are two different ways to code in Python for use in the Blender Game Engine. The first way is internally. This means that you script for each object to run in Blender itself, and point to the code via a Python controller. The second way is externally, which means coding a python script and saving it externally in the same directory as the blend file, then using a Python controller to point to the file and function that we wish to execute. The second method is what we will be using, as this also allows us the capability to code in an external text editor. One editor that is good is Komodo Edit, which is free and cross-platform.

The way this works is that we create a Python file (a file that ends in .py, a source file, or .pyc, a compiled source file that cannot be edited) that will hold the code our Player runs. Blender supports for multiple pieces of code per code file via functions, so we can make multiple objects run code that is in a single file. So, it's up to us how we organize our code - for example, the Player's code and the Player's bullet's code could be in the Player code file, while enemy code could be in an Enemy code file.
What we will be doing for our game is pretty simple - we specify each object (like the Player) to run a function that specifies how our object will behave. Here's the setup for the game logic in Blender.
Logic Brick setup for the Player - just an Always sensor with True pulse setting active going into a Python controller.

As can be seen, the Always sensor runs every frame, and drives the Python controller it is attached to. The Python controller is set to Module mode, which allows us to use external python files and run single functions, rather than having to use whole script files for separate objects. So, then as you can see, the Python controller is running an external script file - the first word is the file in which to find the script, and inside of it, which function to use. This script file, "Objects.py", contains a single function that we will be running - the Player function, which is the second half of the controller's setting. The Player function will be defined inside of the 'Objects.py' Python file. So, the Player can run the script by setting the controller's module to execute 'Objects.Player'.

OK, so on to the actual code. It's actually quite simple.
from bge import logic
def Player():
cont = logic.getCurrentController()
obj = cont.owner
print ("Hi! I'm at", obj.position)
Not too much to it, is there? Let's step through the code line by line, shall we?
from bge import logic
This line imports the logic submodule from the bge code module so that we can access it. The logic submodule contains useful functions and capabilities for us, like getting the current game scene or getting the current object, which we do below. The bge module also contains other modules, like render and types for use in-game.
def Player():
This line begins the definition of the Player function - this function is what the Player object in the Blender Game Engine runs, and will begin our code for the Player. Python uses indents to evaluate statements or define blocks of code. Every line after the def statement is in that block, and so that code is defined by the function name ("Player", in this case).
cont = logic.getCurrentController()
This line creates a new variable, cont, and sets it to be the controller used by the Player object in Blender. The controller of the script can be used to activate actuators, read sensors, and do other useful things.
obj = cont.owner
This line creates a new variable, like before, named obj. This variable is set to point to the owner of the code controller (The Player object itself). This is used to find out object-related variables, like position, rotation, and scale.
print ("Hi! I'm at", obj.position)
This line prints out a string, "Hi! I'm at", and also prints another value - the position of the object, next to the previous string. Now that the source code has been explained, you can play the game to see the result. Play (the P-key in the 3D window), and you should see something like this below...
As can be seen, the console of Blender is printed to every frame.

If you read the output, it reads "Vector" - what is that? Well, Vector is a built-in variable type in Blender. Vectors are like simple lists or arrays, but have additional variables and functions, like reflection or the ability to access the individual x, y, and z parts of the vector. If you want to learn more about Blender python, then you can use print( dir( function or variable ) ) to learn more about what a specific part of Blender can do. I would also recommend reading up on Python (specifically the version that Blender uses; To find out, check the console when starting Blender up). Here's the link to the download of the Maze Crawl Part 1 source code. Next up, we'll be moving our Player with Python!

38 comments:

  1. May I recommend Geany instead of Notepadd++ for Linux and Mac users? Geany also works for Windows.

    cheers,
    loopduplicate at burningtoken.com

    ReplyDelete
  2. There are lots of other programs that you can use to code with, which is great. The reason that I used Notepad++ is that you can load in the code-completion file for coding in the BGE (or even coding in Blender, if you want to make add-ons or extend Blender in some way). Anyway, any alternatives are great to know about.

    ReplyDelete
  3. I'm using a 2.49x version of Blender, and I'm getting an error message (ImportError: no module named bge) does this module only exist in newer versions? Or perhaps I have my script in the wrong place, at the moment I've just got it in the same directory as my .blend file, which is no where near my blender folder.

    thanks for the help.

    ReplyDelete
  4. Blender 2.5x has a completely new Python API, so all of the modules have been redesigned. You have to re-learn a lot of things when adjusting from 2.49 to 2.57, and scripting is one of them.

    It's a bit frustrating, but there's no point in fighting it. We'll all have to get used to the new Blender sooner or later, and in the end, we'll really be a lot better off because of it.

    ReplyDelete
  5. The poster above me is correct - this script (and series of tutorials) are based on Blender 2.5. You must use Blender 2.5x (2.57a is the current one) to be able to really use this tutorial, at least without porting it to 2.49. I would recommend using 2.57, as it sports an easier workflow, and a far better user interface.

    ReplyDelete
  6. hmmm... it won't print, but no errors. any help please

    ReplyDelete
  7. Thanks, crist.
    @Anonymous - Sounds like you're not executing the script correctly. Look in the source and note the differences. The script needs to be attached to a controller.

    ReplyDelete
  8. i have literally done this like 20 times. i've made sure everythings exactly how its supposed to be and it dosn't print anything. even when i downloaded the final, it dosn't work. i've done a lot of tests where i do just one line of code that says, print ("does this work"), and it will print that, but for some reason nothing else seems to work. anyways any help would be greatly appreciated, i've done programming before, just not python (for some reason python never seems to like me)

    ReplyDelete
  9. That's really odd. So the console doesn't print anything, even on the example file? Try a later source code download, and make sure you're using the latest version of Blender.

    ReplyDelete
  10. okay i figured it out, i needed to add one more line of code above, from bge import logic, that code was just import bge, seems so simple now. the rest works after that.

    ReplyDelete
    Replies
    1. so , how did you script it?
      like
      import bge logic
      ..?

      Delete
  11. Great, I'm glad you figured it out.

    ReplyDelete
  12. FYI, when using the module controller, it will pass the module to the function it calls if that function has one argument. This means you can do something like:

    def Player(cont):
    ob = cont.owner
    print(ob.position)

    ReplyDelete
  13. Yes, that's right. I guess I should mention that. Thanks for the tip, Moguri.

    ReplyDelete
  14. it didnt work here,ive done exactly the same thing as u tought and didnt print anything,then i made a simple test like print ("Hello") then it printed a whole bunch of hellos so what am i missing?
    thanks in advance

    ReplyDelete
  15. Nvm i just figured it out,i forgot to switch to module in the logic editor..now everything went ok thanks

    ReplyDelete
  16. This comment has been removed by the author.

    ReplyDelete
  17. I'm not seeing a command prompt like in the picture above to verify that anything worked?

    ReplyDelete
  18. You have to enable the console via the Help menu.

    ReplyDelete
  19. Ok, so... I keep having this one problem. I got Notepad++, followed the directions concerning replacing the version of Python that it uses with the one that works with the Blender Game Engine, I named my Cube "Player", I copied the script exactly as it is with the indents and everything, I made sure that I clicked on "Python" in Notepad++ before writing the script, I saved the script as Objects.py, I saved it where other .blend files have been saved before, I plugged an Always sensor into a Python controller and made sure that the controller was set to Module, I typed in Objects.Player and made sure that everything looked exactly like how it did in the picture and for some reason, the console keeps saying:

    Blender Game Engine Started
    Python module can't be imported - object 'Player', controller 'Python#CONTR#1':
    ImportError: No module named Objects

    If you don't mind me asking, what am I doing wrong? This tutorial is very well-written -- I'm just not sure about what to do after several attempts. Is it because I haven't saved the .blend file yet? Like, do I need to save the file first, then open it again and try running the script? I've heard that programs written in Python will not run until they're saved first, so I thought that this might work the same way. Is that the case?

    ReplyDelete
  20. Well, from the sound of it, you haven't defined the function in the script. If you notice, my Python file is named Objects.py, and the function within is named 'Player' (the "def Player():" line ). So, Objects.Player will only work if the Python file is named Objects, and the function is named Player.

    ReplyDelete
  21. I made sure to put def Player(): in the script, though. That's why I'm wondering about why Blender is even still giving me error messages in the first place.

    Thanks for the tip, but what else do you suppose could be wrong?

    ReplyDelete
  22. Oh, I'm sorry - yeah, you need to save the script, and it needs to be in Python and Blender's script path. Basically, save the file in the same folder as the blend file.

    The script doesn't exist on disk until you save it. :)

    ReplyDelete
  23. I DID save the Python script, though. I was asking if I should save the .blend file in order for the script to work. Because, I mean, I put the script where other .blend files are, but the .blend file that's supposed to run the script has not been saved yet. Do I need to save the .blend file in order for it to work?

    ReplyDelete
  24. Actually, that might be the issue. Save the blend file where the script is, and if it still doesn't work after saving, try restarting Blender.

    ReplyDelete
  25. =) It worked, thanks. I'm looking forward to following these other tutorials, as well.

    ReplyDelete
  26. I implement the tutorial and every thing is ok just one thing which is I just get one position record not continuous like in the tutorial

    ReplyDelete
  27. what I mean by my last comment is always in sensor does not work well I replace it with random. random is working but I need always function to work because with always, it capture the motion in equal time not like random. I hope you can help me mate.

    ReplyDelete
  28. Ensure that you ticked the true level pulse button on the Always sensor - it looks like this: [''']. The second picture shows how the logic brick setup should look.

    ReplyDelete
  29. thanks mate it is work perfectly. Do you know how to get the accelartion for the object in python???
    thanks so much again
    King regard

    ReplyDelete
  30. Hi SolarLune how can i rotate the object like platform games when we hit left it turns 180 degree and when we hit right it turns -180. I tried to do it with the code you taught above example but when i hit keys it starts rotating continuously and i tried many things nothing works can you please help me also how can i get the rotation value like the position value to print out

    ReplyDelete
  31. sorry posted in the wrong page. I did what you taught in the Using Python in the Blender Game Engine - Part 2 page

    ReplyDelete
  32. @puppeteer3d - Well, an easy way would be to use the standalone mathutils module and the Euler class. Using this, you can directly set the orientation of an object using easy X, Y, and Z values for rotation. Using it would look like this:

    ----CODE START----

    import mathutils

    euler = mathutils.Euler([X, Y, Z])

    ----CODE END----

    With the X, Y, and Z values substituted out for the amount that you want to manually rotate the object by. You most likely want to rotate the value by the Z axis to turn it around. Also, you can get the object's current rotation in a Euler value to examine with the to_euler() function:

    ----CODE START----

    from bge import logic

    cont = logic.getCurrentController()

    obj = cont.owner

    e = obj.orientation.to_euler()

    ----CODE END----

    You can assign Euler values to an object's orientation just by using the equal sign, as well:

    ----CODE START----

    obj.orientation = e

    ----CODE END----

    ReplyDelete
  33. Note that the X, Y, and Z values that are to be substituted above are radian values. The math module has functions to convert between radians and degrees if you need to use them.

    ReplyDelete
  34. Hi i tried to do what you have said but didn't get a correct rotation can you please post the code to rotate(flip) the character. Sorry to annoy you with stupid questions I am a zero programmer struggling to learn blender and python. Here is what i did with the code.

    from bge import logic
    from bge import events
    import mathutils
    from math import radians


    def Player():
    cont = logic.getCurrentController()
    obj = cont.owner
    e = obj.orientation.to_euler()

    motion = cont.actuators['Motion']
    key = logic.keyboard.events

    kbleft = key[events.AKEY]
    kbright = key[events.DKEY]
    if kbleft > 0 :
    e.z = 180
    elif kbright > 0 :
    e.z = -180


    obj.orientation = e

    ReplyDelete
  35. @puppeteer3d - Ah, I see. You're using degrees when you set the euler rotation there - you need to use radians. For example, to rotate an object 180 degrees, it would be:

    -- CODE START --

    e.z = math.pi

    -- CODE END --

    So make sure you import the math module (the whole thing - not just a part of it). Also, if you code, ensure that you have Blender's console visible. You can open it in Windows in the Help menu.

    ReplyDelete
  36. Thanks for you answers SolarLune

    ReplyDelete