Sprite Engine - 2D image drawing manager

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
keigen-shu
Posts: 8
Joined: Wed Dec 28, 2011 1:35 pm

Sprite Engine - 2D image drawing manager

Post by keigen-shu »

:: Sprite Engine :: version 03_2012
(C) Keigen Shu 2011-2012. Released under the zlib License.

SpriteEngine(SE) is an Irrlicht wrapper I made to manage the process of drawing a very large number of 2D images, each with different transformations on the screen.I wrote it because I find Irrlicht's 2D drawing interface to be lacking some features up-front. This is also my first API-like code. The source code is on the next post because it's really long.

Features:
  • Image transformations like colourMask, rotating and scaling.
  • A very simple programmable particle object API.
  • Documented code.
  • Float-based image positioning.
  • Image movement with rotation angle.
To-do:
  • Animated sprites.
  • Image drawing filters.
Demonstration from my game, LostWave: Image

Compiles on MSVC 2010 & GCC (try C++11 mode if it fails).

How to use
First, we need to setup the wrapper. Include "_SEngine.hpp" and then call SpriteEngine::setup(IrrlichtDevice*) right after you create your Irrlicht Device.

Code: Select all

#include "_SEngine.hxx"
 
IrrlichtDevice* pIrrlicht = createDevice(... blah ...);
if (pIrrlicht == 0) return 1;
 
SpriteEngine* pSpriteEngine = new SpriteEngine;
if (!(pSpriteEngine->setup(pIrrlicht)))
    return 1;
 
Okay, before we go on, I'll do a little explaining here. There are three object types in SpriteEngine: Image, Sprite and Particle(more on this later). An Image is just a container with an ITexture* to a spritesheet ITexture and a recti* to the rectangle of the part in the spritesheet you want. To draw an image, we create a Sprite and pass a Image* along with some drawing parameters into it. These Sprites are populated in a list (because there's a lot of them; one for each image drawn on screen) which is then simply passed to the engine to draw. You can do anything you want with it, like putting a Sprite for every player object and tell that object to manage it, or whatever, it's all up to you. Check out the documentation on _SSprite.hpp if you're wondering what you can do.

Code: Select all

 
// To load ITextures; SpriteEngine will delete them when the engine shuts down
ITexture* JunkTest = pSpriteEngine->loadTextureFromFile ("./Theme/image/JunkTest.png");
 
// Constructing an Image using an entire ITexture.
Image* imgParticle = pSpriteEngine->loadImageFromFile("./Theme/image/Particle.png");
 
// Constructing an Image using only a part of an ITexture
Image* imgBG = pSpriteEngine->loadImageFromFile("./Theme/image/BigBGImage.png", recti(0,100,800,700));
 
// Constructing an Image using an existing ITexture.
Image* imgJunkTest = new Image (tJunk, recti(10,20,30,40));
 
 
// To delete images, just do:
// Note that the ITexture is still not unloaded by the manager.
// Read the documentation on _SEngine.hpp on how to do that.
delete imgJunkTest;
 
// Nyan Nyan Nyan (our first sprite)
Sprite* sprNyanCat = new Sprite (
    imgNyanCat                , // source image
    position2df (80.0f,460.0f), // position (yes it's in float)
    120.0f                    , // rotation in degrees
    vector2df (1.5f)          , // make it extra large
    SColor(255,255,255,255)   , // colour mask
    true // tells the engine that the position value is based on the center of the image
);
 
// Let's put it in a list
irr::core::list<Sprite*>* sprList = new irr::core::list<Sprite*>;
sprList->push_back(sprNyanCat);
 
// Irrlicht's beginScene
pSpriteEngine->getVideoEngine()->beginScene(true, true, 0);
pSpriteEngine->getVideoEngine()->enableMaterial2D(true);
 
// Before doing SpriteEngine specific drawings, you need make this call.
// It was made for performance reasons. 
pSpriteEngine->saveMatrix();
 
