Help on DirectX graphics

Hi! I'm planning to write a shoot'em up sidescroller. I have a big problem with the graphics though. I really wan't the game to run smooth, but i can't even get the simpliest sprite to move without lagging. It moves smooth if i make it to move automaticly across the screen. But as soon as i add DirectInput and let the sprite be moved by the arrow keys it starts to lag. If one for example press the right arrow, the sprite would move smooth for less then a second and the start lagging. If one press and hold right and then at the same time press and hold for example space (which is unassigned), the sprite will stop completely. If anyone have a solution to this it would be greatly appreciated.

Comments

  • I suppose we would need some code to investigate this problem...
  • : I suppose we would need some code to investigate this problem...
    :

    Allright here goes some of the most vital parts of the code. If someone is intrested I could send the entire code on email.

    //----------------------------------------------------------------------------
    // InitD3D() : Initializes Direct3D
    //----------------------------------------------------------------------------
    HRESULT InitD3D( HWND hWnd )
    {
    // Create the D3D object, which is needed to create the D3DDevice.
    if( ( dx8.pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) == NULL )
    return E_FAIL;

    // Get the current desktop display mode
    D3DDISPLAYMODE d3ddm;
    if( FAILED( dx8.pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT,
    &d3ddm )))
    return E_FAIL;

    // 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)
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferWidth = 800;
    d3dpp.BackBufferHeight = 600;
    d3dpp.BackBufferFormat = d3ddm.Format;
    d3dpp.FullScreen_RefreshRateInHz = 60;
    d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;

    // 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( dx8.pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
    hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp, &dx8.pd3dDevice ) ) )
    return E_FAIL;

    // Device state would normally be set here

    return S_OK;
    }

    //----------------------------------------------------------------------------
    // InitDirectInput() : Initialize DirectInput
    //----------------------------------------------------------------------------
    BOOL WINAPI DI_Init()
    {
    HRESULT hr;

    // Create the DirectInput object.
    hr = DirectInput8Create(g_hinst, DIRECTINPUT_VERSION,
    IID_IDirectInput8, (void**)&g_lpDI, NULL);

    if FAILED(hr) return FALSE;

    // Retrieve a pointer to an IDirectInputDevice8 interface
    hr = g_lpDI->CreateDevice(GUID_SysKeyboard, &g_lpDIDevice, NULL);

    if FAILED(hr)
    {
    DI_Term();
    return FALSE;
    }

    // Now that you have an IDirectInputDevice8 interface, get
    // it ready to use.

    // Set the data format using the predefined keyboard data
    // format provided by the DirectInput object for keyboards.

    hr = g_lpDIDevice->SetDataFormat(&c_dfDIKeyboard);

    if FAILED(hr)
    {
    DI_Term();
    return FALSE;
    }

    // Set the cooperative level
    hr = g_lpDIDevice->SetCooperativeLevel(g_hwndMain,
    DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
    if FAILED(hr)
    {
    DI_Term();
    return FALSE;
    }

    // Get access to the input device.
    hr = g_lpDIDevice->Acquire();
    if FAILED(hr)
    {
    DI_Term();
    return FALSE;
    }

    return TRUE;
    }

    //----------------------------------------------------------------------------
    // CSprite::LoadTexture() : Load a texture from a file, returns ptr to texture.
    // D3DX8 supports BMP, PPM, DDS, JPG, PNG, TGA & DIB.
    //----------------------------------------------------------------------------
    LPDIRECT3DTEXTURE8 CSprite::LoadTexture(char *filename)
    {
    LPDIRECT3DTEXTURE8 pd3dTexture;
    // Set magenta as our source color key
    D3DCOLOR colorkey = 0xFFFF00FF;
    // 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( dx8.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::BltSprite() : A replacement of the DirectDraw Blt() function for Direct3D8
    // Supports DDBLTFX_MIRRORLEFTRIGHT and DDBLTFX_MIRRORUPDOWN
    // If pDestRect is NULL, copies it to the same co-ord as src
    // If pSrcRect is NULL, copies the entire texture
    //----------------------------------------------------------------------------
    HRESULT CSprite::BltSprite( RECT *pDestRect, LPDIRECT3DTEXTURE8 pSrcTexture,
    RECT *pSrcRect, DWORD dwFlags )
    {
    D3DXVECTOR2 scaling(1,1), rcenter(0,0), trans(0,0);

    // Set the parameters - translation (screen location)
    if (pDestRect) {
    trans.x = (float) pDestRect->left;
    trans.y = (float) pDestRect->top;
    }
    // Scaling - If Source & Destination are different size rects, then scale
    if (pDestRect && pSrcRect) {
    scaling.x = ((float) (pDestRect->right - pDestRect->left)) /
    ((float) (pSrcRect->right - pSrcRect->left));
    scaling.y = ((float) (pDestRect->bottom - pDestRect->top)) /
    ((float) (pSrcRect->bottom - pSrcRect->top));
    }

    // Handle the flags - need to change scaling & adjust translation
    if (pSrcRect && dwFlags) {
    if (dwFlags&DDBLTFX_MIRRORLEFTRIGHT) {
    scaling.x = -scaling.x;
    trans.x += (float) (pDestRect->right - pDestRect->left);
    }
    if (dwFlags&DDBLTFX_MIRRORUPDOWN) {
    scaling.y = -scaling.y;
    trans.y += (float) (pDestRect->bottom - pDestRect->top);
    }
    }

    // And here we go:
    return dx8.pd3dxSprite->Draw( pSrcTexture, pSrcRect, &scaling,
    &rcenter, 0, &trans, 0xFFFFFFFF );
    }


    //----------------------------------------------------------------------------
    // CSprite::UpdateRect() :
    //----------------------------------------------------------------------------
    void CSprite::UpdateRect()
    {
    x += dX;
    y += dY;

    m_rectSrc.left = nWidth * nFrame;
    m_rectSrc.right = nWidth * nFrame + nWidth;
    m_rectSrc.top = nHeight * nFrame;
    m_rectSrc.bottom = nHeight * nFrame + nHeight;

    m_rectDest.left = x;
    m_rectDest.right = x + nWidth;
    m_rectDest.top = y;
    m_rectDest.bottom = y + nHeight;
    }

    //----------------------------------------------------------------------------
    // CBrian::Animate() : Read user input and update game state
    //----------------------------------------------------------------------------
    void CBrian::Animate()
    {
    HRESULT hr;
    char buffer[256];
    hr = g_lpDIDevice->GetDeviceState(sizeof(buffer),(LPVOID)&buffer);
    if FAILED(hr)
    {
    // If it failed, the device has probably been lost.
    // Check for (hr == DIERR_INPUTLOST)
    // and attempt to reacquire it here.
    return;
    }

    dX = 0;

    // Move right or left
    if (KEYDOWN(buffer, DIK_RIGHT))
    dX = 8;
    else if(KEYDOWN(buffer, DIK_LEFT))
    dX = -8;

    UpdateRect();
    }


    //----------------------------------------------------------------------------
    // Animate() : Animate the sprites
    //----------------------------------------------------------------------------
    void Animate()
    {
    // Animate Brian
    Brian.Animate();
    }


    //----------------------------------------------------------------------------
    // DrawScene() : Draws the contents of the scene
    //----------------------------------------------------------------------------
    void DrawScene()
    {
    // Begin drawing
    dx8.pd3dxSprite->Begin();

    // Blit Brian
    Brian.Blit();

    // Finnish drawing
    dx8.pd3dxSprite->End();

    return;
    }


    //----------------------------------------------------------------------------
    // Render() : Prepares for drawing the scene
    //----------------------------------------------------------------------------
    void Render()
    {
    if( dx8.pd3dDevice == NULL)
    return;

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

    // Begin the scene
    if( SUCCEEDED( dx8.pd3dDevice->BeginScene() ) )
    {
    // Rendering of scene objects
    DrawScene();

    // End the scene
    dx8.pd3dDevice->EndScene();
    }

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

    //----------------------------------------------------------------------------
    // WinMain() : The application's entry point
    //----------------------------------------------------------------------------
    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
    {
    g_hinst = hInst;

    // Register the window class
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
    GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
    "D3D Skeleton", NULL };
    RegisterClassEx( &wc );

    // Create the application's window
    g_hwndMain = CreateWindow( "D3D Skeleton", "D3D Skeleton: CreateDevice",
    WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
    GetDesktopWindow(), NULL, (HINSTANCE) wc.hInstance, NULL );

    // Initialize DirectInput
    DI_Init();

    // Initialize Direct3D
    if( SUCCEEDED( InitD3D( g_hwndMain ) ) )
    {
    // Create the sprite object
    D3DXCreateSprite(dx8.pd3dDevice, &dx8.pd3dxSprite);

    // Initiate Brian
    Brian.Init();

    // Hide the cursor
    ShowCursor( FALSE );

    // Show the window
    ShowWindow( g_hwndMain, SW_SHOWDEFAULT );
    UpdateWindow( g_hwndMain ); // Forces a WM_PAINT

    // Enter the message loop
    MSG msg;
    ZeroMemory( &msg, sizeof(msg) );

    while( msg.message!=WM_QUIT )
    {
    if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
    {
    TranslateMessage( &msg );
    DispatchMessage( &msg );
    }
    else
    Animate();
    Render();
    }
    }

    // Clean up everything and exit the app
    Cleanup();
    UnregisterClass( "D3D Skeleton", (HINSTANCE) wc.hInstance );
    return 0;
    }
  • I must say I don't really have a clue, but I could give a suggestion. It might lie in the fact that you use a fullscreen application with shared direct-input support. Altough this should not be any problem (I use it all the time), there might be another application (your IDE?) eating up input messages. But then again: I don't know, this is just a guess. Maybe someone else will know...
  • : I must say I don't really have a clue, but I could give a suggestion. It might lie in the fact that you use a fullscreen application with shared direct-input support. Altough this should not be any problem (I use it all the time), there might be another application (your IDE?) eating up input messages. But then again: I don't know, this is just a guess. Maybe someone else will know...
    :

    Ok, thanks for the tip. I'll try to experiment a bit with that.
    In case someone has more suggestions I have uploaded the source and executable here:

    http://w1.522.telia.com/~u52215851/sprite.zip
  • After several hours of searching i finally spotted the error. It turned out that the solution was to delay the cpu just a little bit just before calling Animate()!! Look at these two code snippets. An explanation would certanly be intresting to read ;)

    Before:

    [code=ff0000]while( msg.message!=WM_QUIT )
    {
    if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
    {
    TranslateMessage( &msg );
    DispatchMessage( &msg );
    }
    else
    Animate();
    Render();[/code]

    After:

    [code=ff0000]while( msg.message!=WM_QUIT )
    {
    if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
    {
    TranslateMessage( &msg );
    DispatchMessage( &msg );
    }
    else
    int stupidVariable; // This was all I added!
    Animate();
    Render();[/code]
  • ummm.. you forgot your brackets {} around the else block. Also, declaring an int doesn't delay the CPU. You're not doing anything with that variable, so it's ignored completely.


    : After several hours of searching i finally spotted the error. It turned out that the solution was to delay the cpu just a little bit just before calling Animate()!! Look at these two code snippets. An explanation would certanly be intresting to read ;)
    :
    : Before:
    :
    : [code=ff0000]while( msg.message!=WM_QUIT )
    : {
    : if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
    : {
    : TranslateMessage( &msg );
    : DispatchMessage( &msg );
    : }
    : else
    : Animate();
    : Render();[/code]
    :
    : After:
    :
    : [code=ff0000]while( msg.message!=WM_QUIT )
    : {
    : if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
    : {
    : TranslateMessage( &msg );
    : DispatchMessage( &msg );
    : }
    : else
    : int stupidVariable; // This was all I added!
    : Animate();
    : Render();[/code]
    :

  • You got me! Didn't notice that lack of brackets. That explains everything. Thank you very much ;)

    : ummm.. you forgot your brackets {} around the else block. Also, declaring an int doesn't delay the CPU. You're not doing anything with that variable, so it's ignored completely.
    :
    :
    : : After several hours of searching i finally spotted the error. It turned out that the solution was to delay the cpu just a little bit just before calling Animate()!! Look at these two code snippets. An explanation would certanly be intresting to read ;)
    : :
    : : Before:
    : :
    : : [code=ff0000]while( msg.message!=WM_QUIT )
    : : {
    : : if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
    : : {
    : : TranslateMessage( &msg );
    : : DispatchMessage( &msg );
    : : }
    : : else
    : : Animate();
    : : Render();[/code]
    : :
    : : After:
    : :
    : : [code=ff0000]while( msg.message!=WM_QUIT )
    : : {
    : : if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
    : : {
    : : TranslateMessage( &msg );
    : : DispatchMessage( &msg );
    : : }
    : : else
    : : int stupidVariable; // This was all I added!
    : : Animate();
    : : Render();[/code]
    : :
    :
    :

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories