四国军棋界面开发(1) 棋盘与棋子

本人比较喜欢下四国军棋,由于网上并没有一款好的四国军棋单机版软件,所以打算自己开发一个。软件分为界面和引擎2部分,为了可维护性和降低开发难度的考虑,使用C语言作为开发语言,界面用的是GTK+ 3。

开发顺序是先完成界面的开发,再开发引擎。本文就来介绍棋盘与棋子的显示。

1.界面布局

每一个界面软件都要新建一个窗口,GTK也不例外,代码如下

int main(int argc, char *argv[])
{
    GtkWidget *window;
    gtk_init(&argc,&argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "四国军棋");
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    //gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
    g_signal_connect(window, "destroy", gtk_main_quit, NULL);

    BoardInit(window);

    gtk_widget_show_all(window);

    gtk_main();
    return 0;
}

由于在GTK+中,窗口是单控件容器,所以需要新建一个盒状容器,盒状容器放在窗口上,然后再在盒状容器中存放其他控件。创建步骤如下:
1.先建一个横向hbox,把它放在窗口容器里
2.再新建一个纵向vbox,将其放在hbox第1格
3.菜单可以放在vbox的第1格(目前暂时不用)
4.新建1个固定布局的容器fixed放在vbox
5.此后所有的控件都放在fixed里

    GtkWidget *vbox, *hbox, *vbox2;

    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_container_add (GTK_CONTAINER (window), hbox);
    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
    vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
   // set_menu(vbox2);

    GtkWidget *fixed = gtk_fixed_new();
    gtk_box_pack_start (GTK_BOX (vbox), fixed, TRUE, TRUE, 0);

2.显示棋盘

新建一块画布,棋盘由图片导入,再把该图片画在画布上作为背景图片

    GtkWidget* draw_area = gtk_drawing_area_new();
    GtkWidget *fixed = gtk_fixed_new();
    gtk_box_pack_start (GTK_BOX (vbox), fixed, TRUE, TRUE, 0);
    gtk_widget_set_size_request(draw_area, 733,688);
    gtk_fixed_put(GTK_FIXED(fixed), draw_area, 0, 0);
    background = gdk_pixbuf_new_from_file("./res/1024board.bmp", NULL);
    g_signal_connect (draw_area, "draw",G_CALLBACK (draw_cb), NULL);
static GdkPixbuf *background;

static gint draw_cb (
     GtkWidget *widget,
     cairo_t   *cr,
     gpointer   data)
{
  gdk_cairo_set_source_pixbuf (cr, background, 0, 0);
  cairo_paint (cr);

  return TRUE;
}

3.按钮

最基本的需求是每一家都有一个调入布局的按钮来调入布局,另外还有一个开始按钮,代表调度完成开始行棋,开始后该按钮变为走棋来强制软件出招。

调入布局是一个带图片的按钮,需要把原按钮设置透明

        gtk_button_set_image(GTK_BUTTON(button[i]), image);
        gtk_button_set_relief(GTK_BUTTON(button[i]),GTK_RELIEF_NONE);
        switch(i)
        {
        case 0:
            gtk_fixed_put(GTK_FIXED(fixed), button[i], 470,621);
            break;
        case 1:
            gtk_fixed_put(GTK_FIXED(fixed), button[i], 614,202);
            break;
        case 2:
            gtk_fixed_put(GTK_FIXED(fixed), button[i], 169,40);
            break;
        case 3:
            gtk_fixed_put(GTK_FIXED(fixed), button[i], 60,452);
            break;
        default:
            break;
        }

点击开始后,把调入布局按钮隐藏掉

    for(int i=0; i<4; i++)
    {
        gtk_widget_hide(board.button[i]);
    }

4.显示棋子

首先制作四家的棋子图片素材,有如下4张图片,如下图所示:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

先导入图片素材,再对具体某一颜色的棋子进行分割,获取每一个棋子,以橙色为例

pJunqi->ChessImage[ORANGE] = gdk_pixbuf_new_from_file("./res/orange.bmp",NULL);

获取棋子时要注意橙绿与蓝紫的长宽是不一样的,要注意区分

    if( color==ORANGE || color==GREEN )
    {
        iWidth = 36;
        iHeight = 27;
    }
    else
    {
        iWidth = 27;
        iHeight = 36;
    }

把取得的棋子保存在pJunqi->Chess在后续调入布局时使用

    pColor = pJunqi->ChessImage[color];

    for(i=JUNZH; i<=GONGB; i++)
    {
        pJunqi->Chess[color][i] = gdk_pixbuf_new_subpixbuf(pColor,(i-5)*iWidth,0,iWidth,iHeight);
    }

根据布阵文件取得布阵时棋子的位置,布局文件的格式为参考下面网友给出的文档说明
https://wenku.baidu.com/view/0234a33c67ec102de2bd8977.html

每一方有25颗棋子,加上5个行营总共是30颗,也就是一个5*6的矩阵

void InitLineup(Junqi *pJunqi, enum ChessColor color)
{
    int fd;
    u8 aBuf[4096];
    Jql *pLineup;
    int i;
    fd = open("./res/5.jql", O_RDWR|O_CREAT, 0600);
    OsRead(fd, aBuf, 4096, 0);
    pLineup = (Jql*)(&aBuf[0]);
    if( memcmp(pLineup->aMagic, aMagic, 4)!=0 )
    {
        assert(0);
    }
    for(i=0; i<30; i++)
    {
        pJunqi->ChessPos[color][i].type = pLineup->chess[i];
    }

}

最后就是根据布阵把相应的棋子画在棋盘上,每一家棋子的方位都不一样,需要事先计算好

    for(i=0;i<30;i++)
    {
        iType = pJunqi->ChessPos[color][i].type;
        if( iType!=NONE )
        {
            assert( iType>NONE && iType<=GONGB );
            pPixbuf = pJunqi->Chess[color][iType];
            pImage = gtk_image_new_from_pixbuf(pPixbuf);
            pJunqi->ChessPos[color][i].pImage = pImage;
            switch(color)
            {
            case ORANGE:
                gtk_fixed_put(GTK_FIXED(pJunqi->fixed), pImage, 265+(i%5)*40,13+(i/5+11)*39);
                break;
            case PURPLE:
                gtk_fixed_put(GTK_FIXED(pJunqi->fixed), pImage, 38+(i/5+11)*39,242+(4-i%5)*39);
                break;
            case GREEN:
                gtk_fixed_put(GTK_FIXED(pJunqi->fixed), pImage, 265+(4-i%5)*40,13+(5-i/5)*39);
                break;
            case BLUE:
                gtk_fixed_put(GTK_FIXED(pJunqi->fixed), pImage, 38+(5-i/5)*39,242+(i%5)*39);
                break;
            default:
                break;
            }
        }
    }

最后效果如下图所示
这里写图片描述

5.参考资料及源代码

GTK+开发环境搭建
https://blog.csdn.net/pfysw/article/details/81048379
GTK+ 3 基础知识学习
https://blog.csdn.net/pfysw/article/details/81190404
源代码
https://github.com/pfysw/JunQi

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页