📄 main.cpp
字号:
//读入200个字符,如果碰到换行符结束,换行符被提取,但不放入szName中
LevelData.getline(szName,200); //读入游戏名字
// Read number of horizontal lines
LevelData >> g_nNoOfLevels; //提取游戏共有多少关卡
g_pLevel = new SLEVEL[g_nNoOfLevels]; //分配内存,每一关有一 SLEVEL 结构体,记录地图文件名和敌人的数目
if (g_pLevel == NULL)
return -1;
for (int nI = 0; nI < g_nNoOfLevels; nI++) {//g_nNoOfLevels关卡数目
LevelData >> g_pLevel[nI].szLevelFile; //提取迷宫地图文件名
LevelData >> g_pLevel[nI].nNoOfEnemys; //提取敌人的数目
}
//创建和显示应用程序主窗口,从资源载入加速键表
if( FAILED( WinInit( hInst, nCmdShow, &hWnd, &hAccel ) ) )
return FALSE;
//
if( FAILED( InitDirectDraw( hWnd ) ) ) //创建 DirectDraw8对象,创建所有表面,创建DirectSound 和DirectInput
{
MessageBox( hWnd, TEXT("DirectDraw init failed. ")
TEXT("The program will now exit. "), TEXT("Maze Test program"),
MB_ICONERROR | MB_OK );
return FALSE;
}
InitSprites();//初始化精灵
g_dwLastTick = timeGetTime();
while( TRUE )
{
// Look for messages, if none are found then
// update the state and display it
if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if( 0 == GetMessage(&msg, NULL, 0, 0 ) )//如果消息为WM_QUIT 则退出
{
// WM_QUIT was posted, so exit
FreeDirectDraw();
CoUninitialize(); //Closes the COM library on the current apartment, unloads all DLLs loaded
delete[] g_pLevel;
return (int)msg.wParam;
}
// Translate and dispatch the message
//The TranslateAccelerator function processes accelerator keys for menu commands.
//The function translates a WM_KEYDOWN or WM_SYSKEYDOWN message to a WM_COMMAND or WM_SYSCOMMAND message
//(if there is an entry for the key in the specified accelerator table)
//and then sends the WM_COMMAND or WM_SYSCOMMAND message directly to the appropriate window procedure.
//TranslateAccelerator does not return until the window procedure has processed the message.
if( 0 == TranslateAccelerator( hWnd, hAccel, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
else
{
if( g_bActive )
{
// Move the sprites, blt them to the back buffer, then
// flip or blt the back buffer to the primary buffer
if( FAILED( ProcessNextFrame( hWnd ) ) )//处理下一帧
{
SAFE_DELETE( g_pDisplay );
MessageBox( hWnd, TEXT("Displaying the next frame failed. ")
TEXT("The program will now exit. "), TEXT("Adv In Abt"),
MB_ICONERROR | MB_OK );
return FALSE;
}
}
else
{
// Go to sleep if we have nothing else to do
WaitMessage();
// Ignore time spent inactive
g_dwLastTick = timeGetTime();
}
}
}
}
//-----------------------------------------------------------------------------
// Name: WinInit()
// Desc: Init the window
// 初始化window:
//-----------------------------------------------------------------------------
HRESULT WinInit( HINSTANCE hInst, int nCmdShow, HWND* phWnd, HACCEL* phAccel )
{
WNDCLASSEX wc;
HWND hWnd;
HACCEL hAccel;
// Register the window class
wc.cbSize = sizeof(wc);
wc.lpszClassName = TEXT("AdvInAbatWndClass");
wc.lpfnWndProc = MainWndProc;
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.hInstance = hInst;
wc.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN) );
wc.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN) );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = 0;//MAKEINTRESOURCE(IDR_MENU);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
if( RegisterClassEx( &wc ) == 0 ) {//注册,如果失败输出信息
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, //Pointer to a buffer for the formatted (and null-terminated) message
0,
NULL
);
OutputDebugString( (LPCTSTR)lpMsgBuf);//debug时输出信息
// Free the buffer.
LocalFree( lpMsgBuf ); //释放
return E_FAIL;
}
// Load keyboard accelerators 从资源载入加速键
hAccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
// Calculate the proper size for the window given a client of 640x480
DWORD dwFrameWidth = GetSystemMetrics( SM_CXSIZEFRAME ); //边框的线宽度 比如 3个点
DWORD dwFrameHeight = GetSystemMetrics( SM_CYSIZEFRAME ); //边框的线高度
DWORD dwMenuHeight = GetSystemMetrics( SM_CYMENU ); //菜单的高度
DWORD dwCaptionHeight = GetSystemMetrics( SM_CYCAPTION ); //标题栏的高度
DWORD dwWindowWidth = SCREEN_WIDTH + dwFrameWidth * 2; //窗口的宽度=屏幕+两倍边框线宽
DWORD dwWindowHeight = SCREEN_HEIGHT + dwFrameHeight * 2 +
dwMenuHeight + dwCaptionHeight;
// Create and show the main window
// 创建和显示主窗口
DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX; //没有最大化按钮
hWnd = CreateWindowEx( 0, TEXT("AdvInAbatWndClass"), //class name
TEXT("Maze Test program"), //标题
dwStyle, CW_USEDEFAULT, CW_USEDEFAULT,
dwWindowWidth, dwWindowHeight, NULL, NULL, hInst, NULL );
if( hWnd == NULL )
return E_FAIL;
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// Save the window size/pos for switching modes
GetWindowRect( hWnd, &g_rcWindow ); //g_rcWindow 全局变量,为窗口的大小
*phWnd = hWnd; //返回创建的主窗口的指针
*phAccel = hAccel; //返回加速键表的指针
g_hMainWnd = hWnd; //使用全局变量记录应用程序主窗口的句柄
return S_OK;
}
HFONT GetGameFont() //设置游戏显示用字体
{
HFONT hFont ;
LOGFONT lf ;
lf.lfHeight = 40; //字高
lf.lfWidth = 20; //字宽
lf.lfEscapement = 0 ;
lf.lfOrientation = 0 ;
lf.lfWeight = 0 ;
lf.lfItalic = false ;
lf.lfUnderline = false;
lf.lfStrikeOut = false;
lf.lfCharSet = DEFAULT_CHARSET ;
lf.lfOutPrecision = 0 ;
lf.lfClipPrecision = 0 ;
lf.lfQuality = 0 ;
lf.lfPitchAndFamily = 0 ;
lstrcpy (lf.lfFaceName, "Times New Roman") ; //字体设置为 “Times New Roman”
hFont = CreateFontIndirect (&lf) ;
// hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
return hFont;
}
//-----------------------------------------------------------------------------
// Name: InitDirectDraw()
// Desc: Create the DirectDraw object, and init the surfaces
//-----------------------------------------------------------------------------
HRESULT InitDirectDraw( HWND hWnd )
{
HRESULT hr;
// Initialize all the surfaces we need
//初始化绘制模式,可为窗口模式或全屏模式(g_bWindowed=true ,false),创建所有的表面,当更改显示模式或设备丢失时会再被调用
if( FAILED( hr = InitDirectDrawMode( hWnd, g_bWindowed ) ) )
return hr;
// Create a static IDirectSound in the CSound class.
// Set coop level to DSSCL_PRIORITY, and set primary buffer
// format to stereo, 22kHz and 16-bit output.
g_pSoundManager = new CSoundManager(); //创建DirectSound8 的设备
if( FAILED(hr= g_pSoundManager->Initialize( hWnd, DSSCL_PRIORITY, 2, 22050, 16 ) ) )//优先级, 双声道, 采样频率22050,16 bit
{
MessageBox( 0, "Error initializing DirectSound. Game will now exit.",
"Game", MB_OK | MB_ICONERROR );
return hr;
}
g_pSoundManager->Create(&g_pPickupSound,"PickUp"); // 创建Csound g_pPickupSound ,加载PickUp 声音
g_pHandleInput = new SHandleInput(); //DirectInput 结构体
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InitDirectDrawMode()
// Desc: Called when the user wants to toggle between full-screen and windowed
// to create all the needed DDraw surfaces and set the coop level
//-----------------------------------------------------------------------------
HRESULT InitDirectDrawMode( HWND hWnd, BOOL bWindowed )
{
HRESULT hr;
LPDIRECTDRAWPALETTE pDDPal = NULL;
// Release all existing surfaces
SAFE_DELETE( g_pMazeSurface);
#ifdef DISPLAY_STATUS
SAFE_DELETE( g_pTextSurface );
#endif
SAFE_DELETE( g_pLifeTextSurface );
SAFE_DELETE( g_pScoreTextSurface );
SAFE_DELETE( g_pLevelTextSurface );
SAFE_DELETE( g_pSpriteSurface );
SAFE_DELETE ( g_pSplashSurface);
SAFE_DELETE( g_pDisplay );
//在满屏模式和窗口模式下,主页面和后台页面的创建方式是不同的
g_pDisplay = new CDisplay(); //CDisplay 为DirectX8.0 提供的一个类,封装了DirectDraw7的表面
//窗口模式
if( bWindowed )
{
if( FAILED( hr = g_pDisplay->CreateWindowedDisplay( hWnd, SCREEN_WIDTH,
SCREEN_HEIGHT ) ) )
return hr;
//CreateWindowedDisplay 创建了Window模式的DirectDraw7 对象,并创建了前后页面,设置了剪裁
// 在窗口方式中添加系统菜单
DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
dwStyle |= WS_SYSMENU;
SetWindowLong( hWnd, GWL_STYLE, dwStyle );//添加菜单属性
// Show the menu in windowed mode
#ifdef _WIN64 //64位
HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hWnd, GWLP_HINSTANCE );
#else
HINSTANCE hInst = (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE );//取得句柄
#endif
HMENU hMenu = LoadMenu( hInst, MAKEINTRESOURCE( IDR_MENU ) ); //从资源加载菜单:IDR_MENU
SetMenu( hWnd, hMenu ); //设置菜单
}
else//满屏独占显示模式
{
if( FAILED( hr = g_pDisplay->CreateFullScreenDisplay( hWnd, SCREEN_WIDTH,
SCREEN_HEIGHT, SCREEN_BPP ) ) ) //较窗口模式多了一个 SCREEN_BPP 参数
{
MessageBox( hWnd, TEXT("This display card does not support 640x480x8. "),
TEXT("DirectDraw Sample"), MB_ICONERROR | MB_OK );
return hr;
}
// 无效菜单
SetMenu( hWnd, NULL );
// 从窗口方式中删除系统菜单
/*
DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
dwStyle &= ~WS_SYSMENU;
SetWindowLong( hWnd, GWL_STYLE, dwStyle );
*/
}
//以上创建了前后台页面,设置了剪裁
//下面创建游戏的表面
// 创建一个页面,在上面绘制文本
#ifdef DISPLAY_STATUS
//创建用于显示游戏状态的页面
if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, (char*)g_szGameStatus, //字体NULL使用原来设置,g_szGameStatus:显示内容文字
RGB(0,0,0), RGB(255, 255, 0) ) ) ) //*背景* ,字体颜色
return hr;
#endif
HFONT hFont = GetGameFont(); //设置显示用字体
if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pLifeTextSurface, hFont, (char*)g_szLifeLeft,
RGB(0,0,0), RGB(255, 255, 0) ) ) ) //创建用于显示 LifeText 的表面
return hr;
if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore,
RGB(0,0,0), RGB(255, 255, 0) ) ) ) //创建用于显示分数的表面
return hr;
// Create a surface, and draw a bitmap resource on it. The surface must
// be newly created every time the screen mode is switched since it
// uses the pixel format of the primary surface
// Create a surface, and draw text to it.
if( FAILED( hr = g_pDisplay->CreateSurface( &g_pMazeSurface, SCREEN_WIDTH, SCREEN_HEIGHT) ))
return hr; //创建迷宫表面,设置表面的宽和高
if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pSpriteSurface, MAKEINTRESOURCE(IDB_SPRITE),0, 0) ))
return hr; //创建精灵表面,加载图形,由图形决定表面的宽和高,该图形上有所有的精灵各种状态的图案
g_pSpriteSurface->SetColorKey(RGB(0,0,0)); //设置透明色
g_Maze.Draw(g_pMazeSurface); //画迷宫
//以下为根据不同的状况加载不同的JPEG画面图像
if (g_nGameState == GAMESTATE_SPLASHSCREEN) { //封面
LoadJPEG(true, SPLASHFILENAME, &g_pSplashSurface); //加载JPEG 封面图像,如果该表面未创建,创建它
}
if (g_nGameState == GAMESTATE_CHOICE) { //游戏选项
LoadJPEG(true, CHOICEFILENAME, &g_pSplashSurface);
}
if (g_nGameState == GAMESTATE_GAMEOVERGOOD) { //游戏好的结束
LoadJPEG(true, GAMEOVERGOODFILENAME, &g_pSplashSurface);
}
if (g_nGameState == GAMESTATE_GAMEOVERBAD) { //游戏不好的结束
LoadJPEG(true, GAMEOVERBADFILENAME, &g_pSplashSurface);
}
if (g_nGameState == GAMESTATE_RUNNING){ //游戏进行中,创建关卡文字页面Level n
g_pDisplay->CreateSurfaceFromText( &g_pLevelTextSurface, hFont, g_Maze.GetName(),
RGB(0,0,0), RGB(255, 255, 0) ) ;
}
DeleteObject(hFont);
return S_OK;
}
inline bool IsHit(RECT& rc) //检测 rc矩形是否与迷宫壁碰撞
{
return g_Maze.IsHit(rc);
}
void BulletFindPath(CSprite* pSprite)
{
pSprite->SetState(ST_KILL);
}
void FindPath(CSprite* pSprite) //路径查找
{
//该函数设置精灵追逐玩家
int nH = rand()%2;
int nV = rand()%2;
int nNRnd = rand()%3; //0,1,2
if (nNRnd) { //三分之二概率,能够自动接近玩家
if (abs(g_pPlayerSprite->m_ptLocation.x - pSprite->m_ptLocation.x) > //精灵与玩家的x坐标差值较大
abs(g_pPlayerSprite->m_ptLocation.y - pSprite->m_ptLocation.y))
{ // x 靠拢
pSprite->m_Movement.m_dy = 0;
if (g_pPlayerSprite->m_ptLocation.x < pSprite->m_ptLocation.x) {
pSprite->m_Movement.m_dx= -1 * (rand()%2+1);
pSprite->SetState(ST_WALK_LEFT);
} else {
pSprite->m_Movement.m_dx= 1 * (rand()%2+1);
pSprite->SetState(ST_WALK_RIGHT);
}
} else { // y 靠拢
pSprite->m_Movement.m_dx = 0;
if (g_pPlayerSprite->m_ptLocation.y < pSprite->m_ptLocation.y) {
pSprite->m_Movement.m_dy= -1 * (rand()%2+1);
pSprite->SetState(ST_WALK_UP);
} else {
pSprite->m_Movement.m_dy= 1 * (rand()%2+1);
pSprite->SetState(ST_WALK_DOWN);
}
}
} else { //三分之一概率,随机乱走
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -