main.cpp

来自「VC游戏编程基础」· C++ 代码 · 共 1,966 行 · 第 1/4 页

CPP
1,966
字号
    DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
    hWnd = CreateWindowEx( 0, TEXT("AdvInAbatWndClass"), 
		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 );
	
    *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") ;
	
	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
    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();
	
    if( FAILED(hr= g_pSoundManager->Initialize( hWnd, DSSCL_PRIORITY, 2, 22050, 16 ) ) )
    {
        MessageBox( 0, "Error initializing DirectSound.  Game will now exit.", 
			"Game", MB_OK | MB_ICONERROR );
        return hr;
    }
	
	g_pSoundManager->Create(&g_pPickupSound,"PickUp");
	g_pHandleInput = new SHandleInput();
	
    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();
	//窗口模式
    if( bWindowed )
    {
        if( FAILED( hr = g_pDisplay->CreateWindowedDisplay( hWnd, SCREEN_WIDTH, 
			SCREEN_HEIGHT ) ) )
            return hr;
		
        // 在窗口方式中添加系统菜单
        DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
        dwStyle |= WS_SYSMENU;
        SetWindowLong( hWnd, GWL_STYLE, dwStyle );
		
        // Show the menu in windowed mode 
#ifdef _WIN64
        HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hWnd, GWLP_HINSTANCE );
#else
        HINSTANCE hInst = (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE );
#endif
        HMENU hMenu = LoadMenu( hInst, MAKEINTRESOURCE( IDR_MENU ) );
        SetMenu( hWnd, hMenu );
    }
    else//满屏显示
    {
        if( FAILED( hr = g_pDisplay->CreateFullScreenDisplay( hWnd, SCREEN_WIDTH, 
			SCREEN_HEIGHT, 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, 
		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) ) ) )
		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);
	
	if (g_nGameState == GAMESTATE_SPLASHSCREEN) {
		LoadJPEG(true, SPLASHFILENAME,  &g_pSplashSurface);
	}
	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){
		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)
{
	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;
	if (nNRnd) {
		
		if (abs(g_pPlayerSprite->m_ptLocation.x - pSprite->m_ptLocation.x) > 
			abs(g_pPlayerSprite->m_ptLocation.y - pSprite->m_ptLocation.y))
			
		{
			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 {
			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 {
		if (nV) {	
			pSprite->m_Movement.m_dx = 0;
			if (nH) {
				pSprite->m_Movement.m_dy = 1 * (rand()%2+1);
				pSprite->SetState(ST_WALK_DOWN);
			} else {
				pSprite->m_Movement.m_dy = -1 * (rand()%2+1);
				pSprite->SetState(ST_WALK_UP);
			}
		} else {
			pSprite->m_Movement.m_dy = 0;
			if (nH) {
				pSprite->m_Movement.m_dx = 1 * (rand()%2+1);
				pSprite->SetState(ST_WALK_RIGHT);
			} else {
				pSprite->m_Movement.m_dx = -1 * (rand()%2+1);
				pSprite->SetState(ST_WALK_LEFT);
			}
			
		}
	}
	
	if (pSprite->GetType() == TYPE_ENEMY4) {
		if (g_BulletSprite.GetState() == ST_DEAD && pSprite->GetState() != ST_KILL 
			&& pSprite->GetState() != ST_DEAD) {
			RECT rc = pSprite->GetRect();
			g_BulletSprite.MoveTo(rc.left,rc.top);
			g_BulletSprite.SetState(ST_DEFAULT);
			switch (pSprite->GetState()) {
			case ST_WALK_UP:
				g_BulletSprite.m_Movement.m_dx =0;
				g_BulletSprite.m_Movement.m_dy = -3;
				break;
			case ST_WALK_DOWN:
				g_BulletSprite.m_Movement.m_dx =0;
				g_BulletSprite.m_Movement.m_dy = 3;
				break;
			case ST_WALK_LEFT:
				g_BulletSprite.m_Movement.m_dx =-3;
				g_BulletSprite.m_Movement.m_dy = 0;
				break;
			case ST_WALK_RIGHT:
				g_BulletSprite.m_Movement.m_dx =3;
				g_BulletSprite.m_Movement.m_dy = 0;
				break;
			}
		}
	}
}

void DeadPig(CSprite* pSprite)
{
	++g_nPigDead;
	--g_nLivesLeft;
#ifdef DISPLAY_STATUS
	wsprintf((char*)g_szGameStatus, (char*)GAMESTATUS_TEXT, g_nPigDead, g_nEnemyDead);
    SAFE_DELETE( g_pTextSurface );
    g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, (char*)g_szGameStatus, 
		RGB(0,0,0), RGB(255, 255, 0) );
#endif
	
	SAFE_DELETE( g_pLifeTextSurface );
	wsprintf((char*)g_szLifeLeft, (char*)LIFE_LEFT_TEXT, g_nLivesLeft-1);
	HFONT hFont = GetGameFont();
    g_pDisplay->CreateSurfaceFromText( &g_pLifeTextSurface, hFont , (char*)g_szLifeLeft, 
		RGB(0,0,0), RGB(255, 255, 0) );
	DeleteObject(hFont);
	
	g_pPlayerSprite->MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
	g_pPlayerSprite->SetState(ST_WALK_UP);
	g_pPlayerSprite->m_Movement.m_nInvulnerable=INVULNERABLE_DELAY;
	if (g_nLivesLeft == 0) {
		g_nLivesLeft = NO_OF_LIFE;
		g_nGameState = GAMESTATE_GAMEOVERBAD;
		LoadJPEG(true, GAMEOVERBADFILENAME,  &g_pSplashSurface);
	}
	
}

void DeadEnemy(CSprite* pSprite)
{
	++g_nEnemyDead;
#ifdef DISPLAY_STATUS
	wsprintf((char*)g_szGameStatus, (char*)GAMESTATUS_TEXT, g_nPigDead, g_nEnemyDead);
    SAFE_DELETE( g_pTextSurface );
    g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, (char*)g_szGameStatus, 
		RGB(0,0,0), RGB(255, 255, 0) );
#endif	
	g_nScore += pSprite->m_nPoints;
	SAFE_DELETE( g_pScoreTextSurface );
	wsprintf((char*)g_szScore, (char*)GAMESCORE_TEXT, g_nScore);
	HFONT hFont = GetGameFont();

    g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore, 
		RGB(0,0,0), RGB(255, 255, 0) );
	DeleteObject(hFont);
	
	if (g_nNoOfEnemies) {
		g_nNoOfEnemies--;
		pSprite->SetState(ST_WALK_LEFT);
		POINT pt = g_Maze.GetRandDeployPoint();
		pt.x *= MAZETEXTURE_WIDTH;
		pt.y *= MAZETEXTURE_HEIGHT;
		pSprite->MoveTo(pt);
		(*pSprite->m_Movement.m_pfnFindPath)(pSprite);
		pSprite->m_Movement.m_nInvulnerable=INVULNERABLE_DELAY;
	}
}
bool KillSpecial(CSprite* pSprite)
{
	if (pSprite->GetState() == ST_DOOR) {
			InitLevel();
			return false;
	}
	return true;
}

