Jump to content
  • Advertisement
Sign in to follow this  
templewulf

Noobie needs help with directX tuning

This topic is 4842 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

I've been going through some of the beginner's tutorials in the GD articles; in particular the Genesis tutorials. I'm trying to learn directX, (I'm just starting out with directdraw right now). I made a little screen saver-like program in which a bitmap scales in size as well as bounces around the screen. The problem is that whenever it reaches the edge of the screen and reverses direction, it stops moving for about a second and a half. I'm programming in C++ with MSVS 7 (.NET), I've tried building it in both Debug and Release modes. My system is kinda like as follows: Athlon XP 3200+ Soyo Dragon 2 MoBo 3x256MB DDR RAM 7200 RPM WD 80GB HDD The code is stored here: home.earthlink.net/~foreverbonded/Genesis.zip If anyone could look at the code and give me some insight as to my performance problem, it would be a big help! Thanks

Share this post


Link to post
Share on other sites
Advertisement
1. ) You can just use the window you passed for setting the clipping data instead of creating clipping regions.

Example:

// use
lpddc->SetHWnd( 0, hwnd ) ;
// instead of

LPRGNDATA lpClipList = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + sizeof(RECT));

// this is the RECT we want to clip to: the whole display area
RECT rcClipRect = {XMIN, YMIN, XMAX, YMAX};

// now fill out all the structure fields
memcpy(lpClipList->Buffer, &rcClipRect, sizeof(RECT)); // copy the actual clip region
lpClipList->rdh.dwSize = sizeof(RGNDATAHEADER); // size of header structure
lpClipList->rdh.iType = RDH_RECTANGLES; // type of clip region
lpClipList->rdh.nCount = 1; // number of clip regions
lpClipList->rdh.nRgnSize = sizeof(RECT); // size of lpClipList->Buffer
lpClipList->rdh.rcBound = rcClipRect; // the bounding RECT



2. ) Use Flip instead of blitting. When using complex surfaces that have attached surfaces using Flip will in fact flip the surfaces. You are using Blt-bad!

3. ) You stupid message box at the end does not show through the window because you have DirectDraw running.

4. ) Rewrite that mess in GenesisMove! I'm not to sure on how it's working but I bet the problem is with that and the timing

[Edited by - sakky on June 16, 2005 11:38:57 PM]

Share this post


Link to post
Share on other sites
Here, I did this for you :D


// ---------------------------------------------------------------------------- //
// File : Test.cpp
// Desc : Test to show GD member 'templewulf' how it's done in DD
//
// Auth : Sakky
// ---------------------------------------------------------------------------- //

#ifndef WIN32_WINNT
#define WIN32_WINNT 0x0501
#endif // WIN32_WINNT

#ifndef WINVER
#define WINVER 0x0501
#endif // WINVER

#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN

#define STRICT

// ---------------------------------------------------------------------------- //
// Dependencies
// ---------------------------------------------------------------------------- //
#pragma comment ( lib, "DXGUID.LIB" )
#pragma comment ( lib, "DDRAW.LIB" )
#pragma comment ( lib, "WINMM.LIB" )

#include <WINDOWS.H>
#include <WINDOWSX.H>
#include <MMSYSTEM.H>
#include <DDRAW.H>
#include <STRING.H>
#include <STDLIB.H>
#include <STDARG.H>
#include <STDIO.H>
#include <CTYPE.H>
#include <VECTOR>
#include <LIST>

// ---------------------------------------------------------------------------- //
// Macros
// ---------------------------------------------------------------------------- //
#define SAFE_RELEASE( P ) if ( NULL != P ) { P->Release( ) ; P = NULL ; }

#define SAFE_DELETE_ARRAY( P ) if ( NULL != P ) { delete [ ] P ; P = NULL ; }
#define SAFE_DELETE( P ) if ( NULL != P ) { delete P ; P = NULL ; }

#define MUTEX_NAME "TEST"

#define CLASS_NAME "TEST"
#define TITLE_NAME "Test"

// ---------------------------------------------------------------------------- //
// Prototypes
// ---------------------------------------------------------------------------- //
HRESULT __stdcall DDInitialize( void ) ;
HRESULT __stdcall DDLoadBitmap( LPSTR, LPDIRECTDRAWSURFACE7* ) ;
HRESULT __stdcall DDSetupEnvironment( void ) ;
HRESULT __stdcall DDTextOut( int, int, DWORD, LPCSTR, ... ) ;
HRESULT __stdcall DDRenderScene( void ) ;
HRESULT __stdcall DDRestore( void ) ;
HRESULT __stdcall DDRelease( void ) ;