// Draw the list
pSpriteEngine->drawSpriteList(spriteList);
 
// Nyan-cat flies by 4.8px, rotating by 2 degrees.
sprNyanCat->move(4.8f, 2.0f);
 
pSpriteEngine->drawSprite(sprNyanCat);
 
// After doing SpriteEngine specific drawings, you need make this call.
// It was made for performance reasons. 
pSpriteEngine->loadMatrix();
 
// end scene
pSpriteEngine->getVideoEngine()->endScene();
 
// to drop SpriteEngine...
pSpriteEngine->drop();
 
How to use Particles
Particles is basically programmable Sprites. The reason I named it as Particle because it was originally made with the ability to draw 2D particles in mind and it was based on Touhou's scipt-based bullet system (that Japanese Bullet Curtain game). A particle contains a list of PObjects, each containing a pointer to a Sprite and an integer counter to keep track of time/state/whatever variables. Like Sprite, a Particle is put into an irr::core::list<Particle*> and then sent to the engine to draw.

To use this, you just make a new class derived from Particle(as the parent class). SpriteEngine will call the update() function in your particle class everytime it wants to draw. You can use your own functions, whatever; it's your own code.

Basically there are three steps:
1. Initialization - make sprites
2. Draw and Update - move/transform sprites around
3. Death - You have complete control of this, but generally you'll want to use the Age counter and Max limit variables in the PObjects.

If you want to know more, just look at the SimpParticle class example in _SParticles.hpp and _SParticles.cpp.
keigen-shu
Posts: 8
Joined: Wed Dec 28, 2011 1:35 pm

Sprite Engine - Source

Post by keigen-shu »

:: Source :: This is pretty long...

_IEngine.h

Code: Select all

 
// Irrlicht header.
#ifndef _SC_IRRLICHT
#define _SC_IRRLICHT
 
#include "irrlicht.h"
 
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
// SpriteEngine uses these type definitions
typedef irr::core::dimension2df dim2f;
typedef irr::core::dimension2di dim2i;
typedef irr::core::dimension2du dim2u;
using   irr::core::recti;
using   irr::core::rectf;
using   irr::core::stringc;
using   irr::core::stringw;
typedef irr::core::vector2df    vec2f;
typedef irr::core::vector2di    vec2i;
typedef irr::core::position2df  pos2f;
typedef irr::core::position2di  pos2i;
 
#endif
 
_SEngine.hpp

Code: Select all

 
/** _SEngine.hxx :: 2D sprite extension for Irrlicht :: SpriteEngine definition
  * Copyright 2011 - 2012 Keigen Shu
  */
 
#ifndef _SC_ENGINE_H
#define _SC_ENGINE_H
 
#include "_IEngine.hxx"
#include "_SSprite.hxx"
#include "_SParticle.hxx"
 
using irr::video::IVideoDriver;
using irr::core::matrix4;
 
class SpriteEngine
{
private:
    IVideoDriver    * mpDriver;
    ITexture        * mp404Texture;   /* texture used if there is an error */
    list<ITexture*> * mpITextureList; /* list of ITextures loaded */
 
    /* Irrlicht Projection matrix storage. */
    matrix4 sysProjMat;
    matrix4 sysViewMat;
    matrix4 sysWorldMat;
 
public:
    /** Constructor: SpriteEngine
      * Initializes class structures. You must call SpriteEngine::Init() to make
      * it functional.
      */
    SpriteEngine (void)
      : mpDriver    (0),
        mp404Texture(0),
        mpITextureList(new list<ITexture*>)
    {   };
 
    /** Function: drop
      * Unload all resources and destroy this SpriteEngine instance.
      */
    void drop (void);
 
    /** Function: setup
      * Initializes the engine. Returns false on failure.
      */
    bool setup (irr::IrrlichtDevice* pDevice);
 
    /** Function: getVideoEngine
      * Returns pointer to the video engine used by this instance.
      */
    IVideoDriver* getVideoEngine (void);
 
