Thread: Id3dxsprite Basic

  1. #1
    Handy Andy andyhunter's Avatar
    Join Date
    Dec 2004
    Posts
    540

    Id3dxsprite Basic

    I was wondering if anyone out there knows of any basic tutorials with regards to using the ID3DXSPRITE interface of DirectX 9. I have the SDK and know the function definitions and stuff but the tutorials are a bit over my head at the moment. I really only do graphics stuff as kind of a hobby (who doesn't like to make their own version of Asteroids?). I am just looking for a simple presentation showing maybe a 2D sprite moving across the screen or something like that. I am comfortable with COM and using the windows API and I am currently using VS.NET 2002 with DirectX 9 SDK installed. Thanks in advance for any information / links.

    PS: I did search through google but a lot of that stuff was oriented towards 3D design and things along those lines. I just wanted to move my recreated games into DirectX for something new to do, vice the windows GDI. Thanx again.

    [edit]

    Well I found an old thread post from Mr Wizard that gave a bare bones example of rotating a sprite. Very useful indeed, especially when I combined it with the posts about alpha blending. Thanx guys for having these questions before me!

    [edit]
    Last edited by andyhunter; 12-20-2004 at 08:14 PM.

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Here is my entire sprite setup. Perhaps you can glean something from it. Keep in mind that it is a work in progress.


    Code:
    #ifndef CSTATICSPRITECONTAINER
    #define CSTATICSPRITECONTAINER
    
    
    #include <d3d9.h>
    #include <vector>
    #include "VertexTypes.h"
    #include "CQuickCom.h"
    
    
    class CStaticSprite
    {
    
      friend class CStaticSpriteContainer;
    
      
      D3DXVECTOR3       Pos;
      float             ZRotation;
      D3DXVECTOR3       Vel;
    
      float             Speed;
      float             ZRotSpeed;
      
      //This is the transformed version of the vertexes
      //These are world-coordinate vertexes
      
    
      float             Scale;
    
      RECT              Bounds;
      D3DCOLOR          Color;
    
      public:
        CStaticSprite(void):Pos(D3DXVECTOR3(0.0f,0.0f,0.0f)),
                            ZRotation(0.0f),
                            ZRotSpeed(0.0f),
                            Vel(D3DXVECTOR3(0.0f,0.0f,0.0f)),
                            Speed(0.0f) {}
        virtual ~CStaticSprite(void) {}
    
        void Create(D3DXVECTOR3 _pos,
                    float _zrotation,
                    float _zrotspeed,
                    D3DXVECTOR3 _vel,
                    float _speed,
                    float _scale)
        {
          Pos=_pos;
          ZRotation=_zrotation;
          Vel=_vel;
          Speed=_speed;
          Scale=_scale;
          ZRotSpeed=_zrotspeed;
        }
        void SetColor(D3DCOLOR _newcolor) {Color=_newcolor;};
        void SetBounds(RECT _newbounds) {Bounds=_newbounds;};
    
    };
    
    class CStaticSpriteContainer
    {
      friend class CStaticSprite;
      ID3DXSprite               *Sprite;
      
    
      std::vector<CStaticSprite> StaticSprites;
      
      IDirect3DTexture9         *Texture;
      IDirect3DDevice9          *Device;
    
      float                     MaxX,MaxY;
    
      float                     Width;
      float                     Height;
      float                     Width2;
      float                     Height2;
    
      bool                      KillAtBorder;
    
      D3DCOLOR                  Color;
    
    
      //This is the original copy of the vertexes for this list
      //All vertexes are centered around 0,0,0.
      TexTLVertex               OrigVerts[4];
      
      public:
          CStaticSpriteContainer(void) {}
          ~CStaticSpriteContainer(void) 
          {
            StaticSprites.clear();
            SAFE_RELEASE(Sprite);
    
          }
    
          void SetColor(D3DCOLOR _newcolor)
          {
            Color=_newcolor;
          }
    
          void Create(IDirect3DDevice9 *_device,std::string _file,float _maxx,float _maxy)
          {
          
            Device=_device;
    
            if (FAILED(D3DXCreateSprite(Device,&Sprite)))
            {
              ::MessageBox(0,0,"Failed to create Sprite interface",0);
              return;
            }
    
    
            MaxX=_maxx;
            MaxY=_maxy;
    
            D3DXCreateTextureFromFile(Device,_file.c_str(),&Texture);
    
            D3DSURFACE_DESC desc;
            Texture->GetLevelDesc(0,&desc);
            Width=(float)desc.Width;
            Height=(float)desc.Height;
            Width2=Width*.5f;
            Height2=Height*.5f;
            
          }
           
          void SetKillAtBorder(bool _cond=true)
          {
            KillAtBorder=_cond;
          }
    
    
          unsigned int Add(D3DXVECTOR3 _pos,
                           float _zrotation,
                           float _zrotspeed,
                           D3DXVECTOR3 _vel,
                           float _speed,
                           float _scale,
                           D3DCOLOR _color)
          {
            CStaticSprite newSprite;
            newSprite.Create(_pos,_zrotation,_zrotspeed,_vel,_speed,_scale);
            newSprite.SetColor(_color);
            
            //RECT bbox=offset_bounds;
                        
            StaticSprites.push_back(newSprite);
            return (StaticSprites.size()-1);
          }
    
          void UpdateAll(void)
          {
            Sprite->Begin(D3DXSPRITE_ALPHABLEND);
            
            std::vector<CStaticSprite>::iterator CurSprite=StaticSprites.begin();
    
            D3DXMATRIX ptrans;
            D3DXMATRIX otrans;
            D3DXMATRIX scale;
            D3DXMATRIX rot;
            D3DXMATRIX world;
            D3DXMatrixIdentity(&world);
    
    
            bool Increment=true;
    
            while (CurSprite!=StaticSprites.end())
            {
              Increment=true;
              
              //Update Sprite position
              CurSprite->Pos+=(CurSprite->Vel*CurSprite->Speed);
              CurSprite->ZRotation+=CurSprite->ZRotSpeed;
      
              //Scroll sprites - leave left enter right, etc.
              if (KillAtBorder==false)
              {
      
                if (CurSprite->Pos.x<0) CurSprite->Pos.x+=MaxX;
                if (CurSprite->Pos.y<0) CurSprite->Pos.y+=MaxY;
                if (CurSprite->Pos.x>MaxX) CurSprite->Pos.x-=MaxX;
                if (CurSprite->Pos.y>MaxY) CurSprite->Pos.y-=-MaxY;
              }
                else
              {
                
                if (CurSprite->Pos.x<0 || 
                    CurSprite->Pos.y<0 ||
                    CurSprite->Pos.x>MaxX ||
                    CurSprite->Pos.y>MaxY)
                {
                  CurSprite=StaticSprites.erase(CurSprite);
                  //Dont increment on kill
                  Increment=false;
    
                }
              }
    
              //Rotate it - only need z rotation
              D3DXMatrixRotationYawPitchRoll(&rot,
                                             0.0f,
                                             0.0f,
                                             CurSprite->ZRotation);
    
              //Scale it - no z scale
              D3DXMatrixScaling(&scale,
                                CurSprite->Scale,
                                CurSprite->Scale,
                                1.0f);
    
              //Translate it - zero out z translation
              D3DXMatrixTranslation(&ptrans,
                                    CurSprite->Pos.x,
                                    CurSprite->Pos.y,
                                    0.0f);
              //Concatenate
              world=rot*scale*ptrans;
              
              Sprite->SetTransform(&world);
                
              Sprite->Draw(Texture,
                           NULL,
                           NULL,
                           &D3DXVECTOR3(-Width2,-Height2,0.0f),
                           CurSprite->Color);
              
                if (Increment) CurSprite++;
              }  
            
              Sprite->End();
          }
    
          void DrawAll(void)
          {
            
            
          }
    };
    
    class CMasterStaticSpriteManager
    {
      static std::vector<CStaticSpriteContainer> StaticContainers;
      
      public:
        CMasterStaticSpriteManager() {}
        ~CMasterStaticSpriteManager() 
        {
          std::vector<CStaticSpriteContainer>::iterator CList;
          while (CList!=StaticContainers.end())
          {
            StaticContainers.erase(CList);
          }
        }
    
        unsigned int AddContainer(CStaticSpriteContainer *_NewContainer)
        {
          StaticContainers.push_back(*_NewContainer);
        }
    
        CStaticSpriteContainer GetContainer(unsigned int _ID)
        {
          return (StaticContainers[_ID]);
        }
    
    
    };
    #endif

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Some comments in that code really need to be cleaned up since they are from an earlier version and no longer apply.

    Sorry for the mess but it should show you how to use ID3DXSprite.

  4. #4
    Handy Andy andyhunter's Avatar
    Join Date
    Dec 2004
    Posts
    540
    Thankyou Bubba, it is very informative indeed.

  5. #5
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    As you're only going to use the sprites for 2D programming, you don't have to use matrices.

    Here's a very good and informative artice:
    http://www.gamasutra.com/features/20010629/geczy_01.htm

    It requires a (free) registration though.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Finally, for those wishing to go one step further, and maybe even dip your toes into 3D waters, the ID3DXSprite interfaces offer an alternate version of the Draw() function, called DrawTransform(). Instead of taking scaling, rotation, and translation (positioning) information, the DrawTransform() function takes a transformation matrix, which defines the geometrical transformations for every pixel using a 4x4 matrix. Using this you gain access to effects involving the Z-axis, meaning distances closer to or farther from the viewer. A popular effect is perspective, which would give your image the impression of receding into the distance. The use of transformation matrices is far beyond the scope of this article, but for those interested you can start with "About 3-D Transformations" in the DirectX 8 SDK and go from there. Be prepared to dig out your old math textbooks.

    Rest assured I'm using this. There is nothing wrong with using matrices with ID3DXSprite. My sprite interface can be used with either 3D or 2D which is probably why it looks so much different than the pure 2D version.

    DrawTransform() has been replaced by doing this:

    ID3DXSprite::SetTransform(D3DXMATRIX matrix)
    ID3DXSprite::Draw()
    The ID3DXSprite interface provides a set of methods that simplify the process of drawing sprites using Microsoft Direct3D.

    ID3DXSprite Members





    BeginPrepares a device for drawing sprites.DrawAdds a sprite to the list of batched sprites.EndCalls ID3DXSprite::Flush and restores the device state to how it was before ID3DXSprite::Begin was called.FlushForces all batched sprites to be submitted to the device. Device states remain as they were after the last call to ID3DXSprite::Begin. The list of batched sprites is then cleared.GetDeviceRetrieves the device associated with the sprite object.GetTransformGets the sprite transform.OnLostDeviceReleases all references to video memory resources and deletes all stateblocks.OnResetDeviceShould be called after the device has been reset.SetTransformSets the sprite transform.SetWorldViewLHSets the left-handed world-view transform for a sprite. A call to this method is required before billboarding or sorting sprites.SetWorldViewRHSets the right-handed world-view transform for a sprite. A call to this method is required before billboarding or sorting sprites.
    Remarks









    The ID3DXSprite interface is obtained by calling the D3DXCreateSprite function.





    The application typically first calls ID3DXSprite::Begin, which allows control over the device render state, alpha blending, and sprite transformation and sorting. Then for each sprite to be displayed, call ID3DXSprite::Draw. ID3DXSprite::Draw can be called repeatedly to store any number of sprites. To display the batched sprites to the device, call ID3DXSprite::End or ID3DXSprite::Flush.



    The LPD3DXSPRITE type is defined as a pointer to the ID3DXSprite interface. typedef interface ID3DXSprite ID3DXSprite;typedef interface ID3DXSprite *LPD3DXSPRITE;




    Interface Information









    Stock Implementationd3d9.dllCustom ImplementationNoInherits fromIUnknownHeaderd3dx9core.hImport libraryd3dx9.libMinimum operating systemsWindows 98
    © 2004 Microsoft Corporation. All rights reserved.




    Feedback? Please provide us with your comments on this topic.
    For more help, visit the DirectX Developer
    There is no longer a DrawTransform function within ID3DXSprite interface as of DirectX 9.0c Summer 2004 and beyond releases.

    BTW none of the links work since they point to my drive/folder structure and not internet links.

    Also ID3DXSprite::Draw() in DirectX9.0 is significantly different than in DX8.

    Syntax

    HRESULT Draw(

    LPDIRECT3DTEXTURE9 pTexture, CONST RECT *pSrcRect, CONST D3DXVECTOR3 *pCenter, CONST D3DXVECTOR3 *pPosition, D3DCOLOR Color);
    Parameters

    pTexture [in] Pointer to an IDirect3DTexture9 interface that represents the sprite texture. pSrcRect [in] Pointer to a RECT [img]mk:@MSITStore:D:DX90SUM2004SDKDocumentationDirectX 9directx9_c.chm::/directx/art/leave-site.gif[/img] structure that indicates the portion of the source texture to use for the sprite. If this parameter is NULL, then the entire source image is used for the sprite. pCenter [in] Pointer to a D3DXVECTOR3 vector that identifies the center of the sprite. If this argument is NULL, the point (0,0,0) is used, which is the upper-left corner. pPosition [in] Pointer to a D3DXVECTOR3 vector that identifies the position of the sprite. If this argument is NULL, the point (0,0,0) is used, which is the upper-left corner. Color [in] D3DCOLOR type. The color and alpha channels are modulated by this value. A value of 0xFFFFFFFF maintains the original source color and alpha data. Use the D3DCOLOR_RGBA macro to help generate this color.

    Last edited by VirtualAce; 12-21-2004 at 02:00 PM.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    So if you are using DirectX 9.0 then yes you must used transformations to rotate, scale, and translate the sprite.

    And finally to quote from the article and to further enforce what I've been saying all along on these boards about ID3DXSprite:

    Possible next steps beyond what are demonstrated in this article involve taking a more serious step into the Direct3D 8 API, using vertex buffers and the DrawPrimitive() call to draw polygons on the screen. While at first this seems very intimidating to 2D programmers, it is actually not overly complex to rewrite the D3DXSprite interface routines from scratch and thereby get full control (and some improved performance).
    Even the writer admits that you can gain more speed by creating your own sprite routines which is what I've done for my space sim game. For asteroids I just used ID3DXSprite because it was simple and easy and I wanted to gain some experience with it. However my sprite's inside of my space sim engine are much faster.

    I would not refer to that article any longer since it is completely out of date unless you are using DirectX 8 which I cannot fathom why you would be.
    Last edited by VirtualAce; 12-21-2004 at 02:16 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. [ANN] New script engine (Basic sintax)
    By MKTMK in forum C++ Programming
    Replies: 1
    Last Post: 11-01-2005, 10:28 AM
  2. what are your thoughts on visual basic?
    By orion- in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 09-22-2005, 04:28 AM
  3. visual basic vs C or C++
    By FOOTOO in forum Windows Programming
    Replies: 5
    Last Post: 02-06-2005, 08:41 PM
  4. Basic Calc
    By Universe in forum C++ Programming
    Replies: 12
    Last Post: 07-17-2002, 10:07 PM