Write an animated program with DirectDraw

zhaozj2021-02-08  216

I. Theoretical article said that DirectDraw may not know why, but one mention DirectX I am afraid that every Computer Fan and Game Fan are familiar. (What! You have never heard of DirectX!? Oh, my God! Where to come, pull down the 50 big board!) DirectX is also called Game SDK, and its biggest feature is to direct the hardware abstraction layer (HAL) Operation, using this feature, you can make high performance Windows games. For details, please see http: // www. Microsoft.com/directx/default.asp. DirectDraw is one of the 6 components of DirectX5. The other 5 components of DirectX5 are: Direct3D: A 3D hardware interface is provided. DirectSound: Stereo and 3D sound effects, and manage the memory of the sound card. Directplay: Supports developing multi-person online games and can handle communication between networks in the game. DirectInput: Provides input support for a large number of devices. DirectSetup: Automatically install the DirectX driver. DirectDraw is DirectX's cornerstone, and other components of DirectX are based on it. DirectDraw uses page switching methods to implement animation, but not only access to system memory, but also access to display memory, which is due to the past Windows programmers. In addition, we can use DirectDraw to generate, move, cut, transform, synthesize image data, thereby writing a variety of "dazzling colorful" graphics applications. Introduced such a large pile of DirectX, your head is not a little big? The heart must be 咕: "Oh, it turned out to be a rivers and lake liar, and the light did not practice." Dear officials don't worry, don't understand these basic theories, you can see the procedures below. You must be "the ghosts watch - stunned" . First, let's first understand the three important concepts of DirectDraw. 1. Surface When writing a program with DirectDraw, we must first create several graphics data buffers and put these graphics data into it, and then perform operations such as conversion, stretching, and bagbess, and also display these buffers. Graphic data, these buffers are called surfaces. The surface can be divided into several categories. The main surface is the user can see on the screen, which is part of the display memory. All DirectDraw programs have a main surface and there is only one. It already exists before the DirectDraw surface object, so it cannot be changed, format, and location. The main surface has a very important feature - flip. The page flips is used in the program, which can produce a fairly smooth, not flashing animation. A main surface that can be flip is actually two surfaces, one is visible, one is invisible. The unacceptable surface is called a backup buffer. When the surface is flipped, the backup buffer is visible, and the previous visible surface is a backup buffer. There is also a surface called the surface of the surface (Off_Screen Surface), which cannot be seen directly. The slave surface is used as the storage buffer to help each other between the surface, and its size can be changed. The main surface and the off-screen surface are divided into these two categories with a palette and a tone palette. The surface of the pixel depth is 8 bits (256 colors) is called the surface of the palette; the pixel depth is 16 bits (64 k color), and the 24-bit (16 M color) pixel surface is called the surface of the tone palette, Store the actual color value (RGB value). In the program below this article, we use the 24-bit surface, that is, the surface of the palette. 2. BLTTING BLTTING is a language for copying graphics, which can copy images from one place to another. For example, Bitblt () of the CDC class (device description form) that everyone is familiar with is the function of such a function.

