main.cpp

来自「Visual C++ 游戏开发与设计实例 源代码(所有)」· C++ 代码 · 共 1,966 行 · 第 1/4 页

CPP
1,966
字号
//-----------------------------------------------------------------------------
// File: Main.cpp
//
//-----------------------------------------------------------------------------
#define STRICT
#include <windows.h>
#include <ddraw.h>
#include <dshow.h>
#include <mmsystem.h>
#include <math.h>
#include <fstream>
#include <list>
#include "resource.h"
#include "DSUtil.h"
#include "ddutil.h"
#include "Maze.h"
#include "Sprite.h"
#include "SpriteManager.h"
#include "GameErrors.h"
#include "InputLayer.h"
#include "Keyboard.h"
#include "ijl.h"  // Intel JPEG header file
//#define DISPLAY_STATUS
#undef DISPLAY_STATUS
//-----------------------------------------------------------------------------
// Defines, constants, and global variables
//-----------------------------------------------------------------------------
#define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

#define TITLE "Adventure in Abit"
#define SPLASHFILENAME "AdvInAbat.jpg"
#define CHOICEFILENAME "choose.jpg"
#define GAMEOVERBADFILENAME "GameOver.jpg"
#define GAMEOVERGOODFILENAME "Finish.jpg"

#define SCREEN_WIDTH    1024
#define SCREEN_HEIGHT   768
#define SCREEN_BPP      16
#define SPRITE_WIDTH    64
#define SPRITE_HEIGHT   64
#define MAZETEXTURE_WIDTH    32
#define MAZETEXTURE_HEIGHT   32

#define TYPE_PLAYER   1
#define TYPE_ENEMY1 2
#define TYPE_ENEMY2 3
#define TYPE_ENEMY3 4
#define TYPE_ENEMY4 5
#define TYPE_POO    10
#define TYPE_SPECIAL 11
#define TYPE_BULLET  12

#define ST_STAND_STILL 1 
#define ST_WALK_UP     2
#define ST_WALK_DOWN   3
#define ST_WALK_LEFT   4
#define ST_WALK_RIGHT  5
#define ST_DEFAULT     6
#define ST_KEY         7
#define ST_DOOR        8
#define ST_FOOD1       9
#define ST_FOOD2       (ST_FOOD1+1)
#define ST_FOOD3       (ST_FOOD1+2)
#define ST_FOOD4       (ST_FOOD1+3)
#define ST_FOOD5       (ST_FOOD1+4)
#define ST_FOOD6       (ST_FOOD1+5)

#define GAMESTATE_SPLASHSCREEN 0
#define GAMESTATE_CHOICE       1
#define GAMESTATE_RUNNING      2
#define GAMESTATE_GAMEOVERBAD  3
#define GAMESTATE_GAMEOVERGOOD 4

#define POO_DELAY   500
#define INVULNERABLE_DELAY  200
#define NO_OF_LIFE     4
#define NO_OF_SPECIALS 5

#define GAMESTATUS_TEXT "Dead Pigs:%d Dead Enemies:%d"
char g_szGameStatus[200];

#define LIFE_LEFT_TEXT "Lives:%d"
char g_szLifeLeft[100];

#define GAMESCORE_TEXT "Score:%06d"
char g_szScore[100];

