auto search shiny done.

This commit is contained in:
yanweitong 2023-08-22 00:01:59 +08:00
parent ea08b62096
commit 87ca8c6ec8
15 changed files with 917 additions and 58 deletions

191
Cargo.lock generated
View File

@ -241,6 +241,27 @@ dependencies = [
"windows",
]
[[package]]
name = "errno"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "exr"
version = "1.7.0"
@ -257,6 +278,12 @@ dependencies = [
"zune-inflate",
]
[[package]]
name = "fastrand"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
[[package]]
name = "fdeflate"
version = "0.3.0"
@ -400,6 +427,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lebe"
version = "0.5.2"
@ -422,6 +455,12 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
[[package]]
name = "lock_api"
version = "0.4.10"
@ -434,9 +473,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.19"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "malloc_buf"
@ -500,7 +539,11 @@ dependencies = [
"crossterm",
"enigo",
"image",
"log",
"rand",
"rusty-tesseract",
"screenshots",
"simple-logging",
]
[[package]]
@ -576,7 +619,7 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"redox_syscall 0.3.5",
"smallvec",
"windows-targets",
]
@ -626,6 +669,12 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.66"
@ -662,6 +711,36 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rayon"
version = "1.7.0"
@ -684,6 +763,12 @@ dependencies = [
"num_cpus",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "redox_syscall"
version = "0.3.5"
@ -693,6 +778,32 @@ dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "rustix"
version = "0.38.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
dependencies = [
"bitflags 2.4.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "rusty-tesseract"
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af2176026d24dbb67968571c7d464d287934820490ece864e17b88d2e5e3eee8"
dependencies = [
"image",
"subprocess",
"substring",
"tempfile",
"thiserror",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -753,6 +864,17 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "simple-logging"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b00d48e85675326bb182a2286ea7c1a0b264333ae10f27a937a72be08628b542"
dependencies = [
"lazy_static",
"log",
"thread-id",
]
[[package]]
name = "smallvec"
version = "1.11.0"
@ -768,6 +890,25 @@ dependencies = [
"lock_api",
]
[[package]]
name = "subprocess"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "substring"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86"
dependencies = [
"autocfg",
]
[[package]]
name = "syn"
version = "2.0.28"
@ -779,6 +920,50 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
dependencies = [
"cfg-if",
"fastrand",
"redox_syscall 0.3.5",
"rustix",
"windows-sys",
]
[[package]]
name = "thiserror"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread-id"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1"
dependencies = [
"libc",
"redox_syscall 0.1.57",
"winapi",
]
[[package]]
name = "tiff"
version = "0.8.1"

View File

@ -10,10 +10,10 @@ edition = "2021"
default = ["pokemmo"]
pokemmo = ["screen","ocr","joystick","dep:image","pokemon","detector"]
pokemmo = ["screen", "ocr", "joystick", "dep:image", "pokemon", "detector"]
screen = ["dep:screenshots"]
ocr = []
joystick = ["dep:enigo"]
ocr = ["dep:rusty-tesseract", "dep:image"]
joystick = ["dep:enigo","dep:rand"]
pokemon = []
detector = ["dep:crossterm"]
@ -26,5 +26,8 @@ path = "src/lib.rs"
log = "0.4.20"
enigo = { version = "0.1.2", optional = true }
screenshots = { version = "0.7.0", optional = true }
image = {version = "0.24.6", optional = true}
crossterm = {version = "0.27.0", optional = true}
image = { version = "0.24.6", optional = true }
crossterm = { version = "0.27.0", optional = true }
rusty-tesseract = { version = "1.1.7", optional = true }
rand = { version = "0.8.5", optional = true }
simple-logging = {version = "2.0.2"}

58
src/joystick/joystick.rs Normal file
View File

@ -0,0 +1,58 @@
#[cfg(feature = "joystick")]
pub(crate) mod joystick{
use std::thread;
use std::time::Duration;
use enigo::{Enigo, Key, KeyboardControllable};
use rand::Rng;
pub enum MoveMode{
// 横向
HORIZONTAL,
// 纵向
PORTRAIT,
// 随机
RANDOM,
}
impl MoveMode {
pub fn to_key_list(&self) -> Vec<Key>{
return match self {
MoveMode::HORIZONTAL => vec![Key::Layout('j'),Key::Layout('l')],
MoveMode::PORTRAIT => vec![Key::UpArrow,Key::DownArrow],
MoveMode:: RANDOM => vec![Key::LeftArrow,Key::RightArrow,Key::UpArrow,Key::DownArrow],
}
}
}
pub(crate) fn move_once_by_mode(road : &MoveMode, index : usize){
let mut enigo = Enigo::new();
let moves = road.to_key_list();
let move_index = index % moves.len();
let move_key = moves[move_index];
long_press(enigo,move_key,1000,500);
}
pub(crate) fn once_press(mut enigo:Enigo, key: Key){
enigo.key_click(key);
}
pub(crate) fn quick_press(key: Key){
let mut enigo = Enigo::new();
let mut rng = rand::thread_rng();
enigo.key_down(key);
thread::sleep(Duration::from_millis(rng.gen_range(0 .. 20)));
enigo.key_up(key);
}
pub(crate) fn long_press(mut enigo:Enigo, key: Key, est_time: isize, random_time: isize){
let mut rng = rand::thread_rng();
enigo.key_down(key);
let act = est_time + rng.gen_range((-random_time .. random_time));
thread::sleep(Duration::from_millis(act as u64));
enigo.key_up(key);
}
}

View File

@ -0,0 +1,17 @@
#[cfg(test)]
mod tests {
use crate::joystick::joystick::joystick::{move_once_by_mode, MoveMode};
#[test]
fn try_move() {
let mut count = 0;
let mode = MoveMode::HORIZONTAL;
while count < 100 {
move_once_by_mode(&mode, 0);
count = count + 1;
}
}
}

View File

@ -0,0 +1,2 @@
pub mod joystick;
pub mod joystick_test;

View File

@ -2,4 +2,5 @@ pub(crate) mod screen;
pub(crate) mod joystick;
pub(crate) mod pokemmo;
pub(crate) mod pokemon;
pub(crate) mod detector;
pub(crate) mod detector;
pub(crate) mod ocr;

2
src/ocr/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub(crate) mod ocr;
mod ocr_test;

65
src/ocr/ocr.rs Normal file
View File

@ -0,0 +1,65 @@
#[cfg(feature = "ocr")]
pub(crate) mod ocr {
use std::error::Error;
use image::DynamicImage;
use rusty_tesseract::{Args, Image};
/**
OEM
0
1 LSTM
2 + LSTM
3
PSM
0 (OSD)
1 使 OSD
2 OSD OCR
3 OSD
4
5
6
7
8
9
10
11
12 OSD
13 线
*/
pub(crate) fn find_string_in_image(image: &DynamicImage, psm:i32) -> String {
let img = Image::from_dynamic_image(image).expect("from image failed");
let mut args = Args {
lang: "chi_sim".to_string(),
config_variables: Default::default(),
dpi: Some(300),
psm: Some(psm),
oem: Some(3),
};
let output = rusty_tesseract::image_to_string(&img, &args).expect("image to string failed");
return output;
}
pub(crate) fn find_text_in_image(key_words: &Vec<String>, image: &DynamicImage) -> bool {
let img = Image::from_dynamic_image(image).expect("from image failed");
let mut args = Args {
lang: "chi_sim".to_string(),
config_variables: Default::default(),
dpi: Some(600),
psm: Some(6),
oem: Some(3),
};
let output = rusty_tesseract::image_to_string(&img, &args).expect("image to string failed");
for word in key_words{
if output.contains(word){
return true;
}
}
return false;
}
}

44
src/ocr/ocr_test.rs Normal file
View File

@ -0,0 +1,44 @@
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use image::io::Reader;
use rusty_tesseract::{Args, Image};
use crate::ocr::ocr::ocr::find_text_in_image;
#[test]
fn test_ocr_image() {
println!("ocr !");
// let img = Image::from_path("test/image/group_5.png").expect("image not found");
let img = Image::from_path("test/image/sb.png").expect("image not found");
let mut args = Args {
lang: "chi_sim".to_string(),
config_variables: Default::default(),
dpi: Some(300),
psm: Some(1),
oem: Some(3),
};
// string output
let output = rusty_tesseract::image_to_string(&img, &args).expect("ocr error!");
println!("The String output is: {:?}", output);
}
#[test]
fn test_ocr_dynamic_image() {
let dynamic_image = Reader::open("test/image/1.png")
.unwrap()
.decode()
.unwrap();
let key_words = vec!["头目".to_string(),"白银山".to_string()];
let has_word = find_text_in_image(&key_words,&dynamic_image);
println!("含有关键词:{}",has_word);
}
}

View File

@ -7,25 +7,142 @@ pub mod pokemmo_const_value{
right: 80,
top: 0,
bottom: 20,
psm : 3,
};
pub(crate) const MAP_CITY: Area = Area{
left: 0,
right: 250,
top: 24,
bottom: 55,
psm : 7,
};
pub(crate) const SHORTCUT_KEY_1: Area = Area{
left: 255,
right: 298,
top: 28,
bottom: 70,
psm : 8,
};
pub(crate) const SHORTCUT_KEY_5: Area = Area{
left: 445,
right: 485,
top: 28,
bottom: 70,
psm : 8,
};
pub(crate) const TEXT_AREA: Area = Area{
left: 0,
right: 800,
top: 1020,
bottom: 1340,
psm : 6,
};
// 战斗对话狂
pub(crate) const TEMP_BATTLE_TEXT_AREA: Area = Area{
left: 400,
right: 1100,
top: 850,
bottom: 1020,
psm : 6,
};
pub(crate) const LAST_TEXT_AREA: Area = Area{
left: 0,
right: 800,
top: 1295,
bottom: 1340,
psm : 7,
};
pub(crate) const SINGLE_BATTLE: Area = Area{
left: 400,
right: 800,
top: 180,
bottom: 260,
psm : 3,
};
pub(crate) const GROUP_5_1: Area = Area{
left: 700,
right: 1050,
top: 90,
bottom: 148,
psm : 3,
};
pub(crate) const GROUP_5_2: Area = Area{
left: 1100,
right: 1400,
top: 90,
bottom: 148,
psm : 3,
};
pub(crate) const GROUP_5_3: Area = Area{
left: 1500,
right: 1800,
top: 90,
bottom: 148,
psm : 3,
};
pub(crate) const GROUP_5_4: Area = Area{
left: 740,
right: 1050,
top: 170,
bottom: 210,
psm : 3,
};
pub(crate) const GROUP_5_5: Area = Area{
left: 1500,
right: 1800,
top: 170,
bottom: 210,
psm : 3,
};
pub(crate) const BUTTON_HL_1: Area = Area{
left: 392,
right: 406,
top: 863,
bottom: 878,
psm : 3,
};
pub(crate) const BUTTON_HL_2: Area = Area{
left: 708,
right: 722,
top: 863,
bottom: 878,
psm : 3,
};
pub(crate) const BUTTON_HL_3: Area = Area{
left: 392,
right: 406,
top: 942,
bottom: 957,
psm : 3,
};
pub(crate) const BUTTON_HL_4: Area = Area{
left: 708,
right: 722,
top: 942,
bottom: 957,
psm : 3,
};
#[derive(Debug)]
pub enum PokemmoStatus {
// 遇见闪光
MeetShiny,
// 无状态
Free,
// 加载遇怪动画
LoadBattle,
// 遇怪状态
InBattle,
// 逃跑中
Running,
// 检查逃跑成功
CheckRun,
}
}

View File

@ -1,34 +1,233 @@
#[cfg(feature = "pokemmo")]
pub mod pokemmo{
use screenshots::Compression;
use crate::pokemmo::const_value::pokemmo_const_value::LOGO;
use crate::screen::screen::screen::{screen_shot};
pub mod pokemmo {
use std::thread;
use std::time::Duration;
use enigo::Key;
use enigo::Key::{N, V};
use image::{DynamicImage, RgbaImage};
use image::io::Reader as ImageReader;
use log::{error, info, trace};
use rand::thread_rng;
use rusty_tesseract::Image;
use screenshots::Compression;
use crate::joystick::joystick::joystick::{move_once_by_mode, MoveMode, quick_press};
use crate::ocr::ocr::ocr::find_string_in_image;
use crate::pokemmo::const_value::pokemmo_const_value::{BUTTON_HL_1, BUTTON_HL_2, BUTTON_HL_3, BUTTON_HL_4, GROUP_5_1, GROUP_5_2, GROUP_5_3, GROUP_5_4, GROUP_5_5, LAST_TEXT_AREA, LOGO, PokemmoStatus, SINGLE_BATTLE, TEMP_BATTLE_TEXT_AREA, TEXT_AREA};
use crate::pokemmo::const_value::pokemmo_const_value::PokemmoStatus::{Free, InBattle, LoadBattle, MeetShiny, Running};
use crate::screen::screen::screen::{Area, screen_shot};
// 单遇闪光
pub fn single_meet_shiny(key_words: &Vec<String>) {
let mut status = PokemmoStatus::Free;
let move_mode = MoveMode::HORIZONTAL;
let mut move_index = 0_usize;
let mut meet_pokemmo: String = String::new();
loop {
trace!("当前状态:{:?}",status);
match status {
PokemmoStatus::MeetShiny => {
return;
}
PokemmoStatus::Free => {
trace!("自由状态,移动一步");
move_once_by_mode(&move_mode, move_index);
move_index = move_index + 1;
let text = get_last_string();
trace!("查询战斗文字 : {}",text);
if text.contains("野生") || text.contains("派出") {
info!("遇怪:{}.",text);
meet_pokemmo = text.clone();
status = LoadBattle;
}else {
let temp_battle = read_area(TEMP_BATTLE_TEXT_AREA);
if temp_battle.contains("战斗") || temp_battle.contains("逃跑"){
status = LoadBattle;
}
}
}
PokemmoStatus::LoadBattle => {
info!("进入加载动画");
let mut btn_index = None;
while btn_index == None {
trace!("等待按钮加载");
let est_index = get_choose_btn();
if est_index.is_some() {
btn_index = est_index;
status = InBattle;
}
thread::sleep(Duration::from_millis(100));
}
}
PokemmoStatus::InBattle => {
trace!("检查遇怪种类..");
let text = get_text_list();
let filter_text: Vec<String> = text.into_iter().filter(|x| x.contains("野生")).collect();
if filter_text.is_empty() {
error!("遇怪错误!");
return;
}
let filter_size = filter_text.len();
let pokemon_text = filter_text[filter_size - 1].clone();
if pokemon_text.contains("怪群") {
info!("遇见怪群");
let five_names = read_group_5();
for name in five_names {
for key_word in key_words {
if name.contains(key_word) {
status = MeetShiny;
return;
}
}
}
} else {
let name = read_area(SINGLE_BATTLE);
info!("单遇:{}",name);
for key_word in key_words {
if name.contains(key_word) || meet_pokemmo.contains(key_word) {
info!("遇见{}",key_word);
status = MeetShiny;
return;
}
}
}
// 进入招式界面
status = PokemmoStatus::Running
}
PokemmoStatus::Running => {
thread::sleep(Duration::from_micros(100));
quick_press(Key::Layout('l'));
thread::sleep(Duration::from_micros(100));
quick_press(Key::Layout('k'));
thread::sleep(Duration::from_micros(100));
let mut est_index = get_choose_btn();
while est_index.is_none() || est_index.unwrap() != 3 {
quick_press(Key::Layout('l'));
quick_press(Key::Layout('k'));
trace!("尝试获取激活按钮");
est_index = get_choose_btn();
}
quick_press(Key::Layout('z'));
thread::sleep(Duration::from_micros(100));
status = PokemmoStatus::CheckRun;
}
PokemmoStatus::CheckRun => {
let mut last_word = get_last_string();
// 读取十次后默认成功
let mut times = 0_usize;
while !last_word.contains("成功")
&& !last_word.contains("中逃跑")
&& !last_word.contains("不能跑")
&& times < 10{
trace!("读取逃跑文档 {}",last_word);
last_word = get_last_string();
thread::sleep(Duration::from_millis(200));
times = times + 1;
}
if last_word.contains("成功") || last_word.contains("逃跑") {
trace!("逃跑成功.");
status = Free;
} else {
trace!("逃跑失败");
status = Free;
}
}
}
}
}
pub fn get_text_list() -> Vec<String> {
let text_image = read_area(TEXT_AREA);
let text_list: Vec<String> = text_image.split("\r\n").filter(|x| !x.is_empty()).map(|x| String::from(x)).collect();
return text_list;
}
pub fn get_last_string() -> String {
let text_image = read_area(LAST_TEXT_AREA);
return text_image;
}
pub(crate) fn check_screen_active() -> bool{
pub(crate) fn check_screen_active() -> bool {
let logo_image = screen_shot(Some(LOGO));
let data= logo_image.to_png(Some(Compression::Default)).expect("image to png failed");
let data = logo_image.to_png(Some(Compression::Default)).expect("image to png failed");
let active_logo = ImageReader::open("./resources/pokemmo/image/logo_active.png").expect("read active logo image failed").decode().expect("decode image failed");
let active_logo_data = active_logo.as_bytes().to_vec();
let size = data.len();
let mut dis = 0_isize;
for i in 0 .. size{
dis += active_logo_data[i].clone() as isize - data[i].clone() as isize;
for i in 0..size {
dis += active_logo_data[i.clone()].clone() as isize - data[i].clone() as isize;
}
println!("dis : {}",dis);
println!("dis : {}", dis);
return dis <= 5000;
}
pub fn read_area(area: Area) -> String {
let psm = area.psm.clone();
let image = screen_shot(Some(area));
let image_data = image.rgba().clone();
let image_width = image.width();
let image_height = image.height();
let dy_image = DynamicImage::from(RgbaImage::from_vec(image_width, image_height, image_data).unwrap());
let text = find_string_in_image(&dy_image, psm);
return text;
}
pub fn read_group_5() -> Vec<String> {
let mut result = Vec::new();
result.push(read_area(GROUP_5_1));
result.push(read_area(GROUP_5_2));
result.push(read_area(GROUP_5_3));
result.push(read_area(GROUP_5_4));
result.push(read_area(GROUP_5_5));
return result;
}
pub fn get_choose_btn() -> Option<usize> {
let mut btn_list = Vec::new();
btn_list.push(screen_shot(Some(BUTTON_HL_1)));
btn_list.push(screen_shot(Some(BUTTON_HL_2)));
btn_list.push(screen_shot(Some(BUTTON_HL_3)));
btn_list.push(screen_shot(Some(BUTTON_HL_4)));
let mut y_max = 0_f32;
let mut max_index = None;
for index in 0..4 {
let image = &mut btn_list[index];
let data = image.rgba();
let size = data.len();
let pixel_size = size / 4;
let mut r_total = 0_usize;
let mut g_total = 0_usize;
let mut b_total = 0_usize;
for i in 0..pixel_size {
r_total += (data[i.clone() * 4].clone() as usize);
g_total += (data[i.clone() * 4 + 1].clone() as usize);
b_total += (data[i.clone() * 4 + 2].clone() as usize);
}
let r_avg = r_total / pixel_size;
let g_avg = g_total / pixel_size;
let b_avg = b_total / pixel_size;
let r1 = r_avg as f32 / 255_f32;
let g1 = g_avg as f32 / 255_f32;
let b1 = b_avg as f32 / 255_f32;
let max = r1.max(g1).max(b1);
let k = 1_f32 - max;
let y = (1_f32 - b1 - k) / (1_f32 - k);
if y > y_max && y > 0.4_f32 {
y_max = y;
max_index = Some(index);
}
}
return max_index;
}
}

View File

@ -3,52 +3,81 @@ mod tests {
use std::thread::sleep;
use std::time::Duration;
use image::io::Reader as ImageReader;
use crate::pokemmo::const_value::pokemmo_const_value::{LOGO, MAP_CITY, SHORTCUT_KEY_1, SHORTCUT_KEY_5};
use crate::pokemmo::pokemmo::pokemmo::check_screen_active;
use log::LevelFilter;
use crate::pokemmo::const_value::pokemmo_const_value::{BUTTON_HL_1, BUTTON_HL_2, BUTTON_HL_3, BUTTON_HL_4, GROUP_5_1, GROUP_5_2, GROUP_5_3, GROUP_5_4, GROUP_5_5, LAST_TEXT_AREA, LOGO, MAP_CITY, SHORTCUT_KEY_1, SHORTCUT_KEY_5, SINGLE_BATTLE, TEMP_BATTLE_TEXT_AREA, TEXT_AREA};
use crate::pokemmo::pokemmo::pokemmo::{check_screen_active, get_choose_btn, get_last_string, read_area, read_group_5, single_meet_shiny};
use crate::screen::screen::screen::{print_image, screen_shot};
#[test]
fn print_logo() {
sleep(Duration::from_secs(1));
fn try_meet_shiny(){
simple_logging::log_to_file("./test/log/meet_shiny.log",LevelFilter::Info).expect("set log failed");
let logo_image = screen_shot(Some(LOGO));
print_image(logo_image, "logo".to_string());
let key_words = vec![
"".to_string(),
"".to_string(),
];
single_meet_shiny(&key_words);
}
let active = check_screen_active();
println!("main screen active : {}", active);
#[test]
fn print_shortcut() {
let text = screen_shot(Some(TEMP_BATTLE_TEXT_AREA));
print_image(text, "temp_battle_text".to_string());
}
#[test]
fn print_city() {
sleep(Duration::from_secs(1));
fn print_group_5() {
let group_5_1 = screen_shot(Some(GROUP_5_1));
print_image(group_5_1, "group_5_1".to_string());
let group_5_2 = screen_shot(Some(GROUP_5_2));
print_image(group_5_2, "group_5_2".to_string());
let group_5_3 = screen_shot(Some(GROUP_5_3));
print_image(group_5_3, "group_5_3".to_string());
let group_5_4 = screen_shot(Some(GROUP_5_4));
print_image(group_5_4, "group_5_4".to_string());
let group_5_5 = screen_shot(Some(GROUP_5_5));
print_image(group_5_5, "group_5_5".to_string());
}
#[test]
fn print_button() {
let btn_hl_1 = screen_shot(Some(BUTTON_HL_1));
print_image(btn_hl_1, "btn_hl_1".to_string());
let btn_hl_2 = screen_shot(Some(BUTTON_HL_2));
print_image(btn_hl_2, "btn_hl_2".to_string());
let btn_hl_3 = screen_shot(Some(BUTTON_HL_3));
print_image(btn_hl_3, "btn_hl_3".to_string());
let btn_hl_4 = screen_shot(Some(BUTTON_HL_4));
print_image(btn_hl_4, "btn_hl_4".to_string());
let logo_image = screen_shot(Some(MAP_CITY));
print_image(logo_image, "city".to_string());
}
#[test]
fn print_shortcut_key_1() {
sleep(Duration::from_secs(1));
let logo_image = screen_shot(Some(SHORTCUT_KEY_1));
print_image(logo_image, "key_1".to_string());
fn find_text() {
let text = read_area(TEMP_BATTLE_TEXT_AREA);
println!("text in image: {}",text);
}
#[test]
fn print_shortcut_key_5() {
sleep(Duration::from_secs(1));
let logo_image = screen_shot(Some(SHORTCUT_KEY_5));
print_image(logo_image, "key_5".to_string());
fn get_active_btn() {
let index_op = get_choose_btn();
if index_op.is_some(){
println!("激活索引:{}",index_op.unwrap());
}else {
println!("无激活索引");
}
}
#[test]
fn compare_logo() {
let active_logo = ImageReader::open("./resources/pokemmo/image/logo_active.png").expect("read active logo image failed").decode().expect("decode image failed");
let active_logo_data = active_logo.as_bytes().to_vec();
@ -59,11 +88,8 @@ mod tests {
let mut dis = 0_isize;
for i in 0 .. size{
dis += na_logo_data[i].clone() as isize - active_logo_data[i].clone() as isize;
dis += na_logo_data[i.clone()].clone() as isize - active_logo_data[i.clone()].clone() as isize;
}
println!("dis = {}",dis);
}
}

View File

@ -1,4 +1,147 @@
#[cfg(feature = "pokemon")]
pub(crate) mod pokemon{
pub(crate) mod pokemon {
pub enum PokeType {
Normal,
Fighting,
Flying,
Poison,
Ground,
Rock,
Bug,
Ghost,
Steel,
File,
Water,
Grass,
Electric,
Psychic,
Ice,
Dragon,
Dark,
Fairy,
}
pub struct Pokemon {
pub(crate) dex: PokeDex,
pub(crate) moves: Vec<MoveCategory>,
pub(crate) lv: u32,
pub(crate) stat: Stat,
pub(crate) status: StatusChange,
pub(crate) nature: Nature
}
pub struct PokeDex {
pub(crate) no: u32,
pub(crate) fir_type: PokeType,
pub(crate) sec_type: Option<PokeType>,
pub(crate) iv: Iv,
}
pub struct Iv {
pub(crate) hp: u32,
pub(crate) attack: u32,
pub(crate) defense: u32,
pub(crate) sp_atk: u32,
pub(crate) sp_def: u32,
pub(crate) speed: u32,
}
pub struct Ev {
pub(crate) hp: u32,
pub(crate) attack: u32,
pub(crate) defense: u32,
pub(crate) sp_atk: u32,
pub(crate) sp_def: u32,
pub(crate) speed: u32,
}
pub struct Stat {
pub(crate) hp: u32,
pub(crate) attack: u32,
pub(crate) defense: u32,
pub(crate) sp_atk: u32,
pub(crate) sp_def: u32,
pub(crate) speed: u32,
}
pub struct StatusChange {
pub(crate) attack: i32,
pub(crate) defense: i32,
pub(crate) sp_atk: i32,
pub(crate) sp_def: i32,
pub(crate) speed: i32,
pub(crate) accuracy: i32,
pub(crate) evasion: i32,
}
pub enum MoveCategory {
Physical,
Special,
Status,
}
pub struct Move {
pub(crate) cat: MoveCategory,
pub(crate) value: u32,
}
pub enum Nature {
Hardy,
Lonely,
Brave,
Adamant,
Naughty,
Bold,
Docile,
Relaxed,
Impish,
Lax,
Timid,
Hasty,
Serious,
Jolly,
Naive,
Modest,
Mild,
Quiet,
Bashful,
Rash,
Calm,
Gentle,
Sassy,
Careful,
Quirky,
}
impl Nature {
pub fn influence(&self) -> (f32, f32, f32, f32, f32) {
return match self {
Hardy => (0_f32, 0_f32, 0_f32, 0_f32, 0_f32),
Lonely => (1.1_f32, 0.9_f32, 0_f32, 0_f32, 0_f32),
Brave => (1.1_f32, 0_f32, 0_f32, 0_f32, 0.9_f32),
Adamant => (1.1_f32, 0_f32, 0.9_f32, 0_f32, 0_f32),
Naughty => (1.1_f32, 0_f32, 0_f32, 0.9_f32, 0_f32),
Bold => (0.9_f32, 1.1_f32, 0_f32, 0_f32, 0_f32),
Docile => (0_f32, 0_f32, 0_f32, 0_f32, 0_f32),
Relaxed => (0_f32, 1.1_f32, 0_f32, 0_f32, 0.9_f32),
Impish => (0_f32, 1.1_f32, 0.9_f32, 0_f32, 0_f32),
Lax => (0_f32, 1.1_f32, 0_f32, 0.9_f32, 0_f32),
Timid => (0.9_f32, 0_f32, 0_f32, 0_f32, 1.1_f32),
Hasty => (0_f32, 0.9_f32, 0_f32, 0_f32, 1.1_f32),
Serious => (0_f32, 0_f32, 0_f32, 0_f32, 0_f32),
Jolly => (0_f32, 0_f32, 0.9_f32, 0_f32, 1.1_f32),
Naive => (0_f32, 0_f32, 0_f32, 0.9_f32, 1.1_f32),
Modest => (0.9_f32, 0_f32, 1.1_f32, 0_f32, 0_f32),
Mild => (0_f32, 0.9_f32, 1.1_f32, 0_f32, 0_f32),
Quiet => (0_f32, 0_f32, 1.1_f32, 0_f32, 0.9_f32),
Bashful => (0_f32, 0_f32, 0_f32, 0_f32, 0_f32),
Rash => (0_f32, 0_f32, 1.1_f32, 0.9_f32, 0_f32),
Calm => (0.9_f32, 0_f32, 0_f32, 1.1_f32, 0_f32),
Gentle => (0_f32, 0.9_f32, 0_f32, 1.1_f32, 0_f32),
Sassy => (0_f32, 0_f32, 0_f32, 1.1_f32, 0.9_f32),
Careful => (0_f32, 0_f32, 0.9_f32, 1.1_f32, 0_f32),
Quirky => (0_f32, 0_f32, 0_f32, 0_f32, 0_f32),
};
}
}
}

View File

@ -9,8 +9,10 @@ pub mod screen {
pub right: i32,
pub top: i32,
pub bottom: i32,
pub psm : i32,
}
pub fn screen_shot(area: Option<Area>) -> Image {
let main_screen_list: Vec<Screen> = Screen::all().expect("get all screen failed").into_iter().filter(|x| x.display_info.is_primary).collect();
let main_screen = main_screen_list.first().expect("get main screen failed");
@ -25,12 +27,9 @@ pub mod screen {
return image
}
pub fn print_image(image: Image,file_name : String){
fs::write(format!("test/image/{}.png", file_name), image.to_png(Some(Compression::Default)).expect("image to png failed")).unwrap();
}
}

View File

@ -10,12 +10,10 @@ mod tests {
right: 300,
top: 0,
bottom: 300,
psm: 3,
};
let image = screen_shot(Some(area));
print_image(image,"abc".to_string());
}