    ////////////////////////////////////////////////////////////////
    // Tools
    ////////////////////////////////////////////////////////////////
 
    /** Function: loadTextureFromFile
      * Loads an ITexture from file and puts it into mpITextureList.
      */
    ITexture* loadTextureFromFile (const char* pFileName);
 
    /** Function: loadImageFromFile
      * Loads an ITexture from file and puts it into mpITextureList.
      * Returns an Image* that uses provided recti*. If the provided recti*
      * points to NULL, then the function will create one using the texture's
      * dimensional properties.
      */
    Image* loadImageFromFile (const char* pFileName, recti* srcRect = 0);
 
    /** Function: dropTexture
      * Deletes the texture, releasing memory used by texture.
      * Any sprite-sheets that uses this texture will become invalid.
      */
    void dropTexture (ITexture* pTexture);
 
    /** Function: dropAllTextures
      * Deletes all textures in the TextureList.
      */
    void dropAllTextures (void);
 
    ////////////////////////////////////////////////////////////////
    // Drawing Functions
    ////////////////////////////////////////////////////////////////
    /** Function: drawSprite
      * Draws a sprite into the screen with transformation effects.
      *
      * This function contains code under the zlib license
      * written by Lonesome Ducky and mrdoubled - Oct. 12, 2011 ver.
      * taken from http://irrlicht.sourceforge.net/forum/viewtopic.php?p=246138
      */
    void drawSprite (Sprite* pSprite);
 
    /** Function: drawSpriteList
      * Draws all sprite objects contained in the given sprite list.
      * It also can delete all the sprites in the list if required.
      */
    void drawSpriteList (list<Sprite*>* spriteList, bool deleteOnDraw = false);
 
    /** Function: drawParticleList
      * Draws all Particle Objects in the particle, and updates them by the
      * given value.
      */
    void drawParticleList (list<Particle*>* particleList, unsigned int updateTime = 30);
 
    /** Function: saveMatrix
      * Store and clear the projection, view and world matrices
      */
    void saveMatrix ();
 
    /** Function: loadMatrix
      * Restore projection, world, and view matrices
      */
    void loadMatrix ();
 
}; // end class
 
#endif
 
_SEngine.cpp

Code: Select all

 
/** _SEngine.cxx :: 2D sprite extension for Irrlicht :: SpriteEngine definition
  * Copyright 2011 - 2012 Keigen Shu
  */
 
#ifndef _SC_ENGINE_C
#define _SC_ENGINE_C
 
#include "_SEngine.hxx"
 
using namespace irr;
using namespace irr::core;
using namespace irr::video;
 
void SpriteEngine::drop (void)
{
    dropAllTextures();
    delete mpITextureList;
    delete this;
}
 
bool SpriteEngine::setup (IrrlichtDevice* pDevice)
{
    if (pDevice) {
        mpDriver = pDevice->getVideoDriver();
 
        mp404Texture = mpDriver->getTexture("./Theme/image/404.png");
        mpITextureList->push_back(mp404Texture);
 
        return true;
    } else {
        return false;
    }
}
 
IVideoDriver* SpriteEngine::getVideoEngine (void) { return mpDriver; }
 
////////////////////////////////////////////////////////////////
// Tools
////////////////////////////////////////////////////////////////
ITexture* SpriteEngine::loadTextureFromFile (const char* pFileName)
{
    ITexture* nTexture = mpDriver->getTexture(pFileName);
    if (nTexture) {
        mpITextureList->push_back(nTexture);
        return nTexture;
    } else { return mp404Texture; }
}
 
Image* SpriteEngine::loadImageFromFile (const char* pFileName, recti* srcRect)
{
    ITexture* nTexture = loadTextureFromFile(pFileName);
 
    Image* nImage = new Image (
        nTexture,
        srcRect == 0 ?
            new recti (0, 0, nTexture->getSize().Width, nTexture->getSize().Height)
          : srcRect
    );
    return nImage;
}
 
