1 directdraw basics cis 487/587 bruce r. maxim um-dearborn

25
1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn

Upload: austen-dorsey

Post on 22-Dec-2015

219 views

Category:

Documents


1 download

TRANSCRIPT

1

DirectDraw Basics

CIS 487/587

Bruce R. Maxim

UM-Dearborn

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)

4

LaMothe Examples

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)