Defina 游戏介绍
Defina Finance是一款区块链游戏,它利用并融合了DeFi(去中心化金融)和NFT(非同质化通证)技术让玩家拥有属于自己的游戏资产。玩家可以购买或收集各种NFT神秘盒子来获得英雄和武器,在众多游戏场景中学习技能。参与DeFi收益耕作,在享受PVP和PVE模式的有趣且具有战略意义的卡牌游戏的同时,获得丰厚的链上收益。
腳本交流微信群
开发语言:C#
基本思路
使用图像识别技术,通过机器学习的方式,识别游戏页面的元素,提取出对应内容,然后进行相应操作。
- 工具库:WIN32函数 (鼠标、键盘的模拟,窗口查找等等)下载
游戏界面识别的配置信息(识别出当前在什么界面,如首页、采矿页面等等)
[
{
"Page": "Loading", // 游戏等待页面
"x": 352,
"y": 649,
"width": 10,
"height": 25,
"hash": [ "0001111111111111111111111000000110000001100000011011000110111001" ]
},
{
"Page": "Login", // 登录页面
"x": 389,
"y": 580,
"width": 184,
"height": 45,
"hash": [ "1100000110000001100000011000111110001001100111111000000110000001" ]
},
{
"Page": "Home", // 主页
"x": 889,
"y": 434,
"width": 30,
"height": 30,
"hash": [
"1000000010110000100110111000111110001110100111111001101110100000",
"1000000010000000100110101000111110000110100011111001100110010000",
"0000000001100001001100100001111000011100001111100011011101000001",
"0000000001000001011000100011110000011100001111100111010001001011",
"0000000101100011001101100001111000011100001101100110011100000001",
"0000000001000001011000100011011000011100001111100011011001100011"
]
},
{
"Page": "Mine", // 矿场页面
"x": 155,
"y": 474,
"width": 160,
"height": 160,
"hash": [ "0000000100000101000000110000000000100000100000100000111100001100" ]
},
{
"Page": "MyMine", // 我的矿场
"x": 302,
"y": 228,
"width": 98,
"height": 32,
"hash": [ "0000000000111100001000000100010001000100001111000011110000111100" ]
},
{
"Page": "Fighting", // 抢矿战斗页面
"x": 1135,
"y": 596,
"width": 112,
"height": 112,
"hash": [ "0000000000000001001000000111110000011001011111000010100000010101" ]
},
{
"Page": "Hero", // 选英雄的页面
"x": 71,
"y": 135,
"width": 140,
"height": 35,
"hash": [ "0000000000100110001011010011111100110110001111100011100000001010" ]
},
{
"Page": "Victory", // 战斗胜利
"x": 387,
"y": 108,
"width": 520,
"height": 122,
"hash": [ "0111001001111000011000100111000001110010011111100111000001110000" ]
},
{
"Page": "Fail", // 战斗失败
"x": 498,
"y": 104,
"width": 280,
"height": 130,
"hash": [ "0000000000111110001010000000111100111110000000010000000000000001" ]
},
{
"Page": "Round", // 战斗中
"x": 1032,
"y": 657,
"width": 85,
"height": 85,
"hash": [ "1101111011111100110110001101100011111000110010001100100011111101" ]
}
]
关键函数
截取图片
/// <summary>
/// 剪裁图片
/// </summary>
/// <param name="image">源图</param>
/// <param name="x">坐标 X</param>
/// <param name="y">坐标 Y</param>
/// <param name="width">剪裁的宽度</param>
/// <param name="height">剪裁的高度</param>
/// <returns></returns>
public static Image Cut(this Image image, int x, int y, int width, int height)
{
using (Bitmap bitmap = new(image))
{
Rectangle area = new(x, y, width, height);
Bitmap bmpCrop = bitmap.Clone(area, bitmap.PixelFormat);
return bmpCrop;
}
}
使用图片生成hash码
/// <summary>
/// 获取图片的指纹哈希
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
public static string GetHash(this Image bitmap, int width = 8, int height = 8)
{
//#1 Reduce size to 8*8
//将图片缩小到8x8的尺寸, 总共64个像素. 这一步的作用是去除各种图片尺寸和图片比例的差异, 只保留结构、明暗等基本信息.
Image image = bitmap.GetThumbnailImage(width, height, () => false, IntPtr.Zero);
//#2 Reduce Color
//将缩小后的图片, 转为64级灰度图片.
Bitmap bitMap = new(image);
byte[] grayValues = new byte[image.Width * image.Height];
for (int x = 0; x < image.Width; x++)
{
for (int y = 0; y < image.Height; y++)
{
Color color = bitMap.GetPixel(x, y);
byte grayValue = (byte)((color.R * 30 + color.G * 59 + color.B * 11) / 100);
grayValues[x * image.Width + y] = grayValue;
}
}
//#3 Average the colors
//计算图片中所有像素的灰度平均值
int sum = 0;
for (int i = 0; i < grayValues.Length; i++)
sum += (int)grayValues[i];
byte avgByte = Convert.ToByte(sum / grayValues.Length);
//#4 Compute the bits
//将每个像素的灰度与平均值进行比较, 如果大于或等于平均值记为1, 小于平均值记为0.
char[] result = new char[grayValues.Length];
for (int i = 0; i < grayValues.Length; i++)
{
if (grayValues[i] < avgByte)
result[i] = '0';
else
result[i] = '1';
}
// 将上一步的比较结果, 组合在一起, 就构成了一个64位的二进制整数, 这就是这张图片的指纹.
return new(result);
}
比对两张图片是否一致
当比对结果小于5的时候,我们一般认为两张图片一致
public static int CompareImage(this string hash1, string hash2)
{
if (hash1.Length != hash2.Length)
throw new ArgumentException();
int count = 0;
for (int i = 0; i < hash1.Length; i++)
{
if (hash1[i] != hash2[i])
count++;
}
return count;
}