void SpriteEngine::dropTexture (ITexture* pTexture)
{
    list<ITexture*>::Iterator i = mpITextureList->begin();
 
    while (i != mpITextureList->getLast())
    {
        if (*i == pTexture) {
            mpITextureList->erase(i);
            break;
        } else { i++; }
    }
 
    pTexture->drop();
}
 
// Deletes all textures in texture list.
void SpriteEngine::dropAllTextures (void)
{
    list<ITexture*>::Iterator i = mpITextureList->begin();
 
    while(!mpITextureList->empty())
    {
        ITexture*   p_dTexture = *i;
        i = mpITextureList->erase(i);
        p_dTexture->drop();
    }
}
 
////////////////////////////////////////////////////////////////
// Drawing Functions
////////////////////////////////////////////////////////////////
// Draws a sprite into the screen with transformation effects
// written by Lonesome Ducky and mrdoubled - Oct. 12, 2011 ver.
// This function contains code under the zlib license.
// taken from http://irrlicht.sourceforge.net/forum/viewtopic.php?p=246138
void SpriteEngine::drawSprite (Sprite* pSprite)
{
    ITexture* pTexture  =   pSprite->mpSrcImage->pTexture;
    recti     srcRect   = *(pSprite->mpSrcImage->pSrcRect);
 
    pos2f  drawPos      = pSprite->mPosition;
    float  drawRotation = pSprite->mRotation;
    vec2f  drawScale    = pSprite->mScale;
    SColor drawColor    = pSprite->mColor;
 
    // Position set is center.
    if (pSprite->useCenter() == true)
    {
        drawPos.X -= srcRect.getWidth()/2;
        drawPos.Y -= srcRect.getHeight()/2;
    }
 
    pos2f rotationPoint((srcRect.getWidth()/2)+drawPos.X,
                              (srcRect.getHeight()/2)+drawPos.Y);
 
    // Find horizontal and vertical axes after rotation
    float c = cos(-drawRotation * DEGTORAD);
    float s = sin(-drawRotation * DEGTORAD);
    vec2f horizontalAxis(c,s);
    vec2f verticalAxis(s,-c);
 
    // First, we'll find the offset of the center and then where the center would be after rotation
    vec2f centerOffset(drawPos.X+srcRect.getWidth()/2.0f*drawScale.X-rotationPoint.X,drawPos.Y+srcRect.getHeight()/2.0f*drawScale.Y-rotationPoint.Y);
    vec2f center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis;
    center.X += rotationPoint.X;
    center.Y += rotationPoint.Y;
 
    // Now find the corners based off the center
    vec2f cornerOffset(srcRect.getWidth()*drawScale.X/2.0f,srcRect.getHeight()*drawScale.Y/2.0f);
    verticalAxis *= cornerOffset.Y;
    horizontalAxis *= cornerOffset.X;
    vec2f corner[4];
    corner[0] = center + verticalAxis - horizontalAxis;
    corner[1] = center + verticalAxis + horizontalAxis;
    corner[2] = center - verticalAxis - horizontalAxis;
    corner[3] = center - verticalAxis + horizontalAxis;
 
    // Find the uv coordinates of the srcRect
    vec2f textureSize(pTexture->getSize().Width, pTexture->getSize().Height);
    vec2f uvCorner[4];
    uvCorner[0] = vec2f(srcRect.UpperLeftCorner.X,srcRect.UpperLeftCorner.Y);
    uvCorner[1] = vec2f(srcRect.LowerRightCorner.X,srcRect.UpperLeftCorner.Y);
    uvCorner[2] = vec2f(srcRect.UpperLeftCorner.X,srcRect.LowerRightCorner.Y);
    uvCorner[3] = vec2f(srcRect.LowerRightCorner.X,srcRect.LowerRightCorner.Y);
    for (s32 i = 0; i < 4; i++)
        uvCorner[i] /= textureSize;
 
    // Vertices for the image
    S3DVertex vertices[4];
    u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 };
 
    // Convert pixels to world coordinates
    vec2f screenSize(mpDriver->getViewPort().getWidth(), mpDriver->getViewPort().getHeight());
    for (s32 i = 0; i < 4; i++) {
        vertices[i].Pos = vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1);
        vertices[i].TCoords = uvCorner[i];
        vertices[i].Color = drawColor;
    }
 
    // Create the material
    // IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE:
    // material.BlendOperation = EBO_ADD;
    SMaterial material;
    material.Lighting        = false;
    material.ZWriteEnable    = false;
    material.ZBuffer         = false;
    material.BackfaceCulling = false;
    material.TextureLayer[0].Texture = pTexture;
    material.MaterialTypeParam = pack_texureBlendFunc(EBF_SRC_ALPHA, EBF_ONE_MINUS_SRC_ALPHA, EMFN_MODULATE_1X, EAS_TEXTURE | EAS_VERTEX_COLOR);
    // material.BlendOperation = EBO_ADD;
    material.MaterialType = EMT_ONETEXTURE_BLEND;
 
    mpDriver->setMaterial(material);
    mpDriver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2);
}
 
