Skip to content

Commit

Permalink
v0.1.5 删除了不必要的锁和线程,调整和优化部分代码
Browse files Browse the repository at this point in the history
  • Loading branch information
qiutongxue committed Oct 31, 2024
1 parent 864e451 commit b2a5fb2
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 193 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sr_plot_rs"
version = "0.1.4"
version = "0.1.5"
edition = "2021"

[dependencies]
Expand Down
98 changes: 62 additions & 36 deletions src/automation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,64 @@ use opencv::{
imgcodecs::{imdecode, ImreadModes},
};

use crate::plot::CropRatio;
use crate::{
error::{SrPlotError, SrPlotResult},
input::Input,
screenshot,
};

pub type ScaleRange = (f64, f64);
pub type Coordinate = ((u32, u32), (u32, u32));

#[derive(Debug, Clone, Copy)]
pub struct Region {
pub x: u32,
pub y: u32,
pub width: u32,
pub height: u32,
}

impl Region {
pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
Self {
x,
y,
width,
height,
}
}
}

pub struct Automation {
screenshot: Option<RgbaImage>,
screenshot_pos: Option<(u32, u32, u32, u32)>,
screenshot_pos: Option<Region>,
screenshot_factor: f64,
window_title: String,
window_region: Option<Region>,
cache: HashMap<String, Mat>,
}

pub type ScaleRange = (f64, f64);
type Coordinate = ((u32, u32), (u32, u32));
pub type Crop = (u32, u32, u32, u32);

