= PPS Coding tutorial =
== Summary and goals ==
In this tutorial, you will
* Download the source code and setup a programming environment on your tardis box
* Compile the code into a working version of the game
* Add an in-game object to the game and configure it
Since Orxonox is quite a large project, several steps are required to achieve the above.
== Preparations ==
You should have already downloaded and build orxonox last time. If not, refer to this: [wiki:PPS_download]
== Before you start coding ==
Before you start coding there's one [wiki:howto/XMLPort page] which is extremely useful for the following tasks. You might want to have it open in the background.
== The task ==
Our goal is to create a drone in Orxonox that does some kind of autonomous flying.
In Orxonox we try our best to separate different kinds of functionality. You will see that this is also the case here.
In the case of the drone we want to create, we separate the drone itself (called AutonomousDrone) from the entity that controls the drone (called the AutonomousDroneController) and the thing that gives shape and texture to our drone (basically that is the model). Or put more crudely, the AutonomousDrone is the physical entity, the AutonomousDroneController is its intelligence and the model is its visual representation. This is done for several reasons, the most important being, that with this kind of separation we can have multiple controllers for just one drone, we could also have one controller for multiple types of flying objects. And the behavior of our drone is independent of how it looks like. That makes your code more generic and leads to cleaner code, less dependencies and also less code in general.
The implementation of our drone will happen in three steps:
* '''The AutonomousDrone:''' Core C++ code for the AutonomousDrone class, contains the C++ ↔ XML interface
* '''The XML part:''' An instantiation in the level file
* '''The AutonomousDroneController:''' Controller C++ code to steer the drone
== The AutonomousDrone ==
At first we need to create the drone itself. The drone provides the functionality of physically having a place in the game world (because it's a WorldEntity) and being able to move in it. Also, this is the place where the XML interface functions are defined
so that the game knows what to do if an AutonomousDrone is instantiated in a level file, as we will do in the third part of
the tutorial.
{{{
#!html
Note: Do not just copy & paste! Most commands / codelines need to be edited. But that doesn't mean you shouldn't copy & paste, but you should think about whether what you paste should be modified and how.
}}}
Otherwise you'll get tons of compiler errors.
Be sure to also read the comments labeled with TODO in the code files.
We created for you the skeleton of an autonomous drone. You can download them by running these commands:
{{{
# make sure you're in the right folder (trunk)
pwd
# should print:
# /scratch//orxonox/trunk
wget http://svn.orxonox.net/game/code/branches/tutorial6/src/orxonox/controllers/AutonomousDroneController.{cc,h} -P src/orxonox/controllers/
wget http://svn.orxonox.net/game/code/branches/tutorial6/src/orxonox/worldentities/AutonomousDrone.{cc,h} -P src/orxonox/worldentities/
wget http://svn.orxonox.net/game/code/branches/tutorial6/data/levels/tutorial.oxw -O data/levels/tutorial.oxw
}}}
This will download the template files to ''src/orxonox/worldentities/AutonomousDrone.{cc|h}'' and ''src/orxonox/controllers/AutonomousDroneController.{cc|h}'' in the trunk folder that you checked out from our repository.
1. Open the file ''AutonomousDrone.cc'' and have a look at the code (the file can be found in ''src/orxonox/worldentities/'').
2. In order to be able to create an AutonomousDrone object from the XML file just by using the class name, you need to add a call of ''RegisterClass(Classname)'' somewhere inside the ''.cc'' (global, inside the namespace). This is best done just above the constructor.
{{{
RegisterClass(ClassX);
}}}
Note: You have to replace ''ClassX'' with the appropriate class.
3. Make sure that each drone object gets registered to the core by adding a call of ''RegisterObject(Classname)'' inside the constructor.
{{{
RegisterObject(ClassX);
}}}
The next part happens inside the ''XMLPort'' function. ''XMLPort'' allows you to specify how your class can be instantiated (i.e. how an object can be created) purely through XML. This is important when we want to create levels, which in Orxonox are specified in XML files.
The AutonomousDrone has two variables called ''auxiliaryThrust_'' and ''rotationThrust_'' defined in the header file (''src/orxonox/worldentities/AutonomousDrone.h''). To be able to set these variables to values from XML, we need
to add some code to the XMLPort function. There is already an example for the ''primaryThrust_'' variable.
4. Inside XMLPort, add similar calls for ''auxiliaryThrust_'' and ''rotationThrust_'' using the following scheme:
{{{
XMLPortParam(Classname, "xml-attribute-name (i.e. variablename)", setFunction, getFunction, xmlelement, mode)
}}}
'''Note:''' You need to add set- and get-functions for ''auxiliaryThrust_'' and ''rotationThrust_'' inside the ''AutonomousDrone.h'' file (have a look at {get/set}PrimaryThrust).
5. Now you need to add the AutonomousDrone to the build system. Open the file ''src/orxonox/worldentities/CMakeLists.txt'' and add ''AutonomousDrone.cc'' to the ORXONOX_SRC_FILES. This makes ''cmake'' consider the ''AutonomousDrone.cc'' file for further builds.
That's it for the AutonomousDrone class. Try to build your code.
{{{
make -j3
}}}
If you have been having '''problems''', consider the following suggestions, that might help you resolve them.
* Is the classname that you specified for ''RegisterClass(Classname)'' and ''RegisterObject(Classname)'' correct? If it is either ''Classname'', ''ClassX'' or ''ClassXY'', then it is incorrect, try to think about what it should be. If you can't find the solution ask one of the assistants.
* Have you created 2 set-functions and 2 get-functions for the two variables ''auxiliaryThrust_'' and ''rotationThrust_''?
* Did you edit the ''CMakeList.txt'' file?
== The XML Part ==
Next we will include the drone in our level and add the visual part of the drone, the model.
Open the level file:
1. Open ''trunk/data/levels/tutorial.oxw''.
2. We want to add a drone to the level now, so put in an entry for it (below the comment that tells you to do so). Look at this example:
{{{
}}}
Of course ClassX has to be replaced with the class name of the object you want to create. Additionally the parameters ''variable1'', ''string1'' and ''coord1'' are just examples, they have to be replaced by the appropriate parameters for your drone.
3. Now add the appropriate entries for the variables you defined in ''AutonomousDrone.cc''. (Have a look at ''data/levels/templates/spaceshipAssff.oxt'' for example values of the different thrusts).
4. As we want our drone to be visible we have to attach a model to it. Add the following code between the above 2 lines:
{{{
}}}
This adds a model with the mesh drone.mesh and the defined textures at the position of our drone object.
5. Because the physics engine needs a collision shape to work with, we will add the following entry (before ):
{{{
}}}
This will tell the physics engine what dimensions our drone has (in this case its just a cube).
6. Now we define the mass and two damping parameters of our drone. Append definitions for the following variables as attributes to your drone. (as in 3.)
{{{
mass = 50
linearDamping = 0.9
angularDamping = 0.7
}}}
Note: The Drone definition should now look like this:
{{{
mass=50 linearDamping=0.9 angularDamping=0.7>
}}}
7. Test it! E.g. start the game, open the level ''Coding tutorial'' and you should be able to see the drone.
It's a bit boring, as it doesn't move yet. This is the job of the controller.
== The AutonomousDroneController ==
Now you will finish the AutonomousDroneController which gets called each tick and steers the drone using the functionality of movement in the game world that the drone provides. i.e. the drone's intelligence.
1. Open the file ''AutonomousDroneController.cc'' and look at it (''src/orxonox/controllers/'').
2. Have a look at the constructor and make sure nothing is missing (think of the what we did for the AutonomousDrone).
3. Now look at the ''tick'' function. It gets called each time before a new frame is drawn. you can put in some steering code here (for instance by using the moveFrontBack function). If you want you can use some functions provided by Math.h:
{{{
rnd() // Return a random value between 0 and 1
sin() // Should be clear (also cos)
// Many other functions (have a look at src/util/Math.h for details)
}}}
4. Repeat step 5 (CMakeLists) of the AutonomousDrone for the AutonomousDroneController.
5. Compile it.
{{{
make -j3
}}}
Again if you have been having '''problems''' consider the following suggestions:
* Did you edit the correct CMakeList.txt?
* Did you register the object and create a factory for it? If not or you don't know what this means, have a look at steps 2 and 3 of the AutonomousDrone and think about how this applies to the AutonomousDroneController.
6. To see any change, you need to edit the level file again.
To do that, add these two lines below the AutonomousDrone (or anywhere in between the scene tags):
{{{
}}}
== Have a look at your AutonomousDrone ==
- Now start the game again and have a look at how your drone behaves.
- Don't worry if it does not react to your steering commands as expected. Try to modify some things.
- If you want to do some more things you can try to let the drone fly in circles or helixes.
- Play around a little bit with the linear/angular-Damping parameters.