void DeadSpecial(CSprite* pSprite)
{
	static long nSpecialState = ST_FOOD1;
	g_nScore += pSprite->m_nPoints;
	SAFE_DELETE( g_pScoreTextSurface );
	wsprintf((char*)g_szScore, (char*)GAMESCORE_TEXT, g_nScore);
	HFONT hFont = GetGameFont();
	g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore, 
		RGB(0,0,0), RGB(255, 255, 0) );
	DeleteObject(hFont);
	if (g_nNoOfSpecials) {
		pSprite->SetState(rand()%6 + ST_FOOD1);
		POINT pt = g_Maze.GetRandDeployPoint();
		pt.x *= MAZETEXTURE_WIDTH;
		pt.y *= MAZETEXTURE_HEIGHT;
		pSprite->MoveTo(pt);
		nSpecialState = ST_FOOD1;
		--g_nNoOfSpecials;
	} else {
		switch (nSpecialState) {
		case ST_FOOD1:
			pSprite->SetState(ST_KEY);
			POINT pt = g_Maze.GetRandDeployPoint();
			pt.x *= MAZETEXTURE_WIDTH;
			pt.y *= MAZETEXTURE_HEIGHT;
			pSprite->MoveTo(pt);
			nSpecialState = ST_KEY;
			break;
		case ST_KEY:
			pSprite->SetState(ST_DOOR);
			pt = g_Maze.GetRandDeployPoint();
			pt.x *= MAZETEXTURE_WIDTH;
			pt.y *= MAZETEXTURE_HEIGHT;
			pSprite->MoveTo(pt);
			nSpecialState = ST_DOOR;
			break;
		case ST_DOOR:
			InitLevel();
		}
	}
}