CDisplay*            g_pDisplay        = NULL;
#ifdef DISPLAY_STATUS
CSurface*            g_pTextSurface    = NULL;  
#endif
CSurface*            g_pLifeTextSurface = NULL;  
CSurface*            g_pScoreTextSurface = NULL;  
CSurface*            g_pLevelTextSurface = NULL;  
CSurface*            g_pMazeSurface    = NULL;  
CSurface*            g_pSpriteSurface  = NULL;
CSurface*            g_pSplashSurface  = NULL;
RECT                 g_rcWindow;            
RECT                 g_rcViewport;          
RECT                 g_rcScreen;            
BOOL                 g_bWindowed   = false;  
BOOL                 g_bActive     = FALSE;
DWORD                g_dwLastTick;
CMaze                g_Maze(MAKEINTRESOURCE(IDB_TEXTURE));
CSprite              g_PigSprite;
CSprite              g_RabbitSprite;
CSprite              g_SheepSprite;
CSprite*             g_pPlayerSprite = NULL;
CSprite              g_Enemy1Sprite;
CSprite              g_Enemy2Sprite;
CSprite              g_Enemy3Sprite;
CSprite              g_Enemy4Sprite;
CSprite              g_Enemy5Sprite;
CSprite              g_PigPooSprite;
CSprite              g_RabbitPooSprite;
CSprite              g_SheepPooSprite;
CSprite*              g_pPooSprite= NULL;
CSprite              g_SpecialSprite;
CSprite              g_BulletSprite;
CSpriteManager       g_EnemySpriteManager;
CSound*              g_pSplashSound = NULL;
CSound*              g_pPickupSound = NULL;
CSoundManager*       g_pSoundManager = NULL;
int                  g_nGameState = GAMESTATE_SPLASHSCREEN;
int                  g_nPigDead = 0;
int                  g_nEnemyDead = 0;
long                 g_nPooDelay = 0;
long                 g_nNoOfEnemies = 10;
long                 g_nLivesLeft = NO_OF_LIFE;
long                 g_nNoOfSpecials = NO_OF_SPECIALS;
long                 g_nScore = 0;

struct SLEVEL {
	char  szLevelFile[100];
	int   nNoOfEnemys;
}* g_pLevel;

long                 g_nNoOfLevels;
long                 g_nCurrLevel=0;


HINSTANCE g_hInstance;
HWND      g_hMainWnd;

//-----------------------------------------------------------------------------
// Function-prototypes
//-----------------------------------------------------------------------------
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
HRESULT WinInit( HINSTANCE hInst, int nCmdShow, HWND* phWnd, HACCEL* phAccel );
HRESULT InitDirectDraw( HWND hWnd );
VOID    FreeDirectDraw();
HRESULT InitDirectDrawMode( HWND hWnd, BOOL bWindowed );
HRESULT ProcessNextFrame( HWND hWnd );
HRESULT DisplayFrame();
HRESULT RestoreSurfaces();
bool LoadJPEG(bool bFromFile, LPCTSTR szName,  CSurface** ppSurface);
void DisplaySplashScreen(bool bDisplay);
void InitSprites();
void InitLevel();
void MoveCharacterRelative(long dX, long dY);