void SpriteEngine::saveMatrix () {
    // Store and clear the projection, view and world matrices
    sysProjMat = mpDriver->getTransform(ETS_PROJECTION);
    mpDriver->setTransform(ETS_PROJECTION,matrix4());
 
    sysViewMat = mpDriver->getTransform(ETS_VIEW);
    mpDriver->setTransform(ETS_VIEW,matrix4());
 
    sysWorldMat = mpDriver->getTransform(ETS_WORLD);
    mpDriver->setTransform(ETS_WORLD,matrix4());
}
 
void SpriteEngine::loadMatrix () {
    // Restore projection, world, and view matrices
    mpDriver->setTransform(ETS_PROJECTION,sysProjMat);
    mpDriver->setTransform(ETS_VIEW,sysViewMat);
    mpDriver->setTransform(ETS_WORLD,sysWorldMat);
}
 
// Draw all sprites contained in the given sprite list
// Deletes all the sprites in the list by default
void SpriteEngine::drawSpriteList (list<Sprite*>* spriteList, bool deleteOnDraw)
{
    list<Sprite*>::Iterator i = spriteList->begin();
 
    if (deleteOnDraw == true) {
        while (!spriteList->empty())
        {
            Sprite* pSprite = *i;
            drawSprite(pSprite);
 
            i = spriteList->erase(i);
            pSprite->drop();
        }
    } else {
        for (u32 c = 0; c < spriteList->size(); c++)
        {
            drawSprite(*i);
            i++;
        }
    }
}
 
void SpriteEngine::drawParticleList (list<Particle*>* particleList, unsigned int updateTime)
{
    list<Particle*>::Iterator i = particleList->begin();
 
    for (u32 c = 0; c < particleList->size(); c++)
    {
        if ((*i)->getSpriteList()->size() == 0) {
            // Particle is empty, probably has expired.
            Particle* p = *i;
            i = particleList->erase(i);
            delete p;
        } else {
            this->drawSpriteList((*i)->getSpriteList());
            (*i)->update(updateTime);
            i++;
        }
    }
 
}
 
#endif
 
_SSprite.hpp

Code: Select all

 
/** _SSprite.hxx :: 2D sprite extension for Irrlicht :: Sprite definition
  * Copyright 2011 - 2012 Keigen Shu
  */
#ifndef _SC_SPRITE_H
#define _SC_SPRITE_H
 
#include "_IEngine.hxx"
 
using irr::core::list;
 
using irr::video::ITexture;
using irr::video::SColor;
 
typedef struct Image {
    ITexture* pTexture;
    recti   * pSrcRect;
    Image (ITexture* pt, recti* pr) : pTexture(pt), pSrcRect(pr) { }
} Image;
 
