Windows Game Programming Quick Start Method
Easideao (Simple Thoughts)
Preamble:
From 2001 to 2005, I have already spent 4 years of occupational game development career in unconsciousness. In these four years, some netizens will have a shortcut to me inquiry. Every time I don't know how to answer, I have always want to express my ideas and ideas, but I have never been able to express my insights in writing. In fact, I think the program is not a difficult thing. The most important thing is whether you are interested in him, it is hard to persist in learning. If you are not interested, even if you have just entered it, if you don't stick to it, it is nothing.
Although perseverance has an unsuspetent position in the process of learning, there is a suitable method and the method suitable for you. If your interest and perseverance have passed, I will write down with a game's code, I insist on writing, you insist on reading, follow the steps I tell. I won't tell all the details here, because it is too large task, my strength can not be realized, the following method is: I said how to do it, how do you do it, first know how to do something, when you Ability to make the correct results I have explained that you have already, if you don't know how to view the relevant information.
Some cumbersome said above, I am not willing to write it, my text is limited, please understand. The most important thing is to follow me. If you have any opinions or questions, you can send me E-mail: chinagdh@163.com.
Chapter 1 Windows program
Open Visual Studio 2003.net, select File -> Blank Solution.
Enter Battlecity in the Name column and press the OK button, press Browse to select Solution to save the location
3. Press the right button in Solution Explorer. Select Add -> New Project in the drop-down menu.
4. Select Visual C Projects -> Win32 -> Win32 Project in the Add New Project dialog box, hit TANK in the Name column and press Enter
5. Select Application Settings and hook in front of the Empty Project to create an empty Win32 project.
6. Press Right click on the TANK item to select Add -> New Folder Add Folder and Name WinApp
7. Press Right click on WinApp folder to select Add -> Add New Item
8. Select Visual C -> C File (.cpp) Enter winApp.cpp in the Name column.
9. Repeated 7.8 steps increase WinApp.h appentry.cpp appentry.h
10. Double-click WinApp.h Open File We add the following code in WinApp.h header files.
11. Treated APPENTRY.H in the same method. This method guarantees that the header is only included once, this is a way I like to use it. #Pragma overce
12. Open AppenTry.h Add to Code #include
13. Open WinApp.h Add to Code #include "AppenTry.h"
14. Open WinApp.cpp to join the code #include "winapp.h"
15. Define the primary program handle and the main window handle
16. Add Global Functions that get the master handle and the main window handle
17. For the convenience, the main program handle and the main window handle are declared in WinApp.h.
Hinstance getApphandle ();
HWnd getMainWnd (); 18. Define the Windows program main function, this is an entry function of a Windows program, we think the program starts from this function.
19. Select the TANK item in Solution Explorer, press Right click to select Build to compile, see if the program can be compiled.
Compile success will appear in the Output window Build: 1 succeeded, 0 failed, 0 Skipped means successful 0 failed 0 skipping
20. Set the path generated by TANK, press Right click on the project TANK to select Properties
21. Select the program generation path (Output file) is ../runtime/tank.exe
22. Select the Working Directory to compile it ../Runtime
23. Increase the initialization of several function programs, the main loop message processing function, the code is as follows
#include "winapp.h"
/ / Define the main program handle
Hinstance g_htheapp = NULL;
/ / Define the main window handle
HWnd g_hmainwnd = null;
//
/ / Get the main program handle
Hinstance getAppHandle ()
{
Return g_htheapp;
}
// Get the main window handle
HWND getMainWnd ()
{
Return g_hmainwnd;
}
//
// Windows program initialization
HWnd Appinit (Hinstance Hinstance, INT NSHOWCMD);
// Windows program ends
void appterm ();
// Windows message loop and main loop
int Appmsgloop ();
// Windows message handler
LResult Callback AppWndProc (HWND HWND, UINT MSG, WPARAM WPARAM, LPARAM LPARAM);
//
// Windows program main function
Int Winapi WinMain
In hinstance hinstance,
In hinstance hprevinstance,
In lpstr lpcmdline,
INT nshowcmd
)
{
/ / Save the main program handle
g_htheapp = hinstance;
// Initialize the Window window and program
g_hmainwnd = appinit (g_htheapp, nshowcmd);
IF (g_hmainwnd == null)
{
Messagebox (Null, "Can't Create Main Window", "Error", MB_OK;
Return 0;
}
// Enter the main message loop
Return AppmsGloop ();
}
// Windows program initialization
HWnd Appinit (Hinstance Hinstance, INT NSHOWCMD)
{
Return NULL;
}
// Windows program ends
void appterm ()
{
}
// Windows message loop and main loop
int Appmsgloop ()
{
Return 0;
}
// Windows message handler
LResult Callback AppWndProc (HWND HWND, UINT MSG, WPARAM WPARAM, LPARAM LPARAM)
{
Return DefWindowProc (HWND, MSG, WPARAM, LPARAM);
}
24. Register the program and create the main window in the appinit () function
// Windows program initializes hWnd appinit (Hinstance Hinstance, Int NshowCMD)
{
// Program instance class name
Static char szwindowsclassname [] = "tankbattlecity";
Static int tent = 800; // Window width
Static int opyheight = 600; // Window height
// Register window class
WNDCLASS WC;
Wc.style = CS_HREDRAW | CS_VREDRAW;
/ / Set the main window message processing function
Wc.lpfnwndproc = appwndproc;
wc.cbclsextra = 0;
wc.cbWndextra = 0;
wc.hinstance = hinstance;
wc.hicon = loading; 0, IDi_Application;
wc.hcursor = loadingcursor (0, IDC_ARROW);
Wc.hbrbackground = static_cast
wc.lpszMenuname = 0;
Wc.lpszclassname = szwindowsclassname;
IF (! RegisterClass (& WC))
{
MessageBox (NULL, "RegisterClass - Failed", "Error", MB_OK;
Return False;
}
// Create a main window
HWND HWND = CREATEWINDOW (SzWindowsClassName
, SzwindowsClassName
, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
CW_USEDEFAULT
CW_USEDEFAULT
, IwindowWidth
, Iwindowheight
0
0
Hinstance
, 0);
IF (null == hwnd)
{
MessageBox (Null, "Create Main Window - Failed", "Error", MB_OK;
Return NULL;
}
// Display the main window
ShowWindow (hwnd, sw_show);
/ / Update the main window display content
UpdateWindow (HWND);
Return hwnd;
}
25. Writing AppMsgloop () program main loop
// Windows message loop and main loop
int Appmsgloop ()
{
MSG msg;
ZeromeMory (& MSG, SIZEOF (MSG));
_Apploop:
// Test if there is a message to be processed
IF (PEEKMESSAGE (& MSG, NULL, 0, 0, PM_NOREMOVE))
{
// If the message is not received, you want to exit the program.
IF (! GetMessage (& MSG, NULL, 0, 0))
{
// Steering End Procedure
Goto _exitApp;
}
// Perform message processing
TranslateMessage (& MSG);
DispatchMessage (& MSG);
}
Else
{
// If there is no message to handle, call the main loop.
Sleep (1);
Goto _Apploop;
_ExitApp:
Apputerm ();
Return (int) msg.wparam;
}
26. Join the launch program message processing in the AppWndProc () function
// Windows message handler
LResult Callback AppWndProc (HWND HWND, UINT MSG, WPARAM WPARAM, LPARAM LPARAM)
{
Switch (msg)
{
Case WM_DESTROY:
PostquitMessage (0);
Break;
}
Return DefWindowProc (HWND, MSG, WPARAM, LPARAM);
}
To now we can compile and implement a Windows program that does not do anything, I don't want to discuss anyone with any person on the code of code, such as in the appmsgloop () function, using goto and labels. I personally feel that it is not appropriate to discuss this problem. We are important to know how to make the program, about the details of Windows programming, you can check the "Windows programming" book.
Chapter II Simplified Program Interface
In the previous chapter, we introduced how to write a Windows program, have completed a simple Windows program with a main window, and then we wrote our game program. For future writing, the contents of each part of the program are independent, and we now start to define a simple program interface, we don't need to worry too much about Windows programs.
Program interface implementation we use the most common functional function in C to implement interface functions. Here you only need to know a Virtual keyword in front of the function defined in the base class, and you can override the function content in the derived class.
1. Open APPENTRY.H Enter the following program
#ifndef __appenTry_H__
#define __APPENTRY_H__
#include
Class IappenTry
{
PUBLIC:
// Initializer
Virtual Bool Initialize (Hinstance Hinstance, HWND HWND) = 0;
// End the program
Virtual void terminal () = 0;
// Main processing function
Virtual void process () = 0;
// Main rendering function
Virtual void render () = 0;
// Main window message processing function
Virtual Lresult WndProc (Uint Message, WPARAM WPARAM, LPARAM LPARAM) = 0;
// Define the Window program class function
Virtual const char * windowclassname () = 0;
/ / Define the Window Width
Virtual const Int windowWidth () = 0;
/ / Define the Height of the Window window
Virtual const INT windowHeight () = 0;
// Get the main program handle
Virtual Hinstance GetInstance () = 0;
// Get the main window handle
Virtual hwnd getWnd () = 0;
}
#ENDIF / / __APPENTRY_H__
Every function is written here with = 0 indicates that the function is a pure virtual function, and it must be rewritten in the derived class. This method is to define common methods for interfaces.
2. Open WinApp.cpp to join the following code
// Windows message loop and main loop
int Appmsgloop ();
// Windows message handler
LRESULT CALLBACK AppWndProc (HWND HWND, UINT MSG, WPARAM WPARAM, LPARAM LPARAM); // Get simple program interface instance, we will define in GameApp.cpp
IAPPENTRY * APPENTRYCLASS ();
//
// Windows program main function
Int Winapi WinMain
In hinstance hinstance,
In hinstance hprevinstance,
In lpstr lpcmdline,
INT nshowcmd
)
3. Add the following code in the WinMain function
// Windows program main function
Int Winapi WinMain
In hinstance hinstance,
In hinstance hprevinstance,
In lpstr lpcmdline,
INT nshowcmd
)
{
/ / Save the main program handle
g_htheapp = hinstance;
// Initialize the Window window and program
g_hmainwnd = appinit (g_htheapp, nshowcmd);
IF (g_hmainwnd == null)
{
Messagebox (Null, "Can't Create Main Window", "Error", MB_OK;
Return 0;
}
// Initialization master program
IF (! appentryclass () -> initialize (g_htheapp, g_hmainwnd))
{
MessageBox (NULL, "Initialize AppenTry Failed", "Error", MB_OK;
Return 0;
}
// Enter the main message loop
Return AppmsGloop ();
}
4. Add the following code in the applerm () function
// Windows program ends
void appterm ()
{
// End the program
APPENTRYCLASS () -> Terminal ();
}
5. Add the following code in the AppMsgloop () function
// Windows message loop and main loop
int Appmsgloop ()
{
MSG msg;
ZeromeMory (& MSG, SIZEOF (MSG));
_Apploop:
// Test if there is a message to be processed
IF (PEEKMESSAGE (& MSG, NULL, 0, 0, PM_NOREMOVE))
{
// If the message is not received, you want to exit the program.
IF (! GetMessage (& MSG, NULL, 0, 0))
{
// Steering End Procedure
Goto _exitApp;
}
// Perform message processing
TranslateMessage (& MSG);
DispatchMessage (& MSG);
}
Else
{
// If there is no message to handle, call the main loop.
AppenTryClass () -> Process ();
Sleep (1);
}
Goto _Apploop;
_ExitApp:
Apputerm ();
Return (int) msg.wparam;
}
6. Add the following code in the AppWndProc () function
// Windows message handler
LResult Callback AppWndProc (HWND HWND, UINT MSG, WPARAM WPARAM, LPARAM LPARAM)
{
Switch (msg)
{
Case WM_DESTROY:
PostquitMessage (0);
Break;
}
// Call the message processing function of the simple program interface, if returned, not false, complete the message processing / / otherwise, continues to call the Windows program default message processing function.
LRESULT LR = AppenTryClass () -> WndProc (MSG, WPARAM, LPARAM);
IF (lr! = false)
Return LR;
Return DefWindowProc (HWND, MSG, WPARAM, LPARAM);
}
7. Built a new directory GameApp on the TANK project and create two file appgame.cpp appgame.h
8. Add the following code in appgame.h
#ifndef __Appgame_H__
#define __Appgame_H__
#include "winapp.h"
Class Cappgame: Public IAPPENTRY
{
PUBLIC:
Cappgame ();
Virtual ~ cappgame ();
// Initializer
Virtual Bool Initialize (Hinstance Hinstance, HWND HWND);
// End the program
Virtual void terminal ();
// Main processing function
Virtual void process ();
// Main rendering function
Virtual void render ();
// Main window message processing function
Virtual LRESULT WNDPROC (Uint Message, WPARAM WPARAM, LPARAM LPARAM);
// Define the Window program class function
Virtual const char * windowclassname ();
/ / Define the Window Width
Virtual const Int windowwidth ();
/ / Define the Height of the Window window
Virtual const Int windowheight ();
// Get the main program handle
Virtual hinstance getInstance ();
// Get the main window handle
Virtual hwnd getWnd ();
protected:
/ / Save the main program handle
Hinstance M_HINSTANCE;
/ / Save the main window handle
HWND M_HWND;
}
#ENDIF / / __APPGAME_H__
9. Open AppGame.cpp to join the simple interface program instance, and get functions for program instance
#include "appgame.h"
/ / Define the primary game program instance
Cappgame theappgame;
// Define the simple program interface instance function, this is used in WinApp.cpp, and must be defined
// This is the interface of the Windows program call game program
IAPNTRY * APPENTRYCLASS ()
{
Return & theAppgame;
}
10. Add the following code to write the pure virtual function of the simple program interface
//
CAPPGAME :: Cappgame ()
{
M_HINSTANCE = NULL;
m_hwnd = NULL;
}
CAPPGAME :: ~ CAPPGAME ()
{
}
// Initializer
Bool Cappgame :: Initialize (Hinstance Hinstance, HWND HWND)
{
M_HINSTANCE = Hinstance;
m_hwnd = hwnd;
Return True;
}
// End the program
void cappgame :: terminal ()
{
}
// Main processing function
Void cappgame :: process ()
{
}
// Main rendering function
Void cappgame :: render ()
{
}
// Main window message processing function
LResult Cappgame :: WndProc (uint message, wparam wparam, lparam lparam) {
Return False;
}
// Define the Window program class function
Const char * cappgame :: windowclassname ()
{
Return "Tankbattlecity";
}
/ / Define the Window Width
Const int cappgame :: windowwidth ()
{
Return 800;
}
/ / Define the Height of the Window window
Const Int Cappgame :: WindowHeight ()
{
Return 600;
}
// Get the main program handle
Hinstance Cappgame :: getInstance ()
{
Return M_HINSTANCE;
}
// Get the main window handle
HWnd cappgame :: getWnd ()
{
Return m_hwnd;
}
11. Open WinApp.cpp and do the following modifications in the Appinit () function
// Windows program initialization
HWnd Appinit (Hinstance Hinstance, INT NSHOWCMD)
{
// Program instance class name
Const char * szwindowsclassname = appentryclass () -> windowclassname ();
Static int ● () -> windowwidth (); // Window width
Static int windowheight = appentryclass () -> windowheight (); // window height
// Register window class
WNDCLASS WC;
Wc.style = CS_HREDRAW | CS_VREDRAW;
12. Introduce a little tool. Add a utility directory on the TANK project to add formatstring.h and formatstring.cpp and join the following code
#ifndef __FormatString_H__
#define __fromatstring_h__
#include
// format string pad function template
Template
{
Static char szoutstr [ibuflen];
SzoutStr [0] = 0;
VA_LIST VL;
VA_START (VL, SZFORMAT);
vSprintf (SzoutStr, Szformat, VL);
VA_END (VL);
ASSERT (Strlen (SzoutStr) Return SzoutStr; } / / I give a commonly used buffer size of 1024 bytes #define fstr formatstring <1024> // Usage: // OutputDebugstring (FSTR ("Format Out% S", "OK"); #ENDIF / / __FORMATSTRING_H__ We can use it when any need to output a string format, which is very convenient. This cannot be used to nested calls, nor can it be used for complex thread calls, static char soutstr [ibuflen]; this is a unique memory address, and other function calls change his content will be wrong. That is to say, the string combined with this tool should be called immediately. Now our project file is as follows: Chapter III Shows Images and Basic Drawings This chapter I will show how to display pictures on the program main window with WindowsGDI, with GDI shows just for simple and convenient, to complete our task, and if you want more efficient methods, you can use the DirectX 3D or DirectDRAW interface. 1. First we are ready, I am putting it in Runtime. Take name imagec.bmp, which is how to display this picture. 2. Add the render directory in the TANK project, and increase the file gdigraphicsdevice.cpp gdigraphicsdevice.h gdisurface.cpp gdisurface.h gditExtrender.cpp gditExtrender.h 3. Open GDIGRAPHICSDEVICE.H to join the following code #ifndef __gdigraphicsdevice_h__ #define __gdigraphicsDevice_h__ #include // Drawing equipment, here is the device that can be displayed on the screen, which is virtual, // We call it graphic device. Class CGDIGRAPHICSDEVICE { PUBLIC: CGDIGRAPHICSDEVICE (); Virtual ~ cgdigraphicsdevice (); // Create a device, let the device operate object point to a window Bool Create (HWND HWND, IWIDTH, INT IHEIGHT); // Release device Void release (); / / Update the display, make the main surface content on the screen Void UpdateFrame (HDC HDC); // Get the window of the operation pointing HWND getWnd (); protected: // Adjust the window size Void AdjuestWindowsize (int ingidth, int height); protected: // Operate the window handle HWND M_HWND; } #ENDIF / / __GDIGRAPHICSDEVICE_H__ 4. Open GDIGRAPHICSDEVICE.CPP to join the following code #include "gdigraphicsdevice.h" CGDIGRAPHICSDEVICE :: cgdigraphicsdevice () { m_hwnd = NULL; } CGDIGRAPHICSDEVICE :: ~ cgdigraphicsDevice () { } Bool CgdigraphicsDevice :: Create (HWND HWND, INT IWIDTH, IHEIGHT) { Return True; } Void cgdigraphicsDevice :: release () { } Void CGDIGRAPHICSDEVICE :: UpdateFrame (HDC HDC) { } HWnd cgdigraphicsDevice :: getWnd () { Return m_hwnd; } // // Adjust the window size to make the plot area equal to the size of the iWidth Iheight indication Void CgdigraphicsDevice :: AdjuestWindowsize (int iWidth, Int Iheight) { } 5. Implement the adjustment window size function // Adjust the window size to make the plot area equal to the size of the iWidth Iheight indication Void CgdigraphicsDevice :: AdjuestWindowsize (int iWidth, Int Iheight) { / / Define the location and window display area where the window is on the screen RECT RCSCREEN, RCCLIENT; // Get the location and window display area position on the window on the screen GetWindowRect (M_HWND, & RCSCREEN); GetClientRect (M_HWND, & RCCLIENT); // Calculate the wide and high of the two regions INT RSCREENWIDTH = rcscreen.right - rcscreen.Left 1; Int rscreenheight = rcscreen.bottom - rcscreen.top 1; Int rclientwidth = rcclient.right - rcclient.Left 1; INT rclientHeight = rcclient.bottom - rcclient.top 1; / / Calculate the size of the two regions INT rw = rscreenwidth - rclientwidth; INT RH = RSCREENHHET - RCLIENTHEIGHT; / / Calculate the new window size Rcscreen.right = iWidth rw; RcScreen.bottom = IHEIGHT RH; // Set the window size SetwindowPos (M_HWND, NULL, RCSCREEN.LEFT, RCSCREEN.TOP, RCSCREEN.RIGHT, RCSCREEN.BOTTOM, SWP_FRAMECHANGED); / / Show Windows Showwindow (m_hwnd, sw_show); // Update window UpdateWindow (M_HWND); } 6. Implement the creation device function // Create a device, let the device operate object point to a window Bool CgdigraphicsDevice :: Create (HWND HWND, INT IWIDTH, IHEIGHT) { / / Save the window handle m_hwnd = hwnd; // Adjust the size of the display area AdjuesTWindowsize (iWidth, Iheight); Return True; } 7. Open GDisurface.h Enter the following code #ifndef __gdisurface_h__ #define __gdisurface_h__ #include Class CgdigraphicsDevice; / / The surface class is used to store a picture and use it to display pictures. Class CgDisurface { PUBLIC: // bit block transmission method ENUM SURFACEBLTMODE { BLT_BLOCK, // copy mode, completely displayed on the target BLT_ALPHATEST, / / transparent color detection method, if you encounter the pure blue in the RGB (0, 0, 255) pictures, skipping BLT_ALPHABLEND, // Not supported } CgDisurface (); Virtual ~ cgdisurface (); // Create a bitmap Bool Create (cgdigraphicsdevice * pdevice, int obileidth, int height); / / Read a bitmap from the file Bool loadbmp (cgdigraphicsdevice * pdevice, const char * szfilename); // Release bitmap Void release (); // Get wide INT getWidth (); // Get high Int getHeight (); // Get a bitmap device handle HDC getDC (); // Get a transparent channel bitmap device handle HDC getmaskdc (); / / Clear the surface as a color Void Clear (ColorRef C = RGB (0, 0, 0)); // Picture Void SetPixel (int X, int y, colorref c); // Picture Void Line (int X1, int y1, int x2, int y2, colorref c); // painted rectangle Void Rect (int X1, int y1, int x2, int y2, colorref c); // bitmap transmission Void Blt (cgdisurface * psurface, int x, int y, int RX, int in, int w, int h, surfacebltmode sbrmode); protected: // Surface width INT m_iwidth; // surface height Int m_iheight; // bit map handle Hbitmap m_hbitmap; // bitmap transparent channel graph handle Hbitmap m_hmaskbitmap; / / Save two bitmap sects Hbitmap m_holdbitmap; Hbitmap m_holdmaskbitmap; // Two equipment handles displayed // bitmap device handle HDC M_HDC; / / Transparent channel bitmap device handle HDC m_hmaskdc; } #ENDIF / / __GDISURFACE_H__ 8. Open GDISURFACE.CPP Enter the following code #include "gdisurface.h" #include "gdigraphicsdevice.h" CGDisurface :: cgdisurface () { m_iwidth = 0; m_iheight = 0; m_hbitmap = null; m_hmaskbitmap = null; m_holdbitmap = null; m_holdmaskbitmap = null; M_HDC = NULL; m_hmaskdc = NULL; } CGDisurface :: ~ cgdisurface () { } // Create a bitmap Bool CGDisurface :: Create (cgdigraphicsdevice * pdevice, int obileidth, int height) { Return True; } / / Read a bitmap from the file Bool cgdisurface :: loadbmp (cgdigraphicsdevice * pdevice, const char * szfilename) { Return True; } // Release bitmap Void cgdisurface :: release () { } // Get wide Int cgdisurface :: getWidth () { Return m_iwidth; } // Get high Int cgdisurface :: getHeight () { Return m_iheight; } // Get a bitmap device handle HDC CGDisurface :: getDC () { Return M_HDC; } // Get transparent channel bitmap equipment handle HDC CGDisurface :: getmaskdc () { Return m_hmaskdc; } / / Clear the surface as a color Void CGDisurface :: CLORREF C) { } // Picture Void CGDisurface :: SetPixel (int X, int y, colorref c) { } // Picture Void CGDisurface :: Line (int X1, int y1, int x2, int y2, colorref c) { } // painted rectangle Void CGDisurface :: RECT (INT X1, INT Y1, INT X2, INT Y2, ColorRef C) { } // bitmap transmission Void CGDisurface :: Blt (CGDisurface * psurface, int x, int y, int RX, int rt, int w, int h, bltmode immande) { } 10. Implement a bitmap // Create a bitmap Bool CGDisurface :: Create (cgdigraphicsdevice * pdevice, int obileidth, int height) { // Get the master window drawing device handle HWND HWND = PDEvice-> getWnd (); HDC HDCWindow = :: getdc (hwnd); // Create a graphic device handle M_HDC = :: CreateCompatibleDC (HDCWindow); m_hmaskdc = :: createcompatibledc (hdcwindow); // Create a bitmap and transparent bitmap M_Hbitmap = :: CreateCompatibleBitmap (HDCWindow, iWidth, IHEIGHT); m_hmaskbitmap = :: CreateBitmap (iWidth, Iheight, 1, 1, null); // Related equipment and bitmap handle m_holdbitmap = (hbitmap) :: selectObject (m_hdc, m_hbitmap); M_holdmaskbitmap = (hbitmap) :: selectObject (m_hmaskdc, m_hmaskbitmap); // Make a transparent channel bitmap :: setBkcolor (M_HDC, RGB (0,0,255)); :: Bitblt (m_hmaskdc, 0, 0, iWidth, Iheight, M_HDC, 0, 0, SRCCOPY); :: setBkcolor (M_HDC, RGB (0,0,0)); :: SetTextColor (M_HDC, RGB (255, 255, 255); :: Bitblt (M_HDC, 0, 0, IWidth, Iheight, M_HmaskDC, 0, 0, Srcand); / / Release the main window drawing handle :: ReleaseDC (HWND, HDCWindow); / / Save surface size m_iwidth = iWidth; m_iheight = iHEight; Return True; } 11. Implementation from the file read bitmap, method, method, and create bitmap, just in place map from the file to be read from the file. / / Read a bitmap from the file Bool cgdisurface :: loadbmp (cgdigraphicsdevice * pdevice, const char * szfilename) { // Read bitmap file information, determine the size of the bitmap FILE * fp = fopen (SZFileName, "RB"); if (null == fp) { OutputDebugstring ("Open BMP file [% s] failed (% s:% d)", szfilename, __file__, __line__); Return False; } BitmapfileHeader BMFH; BitmapInfoheader BMIH; Fread (& BMFH, SIZEOF (BitmapfileHeader), 1, FP); Fread (& BMIH, Sizeof (BitmapInfoHeader), 1, FP); Fclose (fp); // If it is not a bitmap, return failed IF (BMFH.BFTYPE! = 0x4d42) { OutputDebugstring ("The BMP file [% s] type is failed (% s:% d)", szfilename, __file__, __line__); Return False; } Hbitmap HBMP = (Hbitmap) :: loadImage (null, szfilename, image_bitmap, bmih.biwidth, bmih.biheight, lr_luadfromfile | lr_createdibsection); m_iwidth = bmih.biwidth; m_iheight = bmih.biheight; HWND HWND = PDEvice-> getWnd (); HDC HDCWindow = :: getdc (hwnd); M_Hbitmap = :: CreateCompatibleBitmap (HDCWindow, M_iWidth, M_iHeight); m_hmaskbitmap = :: createBitmap (m_iwidth, m_iheight, 1, 1, null); HDC HTEMPDC = :: CreateCompatibledc (HDCWINDOW); M_HDC = :: CreateCompatibleDC (HDCWindow); m_hmaskdc = :: createcompatibledc (hdcwindow); Hbitmap Holdbitmap = (Hbitmap) :: SelectObject (HTEMPDC, HBMP); m_holdbitmap = (hbitmap) :: selectObject (m_hdc, m_hbitmap); M_holdmaskbitmap = (hbitmap) :: selectObject (m_hmaskdc, m_hmaskbitmap); :: Bitblt (M_HDC, 0, 0, M_IWidth, M_iHeight, HTEMPDC, 0, 0, Srccopy); :: setBkcolor (M_HDC, RGB (0,0,255)); :: Bitblt (m_hmaskdc, 0, 0, m_iwidth, m_iheight, m_hdc, 0, 0, srcopy); :: setBkcolor (M_HDC, RGB (0,0,0)); :: SetTextColor (M_HDC, RGB (255, 255, 255); :: Bitblt (m_hdc, 0, 0, m_iwidth, m_iheight, m_hmaskdc, 0, 0, srcand); :: SelectObject (HTEMPDC, Holdbitmap); DeleteDC (HTEMPDC); DeleteObject (HBMP); :: ReleaseDC (HWND, HDCWindow); Return True; } 12. Realize the release bitmap // Release bitmap Void cgdisurface :: release () { :: SelectObject (m_hdc, m_holdbitmap); :: SelectObject (m_hmaskdc, m_holdmaskbitmap); :: deletedc (m_hmaskdc); :: Deletedc (m_hdc); :: DeleteObject (m_hbitmap); :: DeleteObject (m_hmaskbitmap; } 13. Implement 4 basic drawing operations / / Clear the surface as a color Void CGDisurface :: CLORREF C) { // Create a padding brush Hbrush Hbrush = Createsolidbrush (C); // Fill the entire surface Rect Rect = {0, 0, M_IWidth, M_iHeight}; FillRect (M_HDC, & Rect, Hbrush); // Release the brush DeleteObject (Hbrush); } // Picture Void CGDisurface :: SetPixel (int X, int y, colorref c) { :: setPixel (M_HDC, X, Y, C); } // Picture Void CGDisurface :: Line (int X1, int y1, int x2, int y2, colorref c) { HPEN HPEN = Createpen (PS_SOLID, 1, C); HPEN HOLDPEN = SELECTPEN (M_HDC, HPEN); MoveToex (M_HDC, X1, Y1, (LPPOINT) NULL); LINETO (M_HDC, X2, Y2); SELECTPEN (M_HDC, HoldPen); Deletepen (HPEN); } // painted rectangle Void CGDisurface :: RECT (INT X1, INT Y1, INT X2, INT Y2, ColorRef C) { // draw 4 line rectangular border LINE (X1, Y1, X2, Y1, C); LINE (x1, y2, x2, y2, c); LINE (X1, Y1, X1, Y2, C); LINE (X2, Y1, X2, Y2, C); } 14. Implement a bitmap transmission function // bitmap transmission Void CGDisurface :: Blt (CGDisurface * psurface, int x, int y, int RX, int rt, int w, int h, bltmode immande) { HDC HDCDST = Psurface-> getdc (); Switch (Imode) { Case blt_block: // Basic copy mode transmission bitmap Bitblt (HDCDST, X, Y, W, H, M_HDC, RX, RY, SRCCOPY); Break; Case Blt_alphatest: // Transparent color method transfer bitmap Setbkcolor (HDCDST, RGB (255, 255, 255); SetTextColor (HDCDST, RGB (0,0,0)); Bitblt (HDCDST, X, Y, W, H, M_HmaskDC, RX, RY, SRCAN); Bitblt (HDCDST, X, Y, W, H, M_HDC, RX, RY, SRCPAINT); BREAK; Case Blt_alphablend: Break; } } 15. Open GDIGRAPHICSDEVICE.H to join the following code #ifndef __gdigraphicsdevice_h__ #define __gdigraphicsDevice_h__ #include Class cgdisurface; // Drawing equipment, here is the device that can be displayed on the screen, which is virtual, // We call it graphic device. Class CGDIGRAPHICSDEVICE { PUBLIC: CGDIGRAPHICSDEVICE (); Virtual ~ cgdigraphicsdevice (); // Create a device, let the device operate object point to a window Bool Create (HWND HWND, IWIDTH, INT IHEIGHT); // Release device Void release (); / / Update the display, make the main surface content on the screen Void UpdateFrame (HDC HDC); // Get the window of the operation pointing HWND getWnd (); // Get the main surface CGDisurface * getMainSurface (); protected: // Adjust the window size Void AdjuestWindowsize (int ingidth, int height); protected: // Operate the window handle HWND M_HWND; // live down to the surface CGDisurface * m_pmainsurface; } #ENDIF / / __GDIGRAPHICSDEVICE_H__ 16. Open GDIGRAPHICSDEVICE.CPP to modify and add the following code #include "gdigraphicsdevice.h" #include "gdisurface.h" CGDIGRAPHICSDEVICE :: cgdigraphicsdevice () { m_hwnd = NULL; m_pmainsurface = null; } CGDIGRAPHICSDEVICE :: ~ cgdigraphicsDevice () { } // Create a device, let the device operate object point to a window Bool CgdigraphicsDevice :: Create (HWND HWND, INT IWIDTH, IHEIGHT) { / / Save the window handle m_hwnd = hwnd; // Adjust the size of the display area AdjuesTWindowsize (iWidth, Iheight); M_PMAINSURFACE = New CGDisurface (); Return True; } // Release device Void cgdigraphicsDevice :: release () { Delete m_pmainsurface; m_pmainsurface = null; } 17. Add to get the main surface function // Get the main surface CGDisurface * cgdigraphicsDevice :: getmainsurface () { Return m_pmainsurface; } 18. Add to create a main surface // Create a device, let the device operate object point to a window Bool CgdigraphicsDevice :: Create (HWND HWND, INT IWIDTH, IHEIGHT) { / / Save the window handle m_hwnd = hwnd; // Adjust the display area size AdjuestWindowsize (iWidth, Iheight); M_PMAINSURFACE = New CGDisurface (); IF (! m_pmainsurface-> create (this, iWidth, Iheight)) { OutputDebugstring (FSTR ("GraphicsDevice Create Main Surface Failed"); Return False; } Return True; } // Release device Void cgdigraphicsDevice :: release () { m_pmainsurface-> release (); Delete m_pmainsurface; m_pmainsurface = null; } 19. Add update display function function / / Update the display, make the main surface content on the screen Void CGDIGRAPHICSDEVICE :: UpdateFrame (HDC HDC) { // Returns if the main surface is not created successfully IF (NULL == m_pmainsurface) Return; HDC HDCSRC = m_pmainsurface-> getdc (); INT iWidth = m_pmainsurface-> getWidth (); Int Iheight = m_pmainsurface-> getHeight (); / / Update the display to the screen will be called by WM_Paint Bitblt (HDC, 0, 0, IWidth, Iheight, HDCSRC, 0, 0, SRCCopy); } 20. In order to facilitate our joining a global data definition file on the project TANK, you can define a very public or important global variable here. And join two files sharedata.h sharedata.cpp 21. Open Sharedata.h Add to Code below #ifndef __sharedata_h__ #define __sharedata_h__ #include "gdigraphicsdevice.h" #include "gdisurface.h" #include "gditextrender.h" Extern CGDIGRAPHICSDEVICE * THEGRAPHICSDEVICE; #ENDIF / / __SHAREDATA_H__ 22. Open Sharedata.cpp Add below the code #include "sharedata.h" CGDIGRAPHICSDEVICE * THEGRAPHICSDEVICE = NULL; 23. Open the following code in the appgame.cpp #include "appgame.h" #include "sharedata.h" CGDisurface. / / Define the primary game program instance Cappgame theappgame; 24. Add the following code, create // Initializer Bool Cappgame :: Initialize (Hinstance Hinstance, HWND HWND) { M_HINSTANCE = Hinstance; m_hwnd = hwnd; // Create a graphics device THEGRAPHICSDEVICE = New CGDIGRAPHICSDEVICE (); IF (! THEGRAPHICSDEVICE-> CREATE (M_HWnd, WindowWidth (), WindowHeight ())) { OutputDebugstring ("CREATE GraphicsDevice Failed); Return False; } // Read bitmap IF (! THESURFACE.LOADBMP (THEGRAPHICSDEVICE, "ImageC.BMP")) { OutputDebugstring ("Load Bitmap Failed"); Return False; } Return True; } // End the program void cappgame :: terminal () { // Release bitmap Thessace.release (); / / Release graphics equipment THEGRAPHICSDEVICE-> Release (); DELETE THEGRAPHICSDEVICE; } 25. Modify the following code to display the read picture // Main processing function Void cappgame :: process () { Render (); } // Main rendering function Void cappgame :: render () { // Display bitmap THESURFACE.BLT (THEGRAPHICSDEVICE-> GetMainSurface (), 0, 0, 0, 0, WindowWidth (), WindowHeight (), CGDisurface :: blt_block; } 26. Add to update display code in the message processing function // Main window message processing function LRESULT CAPPGAME :: WndProc (uint message, wparam wparam, lparam lparam) { HDC HDC; Paintstruct PS; Switch (Message) { Case WM_Paint: { HDC = beginpaint (m_hwnd, & ps); IF (THEGRAPHICSDEVICE) { // Call graphics device update display THEGRAPHICSDEVICE-> UPDATEFRAME (HDC); } Endpaint (M_HWND, & PS); } Return True; Case WM_ERASEBKGND: Return True; } Return False; } 27. Join the update display notification in Cappgame :: Render () // Main rendering function Void cappgame :: render () { // Display bitmap THESURFACE.BLT (THEGRAPHICSDEVICE-> GetMainSurface (), 0, 0, 0, 0, WindowWidth (), WindowHeight (), CGDisurface :: blt_block; / / Notify the Window program to update the display window Rect rcwindow; GetClientRect (M_HWND, & RCWINDOW); RedrawWindow (M_HWND, & RCWINDOW, NULL, RDW_INVALIDATE); } 28. Operating procedures can see the following effects 29. Add the following code in Cappgame :: Render () // Main rendering function Void cappgame :: render () { / / Clear the main surface ThegraphicsDevice-> GetMainSurface () -> Clear (RGB (125, 0, 23)); // Display bitmap THESURFACE.BLT (THEGRAPHICSDEVICE-> GetMainSurface (), 0, 0, 0, 0, WindowWidth (), WindowHeight (), cgdisurface :: blt_block; // Notify the Window program to update the display window Rect rcwindow; GetClientRect (M_HWND, & RCWINDOW); RedrawWindow (M_HWND, & RCWINDOW, NULL, RDW_INVALIDATE); } Everyone can see the following effects 30. Modify CAPPGAME :: Render () to Void cappgame :: render () { / / Clear the main surface ThegraphicsDevice-> GetMainSurface () -> Clear (RGB (125, 0, 23)); // Display bitmap S &urface.blt (THEGRAPHICSDEVICE-> GetMainSurface (), 0, 0, 0, 0, WindowWidth (), WindowHeight (), cgdisurface :: blt_alphates; / / Notify the Window program to update the display window Rect rcwindow; GetClientRect (M_HWND, & RCWINDOW); RedrawWindow (M_HWND, & RCWINDOW, NULL, RDW_INVALIDATE); } Can see the following effects There is no blue blue, and the method is changed to transparent way. 31. We change thesurface to theimagec and put it in sharedata.cpp to define it for easy use. // Initializer Bool Cappgame :: Initialize (Hinstance Hinstance, HWND HWND) { M_HINSTANCE = Hinstance; m_hwnd = hwnd; // Create a graphics device THEGRAPHICSDEVICE = New CGDIGRAPHICSDEVICE (); IF (! THEGRAPHICSDEVICE-> Create (m_hwnd, windowwidth (), windowheight ()))) { OutputDebugstring ("CREATE GraphicsDevice Failed); Return False; } // Read bitmap Theimagec = new cgdisurface (); IF (! theimagec-> loadingbmp (thegraphicsdevice, "imagec.bmp"))) { OutputDebugstring ("Load Bitmap Failed"); Return False; } Return True; } // End the program void cappgame :: terminal () { // Release bitmap Theimagec-> Release (); DELETE theIMAGEC; Theimagec = NULL; / / Release graphics equipment THEGRAPHICSDEVICE-> Release (); DELETE THEGRAPHICSDEVICE; ThegraphicsDevice = NULL; } // Main processing function Void cappgame :: process () { Render (); } // Main rendering function Void cappgame :: render () { / / Clear the main surface THEGRAINSDEVICE-> GetMainSurface () -> Clear (RGB (125, 0, 23)); // Display bitmap THEIMAGEC-> BLT (THEGRAPHICSDEVICE-> GetMainSurface (), 0, 0, 0, 0, Windowwidth (), WindowHeight (), cgdisurface :: blt_alphatest); / / Notify the Window program to update the display window Rect rcwindow; GetClientRect (M_HWND, & RCWINDOW); RedrawWindow (M_HWND, & RCWINDOW, NULL, RDW_INVALIDATE); } Chapter 4 Text Display Timer Refresh Rate Some important information when writing programs, help debug programs, where text is very important. Timer We will use the system function TimegetTime (), which is used to get the system from the beginning to the milliseconds experienced, record a start time, and then constantly judgment the current time and start time interval to achieve a certain paragraph The code is performed at a certain frequency. The refresh rate is to indicate how many times the update is displayed within a second, and finally we display it on the screen. 1. Open GDITEXTRENDER.H Enter the following code #ifndef __gditextRender_H__ #define __gditextRender_H__ #include Class cgdisurface; // Text display class Class CgditeXtrender { PUBLIC: CGDiteXtrender (); Virtual ~ cgditeXtrender (); // Create a font Bool Create (PLogFont Pfont); // freed Void release (); / / Output text to the surface Void textout (CGDisurface * psurface, int x, int y, const char * szstring, colorref c, int LEN = 0); protected: // font handle HFONT M_HFONT; } #ENDIF / / __GDITEXTRENDER_H__ 2. Open GDITEXTRENDER.CPP to enter the following code #include "gditextrender.h" CGDiteXtrender :: cgditextRender () { M_HFONT = NULL; } CGDITEXTRENDER :: ~ cgditextrender () { } // Create a font Bool CGDITEXTRENDER :: Create (Plogfont Pfont) { Return True; } // freed Void cgditeXtrender :: release () { } / / Output text to the surface Void CGDiteXtrender :: Textout (CGDisurface * Psurface, Int x, int y, const char * szstring, colorref c, int LEN) { } 3. Implement the creation of font functions // Create a font Bool CGDITEXTRENDER :: Create (Plogfont Pfont) { // Create a font specified by PFont m_hfont = cretefont Pfont-> lfheight, PFONT-> LFWIDTH, Pfont-> LFESCAPEMENT, PFONT-> LirtIntation, Pfont-> LFWeight, Pfont-> lfitalic, PFONT-> Lfunderline, PFONT-> LFSTRIKEOUT, Pfont-> lfcharset, Pfont-> lfoutPrecision, PFONT-> LFCLIPPRecision, PFONT-> LFQuality, Pfont-> LFPITCHFAMILY, PFONT-> LFFCENAME); IF (m_hfont == null) { Outputdebugstring (FSTR ("Create Font Failed:% S% D / N", PFONT-> LFFACENAME, PFONT-> LFHEIGHT); Return False; } Return True; } 4. Realize the release font // freed Void cgditeXtrender :: release () { // If the font has been created IF (m_hfont) { // Delete the font handle DeleteObject (M_HFONT); M_HFONT = NULL; } } 5. Modify the text output function, join the output text function #include "gditextrender.h" #include "gdisurface.h" #include "formatstring.h" #include / / Output text to the surface Void CGDiteXtrender :: Textout (CGDisurface * Psurface, Int x, int y, const char * szstring, colorref c, int LEN) { / / If the specified string length is 0 IF (len == 0) { // Automatically get strings length Len = (int) Strlen (szstring); } // Get a surface device handle HDC HDC = psurface-> getDC (); // Select the font HFONT HOLDFONT = SELECTFONT (HDC, M_HFONT); // Show text SetBKMode (HDC, Transparent); SetBkcolor (HDC, RGB (0, 0)); SetTextColor (HDC, C); :: Textout (HDC, X, Y, Szstring, Len); // Restore the font SELECTFONT (HDC, HoldFont); } 6. Open Sharedata.h Add to Code #ifndef __sharedata_h__ #define __sharedata_h__ #include "gdigraphicsdevice.h" #include "gdisurface.h" #include "gditextrender.h" Extern CGDIGRAPHICSDEVICE * THEGRAPHICSDEVICE; EXTERN CGDISURFACE *. Extern CGDITEXTRENDER * THHETEXTRENDER; #ENDIF / / __SHAREDATA_H__ 7. Open Sharedata.cpp to add the following code #include "sharedata.h" CGDIGRAPHICSDEVICE * THEGRAPHICSDEVICE = NULL; CGDisurface * theimagec = null; cgditeXtrender * ThetExTrender = NULL; 8. Open AppGame.cpp to join the initialization text output function and release // Initializer Bool Cappgame :: Initialize (Hinstance Hinstance, HWND HWND) { M_HINSTANCE = Hinstance; m_hwnd = hwnd; // Create a graphics device THEGRAPHICSDEVICE = New CGDIGRAPHICSDEVICE (); IF (! THEGRAPHICSDEVICE-> Create (m_hwnd, windowwidth (), windowheight ()))) { OutputDebugstring ("CREATE GraphicsDevice Failed); Return False; } // Read bitmap Theimagec = new cgdisurface (); IF (! theimagec-> loadingbmp (thegraphicsdevice, "imagec.bmp"))) { OutputDebugstring ("Load Bitmap Failed"); Return False; } // Initialize the text output function Logfont fontinfo = {16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, Default_charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, Variable_pitch, "体"} Thetrender = new cgditextrender (); IF (! Thetrender-> Create (& FONTINFO)) { OutputDebugstring ("Create Thetrender Failed / N); Return False; } Return True; } // End the program void cappgame :: terminal () { // Release the text output function Thetextrender-> Release (); Delete thetextrender; ThetRender = NULL; // Release bitmap Theimagec-> Release (); DELETE theIMAGEC; Theimagec = NULL; / / Release graphics equipment THEGRAPHICSDEVICE-> Release (); DELETE THEGRAPHICSDEVICE; ThegraphicsDevice = NULL; } 9. Do the following modifications in the Cappgame :: Render () function to test the text output function // Main rendering function Void cappgame :: render () { CGDisurface * pscreen = THEGRAPHICSDEVICE-> getMainSurface (); / / Clear the main surface Pscreen-> Clear (RGB (125, 0, 23)); // Display bitmap Theimagec-> BLT (Pscreen, 0, 0, 0, 0, WindowWidth (), WindowHeight (), CGDisurface :: blt_alphatest); // Show text TEXTRENDER-> Textout (pscreen, 0, 0, "test text ABC", RGB (255, 255, 255)); // Notify the Window program update display window Rect rcwindow; GetClientRect (M_HWND, & RCWINDOW); RedrawWindow (M_HWND, & RCWINDOW, NULL, RDW_INVALIDATE); } See the following results 10. Add fps.cpp fps.h in the TANK project uTility catalog. 11. Open FPS.H Enter the following code #ifndef __fps_h__ #define __fps_h__ #include // FPS class Class CFPS { PUBLIC: CFPS (); Virtual ~ cfps (); // Statistics, no one counter plus 1 and determine if the calculation FPS Void count (); // Get fps INT getfps (); protected: // Record refresh rate INT m_IFPS; // Statistics Int m_icount; // Time to record the FPS last time DWORD M_DWPREVRECORDFPSTIME; / / Calculate the FPS time interval DWORD M_DWRECORDFPSINTERVAL; } #ENDIF / / __FPS_H__ 12. Open fps.cpp Enter the following code #include "fps.h" #include #pragma comment (Lib, "Winmm.Lib") CFPS :: cfps () { m_icount = 0; m_ifps = 0; m_dwprevrecordfpstime = 0; m_dwrecordfpsinterval = 1000; // 1 second record } CFPS :: ~ cfps () { } Void cfps :: count () { // No call once m_icount ; // If time has passed 1000 milliseconds IF (TimegetTime () - m_dwprevrecordfpstime> = m_dwrecordfpsInterval { // Record 1 second call number m_ifps = m_icount; // Reset Counter m_icount = 0; // Reset start timing time m_dwprevrecordfpstime = TimegetTime (); } } Int cfps :: getfps () { Return M_IFPS; } 13. Add the following code in Sharedata.h and Sharedata.cpp, respectively. Sharedata.h: #ifndef __sharedata_h__ #define __sharedata_h__ #include "gdigraphicsdevice.h" #include "gdisurface.h" #include "gditextrender.h" #include "fps.h" Extern CGDIGRAPHICSDEVICE * THEGRAPHICSDEVICE; EXTERN CGDISURFACE *. Extern CGDITEXTRENDER * THHETEXTRENDER; EXTERN CFPS * THHENDERFPS; #ENDIF / / __SHAREDATA_H__ Sharedata.cpp: #include "sharedata.h" cgdigraphicsdevice * thegraphicsdevice = null; CGDisurface * theimagec = null; CGDiteXtrender * thetextrender = NULL; Cfps * therenderfps = NULL; 14. Add the following code to Cappgame :: Initialize () and Cappgame :: Terminal () in AppGame.cpp Thetrender = new cgditextrender (); IF (! Thetrender-> Create (& FONTINFO)) { OutputDebugstring ("Create Thetrender Failed / N); Return False; } // Create a rendering refresh rate statistical device Therenderfps = new cfps (); Return True; } // End the program void cappgame :: terminal () { / / Release Rendering Refunction Statist Delete arenderfps; // Release the text output function Thetextrender-> Release (); 15. Add refresh rate statistics in the cappgame :: render () function and display it on the screen, and AppGame.cpp tops Add to #include "formatstring.h" // Main rendering function Void cappgame :: render () { CGDisurface * pscreen = THEGRAPHICSDEVICE-> getMainSurface (); / / Clear the main surface Pscreen-> Clear (RGB (127, 127, 127)); // Display bitmap // Theimagec-> BLT (Pscreen, 0, 0, 0, 0, WindowWidth (), WindowHeight (), CGDisurface :: blt_alphatest); // Show text TEXTRENDER-> Textout (Pscreen, 0, 0, FSTR ("FPS =% 2D", therenderfps-> getfps ()), RGB (255, 255, 255); / / Notify the Window program to update the display window Rect rcwindow; GetClientRect (M_HWND, & RCWINDOW); RedrawWindow (M_HWND, & RCWINDOW, NULL, RDW_INVALIDATE); Therenderfps-> count (); } The operation program sees the following effects 16. In order to give the CPU more time, we don't need a program to run very fast, how we limit the rendering speed, open AppGame.h to add the following code, then run the FPS is already 30 protected: / / Save the main program handle Hinstance M_HINSTANCE; / / Save the main window handle HWND M_HWND; // last rendering time DWORD M_DWRENDERLASTTIME; } 17. Add to the main rendering function // Main rendering function Void cappgame :: render () { IF (timegettime () - m_dwrenderlasttime <33) { Return; } m_dwrenderlasttime = timegettime (); Chapter 5 Elf Animation Small people who ran around in the game, puppy, tank, etc. As shown in Figure 28x28 size, a piece of film is a picture of the elf animation. The next one is the second, we call each picture, we say that the top of Tank is 2 frames. In our project, we define the framework method is to record a graphic location and size. As shown in Figures x, y, w, h show a frame. 1. Add a directory Animation in the TANK project, and add 6 files frame.h Frame.cpp Animation.h Animation.cpp SpriteManager.h SpriteManager.cpp 2. Add frame class code in frame.h and frame.cpp Frame.h: #ifndef __frame_h__ #define __frame_h__ #include "gdisurface.h" // Animation frame class Class cframe { PUBLIC: / / Location and size on ImageC INT M_IX; INT m_iy; INT m_iw; INT M_IH; // Rendering to the surface Void Render (CGDisurface * psurface, int ix, int y, cgdisurface :: bltmode immande); } #ENDIF / / __FRAME_H__ Frame.cpp: #include "frame.h" #include "sharedata.h" // Rendering to the surface Void Cframe :: Render (cgdisurface * psurface, int ix, int y, cgdisurface :: bltmode ivode) { Theimagec-> BLT (Psurface, IX, IY, M_IX, M_IY, M_IW, M_IH, IMODE); } 3. Open Animation.h Enter the following code #ifndef __animation_h__ #define __animation_h__ #include "frame.h" #include // animation class Class Canimation { PUBLIC: CANIMATION (); Virtual ~ canimation (); // Add frame Void Push (CFrame & F); // Get the number of frames INT getMaxFrame (); // Get a frame data Cframe * getframe (int iframe); protected: // frame data Std :: Vector } #ENDIF / / __ANAMATION_H___ 4. Open Animation.cpp Enter the following code #include "animation.h" CANIMATION :: canimation () { m_vectorframe.clear (); } CANIMATION :: ~ canimation () { m_vectorframe.clear (); } // Add frame Void CANIMATION :: Push (cframe & f) { m_vectorframe.push_back (f); } // Get the number of frames INT canIMation :: getmaxframe () { Return (int) m_vectorframe.size (); } // Get a frame data Cframe * canimation :: getFrame (int iframe) { IF (iframe <0 &&ness> = (int) m_vectorframe.size ()) Return NULL; Return & M_VectorFrame [iframe]; } 5. Open SpriteManager.h Enter the following code #ifndef __spritemanager_h__ #define __SpriteManager_H__ #include "animation.h" Class CspriteManager { PUBLIC: CSPriteManager (); Virtual ~ cspritemanager (); // Create an animation data set Bool crete (); // Release the animation data set Void release (); // Get animated data CANIMATION * GetAnimation (int INDEX); // Total animation Int getAnimationNumber (); protected: // Store animation data Std :: Vector } #ENDIF / / __SPRITEMANAGER_H__ 6. Open SpriteManager.cpp Enter the following code #include "spritemanager.h" CSPRITEMANAGER :: CSPriteManager () { } CSPriteManager :: ~ cspritemanager () { } // Create an animation data set Bool cspritemanager :: create () { Return True; } // Release the animation data set Void CspriteManager :: release () { m_vectoranimation.clear (); } // Get animated data Canimation * CSPRITEMANAGER :: GetAnimation (int index) { IF (Index <0 || index> = (int) m_vectoranimation.size ()) Return NULL; // Return to the animation referred to in INDEX Return & M_VectoraniMation [index]; } // Total animation Int cspritemanager :: getAnimationNumber () { Return (int) m_vectoranimation.size (); } 7. Add the first animation in CSPRITEMANAGER :: Create (), the animation may also have only one frame. Below is the first two frames to 0 animations. The same method can be added to all animations in this function. // Create an animation data set Bool cspritemanager :: create () { CANIMATION * PANI; Cframe F; // First animation PANI = New canimation (); // First frame (0, 0, 28, 28) f.m_ix = 0; F.m_iy = 0; f.m_iw = 28; F.m_ih = 28; PANI-> Push (f); // Second frame (28, 0, 28, 28) f.m_ix = 28; F.m_iy = 0; f.m_iw = 28; F.m_ih = 28; PANI-> Push (f); // ani id = 0 two frame animations joining animation library m_vectoranimation.push_back (* pani); delete PANI; Return True; } 8. Add the following code in Sharedata.h Sharedata.cpp, respectively Sharedata.h: #ifndef __sharedata_h__ #define __sharedata_h__ #include "gdigraphicsdevice.h" #include "gdisurface.h" #include "gditextrender.h" #include "fps.h" #include "spritemanager.h" Extern CGDIGRAPHICSDEVICE * THEGRAPHICSDEVICE; EXTERN CGDISURFACE *. Extern CGDITEXTRENDER * THHETEXTRENDER; EXTERN CFPS * THHENDERFPS; Extern CSPRITEMANAGER * SHESPRITEMANAGER; #ENDIF / / __SHAREDATA_H__ Sharedata.cpp: #include "sharedata.h" CGDIGRAPHICSDEVICE * THEGRAPHICSDEVICE = NULL; CGDisurface * theimagec = null; CGDiteXtrender * thetextrender = NULL; Cfps * therenderfps = NULL; CSPRITEMANAGER * SHESPRITEMANAGER = NULL; 9. Add the following initialization and release animator code in AppGame.cpp Thetrender = new cgditextrender (); IF (! Thetrender-> Create (& FONTINFO)) { OutputDebugstring ("Create Thetrender Failed / N); Return False; } // Create a rendering refresh rate statistical device Therenderfps = new cfps (); // Create an animation manager ThessiTemanager = new cspritemanager (); IF (! thispritemanager-> create ()) { OutputDebugstring ("Create Sprite Manager Failed / N); Return False; } Return True; } // End the program void cappgame :: terminal () { // Release the animator manager Thespritemanager-> release (); DELETE S &PRITEMANAGER; ThesspriteManager = NULL; 10. In the Cappgame :: Render (), make the following modifications to display a frame of an animation. / / Clear the main surface Pscreen-> Clear (RGB (127, 127, 127)); // Display bitmap // theimagec-> BLT (Pscreen, 30, 30, 0, 0, WindowWidth (), WindowHeight (), cgdisurface :: blt_alphates; // Show a frame of an animation Canimation * Pani = thispriteManager-> GetAnimation (0); Cframe * pf = pani-> getframe (0); PF-> Render (Pscreen, 100, 100, CGDisurface :: blt_alphates); // Show text TEXTRENDER-> Textout (Pscreen, 0, 0, FSTR ("FPS =% 2D", therenderfps-> getfps ()), RGB (255, 255, 255); Everyone can see that the display is that a TANK is displayed on the screen. 10. The next task is to bring these animations to use it in order. According to the following figure, we can see that this group of pictures is very regular, this is an animation in the four directions of every TANK, I wrote a loop to create an animation in the cspritemanager.cpp create () function in the cspritemanager.cpp code () function Add initialization Code // Create an animation data set Bool cspritemanager :: create () { CANIMATION * PANI; Cframe F; // All Tank images are 28x28 f.m_iw = 28; F.m_ih = 28; // Two groups of animations, the top is player tank, below is local TANK. For (int K = 0; k <2; k ) { // There are 8 TANK animations in each large group. For (int L = 0; l <8; l ) { // Each Tank has four directions in 4 directions For (int J = 0; j <4; j ) { PANI = New canimation (); / / 2 frames in each direction For (int i = 0; i <2; i ) { f.m_ix = l * 28 * 2 i * 28; F.m_iy = k * 28 * 4 j * 28; PANI-> Push (f); } m_vectoranimation.push_back (* PANI); Delete Pani; } } } // The animation positioning formula is: Animation ID = Tank Model * 4 Direction Return True; } 11. Add and modify the code in CappGame :: Render (), run the program to see the Tank walking animation, randomly change a TANK every 2 seconds // Display bitmap // theimagec-> BLT (Pscreen, 30, 30, 0, 0, WindowWidth (), WindowHeight (), cgdisurface :: blt_alphates; // Current frame Static int icrframe = 0; // Movie meter start time Static dword dwanistarttime = timegettime (); // Current animation ID Static int icsurani = 0; // The last time to change the movie Static DWord dwanichangeLastTime = TimegetTime (); IF (TimegetTime () - DwanichangeLastTime> 2000) { Icurani = rand ()% 64; DwanichangeLastTime = TimegetTime (); } IF (TimegetTime () - DWANISTATTIME> 33) { ICURFRAME ; If (icrframe> = 2) Icurframe = 0; DwanistartTime = TimegetTime (); // Show a frame of an animation CANIMATION * PANI = TheSpriteManager-> GetAnimation (iCurani); Cframe * pf = PANI-> getframe (icrframe); Pf-> Render (Pscreen, 100, 100, CGDisurface :: blt_alphates); Chapter VI Scenario