/* $Id: wopsprites.hpp,v 1.17 2005/06/28 13:55:26 chfreund Exp $ */
#ifndef WOP_GRAPHICS_CLASS_DEFINED
#define WOP_GRAPHICS_CLASS_DEFINED
/**********************************************************/
#include "constants.hpp"
#include "random.hpp"
#include "spriteset.hpp"
class Object;
/**********************************************************/
//! the interface for class WopSprites, that is visible inside class World
class WopSpritesWorldInterface
{
public:
virtual ~WopSpritesWorldInterface( void ) {};
virtual int getSequenceLength( const Object& object ) const = 0;
virtual int getNumSequences( const Object& object ) const = 0;
virtual int getSequenceLength( const Sint32 id,
const Sint32 iseq ) const = 0;
virtual void removeColoredInstance( Object& object ) = 0;
protected:
WopSpritesWorldInterface() {};
};
/**********************************************************/
//! The class, that organizes all sprites for the game
/*! WopSprites in a nutshell:
* - one sprite (class Sprite), i.e. one picture, that is drawn on
* the screen, is called a frame.
* - several frames, organized as a vector of pointers pointing to
* them (class PointerVector) a called an animation sequence, or
* just sequence (class SpriteSequence).
* - again a PointerVector of sequences is called a sprite
* set (class SpriteSet) or just set.
* - and, once again, a PointerVector of sprite sets builds
* the WoP sprites (class WopSprites).
*
* If an object should be drawn, the class WopSprites must select the
* appropriate sprite (== frame).
*
* - Therefore first the correct sprite set must be selected.
* The set belonging to an object is simply determined by
* its object ID (see class Object). This ID is the access index
* in the pointer vector of sprite sets in the WoP Sprites.
* - Furthermore an objects keeps an index of its current sequence
* and of the current frame in this sequence.
*
* There are also objects, like for example the avatars, that exist
* inside the game in differently colored versions. The strategy of
* WoP is to load each frame of such sprite sets as one
* ore more layers. Then these layers are colored separately and
* combined into a specificly colored single frame (also see
* Sprite::colorGrayPixels and SpriteSet::getColoredInstance). Such
* sprite set, that must be colored and built before usage, is
* called templated and the readilly colored set is
* called a colored instance or just an instance. If
* a set is templated, it additionally keeps all its
* instances. Therefore we can ask a templated set for
* an instance specified by an array of colors (with at least
* the length equal to the number of layers).
*
* Therefore an object, that uses a templated set, must implement the
* methods Object::getColors and Object::getNumColors (for an example
* see class AvatarWorm). All objects provide the interface
* Object::setInstance, Object::getInstance. These functions are only
* used by class WopSprites to store and receive the index of the
* instance inside the vector of instances. Now we can answer the
* question ...
*
*
* How is an object drawn by class WopSprites?:
* - WopSprites retrieves the object's ID and selects the corresponding
* sprite set.
* - If this set is templated, WopSprites asks the object for
* the instance index. If this index is < 0, the index is saught
* using the colors of the object. If a matching instance is not
* yet built, it is tried to be created. After that we have a pointer
* to a usable sprite set, either a colored instance
* or an original set.
* - In the finally determined set the sequence and frame is
* selected and drawn, using the indices got from the object.
*
* Why is WopSprites a class template?
* Although WopSprites only represents the graphic sets for all objects,
* it influences the events in the world, nevertheless. For example an
* explosion lives as long, as the last frame of the explosion sequence
* is not drawn. Therefore the sequence length limits the life time of
* the explosion object. This information must be accessible on the
* client as well as on the server. But it would not be a proper
* implementation to load all graphics on the server, too. Therefore
* the WopSprite object is instantiated with a dummy sprite class,
* which supports the full interface of class Sprite, but implements
* no functionality. The result is a fully working WopSprite instance
* with a behaviour identical to the one of the client's version, with
* the only difference, that not a single graphic is loaded or drawn.
*
* The configuration file
* The configuration file for the WoP's graphic set has got only one
* setting, namely "pathconfigpairs". To this setting pairs of strings
* must be assigned. Each of these pairs consist of
* (1) path to the configuration file of the sprite set (path,
* relative to the path, where this file is placed)
* (2) name of the configuration file, that defines the sprite
* sequence. This mentioned file must be found in the path
* defined in part (1)
*
* example for the configuration file:
*
* \code
* pathconfigpairs = explosions, explosion_small.config, \
* explosions, explosion_medium.config, \
* explosions, explosion_big.config, \
* magic, flashes
* \endcode
*/
template
class WopSprites : private PointerVector< SpriteSet >,
public WopSpriteSettingDefs,
public WopSpritesWorldInterface
{
public:
WopSprites();
virtual ~WopSprites();
// implementation for the interface routines
int getSequenceLength( const Object& object ) const;
int getNumSequences( const Object& object ) const;
int getSequenceLength( const Sint32 id,
const Sint32 iseq ) const;
//! \name access to the underlying data
//!@{
//! returns a pointer to the SpriteSet for the object ID "objectID"
/*! Since the objectID does not contain any further information
* in colored case the basic SpriteSet is returned, not the
* colored instance.
*/
inline const SpriteSet* getSet( const int objectID ) const;
//! returns a pointer to the SpriteSet belonging to the passed object.
/*! If the set is templated and the object supports coloring,
* the according instance is returned (which is built, if
* not already present AND "create" is set to true)
*/
inline const SpriteSet* getSet( Object& object,
const bool create = true );
/*! pointer to the SpriteSet object, that represents the
* colored instance with index "instance" for object ID
* "objectID"
*/
inline const SpriteSet* getColorInstance( const int objectID,
const int instance ) const;
/*! pointer to the SpriteSet obhect, that represents the
* colored instance of object ID "objectID" with colors at
* "colors". If "create" is set to true, the class will try
* to create the instance, if not already present.
*/
inline const SpriteSet* getColorInstance( const int objectID,
const Uint32* const colors,
const bool create = true );
/*! pointer to the SpriteSequence object, that is sequence with
* index "sequence" in the sprite set with ID "objectID"
*/
inline const SpriteSequence* getSequence( const int objectID,
const int sequence ) const;
/*! pointer to the Sprite object, that is frame with index
* "frame" in sequence "sequence" in the set of ID "objectID"
*/
inline const T* getSprite( const int objectID,
const int sequence,
const int frame ) const;
//! pointer to the Sprite object, according to the passed object
const T* getSprite( const Object& object,
Sint32* nextSequence = NULL,
const bool create = true );
//! removes and destroys the specified colored instance
void removeColoredInstance( Object& object );
//!@}
void reset();
// load graphics
bool load( ProgressLog* const progresslog = NULL );
bool load( const char* const BasePath,
const char* const ConfigFile,
ProgressLog* const progressloog = NULL );
//! draws the passed object on the surface
/*! This function draws the passed object on the passed surface.
* If the object supports color and the found sprite set is
* templated, the according instance is sought and created, if
* not found.
* \param object the object that should be drawn
* \param surface the SDL_Surface, the object sould be drawn on
* \return the index of the next frame. Set this new frame
* index in the object, if you want the animation to be
* continued
*/
int draw( Object& object,
SDL_Surface *const surface );
//! draws the passed object on the surface
/*! This function draws the passed object on the passed surface.
* If the object supports color and the found sprite set is
* templated, the according instance is sought and created, if
* not found. The object is drawn at the passed position (x,y),
* i.e. the coordinates of the object are ignored.
* \param object the object that should be drawn
* \param surface the SDL_Surface, the object sould be drawn on
* \return the index of the next frame. Set this new frame
* index in the object, if you want the animation to be
* continued
*/
int draw( Object& object,
const int x,
const int y,
SDL_Surface *const surface );
//!
enum { CHOOSE_RANDOM_SEQUENCE = -1 };
};
/**********************************************************/
#endif // WOP_GRAPHICS_CLASS_DEFINED