/** Class: Sprite
  * This is a basic class that contains a pointer to an Image and the drawing
  * parameters for an individual object. The drawing parameters are declared
  * public because they're are accessed very frequently. This class does not
  * delete the supplied Image when deconstructed unless specified on the
  * constructor. The ITexture and recti pointed by the Image is not affected.
  *
  * Call <drop> to delete class.
  *
  * Parameters:
  * mPosition - drawing position of the sprite
  * mRotation - rotates the sprite (in degrees)
  * mScale    - scales the sprite.
  * mColor    - multiply color.
  */
class Sprite
{
public:
    Image*  mpSrcImage;
    pos2f   mPosition;
    float   mRotation;
    vec2f   mScale;
    SColor  mColor;
 
/* Read-only */
private:
    bool    mUseCenter; /* coordinate is anchored on center */
    bool    mDropImage; /* delete mpSrcImage when class is dropped */
 
public:
/* Contructors */
    /** Constructor: Sprite (Image*, ...) [default]
      * Constructs a Sprite using an Image*.
      *
      * @param pImage - Pointer to the Image to draw
      * @param drawPosition - Coordinate on the screen to draw on
      * @param drawRotation - Rotates the image along it's center before drawing
      * @param drawScale  - Scales the image along it's center before drawing
      * @param drawColor  - Color mask on image.
      * @param UseCenter  - If set to true (default), the provided drawing
      *                     coordinate is anchored to the center of the image
      *                     instead of the top-left corner.
      * @param DeleteImageOnDrop  - Set to true to delete the Image* when this
      *                             object is being deleted.
      */
    Sprite( Image*  pImage                      ,
            pos2f   drawPosition  = pos2f(0,0)  ,
            float   drawRotation  = 0.0f        ,
            vec2f   drawScale     = vec2f(1,1)  ,
            SColor  drawColor     = SColor(255,255,255,255) ,
            bool    UseCenter           = false ,
            bool    DeleteImageOnDrop   = false
    ) : mpSrcImage (pImage),
        mPosition  (drawPosition),
        mRotation  (drawRotation),
        mScale     (drawScale),
        mColor     (drawColor),
        mUseCenter (UseCenter),
        mDropImage (DeleteImageOnDrop)
    {   }
 
    /** Constructor: Sprite (ITexture*, recti*, ...)
      * Constructs a Sprite using an Image object constructed from the provided
      * ITexture* and an recti*.
      */
    Sprite( ITexture*   pTexture                ,
            recti*      pSrcRect  = 0           ,
            pos2f   drawPosition  = pos2f(0,0)  ,
            float   drawRotation  = 0.0f        ,
            vec2f   drawScale     = vec2f(1,1)  ,
            SColor  drawColor     = SColor(255,255,255,255) ,
            bool    UseCenter           = false ,
            bool    DeleteImageOnDrop   = false
    ) : mpSrcImage (
            new Image (
                pTexture ,
                pSrcRect == 0 ?
                    new recti(0, 0, pTexture->getSize().Width, pTexture->getSize().Height)
                  : pSrcRect
            )), /* construct a new Image object from provided arguments */
        mPosition  (drawPosition),
        mRotation  (drawRotation),
        mScale     (drawScale),
        mColor     (drawColor),
        mUseCenter (UseCenter),
        mDropImage (DeleteImageOnDrop)
    {   }
 
    /** Constructor: Sprite (Sprite*)
      * Copies the Sprite.
      */
    Sprite (Sprite* pSprite)
      : mpSrcImage (pSprite->mpSrcImage),
        mPosition  (pSprite->mPosition),
        mRotation  (pSprite->mRotation),
        mScale     (pSprite->mScale),
        mColor     (pSprite->mColor),
        mUseCenter (pSprite->mUseCenter),
        mDropImage (false)
        // mDropImage (pSprite->mDropImage)
    {   }
 
