blendenzo.com
News Tutorials Games Downloads Links Contact

Featured Author:

Social
-Social-

Tutorials - Blender Game Engine

Beginning BGE Python

by Social

PREREQUISITES:
  • Basic knowledge of the general Blender interface: Link
  • Basic knowledge of the BGE Logic Brick system: Link
  • Basic knowledge of the Python programming syntax: Link
TUTORIAL FILES:
Control_LBVER.blend (144kb)

WHO THIS TUTORIAL IS FOR:
This tutorial is intended for those of you who have been "messing around" with the BGE for some time, but have not yet found the time to tinker with the python scripting aspect. It is meant to serve as a solid foundation from which you can get a decent start in learning how to use python with the BGE.

START WITH WHAT YOU KNOW:
Because this is the very beginning of your PY-BGE experience, we will use Python to accomplish something that can already be done with logic bricks alone. Our goal here will be to construct a simple control scheme for an object in the gamespace. This way, we eliminate any confusion that could potentially arise from setting a goal that you may not yet be familiar with.

Just to establish our standing knowledge, we should probably start by taking a look at the logic brick only version first. So go ahead and open "Control_LBVER.blend". Take note of the simple logic brick setup for the "Player" object, then press P and give the scheme a try, just to see what it does and how it behaves.

SETTING THINGS UP FOR SCRIPTING:
I already set up the blender window arrangement for you. The 3D window is on the left, the text editor (where you write your code) is on the right, and the logic buttons window is on the bottom (where the logic bricks are of course). You can choose your own arrangement when you feel comfortable enough to do so, but for the time being the current window setup will do ok. All that's left for you to do now, is to simply delete all the "and controllers" along with all the actuators and save this file as: "Controls_PYVER.blend" (no quotes) somewhere on your system.

PYTHON NEEDS LOGIC BRICKS TOO:
Yep, we kept those sensors for a reason. There is a common misconception among beginners that python scripts work on the same principle as some C coded games, where you usually have a main(), under which everything else is programmed, taking logic bricks out of the equation. However, in the BGE Python initiates events by making calls to C functions, and it usually has to be used in conjunction with logic bricks for events to occur. So there is no main(), and you are basically programming a complex controller which will *usually* have to get it's input from sensor bricks, and project it's output to actuators which make things happen.

So in turn, any python script we write will also have to be represented by a logic brick (more specifically a controller).

ASSIGN A SCRIPT TO A CONTROLLER:
  • Add a new controller for the "Player" object.
  • By default it should be an "AND" controller, but we need the "Python" controller, so change it.
At this point you should notice the "Script:" textspace under the Python controller. This is where you input the name of your script. Try to do that now:
  • Click on the "Script:" textspace to enable input mode, and type in "MyScript" (no quotes).
The reason that didn't work is because there is no file named "MyScript" to assign to the controller.
  • Try typing in "Text" this time (no quotes, also keep in mind that everything in blender and python is case sensitive by default)
