Orxonox
0.0.5 Codename: Arcturus
|
The Pickup module adds a special type of object to Orxonox, the so-called Pickupables. More...
Modules | |
Items | |
The actual pickups can be found here. | |
Files | |
file | CollectiblePickup.h |
Definition of the CollectiblePickup class. | |
file | Pickup.h |
Declaration of the Pickup class. | |
file | Pickupable.h |
Definition of the Pickupable class. | |
file | PickupCarrier.h |
Definition of the PickupCarrier class. | |
file | PickupCollection.h |
Declaration of PickupCollection. | |
file | PickupListener.h |
Definition of the PickupListener class. | |
file | PickupManager.h |
Definition of the PickupManager class. | |
file | PickupRepresentation.h |
Definition of the PickupRepresentation class. | |
file | PickupSpawner.h |
Definition of the PickupSpawner class. | |
Classes | |
class | orxonox::CollectiblePickup |
The CollectiblePickup class encompasses all Pickupables that can be added to a PickupCollection and thus be part of such. More... | |
class | orxonox::Pickup |
The Pickup class offers (useful) base functionality for a wide range of pickups. More... | |
class | orxonox::Pickupable |
An Interface (or more precisely an abstract class) to model and represent different (all kinds of) pickups. More... | |
class | orxonox::PickupCarrier |
The PickupCarrier interface provides the means, for any class implementing it, to possess Pickupables. More... | |
class | orxonox::PickupCollection |
The PickupCollection combines different Pickupables (more precisely CollectiblePickups) to a coherent, single pickup and makes them seem (from the outside looking in) just as if they were just one Pickupable. More... | |
struct | orxonox::PickupInventoryContainer |
Data structure to store collected data for one specific Pickupable. More... | |
class | orxonox::PickupListener |
The PickupListener class facilitates the flow of information regarding the picking up, dropping, using and unusing of Pickupables to interested parties (such as the PickupManager). More... | |
class | orxonox::PickupManager |
The PickupManager class manages Pickupables. More... | |
class | orxonox::PickupRepresentation |
The PickupRepresentation class represents a specific pickup type. More... | |
class | orxonox::PickupSpawner |
The PickupSpawner class is responsible for spawning @ref orxonox::Pickupable "Pickupables" of a specific type.More... | |
Enumerations | |
enum | orxonox::PickupActivationType { orxonox::PickupActivationType::immediate, orxonox::PickupActivationType::onUse } |
Enum for the Pickup activation type. More... | |
enum | orxonox::PickupDurationType { orxonox::PickupDurationType::once, orxonox::PickupDurationType::continuous } |
Enum for the Pickup duration type. More... | |
The Pickup module adds a special type of object to Orxonox, the so-called Pickupables.
Pickupables are objects that can be picked up (by virtually any entity, but commonly by the Pawn) and have some kind of effect on the entity that picked the Pickupable up.
Pickupables are designed so that they can be included in levels fairly easily, while also ensuring, that the pickup itself (its game-logic component) and how it is represented (e.g. in the PickupInventory (the GUI that displays Pickupables) or in the game) are neatly seperated. To be able to use Pickupables in a level one must understand some basic concepts.
There is a file called pickupRepresentationTemplates.oxt
in levels/templates
, which holds the templates for the PickupRepresentations and also templates for Pickupables. The templates for the PickupRepresentations define the StaticEntities that are attached to the PickupSpawners to make them look like the Pickupable they are spawning. The templates for the Pickupables can be added just for ease of use. If you want to use pickups you will have to include this file in your level file, somewhere above the Level-tag.
There is another file called pickups.oxi
in level/includes
which creates all PickupRepresentations needed for the Pickupable supplied by the pickupRepresentationTemplates.oxt
file. This file will have to be included as well. It has to be somewhere after the opening Scene-tag and your first use of a pickup.
After that all the predefined pickups specified in those two files can be used just by creating a PickupSpawner for them in the respective level. For example:
Please be aware, that the Pickupable specified for the PickupSpawner, has to be exactly the same (including all parameters) to the one specified in the pickups.oxi
file. To make things simpler, one could just use the templates specified in the pickupRepresentationTemplates.oxt
file. Which, following the previous example, would look like this:
To include a type of pickup (which, as we remember, is the class of the Pickupable with specific values for all the relevant parameters) in a level file, you can just create a new PickupSpawner and specify the Pickupable.
As can be seen in the pickupRepresentationTemplates.oxt
file and the pickups.oxi
file there is no PickupRepresentation defined for this type of pickup. Thus the default representation will be used.
To create an appropriate PickupRepresentation for the inserted pickup above, you can just create a PickupRepresentation within the scene (Within the Scene-tags).
Notice, that the type of pickup specified for the PickupRepresentation, naturally, needs to be the same (this is the way they can be connected). Also, we just used an existing spawnerTemplate, to make things simpler.
The next step is to create a spawnerRepresentation uniquely for our new type of pickup. Lets call it newhealthpickupRepresentation
. Thus the parameter spawnerTemplate of the PickupRepresentation has to be changed to that value.
The spawnerTemplate defines how the PickupSpawner is displayed in a level. In our example case it could look like this:
Please refer to the pickupRepresentationTemplates.oxt
for more examples.
The PickupRepresentation also needs another parameter the inventoryRepresentation. This parameter defined how the Pickupable is displayed in the PickupInventory (a menu to browse the currently equipped pickups).
This is the name of an image defined in the PickupInventory imageset (PickupInventory.imageset
), which can be found in data_extern/gui/imagesets
.
This is all that has to be done. Now you have a new pickup type with an appropriate PickupRepresentation for your use. If you feel that your pickup is useful in general, please don't hesitate to create a template for the pickup and add your pickup to the pickupRepresentationTemplates.oxt
file and the pickups.oxi
file, so that anyone who wants to use it can do so quite easily.
There is also an additional way to create new types of pickups to be used in a level (without having to do any coding). There is a Pickupable called the PickupCollection, which is just a collection (hence the name) of Pickupables (more precisely of CollectiblePickups), behaving as if it was just one Pickupable. A PickupCollection can be created as follows:
Of which types of pickups a collection is made up is entirely up to the one creating the PickupCollection, they can be mixed freely.
Things have been fairly straightforward so far. Creating a Pickupable form scratch isn't as easy. Therefore I'm just going to supply you with a recipe, or a set of steps you have to take, without which your pickup won't work and point out some common pitfalls.
For a new Pickupable you need to create a new class in >modules/pickup/items
. Your class needs to be derived from another pickup class, normally this would either be Pickupable, CollectiblePickup or Pickup. Pickupable is (as mentioned earlier) the base class of all things that can be picked up, thus of all pickups. CollectiblePickup is a (directly) derived class of Pickupable and provides the additional functionality of enabling your pickup to be used in a PickupCollection. However you are probably going to want to derive your class form Pickup, because it is a CollectiblePickup and provides some useful methods. So have a look at Pickup. Once you have created your new pickup class you have to insert it in the PickupPrereqs.h
file in the modules/pickup
folder and in the CMakeList.txt
file in the modules/pickup/items
folder. Also have a look at other pickups to make sure you include all the necessary files in your class.
You also have to choose the entities that are allowed to pick your pickup up. After you have chosen the entity that carries your pickup, you need to do the following.
getCarrierChildren()
and getCarrierParent()
. These tow methods are needed, because all pickups are initially picked up by a Pawn and then handed down to the entity that effectively carries them. With the above mentioned two function just that is accomplished. A hierarchical structure is established with one parent and a set of children, where the Pawn is the root node of this hierarchical structure, the only entity with no parent.addTarget()
function. So you have to make sure the target is added whenever one of your pickups is created (so, most conveniently somewhere in the constructor), with the following command. Now that we have the skeleton of a pickup and we have defined which carriers are allowed to pick our pickup up we are going to take a look at all the methods we can (or sometimes have to) overload from Pickupable, for our pickup to work properly. But first I will introduce some more concepts to make the need for these methods more obvious.
Let's have a look at the important methods.
changedUsed()
method is called whenever the state of the Pickupable transits from being used to not being used or the other way around. Which means this method is probably the most important method you have at your fingertips, since it enables you to apply the effect of your pickup when it gets used and remove the effect as soon as it is no longer in use.changedPickedUp()
method is called whenever the state of the Pickupable changes from being picked up to not being picked up or the other way around. For example if you want your pickup to be used as soon as it is picked up, this is the method you have to overload to achieve that behavior (or just let your pickup be derived from Pickup, which implements exactly that behavior, if the activationType is set to immediate). You don't have to concern yourself with destroying the pickup or creating a spawner when it changes to not picked up, since that is already implemented with the Pickupable and PickupCarrier classes. If you want a different behavior, however, once again, this is the method.changedCarrier()
method is called whenever the carrier of the Pickupable changes. And by that I don't mean the class that is allowed to carry the pickup, but the object that actually carries (or carried) the pickup. Please do not overload this class to implement behavior for picked up -> not picked up transitions, use changedPickedUp()
for that. For most pickup classes this method doesn't need to be overloaded. Where it is used, however is in the PickupCollection class, where the new carrier needed to be communicated to all pickups the collection consists of, whenever the carrier was changed.Please be aware, that these three methods are methods registered with Super, meaning, that whenever overloading them, don't forget to call SUPER(MyClass, myMethod);
. Also when implementing the above methods you should think of what should happen in unexpected situations, e.g. when your pickup is unused manually and set to used again. Additionally you should use the destroy()
method of Pickupable instead of the method provided by OrxonoxClass, meaning Pickupable::destroy()
instead of plain destroy()
.
clone()
method creates a new pickup of the same type as the pickup it is cloned from. So the cloned pickup is not exactly the same, as it doesn't necessarily completely reflect the status of the pickup it is cloned from, but it reflects all the parameters and their values, that distinguish different types of this pickup class. It needs to be implemented by every pickup class. And it is best if this is done in a very specific way. Below is shown how: initializeIdentifier()
method initializes (or more simply put, creates) the PickupIdentifier of the instance of your pickup. Since the important values of the parameters are not yet available in the constructor of your pickup this initializeIdentifier()
method must be called as soon as they are available, which normally is in the XMLPort()
method, and the clone()
method, as seen above. In the initializeIdentifier()
method you need to register each parameter that is important for the type of your pickup to its identifier, this is normally done as follows: Be aware, this only works for parameters that are simple enough, meaning with pointers for example it will, naturally, not work, and other ways must be found (this is for example done in PickupCollection with a derived class of the PickupIdentifier, the PickupCollectionIdentifier) or in the DronePickup class by using a Template.
createSpawner()
method needs to be implemented by any pickup directly inheriting from Pickupable (or directly from CollectiblePickup), so if you inherit from Pickup, you don't need to implement this. It is used to create a PickupSpawner, when the pickup is dropped. A standard implementation would look like this.
|
strong |
|
strong |