|
Featured Author:
-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...
|