Well, that worked, because the "Text" file is created by default whenever you start blender. (Actually it's the very same file displayed right now in the blender text editor) Therefore it can be assigned as a script to a Python controller.
  • In the text editor window, browse existing files (by clicking that little arrow box to the left of the "TX: Text" textspace).
There should be 3 options "Text", "ADD NEW" and "OPEN NEW". "Text" is obviously the name of the only existing file (so far), "ADD NEW" will add a new file (which will by default be called Text.001) and "OPEN NEW" would open a python script from anywhere on your system. (which could be very useful when you wish to work with an IDE like IDLE etc, but want to use the script in the BGE afterward)
  • Click on the "ADD NEW" option, rename the created file (Text.001) to "MyScript" (no quotes, case sensitive).
  • Now assign "MyScript" (no quotes, case sensitive) to the Python controller.
  • Go to the text editor window, and rename "MyScript" to a name of your preference. It doesn't matter what name you choose, as long as it's something different than "MyScript".
Now look at the Python controller again. Just like magic, it changed automatically to correspond with your rename in the text editor. It's a neat little function.

YOUR FIRST LINES (of code):
In the text editor window, on the first line type:

cont = GameLogic.getCurrentController()

As you may have already speculated, "cont" is short for controller. It is simply an assignment variable, for which you can choose any name you wish. Writing out "controller" instead of "cont" would not be wrong here, just like any other name. However it should be noted that within the BGE community "cont" is the most common naming standard used, so it would probably be best for you to go with the flow and use "cont", so as to avoid any probable confusion in the future.

What we assign to "cont" is a function called "getCurrentController()" which returns the current controller (as the name implies) and gives us access to it, and various other functions. "GameLogic" has to be listed before "getCurrentController()", because "GameLogic" is the module containing all the functions available to us in the BGE.
  • Connect the Up sensor to our python controller. In our script, input this code, two lines down from "cont":

print dir(GameLogic)

  • Start the game with P, press the [Up] key once, and then stop the game [ESC].
Now if you look in the blender command prompt, you will find all the functions available to you under the GameLogic module. It's a nice method to get a quick overview, but for more detailed information on what exactly is available and how to use it, you should check the official documentation: Link
  • Remove the "print dir(GameLogic)" line from the script.
Basically, it's a hiearchical structure. Think of in terms of ordinary files, stashed somewhere on your system. You have a directory(folder) named "GameLogic", and in that directory you have a subdirectory named "getCurrentController". Now in order to get to the "getCurrentController" directory, you have to open the "GameLogic" folder first, because that's what "getCurrentController" is under. And why did we assign this to "cont" in the first place?
  • Under "cont" type this line:

own = cont.getOwner()

Well, because if we didn't assign the "getCurrentController" function to "cont", the line above would have to look like this:
  • Don't type this in, it's just for show:

own = GameLogic.getCurrentController().getOwner()

As you can see, it's considerably longer, and nowhere near pretty, but it is the same exact thing. We just saved ourselves some typing by making an assignment shortcut.

The "getOwner()" function gives us access to the owner, (in this case the "Player" object) and subsequent functions. To see a list of all available functions under it, you can do "print dir(own)" if you want, or better yet, you can get detailed info in the official blender documentation. In addition to the available functions, "getOwner()" is most commonly used to access properties, which you assign with the big "Add Property" button in the buttons window.
  • Go ahead and add a "Timer" property in the buttons window and name it "time" (no quotes)
  • In your script add the following, two lines down from "own = cont.getOwner()":

print own.time

  • Start game with P, wait a few seconds, press [Up] once, stop game [ESC].
Now, looking at the blender command prompt, you will see a time value (in seconds) printed. The time property that you assigned is something like a stopwatch that starts ticking up seconds as soon as you begin game. It is very useful because you can access it through own (as shown) and trigger events by it, modify it, keep track of time obviously etc. The main point to remember here is that to access those properties from your script, you have to do it through own. So it's "own.yourpropertyname" to access/modify/store a value/string which the property represents.
  • Remove the "print own.time" line from your script, and remove the "time" Timer property in the buttons window.
  • Insert the following code where "print own.time" was previously located:

#Sensors: forward = cont.getSensor("Up") backward = cont.getSensor("Down") turnleft = cont.getSensor("Left") turnright = cont.getSensor("Right")

See a pattern? "#Sensors" as I'm sure you already know, is a comment (as is anything preceded with a "#" in python). Here I'm just giving the code some organization by stating that what follows are my sensor assignments. The basic routine to get a sensor is as you can plainly see: cont.getSensor("yoursensorname"). That is, the name that your sensor brick carries. When getting a sensor name you have to use quotes, and as with everything in python, this too is case sensitive. So if you were to type: getSensor("up") instead of ("Up") you would get an error (errors will show up in the blender command prompt). In order for things to work properly the name in cont.getSensor("name") has to be exactly the same as the name on the sensor logic brick, (only with quotes) and the sensor brick itself has to be connected to the python controller. So on that note:
  • Connect the remaining three unconnected sensor logic bricks to the python controller.
  • Add an actuator (It should be a Motion actuator by default) and name it "motion" (no quotes)
  • Connect this actuator to the python controller as well
  • In your script enter the following, two lines down from "turnright":

#Actuators motion = cont.getActuator("motion")

Pretty much the same thing as with the sensors. Here, the assignment name is the same as the actuator name. Just to show you that you can do that (if you want to). Assignment names don't have to be the same though (as I demonstrated with the sensors) as long as the right name is called with .get.
  • Two lines down from motion, insert the following code:

#Process speed = 5 rspeed = 0.02 walk = 0 turn = 0 if forward.isPositive(): walk = speed if backward.isPositive(): walk = -speed if turnleft.isPositive(): turn = rspeed if turnright.isPositive(): turn = -rspeed motion.setLinearVelocity(0, walk, 0, 1) motion.setDRot(0, 0, turn, 1) GameLogic.addActiveActuator(motion, 1)

Let's start with the variables at the top. These are here pretty much to hold the values we wish to assign to the motion actuator depending on what keys we press. The "speed" and "rspeed" hold the numbers that we want to assign to the "walk" and "turn" variables when we are pressing some of the movement keys (weather they will be positive or negative values is determined by which keys are currently active). "walk" and "turn" variables are the default assign when nothing is happening (hence they are initially set to 0), so it is these variables that will be assigned to the actuator. "speed" and "rspeed" will only be assigned to "walk" and "turn" when the situation calls for it. Otherwise "walk" and "turn" are by default 0, and nothing happens.

NOTE: The variables that we have set here, are reset at every script pass (a pass/pulse is simply referring to when the "script is read", which is something that happens very fast, and many times during a games run). Meaning that any values that these variables might have held in a previous pass, will be replaced by default when the initial value assignments are re-read. So if you are looking to make a counter, or something along those lines, you should use a property, and call to it through "own.propertyname", because variables like the ones we are using here won't do in that case.

The "if" statements should be self explanatory "if sensorassigment.isPositive():" checks for weather or not a key is pressed, and if it is, the code below is run, and so "walk" and "turn" variables are set accordingly.

"motion.setLinearVelocity(0, walk, 0, 1)" is where the "walk" variable is assigned to the actuators Y axis exertion placeholder. The general input that setLinearVelocity will recieve is (X, Y, Z, L/G). L/G standing for weather or not the exerted velocity will be administered locally(1) or globally(0).

"motion.setDRot(0, 0, turn, 1)" functions on the same exact principle. Except this time we are using DRot as our translation method, and the "turn" value is applied to the Z axis placeholder, instead of the Y.

"GameLogic.addActiveActuator(motion, 1)" is simply used to activate the actuator, and get it to make movements according to the assigned values via motion.set[TranslationMethod](). The general input that the addActiveActuator will recieve is: (actuatorassigment, 0/1). 1 activates the actuator, 0 deactivates it.

If you did everything right, your script should look like this, in it's entirety:

cont = GameLogic.getCurrentController() own = cont.getOwner() #Sensors: forward = cont.getSensor("Up") backward = cont.getSensor("Down") turnleft = cont.getSensor("Left") turnright = cont.getSensor("Right") #Actuators motion = cont.getActuator("motion") #Process speed = 5 rspeed = 0.02 walk = 0 turn = 0 if forward.isPositive(): walk = speed if backward.isPositive(): walk = -speed if turnleft.isPositive(): turn = rspeed if turnright.isPositive(): turn = -rspeed motion.setLinearVelocity(0, walk, 0, 1) motion.setDRot(0, 0, turn, 1) GameLogic.addActiveActuator(motion, 1)

If it looks good, give it a run. If it works *and* you feel like you understand most of it, you have successfully completed this tutorial. If not, you didn't.

GOING FURTHER:
This was simply a presentation of the very basics. In order to further progress, you will have to study, and implement new features as you learn them. One of the best ways to do so is by looking over .blend files others did, and then tinkering with the python code there. Try to figure out what the code actually does, make your own modifications, try to add a new functionality etc.

For example: Try to add a jumping feature to the player object (via python) to the practice file used in this tutorial, and try to figure out how to make it so that you have to let go of the jump key, before you can jump again. Use this template to practice, and use the BGE API documentation. Don't be afraid to try new things. The worst thing that can happen is: blender crashes (and that's if you really mess up) in which case you can just start it up again.

EPILOGUE:
Now, you may not see the benefit of scripting all that clearly in this situation, but just imagine that you have more than 4 keys, and 2 constant speeds. Changing one variable is a lot easier than going around all your logic bricks, and changing each and every individual actuator value. When a game starts reaching a considerable size, logic bricks in many cases are not even an option, you will have to go with Python sooner or later. There are also other benefits, like being able to change gravity on the fly, and many other things that just can't be done with logic bricks, but that's something that you can look up for yourselves.

I hope this tutorial helped you gain a general idea on how the BGE API works. Just remember: it's a great time to learn how to use the BGE to it's full extent. With the OGRE implementation on the way, and a load of great new features, learning the BGE is not a waste of time. So keep at it.

Social


Back to the tutorials index...


Website design by Tony "blendenzo" DiRienzo. All content © Copyright Tony DiRienzo unless otherwise noted.