本人比较喜欢下四国军棋,由于网上并没有一款好的四国军棋单机版软件,所以打算自己开发一个。软件分为界面和引擎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