    /** Function: drop
      * Deletes this object. Returns true if mpSrcImage is deleted.
      */
    bool drop (void);
 
/* Misc. functions */
 
    /** Function: move
      * Rotate by angle then move along new angle.
      */
    void move (float moveDistance, float rotateAngle = 0);
 
 
    /** Function: scale
      * Scale the image equally.
      */
    void setScale (float newScale);
 
 
    /** Function: useCenter
      * Set to use image center as coordinate anchor point.
      */
    bool useCenter (void);
};
 
/** Function: clearSpriteList
  * Deletes all Sprite objects contained in the given sprite list.
  * This function if provided to make the deletion process easier.
  */
void clearSpriteList (list<Sprite*>* spriteList);
 
/** Sprite vector - used by Animated Sprites, which has not been ported over yet
  * because they're not used by the game.
  *
  * #include <vector>
  * typedef std::vector<Sprite*> vecSprite;
  */
 
#endif
 
_SSprite.cpp

Code: Select all

 
/** _SSprite.cxx :: 2D sprite extension for Irrlicht :: Sprite code
  * Copyright 2011 - 2012 Keigen Shu
  */
#ifndef _SC_SPRITE_C
#define _SC_SPRITE_C
 
#include "_SSprite.hxx"
 
bool Sprite::drop (void)
{
    if (mDropImage == true) {
        delete mpSrcImage;
        delete this;
        return true;
    } else {
        delete this;
        return false;
    }
}
 
void Sprite::move (float moveDistance, float rotateAngle)
{
    mRotation += rotateAngle;
 
    mPosition.X += moveDistance * cos(mRotation);
    mPosition.Y += moveDistance * sin(mRotation);
}
 
void Sprite::setScale (float newScale) { mScale = vec2f(newScale,newScale); }
 
bool Sprite::useCenter (void) { return mUseCenter; }
 
/** End of Sprite **/
 
void clearSpriteList (list<Sprite*>* spriteList)
{
    list<Sprite*>::Iterator i = spriteList->begin();
    while (!spriteList->empty())
    {
        Sprite* pSprite = *i;
        i = spriteList->erase(i);
        delete  pSprite;
    }
}
 
#endif
 
_SParticle.hpp

Code: Select all

 
/** _SParticle.hxx :: 2D sprite extension for Irrlicht :: Particle definition
  * Copyright 2011 - 2012 Keigen Shu
  */
 
#ifndef SC_PARTICLE_H
#define SC_PARTICLE_H
 
#include "_IEngine.hxx"
#include "_SSprite.hxx"
 
/** Struct: PObject
  * This struct denotes a single particle object, which is basically a Sprite
  * with a time counter on it.
  *
  * Parameters:
  * pSprite      - pointer to the Sprite object
  * Age / MaxAge - the life counter of the particle object
  */
struct PObject {
    Sprite* pSprite;      /* the particle's sprite */
    long    Age, Max;  /* age of particle in milliseconds */
};
 
/** Class: Particle
  * This is a basic definition of a 2D particle effect handled by SpriteEngine.
  * All particle effects must be derived from this class.
  *
  * Parameters:
  * mParticle - list of PObjects
  * mOrigin   - the position of the particle effect
  */
class Particle
{
protected:
    list<PObject*>  mParticle;
    pos2f           mOrigin;
 
public:
    /** Constructor: Particle
      * Initializes and sets the position of the particle effect.
      */
    Particle (pos2f Origin) : mOrigin (Origin) { }
 
    /** Destructor: Particle
      * Destroys the object and deletes all PObjects in it's list.
      */
    ~Particle (void);
 
    /** Function: getSpriteList
      * Grabs all the sprite in the particle group and composes a Sprite list.
      */
    list<Sprite*>* getSpriteList (void);
 
    /** Function: update [virtual]
      * Virtual function that updates all the PObjects in the particle group.
      */
    virtual void update (unsigned int time) = 0;
};
 
 
/** Class: SimpParticle
  * A simple sprite spray particle effect.
  */