In DirectDraw, the typical BLT operation is to copy the contents of the slap on the surface of the screen to a backbrew, and the general BLT operation calls a source surface and a target surface, copy the contents of the source surface to the target surface, not only can be overall Copy the source surface, and you can copy any of the rectangular regions within the source surface to any location of the target surface. The BLT also supports transparent copies, which means that a pixel in the surface may not copy in the BLT process, and this pixel value is determined by the DDColor Key. There are three functions that support BLT (), BLTFast (). BLT () is used up to Bltfast () speed than blt (), but the function is limited, such as operation of stretching, shearing, etc. There is also a function Bltsurface (), which is a member function of the DirectWIN class, BLT (), BLTFast () is more adaptable, and it is easier to use. For example, when we copy the source surface to the target surface, you need to crop, and BLTFast () does not support cropping. At this time we use the bltsurface () function, which uses the blt () and bltsurface () internally, and automatically performs cropping according to the situation. 3. Color key code DirectDraw can specify a color or a range of colors as a color value, which is illustrated by the DDCOLORKEY structure, the color key code, the DDCorLorKey structure describes the following: typedef struct _ddcolorKey {DWORD DWCOLORSPACLOWVALUE; / / Color range low DWORD DWCOLORSPACEHIGHVALUE; // Color range high-end} DDCOLORKEY; when we copy the surface, which pixels are not copied by the color key code. For example, when both components of the DDColorKey structure are zero, all pixels that are set to zero in the surface cannot be copied. For example, when the surface is 24-bit RGB mode, if you want to specify the RGB = (120, 120, 120) pixels from being copied, then: DDCOLORKEY DDCK; DDCK.DWCOLORSPACLOWVALUE = RGB (120, 120, 120); DDCK.DWCOLORSPACEHIGHVALUE = RGB ( 120, 120, 120); Surf → setColorKey (DDCKEY_SRCBLT, & DDCK); where the setColorKey () function is assigned to the surface SURF. Thus, the pixels of the RGB value (120, 120, 120) cannot be copied during the BLT operation of the surface SURF. Two. Practice Ancient Language Cloud: "Jun wants to do things, you must first make a tool", before writing DirectDraw applications, we must prepare the following tools: Windows95, Windows98 or WindowsNT4.0 DirectX driver (preferably DirectX3. " 0 or more version) DirectX SDK Visual C 5.0 Direct SDK includes the development of all files required for DirectX applications, all of which require 80 hard disk space. In fact, you only need to install the necessary header file (.h file) and library file (.lib file). After installing DirectX SDK, you need to notify Visual C DirectX SDK path.

The specific approach is: In the compilation environment of the VC, fill in the INCLUDE FILES and LIBRARY FORs in the Tools-Options-Director in the Tools-Options-Directories, as shown in Figure 1. The bitmap of two BMP formats is prepared, requiring 24 bits (16M color), where the background.bmp is background, as shown in Figure 2; another Bird.BMP as a sub-picture, as shown in Figure 3. Bird.BMP consists of 4 small pictures, from left to right, from top to bottom, from 1 to 4 frames of animation. The purpose of this is to avoid unnecessary troubles from multiple bitmap files. Also note that the background of the sub-picture should be black (RGB = (0, 0, 0)), because in the following program, the color key code sets black to transparent color. Ok, everything is ready, let's get started! Enter the programming environment of the VC5, file-new-project, select DirectDraw Appwizard, enter the project name fly, press OK, you can press its default, so AppWizard It will automatically create a project fly, the property is as follows: Application Style Full-Screen Settings 640x480 16-bit class names Flyapp Flywin Content Bitmap This time, press "Ctrl F5" to compile, you will see a "triangle" hit on the screen To hit it.

FlyWin.h add code, as follows: #ifndef FLYWIN_H #define FLYWIN_H #include "DirectDrawWin.h" class FlyWin: public DirectDrawWin {public: FlyWin (); protected: // {{AFX_MSG (FlyWin) afx_msg void OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); afx_msg void OnTimer (UINT nIDEvent); afx_msg void OnDestroy (); //}} aFX_MSG DECLARE_MESSAGE_MAP () private: int SelectDriver (); int SelectInitialDisplayMode (); BOOL CreateCustomSurfaces (); void DrawScene (); void RestoreSurfaces (); private: void CopySurface (LPDIRECTDRAWSURFACE ts, LPDIRECTDRAWSURFACE ss, int x, int y); void SplitSurface (LPDIRECTDRAWSURFACE ts, LPDIRECTDRAWSURFACE ss, CRect & srcc, int x , int y); private: lpdirectdrawsurface bksurf, // Define pointer flysurf in the background screen surface, // pointing to the pointer StoreSurf, // pointing to the storage background area surface, pointing the first frame, pointing the first frame Pointer flysurf2, / / ​​pointing to the pointer flysurf3 of the second frame sub-screen surface, / / ​​pointing to the pointer flysurf4 of the third frame sub-screen surface, / / ​​pointing to a pointer curSurf on the fourth frame surface surface of the fourth frame, pointing to the current movement Pointer // Background Drawing Bac Kground.BMP; total sub-picture refers to Bird.BMP INT X, Y, NPREX, NPREY; / / Define sub-picture moving coordinate int Ninc Ninc Ninc Numi INT NCOUNT; // Define Counter DWORD FW, fH; // Define the width and high} of the total sub-picture; #ENDIF where the COPYSURFACE () function saves the background area covered by the quilt screen. The parameter TS is a pointer to the target surface. SS is a pointer to the source surface, X, Y is a coordinate of the upper left corner of the rectangular area on the source surface. The splitsurface () function is used to isolate a large total bonus surface surface of 4 frames. The parameter TS is a pointer to the target surface. SS is a pointer to the source surface, and the SRCC is a rectangular area that needs to be selected on the source surface, X, Y to copy to the left upper corner coordinate on the target surface. In fact, when we read the prototype of these two functions in Flywin.cpp, the careful friends may find that the two functions can be written into a function. This article is deliberately written into two functions, which is the clear reading of the program, and it is not easy to cause confusion.

The next step is added to flywin.cpp, as shown below: #include "headers.h" #include "resource.h" #include "driverdialog.h" #include "flywin.h" #pragma comment (lib, "DDRAW .lib ") #pragma Comment (lib," dxguid.lib ") const dword desiredWidth = 640; const dword desiredhem = 480; const dword desiredDepth = 16; const Int nmovespeed = 100; // Set animation speed is 100 millisecond / frame Const int nmoveincx = 8; // Set sub-screen moving 8 pixels along the X-axis Const Int NmoveIncy = 8; // Sets sub-screen moving 8 pixels becoming_Message_Map (Flywin, DirectDrawWIN) // {{AFX_MSG_MAP (Flywin) ON_WM_KEYDOWN () ON_WM_CREATE () ON_WM_TIMER () ON_WM_DESTROY () //}} AFX_MSG_MAP END_MESSAGE_MAP () FlyWin :: FlyWin () {x = nPreX = 300; // sprite initial position (300,150) y = nPreY = 150; nIncX = nMoveincx; nincy = nMoveIncy; ncount = 1; // set counter} BOOL FLYWIN :: CreateCustomsurface () {// create your surfaces here ... // Create a background surface, and point to this surface Bksurf = CreateSurface by pointer BKSURF "Background.bmp"); // Create a surface of a total sub-screen (consisting of 4 frames) // Points by pointer FlySurf to this surface. FlySurf = CreateSurface ("Bird.BMP"); // Get the bus screen Surface width (FW), high (fH) GetSurfaceDimensio NS (Flysurf, FW, FH); // Creating 4 frames of width of FW / 2, the surface of the sub-picture of the fH / 2, respectively by // pointer flysurf1, flysurf2, flysurf3, flysurf4 points to them. // The four sub-surfaces are now empty. Flysurf1 = createSurface (fw / 2, fH / 2); flysurf2 = createSurface (fw / 2, fH / 2); flysurf3 = cretesurface (fw / 2, fH / 2); flysurf4 = createssSurface (fw / 2, fH / 2 ); / / Clear the contents of the 4 frame sub-picture surface, so that all pixels in the surface are 0, //, and the surface is transparent. ClearSurface (Flysurf1,0); ClearSurf2,0); ClearSurface (FlySurf3, 0); ClearSurface (FlySurf4, 0); // Define color keycase, indicating black (RGB = (0, 0, 0)) is transparent Color // is not copied during the BLT operation.

DDCOLORKEY ddck; ddck.dwColorSpaceLowValue = 0; ddck.dwColorSpaceHighValue = 0; // key code assigned to the background color of the surface, the total surface of the sub-picture and sub picture surface 4 bksurf → SetColorKey (DDCKEY_SRCBLT, & ddck); flysurf → SetColorKey (DDCKEY_SRCBLT, & ddck); flysurf1 → SetColorKey (DDCKEY_SRCBLT, & ddck); flysurf2 → SetColorKey (DDCKEY_SRCBLT, & ddck); flysurf3 → SetColorKey (DDCKEY_SRCBLT, & ddck); flysurf4 → SetColorKey (DDCKEY_SRCBLT, & ddck); // 4 th on the total sub-screen surface defining The rectangular area, that is, 4 sub-picture surface regions CRECT R1 (0, 0, FW / 2-1, FH / 2-1); CRECT R2 (FW / 2, 0, FW-1, FH / 2-1); CRECT R3 (0, FH / 2, FW / 2-1, FH-1); CRECT R4 (FW / 2, FH / 2, FW-1, FH-1); // Putting 4 on the surface of the total sub-screen The rectangular area is copied to 4 sub-screen surfaces, respectively, that is, the separating total sub-screen surface SPLITSURFACE (FlySurf1, FlySurf, R1, 0); Splitsurface (Flysurf2, FlySurf, R2, 0); Splitsurf3, Flysurf , R3, 0, 0); SPLITSURFACE (FlySurf4, FlySurf, R4, 0); // Create a storage surface, pointing by pointer StoreSurf to it // to store the background area covered when moving the sub-picture STORESURF = CreateSurface (FW / 2, FH / 2); Copysurface (StoreSurf, Bksurf, X, Y); // Initialize the current sub-picture surface Cursurf = flysurf1; return true;} void flywin :: DrawScene () {// Draw background surface and The first frame of the sub-screen surface / / copy the background surface to the backup buffer Bltsurface (Backsurf, B Ksurf, 0, 0, true); // copy the current sub-screen surface to the backup buffer Bltsurface (Backsurf, Cursurf, x, y, true); // page flip, make the contents of the backup buffer primsurf → FLIP (0, ddflip_wait); // copy the background surface to the back buffer Bltsurface (Backsurf, BKSURF, 0, 0, True); function // depending on the surface's function, it may be necessary to restore // surface content as well if (bksurf → IsLost ()) // If bksurf lost {bksurf → restore (); // restore memory LoadSurface (bksurf, " Background.bmp "); // Restore surface content} if (flysurf → islost ()) // If FlySurf is lost {FlySurf → restore ();

// Restore memory LoadSurface (FlySurf, "Bird.BMP"); // Restore surface content}} int Flywin :: selectdriver () {int Numdrivers = getNumDrivers (); if (Numdrivers == 1) Return 0; carrayDrivers;

For (int i = 0; i

{

LPSTR DESC, NAME;

GetDriverInfo (i, 0, & desc, & name);

Drivers.Add (DESC);

}

DriverDialog dialog;

Dialog.setContents (& DRIVERS);

IF (Dialog.Domodal ()! = iDOK)

Return -1;

Return Dialog.getSelection ();

}

INT FLYWIN :: SelectInitialDisplayMode ()

{

DWORD CURDEPTH = GetDisplayDepth ();

INT I, Nummodes = GetNumDisplayModes ();

DWORD W, H, D;

IF (CurDepth! = DesiredDepth)

DDRAW2 → SetDisplayMode (640, 480, Curdepth, 0, 0);

For (i = 0; i

{

GetDisplayModedImensions (i, W, h, d);

IF (w == desiredWidth && H == DesiredHeight && D == DesiredDepth)

Return I;

}

For (i = 0; i

{

GetDisplayModedImensions (i, W, h, d);

IF (d == desiredDepth)

Return I;

}

Return 0;

}

Void flywin :: onkeydown (uint nchar, uint nrepcnt, uint nflags)

{

IF (nchar == vk_escape) // Press ESC to exit

Postmessage (WM_CLOSE);

DirectDrawwin :: onkeyDown (nchar, nrepcnt, nflags);

}

Int flywin :: oncreate (lpcreatestruct lpcreatestruct)

{

IF (directdrawwin :: oncreate (lpcreatestruct) == -1)

Return -1;

// Todo: Add Your Specialized Creation Code Here

Settimer (1, nmovespeed, null); // Setting the timer

Return 0;

}

Void Flywin :: ONTIMER (Uint Nidevent)

{

// Todo: add your message handler code here and / or call default

INT NWHICH = NCOUNT% 4 1;

NCOUNT ;

/ / Judge which one of the current surface is 4 sub-surfaces

Switch (NWHICH)

{

Case 1:

Cursurf = flysurf1;

Break;

Case 2:

Cursurf = flysurf2;

Break;

Case 3:

Cursurf = flysurf3;

Break;

Case 4: Cursurf = flysurf4;

Break;

DEFAULT:

Break;

}

// Process the moving sub-picture

X = Nincx;

Y = nincy;

/ / If the sub-picture moves to or above the screen, the collision should be collided.

IF (y> = (int) (480-fH / 2) || y <= 0)

{

Nincy = -nincy;

Y = nincy;

}

/ / If the sub-picture moves to the right or left, the collision should be collided.

IF (x> = (int) (640-fW / 2) || x <= 0)

{

Nincx = -nincx;

X = Nincx;

}

/ / Copy the current surface to the backup buffer

Bltsurface (Backsurf, Cursurf, X, Y, True);

// Perform the page flip to make the contents of the backup buffer visible

Primsurf → FLIP (0, DDFLIP_WAIT);

// Copy the backup background area to the backup buffer so that recovery has been

// Covered background

Bltsurface (Backsurf, StoreSurf, nprex, nprey);

// Store the background area covered by the sub-picture of the next frame to move in StoreSurf

Copysurface (StoreSurf, Bksurf, X, Y);

Nprex = x;

Nprey = Y;

Directdrawwin :: ONTIMER (Nidevent);

}

Void flywin :: ONDESTROY ()

{

DirectDrawwin :: ONDESTROY ();

// Todo: Add your message Handler Code Here

KillTimer (1); // Cancel the timer

}

Void Flywin :: Copysurface (LPDirectDrawsurface TS,

LPDIRECTDRAWSURFACE SS,

INT X, int y)

{

IF (! ts ||! ss) return;

DDSurfaceDesc TDESC, SDESC;

// Initialize SDESC, TDESC is zero

ZeromeMory (& SDESC, SIZEOF (SDESC));

ZeromeMory (& TDESC, SIZEOF (TDESC));

SDESC.DWSIZE = SIZEOF (SDESC);

TDESC.DWSIZE = SizeOf (TDESC);

// Get the source surface SS, the description of the target surface TS

HRESULT R = SS → GetsurfaceDesc (& SDESC);

IF (r! = dd_ok) return;

R = TS → GetSurfaceDesc (& TDESC);

IF (r! = dd_ok) return;

/ / Define the rectangular area on the source surface, size is equal to the area of ​​the target surface

CRECT RC (X, Y, X TDesc.dwwidth, y tdesc.dwheight);

// Super bound

IF (x tdesc.dwwidth> (int) sdesc.dwwidth) Return;

IF (y tdesc.dwheight> (int) sdesc.dwheight) return;

// Copy source surface SS to target surface TS

R = TS → BLTFAST (0, 0, SS, & RC, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);

IF (r! = dd_ok) return;

}

Void Flywin :: Splitsurface (LPDirectdrawSurface TS,

LPDIRECTDRAWSURFACE SS,

CRECT & SRCC,

INT X, int y)

{

IF (! ts ||! ss) return;

DDSurfaceDesc TDESC, SDESC;

ZeromeMory (& SDESC, SIZEOF (SDESC));

ZeromeMory (& TDESC, SIZEOF (TDESC));

SDESC.DWSIZE = SIZEOF (SDESC);

TDESC.DWSIZE = SizeOf (TDESC);

HRESULT R = TS → GetSurfaceDesc (& TDESC);

IF (r! = dd_ok) return;

R = SS → GetSurfaceDesc (& SDESC);

IF (r! = dd_ok) return;

// Super bound

IF (x srcc.width ()> (int) tdesc.dwwidth) Return;

IF (Y Srcc.height ()> (int) tdesc.dwheight) Return;

/ / Copy the rectangular area of ​​the source surface SRCC to the upper left corner coordinate of the target surface is (x, y)

R = TS → Bltfast (x, y, ss, & srcc,

DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);

IF (r! = dd_ok) return;

}

DDSurfaceDesc is a surface description structure that saves all the information of the surface, its member variable dwsize is the size of the structure and must be initialized; dwheight is the height of the surface; DWWIDTH is the width of the surface. Use a function getSurfaceDesc () to obtain the above description information.

DirectDraw first calls the CreateCustomsurface () function, we will create and prepare the surfaces used in this function. The drawsence () function is responsible for updating the screen, so we use it to display the background picture. All our main work is in the ontimer () function, first determined which of the current sub-picture is 4 frames in the sub-screen, then performs operations such as page flip, display sub-screen, and replication background areas.

The Bltfast () function is used for the copy between the surface. Its first two parameters indicate the target surface position of the BLT, the third parameter is the pointer to the source surface, and the fourth parameter is the rectangular area copied on the source surface, The final parameter is DDBLTFAST_SRCCOLORKEY and DDBLTFAST_WAIT, the first flag is used to activate the color key of the source surface; the second flag represents only the end BLT operation, the BLTFast () function returns.

The flip () function is used to flip operation, making the contents of the Backsurf surface visible. It has two parameters. The first parameter is a surface pointer, which is useful when used to flip the surfaces of multiple back buffers; the second parameter is DDFLIP_WA

IT logo, used to indicate that the function can only return after the surface is completed.

When the program runs, the memory where a surface may be occupied by another application, which forms "surface loss". At this time, DirectDraw calls the restoreSurface () function to resume the lost surface. However, if your graphics card is not old, this situation will generally not happen. So here I only recover for two main surfaces Bksurf, Flysurf, and no other surface.

In addition, the function selectDriver () and selectInitialDisplayMode () are automatically created by AppWizard. SelectDriver () Select a display driver, selectInitialDisplayMode () Selects an initial display mode.

转载请注明原文地址:https://www.9cbs.com/read-2573.html

New Post(0)