impl Automation {
pub fn new(window_title: &str) -> Self {
Self {
screenshot: None,
screenshot_pos: None,
screenshot_factor: 1.0,
window_region: None,
cache: HashMap::new(),
window_title: window_title.to_owned(),
}
}

pub fn take_screenshot(&mut self, crop: Option<Crop>) -> SrPlotResult<()> {
pub fn take_screenshot(&mut self, crop: Option<CropRatio>) -> SrPlotResult<()> {
let timer = Instant::now();

let (screenshot, screenshot_pos, screenshot_factor) =
let (screenshot, screenshot_pos, screenshot_factor, window_region) =
screenshot::take_screenshot(&self.window_title, crop)?;
self.screenshot = Some(screenshot);
self.screenshot_pos = Some(screenshot_pos);
self.window_region = Some(window_region);
self.screenshot_factor = screenshot_factor;
log::debug!(
"截图成功,耗时:{}ms, 截图区域:{:?},缩放比例:{:.2}",
Expand All @@ -60,7 +82,7 @@ impl Automation {
&mut self,
target: (&'static str, &[u8]),
threshold: f64,
scale_range: ScaleRange,
scale_range: Option<ScaleRange>,
) -> SrPlotResult<Option<Coordinate>> {
log::debug!("scale_range: {:?}", scale_range);
let (target_name, target) = target;
Expand All @@ -86,7 +108,7 @@ impl Automation {
};

let (match_val, match_loc) =
scale_and_match_template(&screenshot, template, threshold, scale_range.into())?;
scale_and_match_template(&screenshot, template, threshold, scale_range)?;

log::debug!("目标图片:{}, 相似度:{:.2}", target_name, match_val);

Expand All @@ -103,37 +125,15 @@ impl Automation {
}
}

pub fn click_element(
&mut self,
target: (&'static str, &[u8]),
threshold: f64,
scale_range: ScaleRange,
crop: Crop,
) -> SrPlotResult<Option<()>> {
self.take_screenshot(crop.into())?;
let coordinates = self.find_element(target, threshold, scale_range)?;
if let Some(coordinates) = coordinates {
log::debug!("coordinates: {:?}", coordinates);
self.click_element_with_pos(coordinates)?;
return Ok(Some(()));
}
Ok(None)
}

fn click_element_with_pos(&self, coordinates: Coordinate) -> SrPlotResult<()> {
let ((left, top), (right, bottom)) = coordinates;
let x = (left + right) / 2;
let y = (top + bottom) / 2;

Input::move_and_click(x, y)?;
Ok(())
}

fn calculate_positions(&self, template: &Mat, max_loc: Point) -> SrPlotResult<Coordinate> {
let Size { width, height } = template.size()?;

let scale_factor = self.screenshot_factor;
let (sspos_x, sspos_y, _, _) = self.screenshot_pos.ok_or(SrPlotError::Unexcepted)?;
let Region {
x: sspos_x,
y: sspos_y,
..
} = self.screenshot_pos.ok_or(SrPlotError::Unexcepted)?;
let top_left = (
(max_loc.x as f64 / scale_factor) as u32 + sspos_x,
(max_loc.y as f64 / scale_factor) as u32 + sspos_y,
Expand All @@ -145,6 +145,32 @@ impl Automation {

Ok((top_left, bottom_right))
}

pub fn click(&self) -> SrPlotResult<()> {
let (mouse_x, mouse_y) = Input::position();
log::debug!("鼠标位置:({}, {})", mouse_x, mouse_y);
let Region {
x,
y,
width,
height,
} = self.window_region.ok_or(SrPlotError::Unexcepted)?;
log::debug!("窗口位置:({}, {}, {}, {})", x, y, width, height);
if x <= mouse_x && mouse_x <= x + width && y <= mouse_y && mouse_y <= y + height {
Input::click()
} else {
Err(SrPlotError::User("鼠标不在游戏窗口内!".to_string()))
}
}

pub fn click_with_coordinate(&self, coordinate: Coordinate) -> SrPlotResult<()> {
let ((left, top), (right, bottom)) = coordinate;
let x = (left + right) / 2;
let y = (top + bottom) / 2;

Input::move_mouse(x, y)?;
self.click()
}
}

pub fn scale_and_match_template(
Expand Down
12 changes: 3 additions & 9 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::sync::{MutexGuard, TryLockError};
// use std::sync::{MutexGuard, TryLockError};

#[derive(Debug, thiserror::Error)]
pub enum SrPlotError {
Expand All @@ -8,20 +8,14 @@ pub enum SrPlotError {
Input(#[from] enigo::InputError),
#[error("处理图片时发生错误:{0}")]
ImageProcessing(String),
#[error("死锁了,肯定是代码逻辑出了问题:{0}")]
Deadlock(String),
#[error("{0}")]
User(String),
#[error("未知错误")]
Unexcepted,
}

pub type SrPlotResult<T> = Result<T, SrPlotError>;

impl<T> From<TryLockError<MutexGuard<'_, T>>> for SrPlotError {
fn from(err: TryLockError<MutexGuard<'_, T>>) -> Self {
Self::Deadlock(err.to_string())
}
}

impl From<opencv::Error> for SrPlotError {
fn from(value: opencv::Error) -> Self {
Self::ImageProcessing(value.to_string())
Expand Down
3 changes: 1 addition & 2 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ impl Input {
.map_or((0, 0), |loc| (loc.0 as u32, loc.1 as u32))
}

pub fn move_and_click(x: u32, y: u32) -> SrPlotResult<()> {
pub fn move_mouse(x: u32, y: u32) -> SrPlotResult<()> {
get_enigo().move_mouse(x as i32, y as i32, enigo::Coordinate::Abs)?;
Input::click()?;
Ok(())
}
}
9 changes: 7 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use simple_logger::SimpleLogger;
use sr_plot_rs::plot::Plot;
use std::fmt::Write;
use std::{fmt::Write, thread};
use unicode_width::UnicodeWidthStr;

const WELCOME: &str = r#"
Expand Down Expand Up @@ -32,7 +32,12 @@ fn main() {
"select.png",
include_bytes!("../assets/select.png").to_vec(),
);
Plot::new("崩坏:星穹铁道".to_string(), select_image, image_files).run();

thread::spawn(|| {
Plot::new("崩坏:星穹铁道".to_string(), select_image, image_files).run();
})
.join()
.unwrap();
}

#[cfg(not(debug_assertions))]
Expand Down
Loading

0 comments on commit b2a5fb2

Please sign in to comment.