对战坦克大战vc++Word文件下载.docx

上传人:b****7 文档编号:22032089 上传时间:2023-02-02 格式:DOCX 页数:18 大小:122.82KB
下载 相关 举报
对战坦克大战vc++Word文件下载.docx_第1页
第1页 / 共18页
对战坦克大战vc++Word文件下载.docx_第2页
第2页 / 共18页
对战坦克大战vc++Word文件下载.docx_第3页
第3页 / 共18页
对战坦克大战vc++Word文件下载.docx_第4页
第4页 / 共18页
对战坦克大战vc++Word文件下载.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

对战坦克大战vc++Word文件下载.docx

《对战坦克大战vc++Word文件下载.docx》由会员分享,可在线阅读,更多相关《对战坦克大战vc++Word文件下载.docx(18页珍藏版)》请在冰豆网上搜索。

对战坦克大战vc++Word文件下载.docx

InitServer())

第4章网络游戏开发277

PostQuitMessage(0);

//创建socket监听线程

CreateThread(NULL,0,AcceptThread,NULL,0,NULL);

//创建socket工作线程

CreateThread(NULL,0,WorkerThread,NULL,0,NULL);

return0;

caseWM_SETFOCUS:

SetFocus(hwndList);

caseWM_DESTROY:

TerminateServer();

}

returnDefWindowProc(hwnd,message,wParam,lParam);

WndProc在创建消息中首先调用了InitServer,以初始化服务器。

然后,它开启两个线程,一个是

socket监听线程AcceptThread,另一个是socket工作线程WorkerThread。

初始化服务器函数InitServer,定义如下:

boolInitServer()

WSADATAwsd;

sockaddr_inlocal;

//socket初始化

if(WSAStartup(MAKEWORD(2,2),&

wsd)!

=0)

returnfalse;

//创建监听socket

slisten=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);