FLOAT __stdcall UTQueryTime( void ) ;

LRESULT __stdcall WindowProc( HWND, UINT, WPARAM, LPARAM ) ;

// ---------------------------------------------------------------------------- //
// Globals
// ---------------------------------------------------------------------------- //
LPDIRECTDRAW7 g_lpDD = NULL ;
LPDIRECTDRAWSURFACE7 g_lpDDSPrimary = NULL ;
LPDIRECTDRAWSURFACE7 g_lpDDSBack = NULL ;

FLOAT g_fFps = 0.0F ;
FLOAT g_fLastTime = 0.0F ;
DWORD g_dwFrames = 0L ;

HINSTANCE g_hInstance = NULL ;
HWND g_hWnd = NULL ;

BOOL g_bIsAppActive = FALSE ;

// ---------------------------------------------------------------------------- //
// Name : DDInitialize( )
// Desc : Initializes DirectDraw system & environment
// ---------------------------------------------------------------------------- //
HRESULT __stdcall DDInitialize( void )
{
DDSURFACEDESC2 DDsd ;
LPDIRECTDRAWCLIPPER lpDDClipper = NULL ;
HRESULT hRet ;

// Initialize DirectDraw7 parent
//
if ( FAILED( hRet = DirectDrawCreateEx( NULL, ( void** )&g_lpDD, IID_IDirectDraw7, NULL ) ) )
{
return ( hRet ) ;
}

// Configure hebavior and display for for fullscreen application
//
if ( FAILED( hRet = g_lpDD->SetCooperativeLevel( g_hWnd, DDSCL_ALLOWREBOOT | DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE ) ) )
{
return ( hRet ) ;
}

if ( FAILED( hRet = g_lpDD->SetDisplayMode( 800, 600, 16, 0, 0 ) ) )
{
return ( hRet ) ;
}

// Create primary display surfaces
//
memset( &DDsd, 0, sizeof( DDSURFACEDESC2 ) ) ;
DDsd.dwSize = sizeof( DDSURFACEDESC2 ) ;
DDsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT ;
DDsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP ;
DDsd.dwBackBufferCount = 1 ;

if ( FAILED( hRet = g_lpDD->CreateSurface( &DDsd, &g_lpDDSPrimary, NULL ) ) )
{
return ( hRet ) ;
}

DDsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER ;

if ( FAILED( hRet = g_lpDDSPrimary->GetAttachedSurface( &DDsd.ddsCaps, &g_lpDDSBack ) ) )
{
return ( hRet ) ;
}

// Attach a clipper to the display
//
if ( FAILED( hRet = g_lpDD->CreateClipper( 0L, &lpDDClipper, NULL ) ) )
{
return ( hRet ) ;
}

if ( FAILED( hRet = lpDDClipper->SetHWnd( 0L, g_hWnd ) ) )
{
SAFE_RELEASE( lpDDClipper ) ;

return ( hRet ) ;
}

if ( FAILED( hRet = g_lpDDSPrimary->SetClipper( lpDDClipper ) ) )
{
SAFE_RELEASE( lpDDClipper ) ;

return ( hRet ) ;
}

// Set up environment
//
if ( FAILED( hRet = DDSetupEnvironment( ) ) )
{
return ( hRet ) ;
}

return ( S_OK ) ;
}

