GTK+C语言+CSS开发的小系统 socket局域网聊天+音乐播放器+贪吃蛇游戏 && C语言做界面

我用假期的时间做了一个GTK小系统,组合了之前我学习的GTK知识,并且加入了C语言的链表等工具,结合了C语言的知识,开发了这个小程序,用的环境是VS2015配置的GTK还有socket编程,以及添加了很少部分的CSS知识,首先先看几张截图,之后我会一个一个的讲解小系统的组成以及制作过程,供大家参考,本人水平有限,作品只给大家提供一个思路。
小系统的桌面截图
然后用了一点点css的知识,主界面有鼠标停留滑动效果
这里写图片描述
在我的上一篇博客中写到GTK的版本问题,这个版本的CSS我觉得还是不成熟,但是可以加入一些GTK支持的CSS格式,来让我们的界面更加漂亮!
然后是各个功能的界面效果:

  1. Hello World Chat
    这里写图片描述
  2. Music Player
    这里写图片描述

  3. Snake Game
    这里写图片描述

  4. Connect Me
    这里写图片描述

  5. 最后两个内容是最小化和关闭按钮,同时此系统的最小化可以到系统托盘,这里就不截图了。


以上就是这个系统的全部界面部分,随着博客的更新,我会把小系统全部的小界面制作过程介绍出来!

Hello World Chat

Hello World Chat是一个局域网聊天的界面,有一个服务端和一个客户端,这个客户端可以发到局域网的电脑里面,这样当你打开服务端的时候,好几个客户端可以连接,然后可以一起聊天。首先是学习socket,但是不用学习什么tcp/ip好几本书啥的,我们只是想做一个互相聊天的界面,只要能有这些功能就可以,并且关于socket的知识,你完全可以参考百度C语言socket那几个函数。
网上关于socket的例子很多,当你想学习socket时,最多出现的就是server和client这样的结构的,但是包括百度搜索socket都有一个简单的socket服务端和客户端,但是当你仔细的阅读并且想要把那些代码复制下来编译的时候你就会发现,那些很多都是单向通讯,服务端永远都在

whiletrue)
{
    int ret = recv(sclient,revData,255,0);
    if(ret)
    {
        ......//打印消息或者是显示消息到某一个界面上。
    }
}   

但是这样的问题是server端没有办法发出消息,client端没有办法接收消息,所有的信息都被阻塞到了while这里,你试想一个完整的客户端是可以接收别人的消息并且发送自己的消息的,而且当程序阻塞到了while这里,先看一个例子,也是我编程过程中出现的问题

#include<gtk/gtk.h>
#include<......>

int main(int argc,char *argv[])
{
    GtkWidget *window;
    gtk_init(&argc,&argv);
    window = .......


    while(true)
    {
        //socket接收信息
    }   

    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}

试想不谈界面功能的问题,这样的GTK界面是不会显示出来的,因为程序全部阻塞到了while这里,GTK的界面没有到达gtk_main()是不会出来的。这和C语言不同,当你用C语言无线循环一个东西时,cmd会出现并且正常运行的。所以想做出一个真正的聊天工具,也就是全双工通讯,我们需要开线程,首先让我们的界面到达
gtk_main()这个函数,所以我们要用到多线程,gtk的多线程很简单,当然你也可以使用C语言Windows的多线程,多个线程同时工作完成我们的功能。
然后我们修改一下我们的思路,既然是server/client模式,我们就把server当做真正的服务器,包括我们制作者都要用和其它人一样的client端聊天,server端起到的作用是

  1. 接收任何客户端的连接,并且建立连接
  2. 当一个客户端发送消息过来的时候,server会发送消息到所有的建立连接的客户端中去

    当你知道需求之后,这个服务端是不用做出界面来的,他只负责开端口接收连接并且发送消息。

我们要建立一个结构体存放连接进来的客户端的信息:

struct _client {
    int socket;
    gboolean in_use;
    char name[64];
    char buf[1024];
};

看到这个结构体我们就可以知道如果一个客户端名字叫小红的人发过来一个:大家好,我们服务端发送的格式就是

小红:大家好

既然不需要建立界面,所以server端可以节省一个线程,int main下面直接来一个while,用来接收client的连接,如果有client连接,马上开辟一个线程处理client的事情,即发送消息等等。

同时客户端的作用是:

  1. 建立socket连接server
  2. 接收从server端口发出的消息

客户端要以界面的形式呈献出来,所以int main 下面不要有阻塞,直接开辟线程来接收消息,而发送消息则比较简单,用一个GtkEntry,捕捉ENTER信号,当ENTER的时候运行到函数发送消息。

到这里,聊天的基本的东西和思想都在这里了

Music Player

Music Player是一个音乐播放器,我们实现的功能是:

  1. 添加歌曲到歌单
  2. 可以播放歌曲(当然了)
  3. 播放完音乐之后可以自动播放下一首
  4. 有暂停功能
  5. 自己的歌单可以保存,也就是下一次打开这个系统的时候,可以播放自己的歌单,而不是一次性的东西

