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 + -
显示快捷键?