三国英雄传实现细节及部分源代码

 

 俺用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

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值