四国军棋界面开发(5)吃子规则与声音效果

之前已经完成了对行棋路线的判定,接下来需要实现对军棋中吃子规则的判定

1.大小比较

只有在行棋路线合法的情况下才比较大小,比较棋子大小的函数为CompareChess

输入的参数是选中的棋子和目标棋子(也可能目标位置上没棋子),返回值是比较的结果,比较的结果有4种,分别如下:

  • 移动
  • 吃掉
  • 打兑
  • 碰死

    如果目标位置上没棋,那么说明是没有比较,只是棋子的移动。如果一方有炸弹,则判定为打兑,这个优先级最高。在没炸弹时,目标棋子为军旗,则判定为吃掉。接着如果目标棋子是地雷,除工兵外,都判定为撞死,工兵可以挖雷,判定为吃掉。除去以上棋子,接着就是司令~工兵这9个种类型的棋子之间的比较了,将会产生吃掉、打兑或撞死3种结果,代码如下:

int CompareChess(BoardChess *pSrc, BoardChess *pDst)
{
    enum CompareType result;
    assert( pSrc->type!=NONE );
    if( pDst->type==NONE )
    {
        result = MOVE;
    }
    else if( pDst->type==ZHADAN||pSrc->type==ZHADAN )
    {
        result = BOMB;
    }
    else if( pDst->type==JUNQI )
    {
        result = EAT;
    }
    else if( pDst->type==DILEI )
    {
        if( pSrc->type==GONGB )
        {
            result = EAT;
        }
        else
        {
            result = KILLED;
        }
    }
    else
    {
        assert( pDst->type>=SILING && pDst->type<=GONGB &&
                pSrc->type>=SILING && pSrc->type<=GONGB );
        if( pDst->type == pSrc->type )
        {
            result = BOMB;
        }
        else if( pSrc->type<pDst->type )
        {
            result = EAT;
        }
        else
        {
            result = KILLED;
        }
    }

    return result;
}

2.行棋结果

有了比较的结果之后,需要根据结果来显示棋子,另外除了以上4种判定结果外,有时候还有一些附加效果要处理,如司令死掉后要亮军旗,军旗被挖后,这一家的所有棋子都要消失。最后的处理看下面的注释说明:

//输入参数是原位置和目标位置,type为上一次比较的结果
void PlayResult(Junqi *pJunqi, BoardChess *pSrc, BoardChess *pDst, int type)
{
    //不管是移动还是吃子,都要把选中的棋子移到目标位置上
    if( type==EAT || type==MOVE )
    {
        gtk_fixed_move(GTK_FIXED(pJunqi->fixed),
                       pSrc->pLineup->pImage[pDst->iDir],
                       pDst->xPos,pDst->yPos);
        SendSoundEvent(pJunqi,MOVE);

    }
    //如果是吃子或打兑,需要把目标位置上的棋子隐藏掉
    if( type==EAT || type==BOMB )
    {
        assert(pDst->type!=NONE);
        gtk_widget_hide(pDst->pLineup->pImage[pDst->iDir]);
        if( pDst->pLineup->pFlag )
        {
            gtk_widget_destroy(pDst->pLineup->pFlag);
            pDst->pLineup->pFlag = NULL;
        }
        if( type==BOMB )
        {
            pDst->type = NONE;
            SendSoundEvent(pJunqi,BOMB);
        }
        else
        {
            SendSoundEvent(pJunqi,EAT);
        }
        //吃掉或炸掉的可能是军旗,那么移除军旗所在这一家的所有棋子
        if( pDst->pLineup->type==JUNQI )
        {
            SendSoundEvent(pJunqi, DEAD);
            DestroyAllChess(pJunqi, pDst->iDir);
        }
    }
    //pLineup保存该棋子的图片,将目标位置上的棋子替换为原选中棋子
    if( type==EAT || type==MOVE )
    {
        //之所以现在更新pDst,是因为之前还要判断是否是军旗
        pDst->type = pSrc->pLineup->type;
        pDst->pLineup = pSrc->pLineup;
        //如果有标棋,那么标棋也要跟着移动
        if(pSrc->pLineup->pFlag)
        {
            MoveFlag(pJunqi,pDst,1);
        }
    }
    //司令死后,需要调用ShowBanner显示军旗位置
    if( type==KILLED || type==BOMB )
    {
        if( type==KILLED )
        {
            SendSoundEvent(pJunqi,KILLED);
            //此处是司令撞地雷
            if( pSrc->pLineup->type==SILING )
            {
                ShowBanner(pJunqi, pSrc->pLineup->iDir);
            }
        }
        //撞死或打兑,原棋子已经不存在,相应的标记也要清除
        if(pSrc->pLineup->pFlag)
        {
            gtk_widget_hide(pSrc->pLineup->pFlag);
        }
        if( type==BOMB )
        {
            //打兑时还要判断是否有司令,从而显示军旗位
            if( pSrc->pLineup->type==SILING )
                ShowBanner(pJunqi, pSrc->pLineup->iDir);
            if( pDst->pLineup->type==SILING )
                ShowBanner(pJunqi, pDst->pLineup->iDir);
        }
    }

    assert( pSrc->pLineup->type!=NONE );
    //无论哪一种情况都要隐藏原来位置上的棋子
    gtk_widget_hide(pSrc->pLineup->pImage[pSrc->iDir]);
    pSrc->type = NONE;
    if( type==EAT || type==MOVE )
    {
        //把棋子显示到目标位置上
        gtk_widget_show(pDst->pLineup->pImage[pDst->iDir]);
    }
    //在目标位置上画红色方框表示移动目的地
    ShowRectangle(pJunqi, pDst, RECTANGLE_RED);
    //最后画上行棋路径的箭头
    ShowPathArrow(pJunqi, 0);

}

