2
What is the process?
• You need to ensure that Ddraw.lib and Ddraw.h are included in your project
1. Create and DirectDraw object and obtain access to it (IDirectDraw is main COM object interface
2. Set video mode and cooperation level and create one or more DirectDraw surfaces (IDirectDrawSurface)
3
What is the process?
3. You may need to create a color pallete (IDirectDrawPalette)
4. Create a clipper (IDirectDrawClipper)
5
Game Programs
• The way LaMothe does things in WinMain once the window is opened and registered
// initialize game hereGame_Init(); // enter main event loopwhile(TRUE){ // the usual message stuff goes here // main game processing goes here Game_Main(); } // end while// closedown game hereGame_Shutdown();
6
Game_Init()int Game_Init(void *parms = NULL, int num_parms = 0)
{
// create IDirectDraw interface 7.0 object and test for error
if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd,
ID_IDirectDraw7, NULL)))
return(0);
// set cooperation to normal since this will be a windowed app
lpdd->SetCooperativeLevel(main_window_handle, DDSCL_NORMAL);
// return success or failure
return(1);
} // end Game_Init
7
Game_Main( )
int Game_Main(void *parms = NULL, int num_parms = 0)
{
// main loop of the game, do all your processing here
// if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
SendMessage(main_window_handle,WM_CLOSE,0,0);
// return success or failure
return(1);
} // end Game_Main
8
Game_ShutDown( )
int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
// simply blow away the IDirectDraw7 interface
if (lpdd)
{
lpdd->Release();
lpdd = NULL;
} // end if
// return success
return(1);
} // end Game_Shutdown
9
Cooperation Level
• This allows you to specify the type of application– Windowed or full-screen– ModeX video modes (320x200, 320x240)– Allow ctl-atl-del to get out of game
10
Cooperation Level
• In a windowed application you might use
lpdd->SetCooperativeLevel(main_window_handle,
DDSCL_NORMAL);
• In a full-screen application you might use
lpdd->SetCooperativeLevel(main_window_handle,
DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN |
DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT);
11
Selecting Video Mode
• One of the most important features of DirectX• The function to use if SetDisplayMode( )• This will be done in GameInit( ) after setting
the cooperation level
// set display mode to 640x480x8if (FAILED(lpdd->SetDisplayMode(640,480,8,0,0))){ // error return(0);} // end if
12
Full Screen Popup
• Sometimes it is good to create a popup window that appears to be full screen
• To get this to work on any computer yo need to use GetSystemMetrics( ) to get the current screen size and use the returned values when the popup window is created
13
Surfaces
• In DirectDraw displayable memory is referred to as a surface
• The primary surface represents the visible video screen and is mapped to the video memory on the video card (VRAM)
14
Surfaces
• A surface can be any size, but the primary surface must match the current screen resolution
• Surfaces can be created in video memory of system memory
• All surfaces have the same properties with respect to bit depth and color space
15
Game Surfaces
• Games typically have– Primary display surface (visible video
screen)– Secondary display surface for animation
(aka “backbuffer”)– Off screen surfaces (for bit maps, sprites,
screen items, etc)
16
Creating Surfaces
// You create a primary surface after setting display mode// clear ddsd and set sizememset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd);// enable valid fieldsddsd.dwFlags = DDSD_CAPS;// request primary surface when createddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
// create the primary surfaceif (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))){ return(0); // error} // end if
17
Building Pallete Arrayfor (int color=1; color < 255; color++){ // fill with random RGB values palette[color].peRed = rand()%256; palette[color].peGreen = rand()%256; palette[color].peBlue = rand()%256; palette[color].peFlags = PC_NOCOLLAPSE;} // end for color// now fill in entry 0 and 255 with black and whitepalette[0].peRed = 0;palette[0].peGreen = 0;palette[0].peBlue = 0;palette[0].peFlags = PC_NOCOLLAPSE;palette[255].peRed = 255;palette[255].peGreen = 255;palette[255].peBlue = 255;palette[255].peFlags = PC_NOCOLLAPSE;
18
Using Pallete
// create the palette object after surface created
if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT |
DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE,
palette,&lpddpal, NULL)))
{
return(0); // error
} // end if
// attach the palette to the primary surface
if (FAILED(lpddsprimary->SetPalette(lpddpal)))
{
return(0); // error
} // end if
19
Game_Shutdown( )// cleanup in reverse of object creation order// first the paletteif (lpddpal){ lpddpal->Release(); lpddpal = NULL;} // end if // now the primary surfaceif (lpddsprimary){ lpddsprimary->Release(); lpddsprimary = NULL;} // end if // now blow away the IDirectDraw7 interfaceif (lpdd){ lpdd->Release(); lpdd = NULL;} // end if
20
Linear vs Non-Linear Memory
• In an ideal world your video card has a horizontal pixel memory pitch that matches the way pixels are stored in system memory
• If that were true and you have 640 pixels with 8 bit color there would be 640 bytes of memory per video line
• With non-linear memory they won’t always match (so you will to think about pixel placement in light of this and changing video resolutions)
21
Plotting 8 Bit Pixels
• If you are using 640x480x8 mode and you have 640 bytes per line
• To access any screen pixel using (x,y) you could do it as follows
UCHAR *video_buffer = (UCHAR *)ddsd.lpSurface;
video_buffer[x+y*640] = color;
22
Plotting Pixels
• If you are using 640x480x16 mode and you have 640 words per line
• To access any screen pixel using (x,y) you could do it as follows
USHORT *video_buffer = (USHORT *)ddsd.lpSurface;
video_buffer[x+y*640] = color;
23
Drawing in DirectX
• Drawing (rendering) in DirectX is different than drawing use GDI
• GDI has lots of very slow drawing functions• DirectX has a small number of very fast
drawing functions (programmers use their own libraries and engines)
• In DirectX it is very important to lock a surface before you draw and unlock it when you are done
24
Initial Surface Parameters
// Set the global drawing surface description
LPDIRECTDRAW7 lpdd = NULL; // dd object
LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; // dd primary surface
LPDIRECTDRAWSURFACE7 lpddsback = NULL; // dd back surface
LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to dd palette
LPDIRECTDRAWCLIPPER lpddclipper = NULL; // dd clipper
PALETTEENTRY palette[256]; // color palette
PALETTEENTRY save_palette[256]; // used to save palettes
DDSURFACEDESC2 ddsd; // surface description
DDBLTFX ddbltfx; // used to fill
DDSCAPS2 ddscaps; // surface capabilities
HRESULT ddrval; // result from dd calls
25
Plotting Pixels// clear ddsd and set size, never assume it's cleanmemset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd);// lock surface if (FAILED(lpddsprimary->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL))){ return(0); // error} // end if
// now ddsd.lPitch is valid and so is ddsd.lpSurfaceint mempitch = (int)ddsd.lPitch;UCHAR *video_buffer = (UCHAR *)ddsd.lpSurface;video_buffer[x+y*mempitch] = color;
// now unlock the primary surfaceif (FAILED(lpddsprimary->Unlock(NULL))) return(0)