⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winmain.cpp

📁 这是一个服务端/客户端模式的小型网络游戏
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/**************************************************
WinMain.cpp
Chapter 19 Multiplayer Client Demo

  Programming Role-Playing Games with DirectX
  by Jim Adams (01 Jan 2002)
  
	Required libraries:
	D3D8.LIB, D3DX8.LIB, DINPUT8.LIB, D3DXOF.LIB,
	DXGUID.LIB, DPNET.LIB, DPLAY.LIB, and DPNADDR.LIB
**************************************************/

#include "Core_Global.h"
#include "Frustum.h"
#include "NodeTree.h"
#include "WinMain.h"
#include "resource.h"
#include "Chars.h"
#include "Script.h"
#include "Window.h"


// 4. 实例化一个category对象
log4cpp::Category& warn_log = 
log4cpp::Category::getInstance("Debug_log4cpp");
char sTemp[1024] = "";


// Global names of character meshes
char *g_CharMeshNames[] = {
    { "..\\Data\\Warrior.x" },   // Mesh # 0
    { "..\\Data\\Yodan.x"   }    // Mesh # 1
};

sCharAnimationInfo g_CharAnimations[] = {
    { "Idle",  TRUE  },
    { "Walk",  TRUE  },
    { "Swing", FALSE },
    { "Spell", FALSE },
    { "Spell", FALSE },
    { "Hurt",  FALSE },
    { "Die",   FALSE },
    { "Idle",  TRUE  }
};

char *g_SpellMeshNames[] = {
    { "..\\Data\\Fireball.x"   },
    { "..\\Data\\Explosion.x"  },
    { "..\\Data\\Groundball.x" },
    { "..\\Data\\ice.x" },
    { "..\\Data\\bomb.x" },
};

cApp            *g_Application; // Global application pointer
cNetworkAdapter *g_Adapters;    // Global adapter list pointer



///////////////////////////////////////////////////////////
// cApp functions
///////////////////////////////////////////////////////////
cApp::cApp()
{ 
	// Setup main window information
	m_Width  = 640; 
	m_Height = 480;
	m_Style  = WS_BORDER | WS_CAPTION |                         \
		WS_MINIMIZEBOX | WS_SYSMENU;
	strcpy(m_Class, "ClientClass");
	strcpy(m_Caption, "Network Client Demo by Jim Adams");
	
	// Clear class data
	g_Application = this;
	g_Adapters    = &m_Adapters;
	m_Status = MSG_NORMAL;
	MoveAction = 0;
	
	CamMoved = FALSE;
	m_CamAngle = 0.0f;
	m_YCamAngle = 0.1f;
	m_Count = 0;
	ScripteHandle.Renderflag = FALSE;
	ScripteHandle.EffectCounter = 0;
}

BOOL cApp::Init()
{
	// Select a network adapter to use (or quit if selected)
	if(SelectAdapter() == FALSE)
		return FALSE;
	
	// Initialize the game, set video mode, load data, etc
	if(InitializeGame() == FALSE) {
		Error(FALSE, "Unable to initialize game.");
		return FALSE;
	}
	
	// Join networked game
	if(JoinGame() == FALSE) {
		Error(FALSE, "Unable to connect to server.");
		return FALSE;
	}
	
	return TRUE;
}

BOOL cApp::Shutdown()
{
	// Shutdown network
	m_Adapters.Shutdown();
	m_Client.Disconnect();
	m_Client.Shutdown();
	
	// clean up and flush all appenders
	log4cpp::Category::shutdown();
	// Free controllers
	m_CharController.Free();
	m_SpellController.Free();
	
	m_Script.Free();
	// Free the options texture
	m_Options.Free();
	// Free meshes
	m_NodeTreeMesh.Free();
	m_TerrainMesh.Free();
	
	// Shutdown input
	m_Keyboard.Free();
	m_Mouse.Free();
	m_Input.Shutdown();
	
	// Shutdown graphics
	m_Font.Free();
	m_Graphics.Shutdown();
	
	return TRUE;
}