// ---------------------------------------------------------------------------- //
// Name : DDLoadBitmap( )
// Desc : Loads a bitmap from file or resoruce
// ---------------------------------------------------------------------------- //
HRESULT __stdcall DDLoadBitmap( LPSTR lpszFileName, LPDIRECTDRAWSURFACE7* ppDDSBitmap )
{
DDSURFACEDESC2 DDsd ;
HBITMAP hBitmap, hOldBitmap ;
BITMAP Bitmap ;
HDC hDC, hBitmapDC ;
HRESULT hRet ;

// Load the bitmap from file first, the try resource if unsuccessfull
//
if ( NULL == ( hBitmap = ( HBITMAP )LoadImage( NULL, lpszFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION |
LR_LOADFROMFILE ) ) )
{
if ( NULL == ( hBitmap = ( HBITMAP )LoadImage( g_hInstance,
lpszFileName,
IMAGE_BITMAP,
0, 0,
LR_CREATEDIBSECTION ) ) )
{
return ( E_FAIL ) ;
}
}

// Acuire generic information about the image,
// Use this information to create a surface
//
GetObject( hBitmap, sizeof( BITMAP ), &Bitmap ) ;

memset( &DDsd, 0, sizeof( DDSURFACEDESC2 ) ) ;
DDsd.dwSize = sizeof( DDSURFACEDESC2 ) ;
DDsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS ;
DDsd.dwWidth = Bitmap.bmWidth ;
DDsd.dwHeight = Bitmap.bmHeight ;
DDsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN ;

if ( FAILED( hRet = g_lpDD->CreateSurface( &DDsd, ppDDSBitmap, NULL ) ) )
{
return ( hRet ) ;
}

// Acquire a GDI interface
//
if ( FAILED( hRet = ( *ppDDSBitmap )->GetDC( &hDC ) ) )
{
SAFE_RELEASE( ( *ppDDSBitmap ) ) ;

return ( hRet ) ;
}

// Copy the imagery into the surface
//
hBitmapDC = CreateCompatibleDC( hDC ) ;
hOldBitmap = ( HBITMAP )SelectObject( hBitmapDC, hBitmap ) ;

BitBlt( hDC, 0, 0, Bitmap.bmWidth, Bitmap.bmHeight, hBitmapDC, 0, 0, SRCCOPY ) ;

// Release uses resources
//
( *ppDDSBitmap )->ReleaseDC( hDC ) ;

SelectObject( hBitmapDC, hOldBitmap ) ;
DeleteObject( hBitmap ) ;

DeleteDC( hBitmapDC ) ;

return ( S_OK ) ;
}

// ---------------------------------------------------------------------------- //
// Name : DDSetupEnvironment( )
// Desc : Initializes DirectDraw rendering environment
// ---------------------------------------------------------------------------- //
HRESULT __stdcall DDSetupEnvironment( void )
{
HRESULT hRet ;

// TODO : Setup environment (palettes, artwork, color keys, etc..)

return ( S_OK ) ;
}

// ---------------------------------------------------------------------------- //
// Name : DDTextOut( )
// Desc : Renders text to the back buffer
// ---------------------------------------------------------------------------- //
HRESULT __stdcall DDTextOut( int nX, int nY, DWORD dwColor, LPCSTR lpszText, ... )
{
va_list Ap ;
CHAR szBuffer[ MAX_PATH ] ;
RECT rcTextOut ;
HDC hDC ;
HRESULT hRet ;

// Convert symbols
//
va_start( Ap, lpszText ) ;
vsprintf( szBuffer, lpszText, Ap ) ;
va_end( Ap ) ;

SetRect( &rcTextOut, nX, nY, 0, 0 ) ;

// Acquire GDI itnterface
//
if ( FAILED( g_lpDDSBack->GetDC( &hDC ) ) )
{
return ( hRet ) ;
}

// Set up text display paremeters
//
SetBkMode( hDC, TRANSPARENT ) ;
SetTextColor( hDC, dwColor ) ;

// Render text
//
DrawText( hDC, szBuffer, ( int )strlen( szBuffer ), &rcTextOut, DT_CALCRECT | DT_LEFT ) ;
DrawText( hDC, szBuffer, ( int )strlen( szBuffer ), &rcTextOut, DT_LEFT ) ;

g_lpDDSBack->ReleaseDC( hDC ) ;

return ( S_OK ) ;
}

// ---------------------------------------------------------------------------- //
// Name : DDRenderScene( )
// Desc : Renders the scene in DirectDraw
// ---------------------------------------------------------------------------- //
HRESULT __stdcall DDRenderScene( void )
{
FLOAT fTime = 0.0F ;
DDBLTFX DDfx ;
HRESULT hRet ;

// Clear the back buffer
//
memset( &DDfx, 0, sizeof( DDBLTFX ) ) ;
DDfx.dwSize = sizeof( DDBLTFX ) ;
DDfx.dwFillColor = 0L ;

g_lpDDSBack->Blt( NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &DDfx ) ;

// TODO : Draw something

// Happy message!
//
DDTextOut( 4, 4, RGB( 220, 220, 220 ), "%.2f Fps", g_fFps ) ;
DDTextOut( 4, 24, RGB( 220, 220, 0 ), "Hello, templewulf!", g_fFps ) ;

// Present to user
//
if ( FAILED( g_lpDDSPrimary->Flip( 0L, DDFLIP_WAIT ) ) )
{
if ( FAILED( hRet = DDRestore( ) ) )
{
return ( hRet ) ;
}
else
{
// Reset stats on restore
//
g_fFps = 0.0F ;
g_fLastTime = 0.0F ;
g_dwFrames = 0L ;
}
}
else
{
// Update stats every second
//
fTime = UTQueryTime( ) ;
g_dwFrames++ ;

if ( ( fTime - g_fLastTime ) > 1.0F )
{
g_fFps = ( g_dwFrames / ( fTime - g_fLastTime ) ) ;
g_fLastTime = fTime ;
g_dwFrames = 0L ;
}
}

return ( S_OK ) ;
}

