Sign in to follow this  

DirectX Newbie problems

This topic is 4747 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, I have been away from programming for quite a while now and I am glad to be back :) I have also decided to start learning DirectX. I am trying to create a 2d game, eventually anyway, but I have thrown together a bit of code and it runs fine, but after a little while it starts to get sluggish. I will post the relevent bits and hopefully someone can show me where i went wrong!
// Graphics.h
#include <d3d8.h>
#include <d3dx8.h>


// Graphics Class
class cGraphics
{
      public:
             cGraphics();
             ~cGraphics();
             
             bool Init(HWND hWnd, bool Windowed);
             
             LPDIRECT3DTEXTURE8 LoadTexture(char *filename);
             void Blit(LPDIRECT3DTEXTURE8 Texture, float SrcX, float SrcY,
                       float DestX, float DestY);
             //HRESULT BlitSprite(RECT *pDestRect, LPDIRECT3DTEXTURE8 pSrcTexture, 
             //                   RECT *pSrcRect, DWORD dwFlags);
             //HRESULT BlitSpriteEx( RECT *pDestRect, LPDIRECT3DTEXTURE8 pSrcTexture, 
             //                     RECT *pSrcRect, DWORD dwFlags, D3DCOLOR modulate = 0xFFFFFFFF, 
             //                     float rotation = 0, POINT *prcenter = NULL );
             
             LPDIRECT3D8       GetpD3D(void)   { return m_pD3D;         }
             LPDIRECT3DDEVICE8 GetDevice(void) { return m_pd3dDevice;   }
             LPD3DXSPRITE      GetSprite(void) { return m_Sprite;  }
             D3DCAPS8          GetCaps(void)   { return *m_pd3dcaps;    }
             
      private:
              LPDIRECT3D8       m_pD3D;         // Used to create the D3DDevice
              LPDIRECT3DDEVICE8 m_pd3dDevice;   // Our rendering device
              LPD3DXSPRITE      m_Sprite;       // Interface to Sprite routines
              D3DCAPS8          *m_pd3dcaps;    // Caps for the rendering device

};

class cSprite
{
      public:
             cSprite(LPDIRECT3DDEVICE8 Device);
             ~cSprite();
             
             void Load(char *filename);
             void Draw(float DestX, float DestY,
                       float SrcX = 0, float SrcY = 0);
      private:
              LPD3DXSPRITE       m_Sprite; 
              LPDIRECT3DTEXTURE8 m_Texture;
              LPDIRECT3DDEVICE8  m_pd3dDevice;
              
              int XPos;
              int YPos;

};




// Graphics.cpp
#include "Graphics.h"

cGraphics::cGraphics()
{
   m_pD3D = NULL; 
   m_pd3dDevice = NULL; 
   m_Sprite = NULL;
   m_pd3dcaps = new D3DCAPS8;
}

cGraphics::~cGraphics()
{
   if(m_Sprite)
      m_Sprite->Release();
   if(m_pd3dDevice)
      m_pd3dDevice->Release();
   if(m_pD3D)
      m_pD3D->Release();
                       
   if (m_pd3dcaps) 
      delete m_pd3dcaps;
}

bool cGraphics::Init(HWND hWnd, bool Windowed)
{
   // Initiation of DX3D
   
   // Variables
   D3DDISPLAYMODE d3ddm;
   D3DPRESENT_PARAMETERS d3dpp; 
   
   // Create the D3D object, which is needed to create the D3DDevice.
   if((m_pD3D = Direct3DCreate8(D3D_SDK_VERSION)) == NULL)
        return false;

   // Get the current desktop display mode
   if(FAILED(m_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
             &d3ddm)))
        return false;

   // Parameters for the D3DDevice. Most parameters are zero'd out.
   // This sets the video format to match the current desktop display.
   // Check docs for other options you can set here, such as
   // 'Windowed' which would create a window-based app (not full screen)
     
   ZeroMemory(&d3dpp, sizeof(d3dpp));
   
   d3dpp.Windowed = Windowed;
   //d3dpp.hDeviceWindow = m_hWnd;
   d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
   d3dpp.BackBufferCount = 2;
   d3dpp.BackBufferWidth = d3ddm.Width;
   d3dpp.BackBufferHeight = d3ddm.Height;
   d3dpp.BackBufferFormat = d3ddm.Format;
   d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
   d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;

   //d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
   //d3dpp.BackBufferWidth = d3ddm.Width;
   //d3dpp.BackBufferHeight = d3ddm.Height;
   //d3dpp.BackBufferFormat = d3ddm.Format;
     
   // Make the app a windowed app according to the bool passed to the function
   //d3dpp.Windowed = Windowed;

   // Create the Direct3D device, using the default adapter (most systems 
   // only have one, unless they have multiple graphics hardware cards
   // installed). See SDK for more details on other options here.
   if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,      
                                  hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                  &d3dpp, &m_pd3dDevice)))
        return false;

   // Device state would normally be set here

   // Set up sprite
   if(FAILED(D3DXCreateSprite(m_pd3dDevice, &m_Sprite)))
      return false;

   return true;

}



void cGraphics::Blit(LPDIRECT3DTEXTURE8 Texture, float SrcX, float SrcY,
                       float DestX, float DestY)
{
   RECT Src;
   D3DXVECTOR2 trans(0,0);
   
   Src.left = (long)SrcY;
   Src.top = (long)SrcX;
   
   trans.x = (long)DestX;
   trans.y = (long)DestY;
   
 //  m_Sprite->Draw(Texture, &Src, &D3DXVECTOR2(1.0,1.0), NULL, 0.0f,
  //                trans, 0xFFFFFFFF);
} 

//----------------------------------------------------------------------------
// LoadTexture() : Load a texture from a file, returns ptr to texture.
//                   D3DX8 supports BMP, PPM, DDS, JPG, PNG, TGA & DIB. 
//----------------------------------------------------------------------------
LPDIRECT3DTEXTURE8 cGraphics::LoadTexture(char *filename)
{
     LPDIRECT3DTEXTURE8 pd3dTexture;
     // Set black as our source color key. Use 0xFFFF00FF for magenta instead.
     // Use 0x00000000 for no 'color key' substitution
     D3DCOLOR colorkey = 0xFF000000;
     // The D3DX function will fill in the following image info for us 
     D3DXIMAGE_INFO SrcInfo; // Optional 
  
     // Load image from file - maintain size of original file.
     // It is also possible to specify a new height/width and ask D3DX to      filter
     // the image to the new size (stretch/shrink). See SDK docs for details.
     D3DXCreateTextureFromFileEx(m_pd3dDevice, filename, 0, 0, 1, 0, 
          D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, 
          colorkey, &SrcInfo , NULL, &pd3dTexture);
     // Check the return value here, etc

     // Remember, textures sizes may be larger or smaller than your image, 
     // to allow for legal texture sizes & maximums on user's hardware
     return pd3dTexture;
}





cSprite::cSprite(LPDIRECT3DDEVICE8 Device)
{
   m_Sprite = NULL;
   m_Texture = NULL;
   
   m_pd3dDevice = Device;
}

cSprite::~cSprite()
{
   if(m_Sprite)
      m_Sprite->Release();
}

void cSprite::Draw(float DestX, float DestY,
                   float SrcX, float SrcY)
{
   RECT Src;
   D3DXVECTOR2 trans(0,0);
   D3DXVECTOR2 scaling(1.0,1.0);
   
   Src.left = (long)SrcX;
   Src.top = (long)SrcY;
   
   trans.x = (long)DestX;
   trans.y = (long)DestY;
    
   D3DXCreateSprite(m_pd3dDevice, &m_Sprite);
   
   if(SrcX || SrcY == 0)
       m_Sprite->Draw(m_Texture, NULL, &scaling, NULL, 0.0f,
                     &trans, 0xFFFFFFFF);
   else
       m_Sprite->Draw(m_Texture, &Src, &scaling, NULL, 0.0f,
                     &trans, 0xFFFFFFFF);
} 

void cSprite::Load(char *filename)
{
     // Set black as our source color key. Use 0xFFFF00FF for magenta instead.
     // Use 0x00000000 for no 'color key' substitution
     D3DCOLOR colorkey = 0xFF000000;
     // The D3DX function will fill in the following image info for us 
     D3DXIMAGE_INFO SrcInfo; // Optional 
   
     // Load image from file - maintain size of original file.
     // It is also possible to specify a new height/width and ask D3DX to      filter
     // the image to the new size (stretch/shrink). See SDK docs for details.
     D3DXCreateTextureFromFileEx(m_pd3dDevice, filename, 0, 0, 1, 0, 
          D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, 
          colorkey, &SrcInfo , NULL, &m_Texture);
     // Check the return value here, etc

     // Remember, textures sizes may be larger or smaller than your image, 
     // to allow for legal texture sizes & maximums on user's hardware
}



// main.cpp
// My includes
#include "WinApp.h"
#include "Graphics.h"

// The graphics class
cGraphics Graphics;

int PicX = 180;
int PicY = 120; 

void DrawScene()
{
     // Drawing code goes here...
   
     cSprite test(Graphics.GetDevice());
     
     test.Load("test.jpg");
     test.Draw(PicX, PicY);
     
     return;
}

void Render()
{
     if(Graphics.GetDevice() == NULL)
          return;

     // Clear the backbuffer to a black color
     Graphics.GetDevice()->Clear(0, NULL, D3DCLEAR_TARGET, 
                                 D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

     // Begin the scene
     Graphics.GetDevice()->BeginScene();

     // Rendering of scene objects
     DrawScene();

     // End the scene
     Graphics.GetDevice()->EndScene();

     // Present the backbuffer contents to the display
     Graphics.GetDevice()->Present( NULL, NULL, NULL, NULL );
}

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
     switch( msg )
     {
        case WM_CHAR:
          switch(wParam)
          {
             case 'a':
                  PicY--;
                  Render();
                  break;
             case VK_ESCAPE:
                  PostQuitMessage( 0 );
                  break;
          };
          return 0;

        case WM_DESTROY: // If you use Windowed mode process loss of it
          PostQuitMessage( 0 );
          return 0;

        case WM_PAINT:
          // NOTE: In a full-screen app, you may choose to draw the screen at
          // a different point, such as using a timer message or outside of
          // the windows message loop
        Render();
        ValidateRect( hWnd, NULL );
        return 0;
     }

     return DefWindowProc( hWnd, msg, wParam, lParam );
}


//----------------------------------------------------------------------------
// WinMain() : The application's entry point
//----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{    
     MSG msg;
     
     // Sets up the window and registers the class
     cApp App(CAPTION, CLASS);
     App.Run();
 
     
 
     // Initialize Direct3D
     if(Graphics.Init(App.GethWnd(), false) == true)
     { 
          // Show the window
          //ShowWindow( App.GethWnd(), SW_SHOWDEFAULT );
          //UpdateWindow( App.GethWnd() ); // Forces a WM_PAINT

          // Enter the message loop
          
          
          while(msg.message != WM_QUIT)
          {
             // Peek into queue and see if there is a message waiting
             if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
             {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
             } else {
                    //Render();
             }
          }
     } 

     // Clean up everything and exit the app
     Cleanup();
     UnregisterClass(CLASS, hInst);
     return 0;
}


Thanks

Share this post


Link to post
Share on other sites
I have not played with the DirectX Sprite class but I would say your problem is here:

void cSprite::Draw(float DestX, float DestY,
float SrcX, float SrcY)
{
...

ISSUE ==> D3DXCreateSprite(m_pd3dDevice, &m_Sprite);

...
}

You are always creating a new COM object everytime this method is called but you do not release it. This is a resource leak and in time will bring the system to a halt. Suggestion, create the sprite COM object once, either in constructor or through a method, and release it in the destructor.

Out of curiosity, why are you using two back buffers?

d3dpp.BackBufferCount = 2;

Chris

Share this post


Link to post
Share on other sites
Ahh, thanks for that. Forgot I did that when I was ripping my hair out to actually get it t display something. I have moved it int othe constructer and there was already a release in the destructor.

Unfortunately there is still the sluggishness after i move the picture a few times using the 'a' key.

As to the 2 back buffers, that was because i copied that little piece of code. You will see the origional commented out below it.

Thanks,
Al

Share this post


Link to post
Share on other sites
You're still creating a sprite each frame. Within that frame, you are loading the same texture each time. That texture represents another resource leak. You should create the sprite (along with the texture) once during init. Then, each frame, you only need to draw the sprite.

Share this post


Link to post
Share on other sites

This topic is 4747 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this