昨天苦命鸳鸯节闲得无聊,就想着能不能抄袭一下之前那个像素画的游戏,经过一下午+一晚上的研究,在昨晚终于把这个小游戏的功能集成到了我的qq机器人里面,效果如下:
这个小游戏的代码实现了以下几个基本功能:
可以通过指令修改置顶区域的颜色
颜色完全可以自定义
判断用户是否是过了五分钟后才再次进行颜色修改的,否则拒绝修改
每次修改保存一张备份图片
机器人使用了酷Q pro版(air免费版无法发送图片),和C#sdk(https://cqp.cc/t/29261)
首先,因为是要修改图片,所以我们需要先在C#工程内引入“System.Drawing”
引用完毕后,在开头加上:
using System.Drawing;
修改图片某一个像素点颜色的方法是“SetPixel”,所以构造方法如下:
public static Bitmap SetPels(Bitmap Pict, Color color, int x, int y, int w, int h) { //遍历矩形框内的各象素点 for (int i = x; i < x + w; i++) { for (int j = y; j < y + h; j++) { Pict.SetPixel(i, j, color);//设置当前象素点的颜色 } } return Pict; }
这样就可以改变指定区域的颜色了,但是qq内发的图片不能精确到指定坐标,毕竟就只是一张图片,所以我把像素点给扩大到了17*17的大小,并且增加了新的方法:
//x,y限制0-29 private static Bitmap SetPoint(Bitmap Pict, Color color, int x, int y) { return SetPels(Pict, color, x * 17, y * 17, 17, 17); }
这样就可以方便地修改指定区域了。
我们再加上一个打开文件的方法:
/// <summary> /// 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 /// </summary> /// <param name="path"></param> /// <returns></returns> public static Bitmap ReadImageFile(string path) { FileStream fs = File.OpenRead(path); //OpenRead int filelength = 0; filelength = (int)fs.Length; //获得文件长度 Byte[] image = new Byte[filelength]; //建立一个字节数组 fs.Read(image, 0, filelength); //按字节流读取 System.Drawing.Image result = System.Drawing.Image.FromStream(fs); fs.Close(); Bitmap bit = new Bitmap(result); return bit; }
有了这些方法,我们就可以进行测试了(提前准备好图片文件):
string picPath = @"C:\Users\Administrator\Desktop\kuqpro\data\image\pixel_game\1.bmp"; Bitmap pic = ReadImageFile(picPath); pic = SetPoint(pic, color.red, 1, 1); pic.Save(picPath);
如果不出意外的话,会在左上方出现一个红色方框,而且不是紧贴着边缘的。
我们接下来处理用户时间的问题,首先先使用xml保存配置文件,我写了以下几个方法,效率可能会很低,建议大家使用其他的方法进行替换:
static string path = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; public static string xml_get(long group, string msg) { dircheck(group); XElement root = XElement.Load(path + group + ".xml"); string ansall = ""; foreach (XElement mm in root.Elements("msginfo")) { if (msg == mm.Element("msg").Value) { ansall = mm.Element("ans").Value; break; } } return ansall; } public static void del(long group, string msg) { dircheck(group); string gg = group.ToString(); XElement root = XElement.Load(path + group + ".xml"); var element = from ee in root.Elements() where (string)ee.Element("msg") == msg select ee; if (element.Count() > 0) { element.First().Remove(); } root.Save(path + group + ".xml"); } public static void insert(long group, string msg, string ans) { if(msg.IndexOf("\r\n") < 0 & msg != "") { dircheck(group); XElement root = XElement.Load(path + group + ".xml"); XElement read = root.Element("msginfo"); read.AddBeforeSelf(new XElement("msginfo", //new XElement("group", group), new XElement("msg", msg), new XElement("ans", ans) )); root.Save(path + group + ".xml"); } } public static void createxml(long group) { XElement root = new XElement("Categories", new XElement("msginfo", //new XElement("group", 123), new XElement("msg", "初始问题"), new XElement("ans", "初始回答") ) ); root.Save(path + group + ".xml"); } public static void dircheck(long group) { if (File.Exists(path + group + ".xml")) { //MessageBox.Show("存在文件"); //File.Delete(dddd);//删除该文件 } else { //MessageBox.Show("不存在文件"); createxml(group);//创建该文件,如果路径文件夹不存在,则报错。 } }
另外,因为我们需要统计时间差,所以我使用了timestamp来记录时间(不会用datetime?,求大佬讲解)
/// <summary> /// DateTime时间格式转换为Unix时间戳格式 /// </summary> /// <param name="time"> DateTime时间格式</param> /// <returns>Unix时间戳格式</returns> public static int ConvertDateTimeInt(System.DateTime time) { System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); return (int)(time - startTime).TotalSeconds; }
于是,整段响应群消息的代码如下:
/// <summary> /// Type=2 群消息。 /// </summary> /// <param name="subType">子类型,目前固定为1。</param> /// <param name="sendTime">发送时间(时间戳)。</param> /// <param name="fromGroup">来源群号。</param> /// <param name="fromQQ">来源QQ。</param> /// <param name="fromAnonymous">来源匿名者。</param> /// <param name="msg">消息内容。</param> /// <param name="font">字体。</param> public override void GroupMessage(int subType, int sendTime, long fromGroup, long fromQQ, string fromAnonymous, string msg, int font) { if (fromQQ == 80000000) return; // 处理群消息。 ...一堆代码 else if(msg.IndexOf("pixel") == 0 && (msg.Length - msg.Replace("/","").Length) == 2) { string fromqqtime_get = xml_get(20, fromQQ.ToString()); int fromqqtime = 0; try { fromqqtime = int.Parse(fromqqtime_get); } catch { } if(ConvertDateTimeInt(DateTime.Now)-fromqqtime < 300) { SendMinecraftMessage(fromGroup, CQ.CQCode_At(fromQQ) + "你需要再等" + (300 - ConvertDateTimeInt(DateTime.Now) + fromqqtime) + "秒才能继续放像素点"); return; } string get_msg = msg.Replace("pixel", ""), getx = "", gety = "", getcolor = ""; int placex, placey; string[] str2; int count_temp = 0; str2 = get_msg.Split('/'); foreach (string i in str2) { if (count_temp == 0) { getx = i.ToString(); count_temp++; } else if (count_temp == 1) { gety = i.ToString(); count_temp++; } else if (count_temp == 2) { getcolor = i.ToString(); count_temp++; } } try { placex = int.Parse(getx) - 1; placey = int.Parse(gety) - 1; if (getcolor.IndexOf("#") == -1 || placex > 29 || placey > 29) throw new ArgumentNullException("fuck wrong color"); } catch { SendMinecraftMessage(fromGroup, "放置像素点时遇到未知错误,请检查颜色与坐标是否正确"); return; } int picCount; try { picCount = int.Parse(xml_get(20, "count")); } catch { SendMinecraftMessage(fromGroup, "遇到致命性错误,请联系晨旭修复"); return; } try { string picPath = @"C:\Users\Administrator\Desktop\kuqpro\data\image\pixel_game\" + picCount + ".bmp"; Bitmap pic = ReadImageFile(picPath); pic = SetPoint(pic, ColorTranslator.FromHtml(getcolor), placex, placey); picCount++; picPath = @"C:\Users\Administrator\Desktop\kuqpro\data\image\pixel_game\" + picCount + ".bmp"; pic.Save(picPath); } catch { SendMinecraftMessage(fromGroup, "遭遇未知错误"); return; } del(20, "count"); del(20, fromQQ.ToString()); insert(20, "count", picCount.ToString()); insert(20, fromQQ.ToString(), ConvertDateTimeInt(DateTime.Now).ToString()); SendMinecraftMessage(fromGroup, "[CQ:image,file=pixel_game\\" + picCount + ".bmp]\r\n图片修改完成!" + DateTime.Now.ToString() + CQ.CQCode_At(fromQQ)); } ...一堆代码 }
如有问题,可以在下面留言。
代码写的比较啰嗦,大佬们请耐心地看?
转载保留版权:晨旭的博客 » 《使用C#写一个QQ群版像素画游戏》如果喜欢可以: 点击右侧上方的邮件订阅,订阅本站