if(slisten==SOCKET_ERROR){

WSACleanup();

//绑定地址和端口

local.sin_addr.s_addr=htonl(INADDR_ANY);

local.sin_family=AF_INET;

local.sin_port=htons(sport);

if(bind(slisten,(structsockaddr*)&

local,

sizeof(local))==SOCKET_ERROR){

closesocket(slisten);

//将socket变成文件使用方式,并在上面监听socket

iocp=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);

iocp){

278VisualC++游戏开发技术与实例

//初始化socket池和玩家信息池

olexPool.InitPool(0)||!

playerPool.InitPool(16)){

ZeroMemory(&

gTable,sizeof(GAMETABLE));

//开始监听

if(listen(slisten,SOMAXCONN)!

=0){

Notice(1,"

Serverstartsuccessfully!

"

);

returntrue;

Socket连接监听线程函数AcceptThread定义如下。

它采用轮寻方式监听连接,并将创建的会话

Socket与文件I/O进行关联。

DWORDWINAPIAcceptThread(LPVOIDpParam){

sockaddr_inclient;

intsize;

SOCKETret;

OVERLAPPEDEX*lpolex;

while(true){

size=sizeof(sockaddr_in);

ret=accept(slisten,(sockaddr*)&

client,&

size);

if(ret!

=INVALID_SOCKET)

Notice(2,"

Connect:

inet_ntoa(client.sin_addr));

lpolex=olexPool.GetUsable();

if(lpolex)

//成功接受连接

//将会话Socket和文件关联

CreateIoCompletionPort((HANDLE)ret,iocp,NULL,0);

lpolex->

socket=ret;

RecvMsg(lpolex);

else{

closesocket(ret);

第4章网络游戏开发279

else{//accepterror

ret=WSAGetLastError();

WSAErrorTrigger(ret,TEXT("

AcceptErr:

"

));

return0;

另一个线程函数WorkerThread用于和客户端进行通信,并对整个游戏进行控制。

DWORDWINAPIWorkerThread(LPVOIDpParam){

ULONG_PTRckey;

OVERLAPPED*pol;

OVERLAPPEDEX*polex;

DWORDBytesTransferred;

intret;

int*ibuf;

ret=GetQueuedCompletionStatus(iocp,&

BytesTransferred,

&

ckey,&

pol,INFINITE);

//OVERLAPPEDEX是自定义结构

polex=CONTAINING_RECORD(pol,OVERLAPPEDEX,ol);

//远程主机断开连接

if(ret==0){

intsize=sizeof(sockaddr_in);

getpeername(polex->

socket,(sockaddr*)&

Discont:

//删除所占的座位

for(inti=0;

i<

gTable.current;

i++){

if(gTable.players[i]==polex->

ppla){

if(i>

0)

gTable.players[i-1]->

next=polex->

ppla->

next;

break;

for(;

gTable.current-1;

i++)

gTable.players[i]=gTable.players[i+1];

gTable.current--;

//回收资源

playerPool.Recycle(polex->

ppla);

olexPool.Recycle(polex);

continue;

280VisualC++游戏开发技术与实例

//成功收到消息

switch(polex->

op){

caseOP_READ:

ibuf=(int*)(polex->

wbuf.buf);

switch(ibuf[0]){

//分配玩家座位表

caseNETMSGTK_ASKGROUPINFO:

Notice("

AskGroup:

ibuf[2]);

polex->

ppla=playerPool.GetUsable();

seat=gTable.current;

gTable.players[gTable.current]=polex->

ppla;

gTable.players[gTable.current]->

socket=polex->

socket;

SendMsg(NETMSGTK_ANSWERSEATINFO,polex->

socket,

gTable.current,sizeof(int));

AnswerSeat:

gTable.current);

next=NULL;

if(gTable.current>

0){

gTable.players[gTable.current-1]->

SendMsgToOther(NETMSGTK_MOREPLAYER,gTable,gTable.current,

if(++gTable.current==MAXPLAYER)

SendMsgToTable(NETMSGTK_GAMEREADY,gTable,NULL,0);

caseNETMSGTK_PLAYERREADY:

if(++gTable.counter==MAXPLAYER){

SendMsgToTable(NETMSGTK_GAMESTART,gTable,NULL,0);

//初始化奖子

gTable.food.exsit=false;

gTable.food.existnum=DEFFOODEXFRAME;

gTable.food.notexistnum=DEFFOODNOTEXFRAME;

gTable.food.counter=DEFFOODNOTEXFRAME;

gTable.counter=0;

caseNETMSGTK_CMDINFO:

if(gTable.food.counter--<

if(gTable.food.exsit){//删除

gTable.food.counter=gTable.food.notexistnum;

SendMsgToTable(NETMSGTK_CMDFOODDELETE,gTable,NULL,0);

}else{//创建

gTable.food.counter=gTable.food.existnum;

intfoodparam[3];

foodparam[0]=rand()%FOOD_MAX;

foodparam[1]=rand()%608;

foodparam[2]=rand()%608;

SendMsgToTable(NETMSGTK_CMDFOODCREATE,gTable,foodparam,sizeof(int)*3);

第4章网络游戏开发281

gTable.food.exsit=!

gTable.food.exsit;

SendMsgToOther(NETMSGTK_CMDINFO,gTable,polex->

seat,ibuf+2,

ibuf[1]);

caseNETMSGTK_TEAMVICTORY:

SendMsgToTable(NETMSGTK_TEAMVICTORY,gTable,ibuf+2,ibuf[1]);

RecvMsg(polex);

caseOP_WRITE:

4.10.2对战坦克大战的客户端程序

对战坦克大战的客户端程序界面如图4.16所示。

图4.16坦克大战客户端

注意:

如果想测试这个游戏,需要同时运行4个客户端程序。

282VisualC++游戏开发技术与实例

程序主框架首先调用InitNetwork函数用于初始化网络通信。

InitNetwork函数定义如下:

boolInitNetwork(constchar*serv_addr,unsignedintserv_port)

sockaddr_inlocal,server;

unsignedlongul=1;

//初始化socket

//创建客户端socket并绑定

c_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);

if(c_socket==SOCKET_ERROR)

c_port=NET_CLIENT_PORT_MIN;

while(c_port<

NET_CLIENT_PORT_MAX)

local.sin_port=htons(c_port);

if(bind(c_socket,(structsockaddr*)&

if(ret==WSAEADDRINUSE)

c_port++;

elsebreak;

if(c_port>

=NET_CLIENT_PORT_MAX)

server.sin_addr.s_addr=inet_addr(serv_addr);

server.sin_family=AF_INET;

server.sin_port=htons(serv_port);

//连接服务器

if(connect(c_socket,(constsockaddr*)&

server,sizeof(server))==SOCKET_ERROR)

if(ret==WSAENETDOWN||ret==WSAENETUNREACH)

ERRORMSG("

Can’treachserver.\nPleasecheckyournetworkconnection."

elseif(ret==WSAECONNREFUSED)

Theserverdoesnotwork!

elseif(ret==WSAEPROCLIM)

Toomanyusers.\nPleasetrylater."

第4章网络游戏开发283

//设置socket为非阻塞

if(ioctlsocket(c_socket,FIONBIO,&

ul)==SOCKET_ERROR)

//初始化消息列表

NetList.CreatMsgList(8,true);

//networkmessagelist

//创建消息接受线程

HANDLEhThread=CreateThread(NULL,0,MsgReceiver,NULL,0,NULL);

if(!

hThread)

InitNetwork函数中开启了一个新线程用于接受网络消息,线程函数是MsgReceiver。

在MsgReceiver

中,程序采用轮寻方式检测网络数据,函数定义如下:

DWORDWINAPIMsgReceiver(LPVOIDparam)

fd_setfdread;

timevaltval;

intret,msgsize;

charbuf_char[BUFFERSIZE];

//接受缓冲

char*mark;

CMsgElemelem;

//向服务器查询组信息

ret=0;

SendMsg(NETMSGTK_ASKGROUPINFO,&

ret,sizeof(int));

tval.tv_usec=0;

tval.tv_sec=1;

//轮寻方式检测是否有网络消息

while(true)

FD_ZERO(&

fdread);

FD_SET(c_socket,&

ret=select(0,&

fdread,NULL,NULL,&

tval);

if(ret==0||ret==SOCKET_ERROR){

//可能还未初始化

NetList.GetSize())

//接受数据

284VisualC++游戏开发技术与实例

ret=recv(c_socket,buf_char,BUFFERSIZE,0);

if(ret==SOCKET_ERROR){

NetList.Lock();

char*temp="

Connectionshutdown!

;

elem.CreateMsgElem(MSGNET_RECEIVEERROR,temp,strlen(temp)+1,MSG_NET);

NetList.Push(&

elem);

NetList.UnLock();

//把消息弹入列表中

mark=buf_char;

while(ret>

0&

elem.CreateMsgElemFromBuf(mark,msgsize,MSG_NET)){

mark+=msgsize;

ret-=msgsize;

MsgReceiver中还调用了SendMsg函数,这是向服务器发送消息的函数。

boolSendMsg(intmsg,LPVOIDparam,intsize)

intret=size+sizeof(int)*2;

char*buffer=newchar[ret];

buffer)

*(int*)buffer=msg;

*(int*)(buffer+sizeof(int))=size;

if(param&

size>

0)

memcpy(buffer+sizeof(int)*2,param,size);

ret=send(c_socket,buffer,ret,0);

delete[]buffer;

if(ret==SOCKET_ERROR)

else

在InitNetwork函数完成后,系统调用GameMain进入游戏控制循环。

在GameMain函数中,程序

首先调用MsgProcessor处理网络消息,接着根据当前的游戏状态作出不同动作。

而当游戏处于运行状

态时,程序首先对子弹进行碰撞检测相关计算,接着对坦克运动做计算,然后再对奖子做碰撞检测计

算,最后是向电脑控制的坦克做AI命令。

当这些控制完成后,程序将上面的动作统一发送到服务器

第4章网络游戏开发285

端。

GameMain的最后部分是绘制这些精灵,绘制的顺序是地图、子弹、坦克、鹰巢和草地(雪地)。

这里实现坦克游戏能够完全模仿FC(FamilyComputer)上的坦克大战,所以坦克是可以

在草地中隐藏的,这也是为什么将草地最后绘制的原因。

voidConsoleNet:

:

GameMain(){

staticintcounter=0;

staticDWORDstart_time=0,last_get;

staticDWORDframe_start=0;

DWORDend_time;

if(m_dwStatus==CONSTAT_ENDGAME)

return;

//如果网络消息队列非空,则调用MsgProcessor函数处理消息列表。

NetList.IsEmpty())

MsgProcessor(&

Net

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 电子电路

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1