说到音乐播放器,我们找到播放音乐的函数,C语言有mciSendString函数,mciSendString是用来播放多媒体文件的API指令,可以播放MPEG,AVI,WAV,MP3,等等,它的一般使用方法是:

  1. 播放音乐 mciSendString(TEXT(“open now_play_music.mp3 alias mymusic”), NULL, 0, NULL);
    mciSendString(TEXT(“play mymusic”), NULL, 0, NULL);
  2. 暂停音乐mciSendString(TEXT(“pause mymusic”), NULL, 0, NULL);
  3. 继续播放mciSendString(TEXT(“resume mymusic”), NULL, 0, NULL);
  4. 关闭音乐mciSendString(TEXT(“close mymusic”), NULL, 0, NULL);非常重要,因为不关闭一首音乐是不能打开另一首音乐的,即使这首音乐已经播放完毕。

另一个播放音乐的函数是PlaySound函数,但是这个函数只能播放WAV格式的音乐,一般的音乐如果转换成这个形式的话,文件的大小会非常大,所以不建议用这个函数。


从打开音乐到播放音乐,播放完毕之后关闭音乐,再打开另一首音乐,如此循环就达到了播放完一首就播放另一首的目的我的思路是把歌单的音乐存放到链表里面,

typedef struct node {
    char TITLE[30];//名字
    char ARTIST[30];//作者
    double TIME;//歌曲的时间
    double SIZE;//歌曲的大小
    gboolean NPLAY;//是否正在播放
    struct node *next;
}NODE;//一共五个数据 建立一个链表

每次播放音乐的时候获取音乐的title(歌名),仿照mciSendString的格式,用sprintf存放到一个字符串中,这个字符串就是mcisendstring的第一个参数
“open myworld.mp3 alias mymusic”,(myworld.mp3是一首歌的名字)然后这个字符串即使是TEXT格式,也无法播放音乐,我不知道大家使用这种方法是不是能播放音乐,后来我又想了一个方法,叫以不变应万变,我始终打开同一个名字的音乐 歌名就叫做now_play_music.mp3,然后把要播放的音乐用C语言重命名为now_play_music.mp3然后就解决了这个问题,每当播放完毕或者是关闭音乐播放器的时候,让C语言把now_play_music.mp3改为歌曲本来的名字,这个方法很巧妙的解决了mcisendstring的问题,并且实现了我们需要的所有功能。

再者就是音乐的存放问题,我们的歌单要保存起来,并且在每次打开播放器的时候都要加载歌单,以达到像酷狗一样的功能,所以我的想法就是把歌单存放到文件中,我们再按照格式读取文件,加载到链表中,每次打开播放器的时候加载,每次关闭播放器的时候把新数据写到文件中,这样就实现了音乐歌单的保存问题。

//判断歌曲是否播放完毕
unsigned char length[128] = { 0 };
    mciSendString(TEXT("status mymusic mode"), length, sizeof(length), 0);
if (!strcmp(length, "s"))
{
    //播放完毕之后处理  播放完毕之后会输出S
}

还有, 推荐一个音乐库,叫libzplay,这个库可以让我们非常方便的播放音乐,而且使用非常简单,但是唯一的缺点就是纯C语言用不了的,其它的功能非常强大,比如我们需要获取音乐的总时间,当前正在播放的时间,音乐的歌手,歌名,专辑…..自己在windows下面用winapi会出现问题的。
到这里,音乐播放器的基本思路都完成了

Snake Game

Snake Game是贪吃蛇游戏,用键盘的上下左右或者是wasd控制小蛇的左右移动,我们要实现的功能是:

  1. 小蛇可以移动
  2. 碰撞检测,碰墙GAMEOVER,自己碰自己GAMEOVER
  3. 积分功能
  4. 吃到豆子之后身体的长度增加
  5. 暂停游戏 继续游戏功能

贪吃蛇的界面就是60*40的格子,为什么可以用GTK来做呢,我们可以用一个一个的小照片来填充那些格子,我们定义三种GdkPixbuf

 1.GdkPixbuf *pix_background = NULL;//背景图片
 2.GdkPixbuf *pix_snake = NULL;//蛇图片
 3.GdkPixbuf *pix_bean = NULL;//豆子图片

什么是界面,把pix_background填充60*40就是我们需要的背景,什么是蛇,pix_snake填充的就是蛇,什么是豆子,随机一个地方把图片换成pix_bean就是蛇
怎样记录蛇的坐标,建立一个二维数组

char locate[100][2];//蛇的整体的数组

从定义可以看出,我们的蛇最长就是100,locate[0]即为蛇的x坐标locate[1]即为蛇的y坐标。
那么怎么让蛇动起来呢?

最重要的就是建立一个timeout
每隔某个时间运行一下某一个函数,而这个函数就会检测蛇的方向,从而改变locate[100][2]的坐标,然后我们把改变了的坐标换上pix_snake,这样一个动态的蛇就做成了。

小蛇怎么吃豆子呢?
这就是碰撞检测,一直检测蛇头的坐标和豆子的坐标。
同时也要检测贪吃蛇的自己是否碰到自己。

到这里,贪吃蛇的基本思路就完成了

我会把我的vs2015的工程上传到我的博客中,希望能帮助大家,谢谢!

附上全部资源下载地址点击下载

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值