// ---------------------------------------------------------------------------- //
// Name : DDRestore( )
// Desc : Restores lost DirectDraw interfaces
// ---------------------------------------------------------------------------- //
HRESULT __stdcall DDRestore( void )
{
if ( NULL != g_lpDDSPrimary )
{
g_lpDDSPrimary->Restore( ) ;
}

// TODO : Restore lost interfaces (artwork, etc..)

return ( S_OK ) ;
}

// ---------------------------------------------------------------------------- //
// Name : DDRelease( )
// Desc : Releases DirectDraw system
// ---------------------------------------------------------------------------- //
HRESULT __stdcall DDRelease( void )
{
// TODO : Release other interfaces

SAFE_RELEASE( g_lpDDSPrimary ) ;
SAFE_RELEASE( g_lpDD ) ;

return ( S_OK ) ;
}

// ---------------------------------------------------------------------------- //
// Name : UTQueryTime( )
// Desc : Returns the current time
// ---------------------------------------------------------------------------- //
FLOAT __stdcall UTQueryTime( void )
{
LARGE_INTEGER qwTicksPerSec ;
LARGE_INTEGER qwTime ;
double fTime = 0.0 ;
BOOL bUsingQPF = FALSE ;

// User the high resolution time (if present)
//
bUsingQPF = QueryPerformanceCounter( &qwTime ) ;
if ( bUsingQPF )
{
QueryPerformanceFrequency( &qwTicksPerSec ) ;

fTime = ( ( double )qwTime.QuadPart / ( double )qwTicksPerSec.QuadPart ) ;
}
else
{
fTime = ( timeGetTime( ) * 0.001 ) ;
}

return ( ( FLOAT )fTime ) ;
}