3.声音效果

播放声音需要调用windows下的 PlaySound函数,另外要添加mmsystem.h头文件和winmm.dll库。

首先定义各种类型的声音文件路径

#define MOVE_SOUND         "./sound/move.wav"
#define BOMB_SOUND         "./sound/bomb.wav"
#define EAT_SOUND          "./sound/eat.wav"
#define KILLED_SOUND       "./sound/killed.wav"
#define DEAD_SOUND         "./sound/dead.wav"
#define SHOW_FLAG_SOUND    "./sound/showflag.wav"
#define SELECT_SOUND       "./sound/select.wav"
#define BEGIN_SOUND        "./sound/begin.wav"

如果需要播放打兑的声音,则调用如下:

PlaySound (BOMB_SOUND, NULL, SND_FILENAME | SND_NODEFAULT);

要注意的是在上面PlayResult ()的行棋过程处理中不要直接播放声音,否则会等声音播放完毕后再显示棋子的移动会产生很强烈的延迟感觉。所有为了先让棋子移动后再播放声音,把声音播放放在一个0.5秒的定时器回调函数里

g_timeout_add(500, (GSourceFunc)sound_event, pJunqi);

根据pJunqi->sound_type的类型播放相应的声音

void sound_event(gpointer data)
{
    switch(pJunqi->sound_type)
    {
        ... ...
    }
}

最后只要在声音事件产生后对pJunqi->sound_type赋值即可

void SendSoundEvent(Junqi *pJunqi, enum CompareType type)
{
    pJunqi->sound_type = type;
}

4.源代码

https://github.com/pfysw/JunQi

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我的毕业设计,实现了一个具有小型网络游戏特征的四国军旗游戏,有一个完整的框架,数据库、服务器、客户端、大厅、游戏框架、玩家信息、游戏中的聊天、广告信息、以及防止了闪烁的画面,游戏音乐等 给网络游戏的初学者一些参考 文件列表如下: 网络游戏-四国军棋 .................\客户端.exe .................\数据库 .................\......\user_Data.MDF .................\......\user_Log.LDF .................\服务器.exe .................\毕业论文说明书 .................\..............\中文封面.doc .................\..............\中文摘要.doc .................\..............\任务书.doc .................\..............\文献综述.doc .................\..............\文献综述封面.doc .................\..............\答辩申请表.doc .................\..............\网络游戏-四国军棋论文.doc .................\..............\英文封面.doc .................\..............\英文摘要.doc .................\..............\评阅表.doc .................\..............\鉴定意见表.doc .................\源程序 .................\......\CGameHallFrame .................\......\..............\CGameHallFrame.aps .................\......\..............\CGameHallFrame.cpp .................\......\..............\CGameHallFrame.dsp .................\......\..............\CGameHallFrame.dsw .................\......\..............\CGameHallFrame.h .................\......\..............\CGameHallFrame.ncb .................\......\..............\CGameHallFrame.opt .................\......\..............\CGameHallFrame.plg .................\......\..............\CGameHallFrame.rc .................\......\..............\CGameHallFrameDoc.cpp .................\......\..............\CGameHallFrameDoc.h .................\......\..............\CGameHallFrameView.cpp .................\......\..............\CGameHallFrameView.h .................\......\..............\Client.cpp .................\......\..............\Client.h .................\......\..............\ClientProtocol.cpp .................\......\..............\ClientProtocol.h .................\......\..............\Debug .................\......\..............\GameDlg.cpp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值