BOOL cApp::Frame()
{
	static DWORD UpdateCounter  = timeGetTime();
	static DWORD LatencyCounter = timeGetTime();
	
	// Get local input every frame 
	m_Keyboard.Acquire(TRUE);  
	m_Mouse.Acquire(TRUE);     
	m_Keyboard.Read();
	m_Mouse.Read();
	
	
	// Pressing ESC quits program
	if(m_Keyboard.GetKeyState(KEY_ESC) == TRUE ){
		if(m_Status == MSG_NORMAL && ScripteHandle.Renderflag == FALSE) return FALSE;
	}
	
	
	if(!m_CharController.m_Messages.empty()){
		sMessage pm;
		sAssignPlayerIDProcMessage *apidm;
		sCreatePlayerProcMessage *cppm; 
		sFileProcMessage *fpm;
		// Enter critical section
		EnterCriticalSection(&m_CharController.m_UpdateCS);
		pm = m_CharController.m_Messages.front();		
		// Leave critical section
		LeaveCriticalSection(&m_CharController.m_UpdateCS);
		switch( pm.Header.Type){
		case MSG_ASSIGNID:
			apidm = (sAssignPlayerIDProcMessage *)±
			m_CharController.GetCharacter(0)->dpnidPlayer = apidm->Header.PlayerID;
			break;
		case MSG_INIT_FILE:
			FILE *fp;
			char FilenameBuffer[MAX_PATH];
			fpm = (sFileProcMessage *)±
			sCharacter *Character;
			Character = m_CharController.GetCharacter(0);
			
			if(fpm->FileType == MSG_ICS)
				sprintf(FilenameBuffer, "Save\\ICS%s.dat", Character->Def.Name);
			else if(fpm->FileType == MSG_CHARACTER)
				sprintf(FilenameBuffer, "Save\\%s.dat", Character->Def.Name);
			if((fp=fopen(FilenameBuffer, "wb"))==NULL)
				if((fp=fopen(FilenameBuffer, "wb+"))==NULL)
					break;
				
				fwrite(fpm->Data, 1, fpm->FileSize, fp);
				fclose(fp);

				if(fpm->FileType == MSG_ICS)
					Character->CharICS->Load(FilenameBuffer);
				else if(fpm->FileType == MSG_CHARACTER) m_CharController.Load(Character, FilenameBuffer);

				break;
		case MSG_RELIVE_CHANGE:
			sReliveChangeProcMessage *rcpm;
			rcpm = (sReliveChangeProcMessage *)±

			if((Character = GetCharacterPoint(rcpm->Header.PlayerID)) == NULL) break;
			if(Character->Type == CHAR_PC) Character->Def.Experience = rcpm->Experience;
			Character->Enabled = TRUE;
			if(Character->Type == CHAR_PC || Character->AI == CHAR_STAND) Character->Action = CHAR_IDLE;
			else Character->Action = CHAR_MOVE;
			Character->HealthPoints = Character->Def.HealthPoints;
			Character->ManaPoints	 = Character->Def.ManaPoints;
			break;
		case MSG_PLAYER_INFO: 
		case MSG_CREATE_PLAYER:
			cppm = (sCreatePlayerProcMessage *)±
			
			m_CharController.Add(cppm->Header.PlayerID, cppm->Header.PlayerID, cppm->Definition, cppm->Type, cppm->AI,             \
				cppm->XPos, cppm->YPos, cppm->ZPos, cppm->Direction, cppm->Action, cppm->Name);
			break;
		case MSG_ALTER_EFFECT:
			sAlterEffectProcMessage *aepm;
			sCharacter *Attacker, *Victim;
			char Text[128];
			aepm = (sAlterEffectProcMessage *)±
			Attacker = m_CharController.GetCharacter(aepm->Header.ID);
			Victim = m_CharController.GetCharacter(aepm->VictimID);
			
			if(Victim!=NULL){
				switch( aepm->EffectType){
				case MSG_FAILED:
					m_CharController.SetMessage(Victim, "Failed!", 500);
					break;
				case MSG_MISSED:
					m_CharController.SetMessage(Victim, "Missed!", 500);
					break;
				case MSG_DODGED:
					m_CharController.SetMessage(Victim, "Dodged!", 500);
					break;
				case MSG_ALTERHP:
					if(aepm->AlterHPAmount >= 0) {
						sprintf(Text, "-%lu HP", aepm->AlterHPAmount);
						m_CharController.SetMessage(Victim, Text, 500, D3DCOLOR_RGBA(255,64,0,255));
					} else {
						sprintf(Text, "+%lu HP", -aepm->AlterHPAmount);
						m_CharController.SetMessage(Victim, Text, 500, D3DCOLOR_RGBA(0,64,255,255));
					}
					break;
				}
				Victim->HealthPoints = aepm->HealthPoints;
			}
			if(Attacker!=NULL){
				Attacker->ManaPoints = aepm->ManaPoints;
			}
			break;
		case MSG_DESTROY_PLAYER:
			sDestroyPlayerProcMessage *dppm;
			dppm = (sDestroyPlayerProcMessage *)±
			Character = m_CharController.GetCharacter(dppm->Header.ID);
			
			m_CharController.Remove(Character);
			break;
		}
		
		// Enter critical section
		EnterCriticalSection(&m_CharController.m_UpdateCS);
		m_CharController.m_Messages.pop_front();
		// Leave critical section
		LeaveCriticalSection(&m_CharController.m_UpdateCS);
	}
	
	
	
	// Handle connection and waiting for data screen
	if(m_Client.m_Connected == FALSE || !m_CharController.GetCharacter(0)->dpnidPlayer) {
		
		// Display message(s)
		m_Graphics.Clear();
		if(m_Graphics.BeginScene() == TRUE) {
			m_Font.Print("Connecting to server...", 0, 0);
			if(!m_CharController.GetCharacter(0)->dpnidPlayer)
				m_Font.Print("Waiting for server data...", 0, 20);
			m_Graphics.EndScene();
		}
		m_Graphics.Display();
		
		// Request player ID from server every 2 seconds
		if(timeGetTime() > UpdateCounter + 2000) {
			UpdateCounter = timeGetTime();  // Update counter
			
			sAssignPlayerIDMessage apidm;
			apidm.Header.Type = MSG_ASSIGNID;
			apidm.Header.Size = sizeof(sAssignPlayerIDMessage);
			SendNetworkMessage(&apidm, DPNSEND_NOLOOPBACK |         \
				DPNSEND_GUARANTEED);
		}
		// Update player latency values every 10 seconds
		if(timeGetTime() > LatencyCounter + 10000) {
			UpdateLatency();
			LatencyCounter = timeGetTime(); // Reset counter
		}
		
		return TRUE;
	}
	
	
    // Store movements every frame
	if(m_Keyboard.GetKeyState(KEY_UP) == TRUE)
		MoveAction |= 1;
	if(m_Keyboard.GetKeyState(KEY_RIGHT) == TRUE)
		MoveAction |= 2;
	if(m_Keyboard.GetKeyState(KEY_DOWN) == TRUE)
		MoveAction |= 4;
	if(m_Keyboard.GetKeyState(KEY_LEFT) == TRUE)
		MoveAction |= 8;
	
	// Store attack action
	if(m_Keyboard.GetKeyState(KEY_SPACE) == TRUE)
		MoveAction |= 16;
	if(m_Mouse.GetButtonState(MOUSE_LBUTTON) == TRUE)
		MoveAction |= 16;
	if(m_Keyboard.GetKeyState(KEY_1) == TRUE) {
		MoveAction |= 32;
		m_Keyboard.SetLock(KEY_1, TRUE);
		m_Keyboard.SetKeyState(KEY_1, FALSE);
	}
	
	if(m_Keyboard.GetKeyState(KEY_2) == TRUE) {
		MoveAction |= 64;
		m_Keyboard.SetLock(KEY_2, TRUE);
		m_Keyboard.SetKeyState(KEY_2, FALSE);
	}
	
	if(m_Keyboard.GetKeyState(KEY_3) == TRUE) {
		MoveAction |= 128;
		m_Keyboard.SetLock(KEY_3, TRUE);
		m_Keyboard.SetKeyState(KEY_3, FALSE);
	}
	
	if(m_Keyboard.GetKeyState(KEY_P) == TRUE) {
		MoveAction |= 256;
		m_Keyboard.SetLock(KEY_P, TRUE);
		m_Keyboard.SetKeyState(KEY_P, FALSE);
	}
	
	if(m_Keyboard.GetKeyState(KEY_U) == TRUE) {
		MoveAction |= 512;
		m_Keyboard.SetLock(KEY_U, TRUE);
		m_Keyboard.SetKeyState(KEY_U, FALSE);
	}
	
	if(m_Keyboard.GetKeyState(KEY_S) == TRUE) {
		MoveAction |= 1024;
		m_Keyboard.SetLock(KEY_S, TRUE);
		m_Keyboard.SetKeyState(KEY_S, FALSE);
	}
	
	
	
	if(m_Status == MSG_NORMAL){
		// Rotate camera
		if(m_Mouse.GetXDelta() > 0) {
			m_CamAngle -= 0.1f;
			CamMoved = TRUE;
			if(m_CamAngle <= -3.14f)m_CamAngle = 3.14f;
		}
		if(m_Mouse.GetXDelta() < 0) {
			m_CamAngle += 0.1f;
			CamMoved = TRUE;
			if(m_CamAngle >= 3.14f)m_CamAngle = -3.14f;
		}
		
		// Rotate camera
		if(m_Mouse.GetYDelta() > 0) {
			m_YCamAngle += 0.1f;
			if(m_YCamAngle > 1.4f)m_YCamAngle = 1.4f;
		}
		if(m_Mouse.GetYDelta() < 0) {
			m_YCamAngle -= 0.1f;
			if(m_YCamAngle < 0.1f)m_YCamAngle = 0.1f;
		}
	}
	
	// Only update players every 33ms (30 times a second)
	if(timeGetTime() < UpdateCounter + 33)
		return TRUE;
	
////////////////////////////////////////////////////////////////////////////////////
///////////33秒刷新率
////////////////////////////////////////////////////////////////////////////////////
	
	m_Count++;
	if(m_Count > 2000){
		if(rand() %2){
			MapICS->Add((rand()%2?1:9), 1, -1650 + rand()%3300, 0, rand()%290);
		} else {
			MapICS->Add((rand()%2?1:9), 1, -1650 + rand()%3300, 0, -1259+rand()%397);
		}
		m_Count = 0;
	}
	// Attack a nearby monster or process NPC script
	if(MoveAction & 512) {
		if(m_Status != MSG_ITEMS){
			m_Status = MSG_ITEMS;
			ShowMouse(TRUE);
		}
		else {
			m_Status = MSG_NORMAL;
			ShowMouse(FALSE);
		}
		
	} else if(MoveAction & 1024) {
		if(m_Status != MSG_STATUS ){
			if(m_Status == MSG_ITEMS)ShowMouse(FALSE);
			m_Status = MSG_STATUS;	  
		} else {
			m_Status = MSG_NORMAL;
		}
	}	  
	
	// Update all players
	UpdateCamera();
	
	// Update controllers
	m_CharController.Update();
	
	m_SpellController.Update();
	
	// Render the scene
	RenderScene();
	
	
	MoveAction = 0; // Clear action data for next frame
	
	UpdateCounter = timeGetTime(); // Reset update counter
	
	return TRUE;
}

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev,          \
                   LPSTR szCmdLine, int nCmdShow)
{
	cApp App;
	return App.Run();
}

///////////////////////////////////////////////////////////
// Select adapter dialog and other functions
///////////////////////////////////////////////////////////
BOOL CALLBACK ConnectDialogProc(HWND hWnd, UINT uMsg,         \
                                WPARAM wParam, LPARAM lParam)
{
	int Selection;
	long i;
	char Name[32], IP[16], Text[256];
	static HWND hAdapters;
	

⌨️ 快捷键说明

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