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

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

Dec 22, 2015

Download

Documents

Austen Dorsey
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

1

DirectDraw Basics

CIS 487/587

Bruce R. Maxim

UM-Dearborn

Page 2: 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)

Page 3: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

3

What is the process?

3. You may need to create a color pallete (IDirectDrawPalette)

4. Create a clipper (IDirectDrawClipper)

Page 4: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

4

LaMothe Examples

Page 5: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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();

Page 6: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 7: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 8: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 9: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 10: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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);

Page 11: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 12: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 13: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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)

Page 14: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 15: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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)

Page 16: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 17: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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;

Page 18: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 19: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 20: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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)

Page 21: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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;

Page 22: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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;

Page 23: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

Page 24: 1 DirectDraw Basics CIS 487/587 Bruce R. Maxim UM-Dearborn.

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

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

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)