//初始化精灵,它负责创建猪精灵,兔精灵,羊精灵,敌人精灵,特殊精灵和子弹精灵。
void InitSprites()
{
	const int nHeight = SPRITE_HEIGHT;
	const int nWidth = SPRITE_WIDTH;
	POINT pt;
	RECT rcBounding;
	// ---------------- 猪精灵----------------- //
	g_PigSprite.CreateSprite(&g_pSpriteSurface, TYPE_PLAYER, nHeight,nWidth);
	pt.x = 5*64; pt.y =7*64 ;
	g_PigSprite.AddState(ST_STAND_STILL, pt, 2, 60);
	rcBounding.top = 0;
	rcBounding.bottom = nHeight-10;
	rcBounding.left = 10;
	rcBounding.right= nWidth - 20;
	pt.x = 6*64; pt.y =4*64;
	g_PigSprite.AddState(ST_WALK_UP, pt, 3, 10,&rcBounding);
	rcBounding.top = 10;
	rcBounding.bottom = nHeight-10;
	
	pt.x = 64*9;pt.y = 4*64;
	g_PigSprite.AddState(ST_WALK_DOWN, pt, 3, 10,&rcBounding);
	
	rcBounding.top = 10;
	rcBounding.bottom = nHeight - 20;
	rcBounding.left = 0;
	rcBounding.right=nWidth - 10;
	pt.x = 3*64;pt.y = 4*64;
	//	g_pPlayerSprite->AddState(ST_WALK_LEFT, pt, 2, 20,"WavPigWalk",true);
	g_PigSprite.AddState(ST_WALK_LEFT, pt, 3, 10,&rcBounding);
	pt.x = 64*0;pt.y = 4*64;
	rcBounding.left = 10;
	rcBounding.right=nWidth-10;
	
	g_PigSprite.AddState(ST_WALK_RIGHT, pt, 3, 10,&rcBounding);
	pt.x = 64 * 8; pt.y = 7 * 64;
	g_PigSprite.AddState(ST_KILL, pt, 4, 20);
	g_PigSprite.MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
	g_PigSprite.m_pfnDead = DeadPig;
	g_PigSprite.m_Movement.m_pfnCollision = IsHit;
	
	g_PigPooSprite.CreateSprite(&g_pSpriteSurface, TYPE_POO, nHeight,nWidth);
	rcBounding.top = rcBounding.left = 20;
	rcBounding.right=rcBounding.bottom = nHeight - 40;
	pt.x = 0*64;pt.y = 7*64;
	g_PigPooSprite.AddState(ST_DEFAULT, pt, 3, 50,&rcBounding);
	pt.x = 11*64;pt.y = 10*64;
	g_PigPooSprite.AddState(ST_DEAD, pt, 3, 50,&rcBounding);
	g_PigPooSprite.SetState(ST_DEFAULT);
	
	// --------------- 兔精灵 --------------- //
	g_RabbitSprite.CreateSprite(&g_pSpriteSurface, TYPE_PLAYER, nHeight,nWidth);
	pt.x = 5*64; pt.y =8*64 ;
	g_RabbitSprite.AddState(ST_STAND_STILL, pt, 2, 60);
	rcBounding.top = 0;
	rcBounding.bottom = nHeight-10;
	rcBounding.left = 10;
	rcBounding.right= nWidth - 20;
	pt.x = 6*64; pt.y =5*64;
	g_RabbitSprite.AddState(ST_WALK_UP, pt, 3, 10,&rcBounding);
	rcBounding.top = 10;
	rcBounding.bottom = nHeight-10;
	
	pt.x = 64*9;pt.y = 5*64;
	g_RabbitSprite.AddState(ST_WALK_DOWN, pt, 3, 10,&rcBounding);
	
	rcBounding.top = 10;
	rcBounding.bottom = nHeight - 20;
	rcBounding.left = 0;
	rcBounding.right=nWidth - 10;
	pt.x = 3*64;pt.y = 5*64;
	g_RabbitSprite.AddState(ST_WALK_LEFT, pt, 3, 10,&rcBounding);
	pt.x = 64*0;pt.y = 5*64;
	rcBounding.left = 10;
	rcBounding.right=nWidth-10;
	
	g_RabbitSprite.AddState(ST_WALK_RIGHT, pt, 3, 10,&rcBounding);
	pt.x = 64 * 8; pt.y = 8 * 64;
	g_RabbitSprite.AddState(ST_KILL, pt, 4, 20);
	g_RabbitSprite.MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
	g_RabbitSprite.m_pfnDead = DeadPig;
	g_RabbitSprite.m_Movement.m_pfnCollision = IsHit;
	
	g_RabbitPooSprite.CreateSprite(&g_pSpriteSurface, TYPE_POO, nHeight,nWidth);
	rcBounding.top = rcBounding.left = 20;
	rcBounding.right=rcBounding.bottom = nHeight - 40;
	pt.x = 0*64;pt.y = 8*64;
	g_RabbitPooSprite.AddState(ST_DEFAULT, pt, 3, 50,&rcBounding);
	pt.x = 11*64;pt.y = 10*64;
	g_RabbitPooSprite.AddState(ST_DEAD, pt, 3, 50,&rcBounding);
	g_RabbitPooSprite.SetState(ST_DEFAULT);
	
	// --------------- 羊精灵----------------//
	g_SheepSprite.CreateSprite(&g_pSpriteSurface, TYPE_PLAYER, nHeight,nWidth);
	pt.x = 5*64; pt.y =9*64 ;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?