// ---------------------------------------------------------------------------- //
// Name : WindowProc( )
// Desc : Processes window messages
// ---------------------------------------------------------------------------- //
LRESULT __stdcall WindowProc( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam )
{
switch ( uMessage )
{
// Track application's active status
//
case WM_ACTIVATEAPP :
g_bIsAppActive = ( ( BOOL )( wParam ) ? TRUE : FALSE ) ;
return ( 0L ) ;

// Force application to terminate
//
case WM_KEYDOWN :
switch ( LOWORD( wParam ) )
{
case VK_ESCAPE :
PostQuitMessage( 0 ) ;
break ;
}
return ( 0L ) ;

// Terminate application
//
case WM_DESTROY :
PostQuitMessage( 0 ) ;
return ( 0L ) ;
}

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

// ---------------------------------------------------------------------------- //
// Name : WinMain( )
// Desc : Application entry point
// ---------------------------------------------------------------------------- //
INT_PTR __stdcall WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
HANDLE hMutex ;
WNDCLASSEX WcEx ;
HWND hWnd ;
RECT rcClient ;
MSG Msg ;
BOOL bGotMsg ;

// Initialize mutex, only allow signle application instance!!
//
hMutex = CreateMutex( ( LPSECURITY_ATTRIBUTES )NULL, FALSE, MUTEX_NAME ) ;

if ( ERROR_ALREADY_EXISTS == GetLastError( ) )
{
return ( 0 ) ;
}

// Register application module
//
memset( &WcEx, 0, sizeof( WNDCLASSEX ) ) ;
WcEx.cbSize = sizeof( WNDCLASSEX ) ;
WcEx.style = CS_DBLCLKS ;
WcEx.lpfnWndProc = WindowProc ;
WcEx.hInstance = hInstance ;
WcEx.hIcon = LoadIcon( NULL, IDI_WINLOGO ) ;
WcEx.hCursor = LoadCursor( NULL, IDC_ARROW ) ;
WcEx.hbrBackground = ( HBRUSH )GetStockObject( LTGRAY_BRUSH ) ;
WcEx.lpszClassName = CLASS_NAME ;
WcEx.hIconSm = LoadIcon( NULL, IDI_WINLOGO ) ;

if ( FALSE == RegisterClassEx( &WcEx ) )
{
ReleaseMutex( hMutex ) ;
CloseHandle( hMutex ) ;

return ( 0 ) ;
}

// Compute center screen position, adjust accordingly
//
SetRect( &rcClient, ( ( GetSystemMetrics( SM_CXSCREEN ) / 2 ) - 400 ),
( ( GetSystemMetrics( SM_CYSCREEN ) / 2 ) - 300 ),
( ( GetSystemMetrics( SM_CXSCREEN ) / 2 ) + 400 ),
( ( GetSystemMetrics( SM_CYSCREEN ) / 2 ) + 300 ) ) ;

AdjustWindowRectEx( &rcClient, WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, FALSE, WS_EX_CLIENTEDGE ) ;

// Attach window to process
//
hWnd = CreateWindowEx( WS_EX_CLIENTEDGE,
CLASS_NAME,
TITLE_NAME,
WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
rcClient.left,
rcClient.top,
( rcClient.right - rcClient.left ),
( rcClient.bottom - rcClient.top ),
NULL,
NULL,
hInstance,
NULL ) ;

if ( NULL == hWnd )
{
UnregisterClass( CLASS_NAME, hInstance ) ;

ReleaseMutex( hMutex ) ;
CloseHandle( hMutex ) ;

return ( 0 ) ;
}
else
{
ShowWindow( hWnd, nCmdShow ) ;
UpdateWindow( hWnd ) ;

SetForegroundWindow( hWnd ) ;

g_hInstance = hInstance ;
g_hWnd = hWnd ;
}

// Initialize DirectDraw
//
if ( FAILED( DDInitialize( ) ) )
{
DDRelease( ) ;

DestroyWindow( hWnd ) ;
UnregisterClass( CLASS_NAME, hInstance ) ;

ReleaseMutex( hMutex ) ;
CloseHandle( hMutex ) ;

return ( 0 ) ;
}

// Query any pending messages
//
memset( &Msg, 0, sizeof( MSG ) ) ;
Msg.message = WM_NULL ;
Msg.wParam = 0L ;
Msg.lParam = 0L ;

PeekMessage( &Msg, NULL, 0U, 0U, PM_NOREMOVE ) ;

// Adjust percision
//
timeBeginPeriod( 1 ) ;
ShowCursor( FALSE ) ;

// Run process ...
//
while ( WM_QUIT != Msg.message )
{
// Peek for messages is applicaiton is active, or wait for them other wise
//
if ( g_bIsAppActive )
{
bGotMsg = ( PeekMessage( &Msg, NULL, 0U, 0U, PM_REMOVE ) != 0 ) ;
}
else
{
bGotMsg = ( GetMessage( &Msg, NULL, 0U, 0U ) != 0 ) ;
}

// Process pending messages
//
if ( bGotMsg )
{
TranslateMessage( &Msg ) ;
DispatchMessage( &Msg ) ;
}
else
{
// TODO : Process runtime logic

if ( FAILED( DDRenderScene( ) ) )
{
PostQuitMessage( 0 ) ;
}
}
}

// Reset precision
//
ShowCursor( TRUE ) ;
timeEndPeriod( 1 ) ;

// Release used resources
//
DDRelease( ) ;

UnregisterClass( CLASS_NAME, hInstance ) ;

ReleaseMutex( hMutex ) ;
CloseHandle( hMutex ) ;

return ( static_cast< int >( Msg.wParam ) ) ;
}



I use a lot of things that I'm using in my Direct3D application (timer and mutex mostly). I your case, you can just add a call to DDLoadBitmap in DDSetupEnvironment( ). Release it and/or reload it in DDRestore( ). All you have to do then is place you're drawing code in DDRenderSene there the comment is. Or if you'd like, remove the little message I left for you. If you want to update any logic for animation or what not, you may do so in the main loop by directly coding it in there or by calling a function that updates it. If I were you I would use a function instead of placing it right into the main loop.

You can use the timer to check how much time has passed and adjust you animation accordingly. Hope you like it!

Share this post


Link to post
Share on other sites
Thanks for the reply, Sakky; your advice with SetHwnd was very helpful in cleaning up my code, but it didn't fix the problem.

It turns out, my clipper was set to the primary surface instead of the Back Buffer! So, it just wasn't clipping anything, and that's why it wouldn't draw to the screen when the box bounced off the edges.

I appreciate the help, though.

TempleWulf

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!