struct SHandleInput: public iKeyboardReceiver
{
	SHandleInput() {
		cInputLayer::Create( g_hInstance, g_hMainWnd, 
			true, true, false );
		Input()->GetKeyboard()->SetReceiver( this );
	}
	~SHandleInput() {
		cInputLayer::Destroy();
	}
	void KeyUp( int key ) 
	{
		switch(g_nGameState) 
		{
		case GAMESTATE_SPLASHSCREEN: 
			{
				switch( key )
				{
					
				case DIK_SPACE:
					{
						g_nGameState=GAMESTATE_CHOICE;
						g_pSplashSound->Stop();
						LoadJPEG(true, CHOICEFILENAME,  &g_pSplashSurface);
						
						break;
					}
				}
				
			}
			break;
			
		case GAMESTATE_CHOICE:
			{
				bool bKeyHit = false;
				
				switch( key )
				{
				case DIK_1: g_pPlayerSprite = &g_PigSprite; 
					g_pPooSprite = &g_PigPooSprite;
					bKeyHit = true; break;
				case DIK_2: g_pPlayerSprite = &g_RabbitSprite;
					g_pPooSprite = &g_RabbitPooSprite;
					bKeyHit = true;break;
				case DIK_3: g_pPlayerSprite = &g_SheepSprite; 
					g_pPooSprite = &g_SheepPooSprite;
					bKeyHit = true;	break;
				}
				if (bKeyHit) {
					g_nGameState=GAMESTATE_RUNNING;
					InitLevel();
				}
			}
			break;
			
		case GAMESTATE_RUNNING: 
			{
				switch( key )
				{
					// move up
				case DIK_UP:
				case DIK_NUMPAD8:
					// move down
				case DIK_DOWN:
				case DIK_NUMPAD2:
					// turn right
				case DIK_RIGHT:
				case DIK_NUMPAD6:
					// turn left
				case DIK_LEFT:
				case DIK_NUMPAD4:
					g_pPlayerSprite->SetState(ST_STAND_STILL);
					g_pPlayerSprite->m_Movement.m_dx = g_pPlayerSprite->m_Movement.m_dy =0;
					break;
				}
			}
			break;
		case GAMESTATE_GAMEOVERGOOD: 
		case GAMESTATE_GAMEOVERBAD: 
			{
				switch( key )
				{
					
				case DIK_SPACE:
					{
						g_nGameState=GAMESTATE_SPLASHSCREEN;
						g_nLivesLeft = NO_OF_LIFE;
						g_nScore=0;
						g_nCurrLevel=0;
						
						break;
					}
				}
				
			}
			break;
			
		}
	}
	
	
	void KeyDown( int key )
	{
		switch(g_nGameState) {
			
			
		case GAMESTATE_RUNNING: 
			{
				switch( key )
				{
					
					// move up
				case DIK_UP:
				case DIK_NUMPAD8:
					{
						g_pPlayerSprite->SetState(ST_WALK_UP);
						g_pPlayerSprite->m_Movement.m_dy = -2;
						g_pPlayerSprite->m_Movement.m_dx = 0;
						break;
					}
					
					// move down
				case DIK_DOWN:
				case DIK_NUMPAD2:
					{
						g_pPlayerSprite->SetState(ST_WALK_DOWN);
						g_pPlayerSprite->m_Movement.m_dy = 2;
						g_pPlayerSprite->m_Movement.m_dx = 0;
						break;
					}
					
					// Shoot
				case DIK_SPACE:
					{
						if (g_nPooDelay == 0 && g_pPlayerSprite->GetState()!= ST_KILL) {
							RECT rc = g_pPlayerSprite->GetRect();
							g_pPooSprite->MoveTo(rc.left,rc.top);
							g_nPooDelay = POO_DELAY;
							g_pPooSprite->SetState(ST_DEFAULT);
						}
						break;
					}
					
					// turn right
				case DIK_RIGHT:
				case DIK_NUMPAD6:
					{
						g_pPlayerSprite->SetState(ST_WALK_RIGHT); 
						g_pPlayerSprite->m_Movement.m_dx = 2;
						g_pPlayerSprite->m_Movement.m_dy = 0;
						break;
					}
					
					// turn left
				case DIK_LEFT:
				case DIK_NUMPAD4:
					{
						g_pPlayerSprite->SetState(ST_WALK_LEFT);
						g_pPlayerSprite->m_Movement.m_dx = -2;
						g_pPlayerSprite->m_Movement.m_dy = 0;
						break;
					}
				}
			}
		}
	}
} *  g_pHandleInput = NULL;





//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything and calls
//       UpdateFrame() when idle from the message pump.
//-----------------------------------------------------------------------------
int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow )
{
    MSG	   msg;
    HWND   hWnd;
    HACCEL hAccel;
	
    srand( GetTickCount() );
	
	wsprintf((char*)g_szGameStatus, (char*)GAMESTATUS_TEXT,0,0);
	wsprintf((char*)g_szLifeLeft, (char*)LIFE_LEFT_TEXT,g_nLivesLeft -1);
	wsprintf((char*)g_szScore, (char*)GAMESCORE_TEXT,g_nScore);
	
	g_hInstance = hInst;
	
	char szName[200];
	std::fstream LevelData("config.txt",std::ios::in );
    LevelData.getline(szName,200);
	
	// Read number of horizontal lines
	LevelData >> g_nNoOfLevels;   // Number of Horizontal rows
	g_pLevel = new SLEVEL[g_nNoOfLevels];
	if (g_pLevel == NULL)
		return -1;
	for (int nI = 0; nI < g_nNoOfLevels; nI++) {
		LevelData >> g_pLevel[nI].szLevelFile;
		LevelData >> g_pLevel[nI].nNoOfEnemys;
	}
	
    if( FAILED( WinInit( hInst, nCmdShow, &hWnd, &hAccel ) ) )
        return FALSE;
	
	
    if( FAILED( InitDirectDraw( hWnd ) ) )
    {
        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 was posted, so exit
				FreeDirectDraw();
				CoUninitialize();
				delete[] g_pLevel;
                return (int)msg.wParam;
            }
			
            // Translate and dispatch 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
//-----------------------------------------------------------------------------
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,
			0,
			NULL 
			);
		OutputDebugString( (LPCTSTR)lpMsgBuf);
		// 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 );
    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

⌨️ 快捷键说明

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