class SimpParticle : public Particle
{
private:
    Image* mpImage; // image to spray
 
public:
    /** Constructor: SimpParticle
      * Initializes the particle effect.
      */
    SimpParticle (Image* pImage, pos2f Origin, unsigned int ParticleCount, unsigned int RandomizerSeed);
 
    /** Function: update [virtual implementation]
      * Updates all the particles in the effect.
      */
    virtual void update (unsigned int time);
};
 
 
#endif
 
_SParticle.cpp

Code: Select all

 
/** _SParticle.cxx :: Experimental particle generator
  * Copyright 2011 - 2012 Keigen Shu
  */
 
#ifndef SC_PARTICLE_C
#define SC_PARTICLE_C
 
#include "_SParticle.hxx"
#include <stdlib.h> // Randomizer
 
Particle::~Particle (void)
{
    list<PObject*>::Iterator i = mParticle.begin();
 
    while (!mParticle.empty())
    {
        PObject* p = *i;
        i = mParticle.erase(i);
 
        p->pSprite->drop();
        delete p;
    }
}
 
list<Sprite*>* Particle::getSpriteList (void)
{
    list<Sprite*>* sl = new list<Sprite*>;
    list<PObject*>::Iterator p = mParticle.begin(); unsigned int c = 0;
 
    while (c < mParticle.size())
    {
        sl->push_back( (*p)->pSprite );
        p++;
        c++;
    }
 
    return sl;
}
 
 
 
// simple image spray tool
SimpParticle::SimpParticle (
    Image* pImage,
    pos2f  Origin,
    unsigned int ParticleCount,
    unsigned int RandomizerSeed
) : Particle (Origin),
    mpImage  (pImage)
{
    unsigned int Seed = RandomizerSeed;
    srand ( Seed );
 
    // Generate particles
    for (unsigned int i = 0; i < ParticleCount; i++)
    {
        srand ( Seed++ + rand() + i );
        float r1 = (float)((rand() - rand()) % 256);
        srand ( Seed++ + i*2 );
        float r2 = (float)((rand() - rand()) % 256);
        srand ( Seed++ * i%3 * (rand()%27) );
        
        Sprite *Spr = new Sprite (
            mpImage, mOrigin,
            rand() % 180 + i * i * 25,
            vec2f(r1/160 + 0.2, r1/160 + 0.2),
            SColor(255,r1,r2,(r1+r2)/2),
            true
        );
 
        // Maximum of ~500 ms life
        PObject* po = new PObject;
        po->pSprite = Spr;
        po->Age = 0;
        po->Max = rand() % 400 + 50 * i;
 
        mParticle.push_back(po);
    }
}
 
void SimpParticle::update (unsigned int time)
{
    list<PObject*>::Iterator i = mParticle.begin(); unsigned int c = 0;
 
    while (c < mParticle.size())
    {
        PObject* p = *i;
 
        if (p->Age < p->Max)
        {
            // Update PObject
            p->Age += time;
            Sprite* s = p->pSprite;
            s->move (1.0f - ((float)p->Age / (float)p->Max) + (rand() % 100) / 100.0f);
            s->mScale -= 0.01f;
            s->mColor.setAlpha(((float)s->mColor.getAlpha())*(1.5f-((float)p->Age/(float)p->Max)));
 
            i++;
        } else {
            // Too old. Delete sprite.
            i = mParticle.erase(i);
            p->pSprite->drop();
            delete p;
        }
 
        c++;
    }
}
 
#endif
 
lisacvuk
Posts: 21
Joined: Thu Apr 17, 2014 4:50 pm

Re: Sprite Engine - 2D image drawing manager

Post by lisacvuk »

Looks intersting! Just a question, isn't it a bit outdated? I think, will it work with latest Irrlicht? I'm sorry if I shouldn't answer to an old post.
Post Reply