絕地求生晶片壓槍原理分享 遊藝晶片分享
某寶上吹的神乎其神的晶片壓槍簡直。。。,價格膨脹的看不下去。。。
其實原理很簡單的,無非就是飛易來配合自己寫的驅動來實現壓槍
另外什麼
自動識別
武器配件之類的,就是螢幕取色來判斷是裝備了什麼槍械
下面就由筆者帶大家揭秘一下具體原理
武器識別
筆者使用的是
Asprise-OCR
來實現武器名稱識別(取色也可以,只不過需要不同的取色點,要麻煩一些)
1。1 擷取指定位置圖片
Bitmap
image
=
new
Bitmap
(
globalParam
。
weapon0Location
[
“basicSize”
]。
X
,
globalParam
。
weapon0Location
[
“basicSize”
]。
Y
);
Bitmap
image1
=
new
Bitmap
(
globalParam
。
weapon1Location
[
“basicSize”
]。
X
,
globalParam
。
weapon1Location
[
“basicSize”
]。
Y
);
Graphics
imgGraphics
=
Graphics
。
FromImage
(
image
);
imgGraphics
。
CopyFromScreen
(
globalParam
。
weapon0Location
[
“basic”
],
new
Point
(
0
,
0
),
new
Size
(
image
。
Width
,
image
。
Height
));
1。2 裁剪圖片/反轉顏色
private
void
CutImage
(
Bitmap
source
,
string
imageName
)
{
int
width
=
globalParam
。
IdenWeaponImg
。
Width
;
//獲取圖片寬度
int
height
=
globalParam
。
IdenWeaponImg
。
Height
;
//獲取圖片高度
Bitmap
newmap
=
new
Bitmap
(
width
,
height
);
//儲存新圖片
int
x
=
globalParam
。
IdenWeaponPoint
。
X
;
int
y
=
globalParam
。
IdenWeaponPoint
。
Y
;
int
lengthX
=
x
+
width
;
int
lengthY
=
y
+
height
;
int
originX
=
0
;
int
originY
=
0
;
Color
pixel
;
//顏色匹對
for
(
int
i
=
x
;
i
<
lengthX
;
i
++)
{
for
(
int
j
=
y
;
j
<
lengthY
;
j
++)
{
pixel
=
source
。
GetPixel
(
i
,
j
);
//獲取舊圖片的顏色值(ARGB儲存方式)
int
r
,
g
,
b
,
a
;
r
=
pixel
。
R
;
g
=
pixel
。
G
;
b
=
pixel
。
B
;
//白色RGB(255,255,255),黑色(0,0,0)
//判斷是否屬於白色背景
if
(
r
==
255
&&
g
==
255
&&
b
==
255
)
{
//設定新圖片中指定畫素的顏色為黑色
newmap
。
SetPixel
(
originX
,
originY
,
Color
。
FromArgb
(
0
,
0
,
0
));
}
else
if
(
r
==
0
&&
g
==
0
&&
b
==
0
)
{
//設定新圖片中指定畫素的顏色為白色
newmap
。
SetPixel
(
originX
,
originY
,
Color
。
FromArgb
(
255
,
255
,
255
));
}
else
{
newmap
。
SetPixel
(
originX
,
originY
,
Color
。
FromArgb
(
255
-
r
,
255
-
g
,
255
-
b
));
}
originY
++;
}
originY
=
0
;
originX
++;
}
newmap
。
Save
(
imageName
);
}
1。3 呼叫OCR識別圖片中文字即武器名稱
private
string
GetOCR
(
string
imageName
)
{
string
s
=
Marshal
。
PtrToStringAnsi
(
OCR
。
GetOCR
(
imageName
,
-
1
));
LogHelper
。
ShowLog
(
“圖片識別結果 {0}”
,
s
);
return
Regex
。
Replace
(
s
,
@“\s”
,
“”
);
}
1。4 配件識別
private
Dictionary
<
string
,
string
>
QueryAccessories
(
Dictionary
<
string
,
Point
>
dic
,
Bitmap
image
)
{
Dictionary
<
string
,
string
>
result
=
new
Dictionary
<
string
,
string
>();
Point
basePoint
=
dic
[
“basic”
];
Point
baseSize
=
dic
[
“basicSize”
];
Point
points0
=
dic
[
“qiangkou”
];
Point
points1
=
dic
[
“woba”
];
Point
points2
=
dic
[
“danxia”
];
Point
points3
=
dic
[
“qiangtuo”
];
Point
points4
=
dic
[
“scope”
];
//設定截圖區域
string
colorHex4
=
GetImage
(
image
,
basePoint
,
points4
);
string
colorHex3
=
GetImage
(
image
,
basePoint
,
points3
);
string
colorHex2
=
GetImage
(
image
,
basePoint
,
points2
);
string
colorHex1
=
GetImage
(
image
,
basePoint
,
points1
);
string
colorHex0
=
GetImage
(
image
,
basePoint
,
points0
);
LogHelper
。
ShowLog
(
“Get Color: {0}, {1}, {2}, {3} {4}”
,
colorHex0
,
colorHex1
,
colorHex2
,
colorHex3
,
colorHex4
);
Dictionary
<
string
,
Dictionary
<
string
,
string
>>
dict
=
new
Dictionary
<
string
,
Dictionary
<
string
,
string
>>();
if
(
globalParam
。
ScreenHeight
==
1080
)
{
dict
=
colorDict
。
Pixel_1080
;
}
else
if
(
globalParam
。
ScreenHeight
==
1440
)
{
dict
=
colorDict
。
Pixel_1440
;
}
Dictionary
<
string
,
string
>
qiangkouDict
=
dict
[
“qiangkou”
];
qiangkouDict
。
TryGetValue
(
colorHex0
,
out
string
qiangkouValue
);
result
。
Add
(
“qiangkou”
,
qiangkouValue
!=
null
?
qiangkouValue
:
“槍口空”
);
Dictionary
<
string
,
string
>
woBauDict
=
dict
[
“woBa”
];
woBauDict
。
TryGetValue
(
colorHex1
,
out
string
woBaValue
);
result
。
Add
(
“woBa”
,
woBaValue
!=
null
?
woBaValue
:
“握把空”
);
Dictionary
<
string
,
string
>
magazineDict
=
dict
[
“magazine”
];
magazineDict
。
TryGetValue
(
colorHex2
,
out
string
magazineValue
);
result
。
Add
(
“magazine”
,
magazineValue
!=
null
?
magazineValue
:
“無”
);
Dictionary
<
string
,
string
>
qiangTuoDict
=
dict
[
“qiangTuo”
];
qiangTuoDict
。
TryGetValue
(
colorHex3
,
out
string
qiangTuoValue
);
result
。
Add
(
“qiangTuo”
,
qiangTuoValue
!=
null
?
qiangTuoValue
:
“槍托空”
);
Dictionary
<
string
,
string
>
scopeDict
=
dict
[
“scope”
];
scopeDict
。
TryGetValue
(
colorHex4
,
out
string
scopeValue
);
result
。
Add
(
“scope”
,
scopeValue
!=
null
?
scopeValue
:
“1倍鏡”
);
return
result
;
}
至此絕地求生揹包中裝備的武器配件識別完畢
接下來為了配合飛易來還需要壓槍資料以及壓槍演算法
2 壓槍邏輯
筆者經過大量測試最佳化後較穩定的壓槍邏輯
public
static
void
OpenFire
()
{
Player
player
=
Player
。
GetPlay
();
GunsViewModel
gunsViewModel
=
GunsViewModel
。
GetGunsViewModel
();
JichuViewModel
jichuViewModel
=
JichuViewModel
。
GetJichuViewModel
();
bool
_HasAmmo
=
true
;
GlobalParam
globalParam
=
GlobalParam
。
GetGlobalParam
();
MouseStatus
mouseStatus
=
MouseStatus
。
GetMouseStatus
();
AppInfo
appInfo
=
AppInfo
。
GetAppInfo
();
if
(
player
。
runLogic
&&
player
。
isShoot
&&
!
player
。
useMissiles
&&
!
string
。
IsNullOrEmpty
(
player
。
useWeapon
。
weapon
)
&&
!
player
。
useWeapon
。
weapon
。
Equals
(
“空”
))
{
string
[]
str
=
player
。
useWeapon
。
modelData
。
datas
。
Split
(
‘|’
);
double
[]
datas
=
Array
。
ConvertAll
(
str
,
double
。
Parse
);
int
x
=
0
,
y
=
0
;
int
count
=
(
int
)
datas
[
6
];
int
magNum
=
40
;
int
logicTime
=
(
int
)
(
datas
[
7
]
/
datas
[
6
]
-
1
);
Task
。
Run
(()
=>
{
ValiAmmo
(
ref
_HasAmmo
);
});
if
(!
player
。
runXueWuLogic
&&
jichuViewModel
。
XueWu
)
{
player
。
runXueWuLogic
=
true
;
Task
。
Run
(()
=>
{
ExecLogic
(
player
);
});
}
int
index
=
0
;
while
(
mouseStatus
。
leftDown
&&
_HasAmmo
&&
player
。
isShoot
)
{
DateTime
startTime
=
DateTime
。
Now
;
// 判斷是否沒有子彈
double
j
=
0
;
if
(
magNum
==
40
)
{
j
=
datas
[
0
];
index
=
0
;
}
else
if
(
magNum
<
40
&&
magNum
>=
34
)
{
j
=
datas
[
1
];
index
=
1
;
}
else
if
(
magNum
<
34
&&
magNum
>=
27
)
{
j
=
datas
[
2
];
index
=
2
;
}
else
if
(
magNum
<
27
&&
magNum
>=
19
)
{
j
=
datas
[
3
];
index
=
3
;
}
else
if
(
magNum
<
19
&&
magNum
>=
9
)
{
j
=
datas
[
4
];
index
=
4
;
}
else
{
j
=
datas
[
5
];
index
=
5
;
}
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
if
(
_HasAmmo
&&
player
。
isShoot
)
{
YouyiSdk
。
M_MoveR2
(
globalParam
。
m_Handle
,
0
,
(
int
)
j
);
Task
。
Run
(()
=>
{
if
(
index
!=
globalParam
。
DataIndex
)
{
globalParam
。
DataIndex
=
index
;
gunsViewModel
。
RaisePropertyChanged
(
“Datas”
);
}
LogHelper
。
ShowLog
(
“壓槍耗時 {0} 壓槍幅度:{1} 步進:{2}”
,
0
,
j
,
i
);
});
Thread
。
Sleep
(
logicTime
);
}
}
magNum
-=
1
;
Task
。
Run
(()
=>
{
ValiAmmo
(
ref
_HasAmmo
);
Task
。
Run
(()
=>
{
ValiShoot
(
globalParam
,
player
);
});
});
}
}
}
以上就是整個壓槍晶片驅動中比較核心的邏輯
ps: 寫java後臺的菜鳥,業餘時間現學C#現賣的程式碼,各位多多包涵
某大型同性交友網站有完整原始碼
注意!本軟體不得用於商業用途,僅做學習交流使用