俺用Visula C++ 6和DirectX 7开发了一款三国游戏,限于篇幅,这里只给出内政处理、对战处理中的部分源代码。
内政处理较简单,根据鼠标位置判断执行哪一条内政命令(设置相应标志,移动、开发、征兵、训练、战争、任命太守、任命军师的代码在地图类_SGCMap中实现,理由是执行以上指令必须选择地图中某一城池里面的武将),源代码如下:
void _SGCCommandScene::DoMouseClick(int nCurX,int nCurY)
{
RECT rect;
//单击了内政按钮,显示内政子菜单
sgcCommand.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
sgeCommandState=SGE_COMMANDINSIDE;
//单击了军政按钮,显示军政子菜单
sgcArmy.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
sgeCommandState=SGE_COMMANDARMY;
//单击了任免按钮,显示任免子菜单
sgcOccupy.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
sgeCommandState=SGE_COMMANDOCCUPY;
//单击了系统按钮,显示系统子菜单
sgcSystem.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
sgeCommandState=SGE_COMMANDSYSTEM;
//单击了休息按钮
sgcRest.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
{
sgeCommandState=SGE_COMMANDNULL;
sgcGame.ChangeMonth();
CalculateToken();//根据城池数计算令牌数
EnemyDoCommand();//敌方君主执行内政指令
return;
}
// 内政指令处理
switch(sgeCommandState)
{
case SGE_COMMANDINSIDE:
//移动
sgcMove.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE && nTokenNum>0)
{
sgeGameState=SGE_GAMEMAP;
sgeCommandState=SGE_COMMANDMOVE;
sgcGame.sgcTList.bMultiSelect=TRUE;
sgcGame.sgcMap.sgeMapLocation=SGE_MAPLEFTTOP;
return;
}
//开发
sgcEmpolder.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE && nTokenNum>0)
{
sgeGameState=SGE_GAMEMAP;
sgeCommandState=SGE_COMMANDEMPOLDER;
sgcGame.sgcTList.bMultiSelect=FALSE;
sgcGame.sgcMap.sgeMapLocation=SGE_MAPLEFTTOP;
return;
}
//人才
sgcPeople.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE && nTokenNum>0)
{
sgeCommandState=SGE_COMMANDPEOPLE;
DoCommandPeople();//搜索人才
}
break;
case SGE_COMMANDARMY:
//征兵
sgcDraft.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE && nTokenNum>0)
{
sgeGameState=SGE_GAMEMAP;
sgeCommandState=SGE_COMMANDDRAFT;
sgcGame.sgcTList.bMultiSelect=FALSE;
sgcGame.sgcMap.sgeMapLocation=SGE_MAPLEFTTOP;
return;
}
//训练
sgcTraining.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE && nTokenNum>0)
{
sgeGameState=SGE_GAMEMAP;
sgeCommandState=SGE_COMMANDTRAINING;
sgcGame.sgcTList.bMultiSelect=FALSE;
sgcGame.sgcMap.sgeMapLocation=SGE_MAPLEFTTOP;
return;
}
//战争
sgcWar.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE && nTokenNum>0)
{
sgeGameState=SGE_GAMEMAP;
sgeCommandState=SGE_COMMANDWAR;
sgcGame.sgcTList.bMultiSelect=TRUE;
sgcGame.sgcMap.sgeMapLocation=SGE_MAPLEFTTOP;
}
break;
case SGE_COMMANDOCCUPY:
//任命太守
sgcSatrap.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
{
sgeGameState=SGE_GAMEMAP;
sgeCommandState=SGE_COMMANDSATRAP;
sgcGame.sgcTList.bMultiSelect=FALSE;
sgcGame.sgcMap.sgeMapLocation=SGE_MAPLEFTTOP;
return;
}
//任命军师
sgcCounsellor.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
{
sgeGameState=SGE_GAMEMAP;
sgeCommandState=SGE_COMMANDCOUNSELLOR;
sgcGame.sgcTList.bMultiSelect=FALSE;
sgcGame.sgcMap.sgeMapLocation=SGE_MAPLEFTTOP;
}
break;
case SGE_COMMANDSYSTEM:
//读取进度
sgcRead.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
{
sgeCommandState=SGE_COMMANDREAD;
DoCommandRead();
return;
}
//保存进度
sgcSave.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
{
sgeCommandState=SGE_COMMANDSAVE;
DoCommandSave();
return;
}
//返回
sgcReturn.GetLocation(&rect);
if(MouseInRect(nCurX,nCurY,rect)==TRUE)
{
sgeCommandState=SGE_COMMANDRETURN;
DoCommandReturn();
}
break;
}
}
对战场景的绘制比较麻烦,首先要绘制对战场景的背景,再根据相应状态绘制敌方士兵、敌方武将、我方士兵、我方武将……限于篇幅,这里只给出绘制敌方士兵的源代码,如下:
HRESULT _SGCWar::DrawESoldier(LPDIRECTDRAWSURFACE7 pDest,DWORD dwDrawType)
{
int i,j;
HRESULT hRet=DD_OK;
RECT rect,rcOHRect,rcESRect,rcOSRect;
//绘制敌方士兵(当前版本始终是第一位敌将出战)
if(sgcGame.sgcHero[sgcGame.sgcCity[sgcGame.sgsArmy.nTermini].nHero[0]].nSoldier>0)
{
//根据敌方士兵状态显示相应图片
switch(sgcGame.GetESState())
{
case SGE_SOLDIERWAIT://待命
sgcGame.nESPicNo=0;
break;
case SGE_SOLDIERRUN://跑步8~19
sgcGame.GetOSLocation(rcOSRect);
sgcGame.GetESLocation(rcESRect);
sgcGame.GetOHLocation(rcOHRect);
//将要显示的图片编号限定在合理的范围内
if(sgcGame.nESPicNo>=19)
sgcGame.nESPicNo=7;
sgcGame.nESPicNo++;
//判断是否碰上我方士兵,没有的话让敌方士兵前进,否则让敌方士兵攻击
if(sgcGame.sgcHero[sgcGame.sgsArmy.nHero[sgcGame.sgcPList.GetSelectItem()]].nSoldier>0)
{
if(rcESRect.left+20>rcOSRect.right-70)
{
rcESRect.left-=SGC_SOLDIER_MOVE;
rcESRect.right-=SGC_SOLDIER_MOVE;
//必须修改座标,否则士兵原地不动
sgcGame.SetESLocation(rcESRect);
}
else
{
//敌方士兵攻击,我方士兵还击
sgcGame.nESPicNo=0;
sgcGame.SetESState(SGE_SOLDIERATTACK);
sgcGame.nOSPicNo=17;
sgcGame.SetOSState(SGE_SOLDIERATTACK);
}
}
else
{
//判断是否碰上我方武将,没有的话让敌方士兵前进,否则让敌方士兵攻击
if(rcESRect.left+70>rcOHRect.right-40)
{
rcESRect.left-=SGC_SOLDIER_MOVE;
rcESRect.right-=SGC_SOLDIER_MOVE;
//必须修改座标,否则士兵原地不动
sgcGame.SetESLocation(rcESRect);
}
else
{
//敌方士兵攻击,我方将领还击
sgcGame.nESPicNo=0;
sgcGame.SetESState(SGE_SOLDIERATTACK);
sgcGame.nOHPicNo=8;
sgcGame.sgcHero[sgcGame.sgsArmy.nHero[sgcGame.sgcPList.GetSelectItem()]].SetHeroState(SGE_HEROATTACK);
}
}
break;
case SGE_SOLDIERATTACK://攻击1~7
if(sgcGame.nESPicNo>=7)
sgcGame.nESPicNo=0;
sgcGame.nESPicNo++;
//如果我方还有士兵,敌兵攻击我方士兵
if(sgcGame.sgcHero[sgcGame.sgsArmy.nHero[sgcGame.sgcPList.GetSelectItem()]].nSoldier>0)
{
if(ShouldAttack(0)==TRUE)
sgcGame.sgcHero[sgcGame.sgsArmy.nHero[sgcGame.sgcPList.GetSelectItem()]].nSoldier--;
if(sgcGame.sgcHero[sgcGame.sgsArmy.nHero[sgcGame.sgcPList.GetSelectItem()]].nSoldier<=0)
{
//跑上前去攻击我方武将
sgcGame.sgcHero[sgcGame.sgsArmy.nHero[sgcGame.sgcPList.GetSelectItem()]].nSoldier=0;
sgcGame.SetOSState(SGE_SOLDIERDIE);
sgcGame.SetESState(SGE_SOLDIERRUN);
sgcGame.nESPicNo=7;
}
}
else//如果我方没有士兵,敌兵攻击我方武将
{
if(ShouldAttack(0)==TRUE)
sgcGame.sgcHero[sgcGame.sgsArmy.nHero[sgcGame.sgcPList.GetSelectItem()]].nThew--;
if(sgcGame.sgcHero[sgcGame.sgsArmy.nHero[sgcGame.sgcPList.GetSelectItem()]].nThew<=0)
{
//如果当前武将战败,从军队中删除此武将
sgcGame.sgcHero[sgcGame.sgsArmy.nHero[sgcGame.sgcPList.GetSelectItem()]].nThew=0;
sgcGame.SetESState(SGE_SOLDIERWAIT);
sgcGame.nESPicNo=0;
for(i=0;i<sgcGame.sgsArmy.nHeroCount;i++)
if(sgcGame.sgsArmy.nHero[i]==sgcGame.sgcPList.GetSelectItem())
break;
//武将被俘
sgcGame.sgcCity[sgcGame.sgsArmy.nTermini].nIncage[sgcGame.sgcCity[sgcGame.sgsArmy.nTermini].nIncageNum]=sgcGame.sgsArmy.nHero[i];
sgcGame.sgcCity[sgcGame.sgsArmy.nTermini].nIncageNum++;
for(j=i;j<sgcGame.sgsArmy.nHeroCount-1;j++)
sgcGame.sgsArmy.nHero[j]=sgcGame.sgsArmy.nHero[j+1];
//如果军队中所有的武将均战败,我军作战失败
sgcGame.sgsArmy.nHeroCount--;
if(sgcGame.sgsArmy.nHeroCount<=0)
{
sgeGameState=SGE_GAMECOMMAND;
sgcCommandScene.SetCommandState(SGE_COMMANDNULL);
sgcGame.sgcMap.SetMapState(SGE_MAPMAP);
}
else//当前武将战败,让下一武将出场
{
sgcGame.sgsArmy.nPage=sgcGame.sgsArmy.nHeroCount/SGC_PLIST_NUM;
if(sgcGame.sgsArmy.nHeroCount%SGC_PLIST_NUM>0)
sgcGame.sgsArmy.nPage++;
sgcGame.sgcPList.SetPage(1);
sgeGameState=SGE_GAMEWAR;
}
sgcGame.sgcPList.SetSelectItem(-1);
}
}
break;
}
rect.left=sgcGame.nESPicNo*160;
rect.top=0;
rect.right=rect.left+160;
rect.bottom=rect.top+106;
sgcGame.GetESLocation(rcESRect);
hRet=pDest->BltFast(rcESRect.left,rcESRect.top,pSoldier,&rect,DDBLTFAST_SRCCOLORKEY);
}
return hRet;
}
俺水平有限,随便乱扔了一点代码,不足之处还望各位高手不吝赐教。如果你发现了Bug或者有好的实现方法,请告诉我。欢迎访问我的网站http://www.0735.com.cn/whstuio