= 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 == '''We check out the source and data repository and build for the first time''' 0. Open a Terminal. {{{ Applications > Accessories > Terminal }}} 0. Create a folder for yourself on the local harddrive {{{ mkdir /scratch/ && cd /scratch/ }}} 1. Create your orxonox directory (if not already existing): {{{ mkdir orxonox && cd orxonox }}} 2. Now check out the latest revision of the data repository (you will probably be asked for a username and password once): {{{ svn co http://svn.orxonox.net/game/data/trunk data_extern }}} 4.1 Open a new terminal tab, to work in parallel. {{{ Press Control + Shift + T. }}} 4.2 Now get the latest revision of the tutorial: {{{ svn co http://svn.orxonox.net/game/code/branches/tutorial5 tutorial }}} 4. Prepare to build: {{{ mkdir build && cd build cmake -G"Eclipse CDT4 - Unix Makefiles" -DECLIPSE_CDT4_GENERATE_SOURCE_PROJECT=TRUE ../tutorial }}} 5. Now build for the first time (may take some time, further builds will be faster): {{{ make -j4 }}} The ''-j4'' means to create 4 parallel compile processes. 6. Additionally you can use [wiki:EclipseIDE Eclipse] as IDE to develop (if you don't want to use the console ;)). You can also use [wiki:KDevelop3] as IDE, though the assistants can help you more with Eclipse. '''Start the game for the first time''' 7. Enter to the appropriate folder and start the game. You will see a menu popping up, just press the ''Quickstart'' button. {{{ cd ~/-extra-0/orxonox/build ./run }}} == 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 a look at it. == 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 AutonomousDroneController:''' Controller C++ code to steer the drone * '''The XML part:''' An instantiation in the level file == 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 find the code in the files ''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. 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_''? == 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. 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. Again if you have been having '''problems''' consider the following suggestions: * 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. == The XML Part == As a last step we will include the drone in our level and add the visual part of the drone, the model (and some other stuff, too). Now that you finished the classes you can recompile the project. This is again done by typing in the console: {{{ make -j3 }}} Afterwards open the level file: 1. Open ''tutorial/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. The controller would normally be added to the AutonomousDrone in XML, but as we're currently updating the framework, we need to add this outside the AutonomousDrone. Add these two lines below the AutonomousDrone entry above: {{{ }}} == Have a look at your AutonomousDrone == - Now recompile the code, 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.