Skip to content

Commit 457131e

Browse files
committed
优化:安卓8+下的拟人滑动更拟人
1 parent d0aa701 commit 457131e

File tree

2 files changed

+197
-30
lines changed

2 files changed

+197
-30
lines changed

src/common/version.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,9 @@ export const versionList = [{
12871287
}, {
12881288
version: '20241227_01',
12891289
desc: '增加:协同对弈开始和结算'
1290+
}, {
1291+
version: '20241229_01',
1292+
desc: '优化:安卓8+下的拟人滑动更拟人'
12901293
}];
12911294

12921295
export default versionList[versionList.length - 1].version;

src/system/MyAutomator.ts

Lines changed: 194 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import Bezier from 'bezier-js';
55
export const myShell = isRoot ? new Shell(true) : undefined;
66

77
export interface IMyAutomator {
8-
tapType: number;
9-
dirctionReverse: boolean;
10-
RA: any;
11-
shell: any;
12-
13-
setTapType(tapType: 0 | 1 | 2 | 3): void;
14-
press(x: number, y: number, delay: number): void;
15-
swipe(x0: number, y0: number, x1: number, y1: number, delay: number): void;
16-
regionBezierSwipe(transedOperS: Array<number>, transedOperE: Array<number>, duration: Array<number>, baseSleep: number, randomSleep: number, type?: number): void;
8+
tapType: number;
9+
dirctionReverse: boolean;
10+
RA: any;
11+
shell: any;
12+
13+
setTapType(tapType: 0 | 1 | 2 | 3): void;
14+
press(x: number, y: number, delay: number): void;
15+
swipe(x0: number, y0: number, x1: number, y1: number, delay: number): void;
16+
regionBezierSwipe(transedOperS: Array<number>, transedOperE: Array<number>, duration: Array<number>, baseSleep: number, randomSleep: number, type?: number): void;
1717
}
1818

1919
class MyAutomator implements IMyAutomator {
@@ -97,7 +97,7 @@ class MyAutomator implements IMyAutomator {
9797
gesture = gesture;
9898

9999
// helperBridge过来的
100-
regionBezierSwipe(transedOperS: Array<number>, transedOperE: Array<number>, duration: Array<number>, baseSleep: number, randomSleep: number, type?: number): void {
100+
regionBezierSwipe(transedOperS: Array<number>, transedOperE: Array<number>, duration: Array<number>, baseSleep: number, randomSleep: number, _type?: number): void {
101101
const time = random(duration[0], duration[1])
102102
// swipe(
103103
// random(transedOperS[0], transedOperS[2]), // x1
@@ -117,28 +117,33 @@ class MyAutomator implements IMyAutomator {
117117
sleep(time + 200 + random(0, randomSleep));
118118
return;
119119
}
120-
const xMax = Math.max(x1, x2);
121-
const xMin = Math.min(x1, x2);
122-
const yMax = Math.max(y1, y2);
123-
const yMin = Math.min(y1, y2);
120+
// const xMax = Math.max(x1, x2);
121+
// const xMin = Math.min(x1, x2);
122+
// const yMax = Math.max(y1, y2);
123+
// const yMin = Math.min(y1, y2);
124124
// const screenWidth = getWidthPixels();
125-
let c1, c2;
125+
// let c1, c2;
126126
// TODO 开始和结束的附近的点需要更密集
127-
if (!type) {
128-
c1 = [
129-
random(xMin, xMax),
130-
random(yMin, yMax),
131-
];
132-
c2 = [
133-
random(xMin, xMax),
134-
random(yMin, yMax),
135-
];
136-
} else {
137-
// TODO
138-
}
127+
// if (!type) {
128+
// c1 = [
129+
// random(xMin, xMax),
130+
// random(yMin, yMax),
131+
// ];
132+
// c2 = [
133+
// random(xMin, xMax),
134+
// random(yMin, yMax),
135+
// ];
136+
// } else {
137+
// // TODO
138+
// }
139139

140+
const [c1, c2] = generateRandomPoints([x1, y1], [x2, y2]);
140141
const curve = new Bezier(x1, y1, ...c1, ...c2, x2, y2);
141142
const pointsOrigin = curve.getLUT(200).map(p => [Math.floor(p['x']), Math.floor(p['y'])]);
143+
144+
// const pointsOrigin = bezierCreate(x1, y1, p1[0], p1[1], p2[0], p2[1], x2, y2);
145+
// console.log(pointsOrigin);
146+
142147
let toRetain = [0, 1, 2, 3, 4, 5, 191, 192, 193, 194, 195, 196, 197, 198, 199];
143148
for (let i = 190, stepLen = 1; i > 5; i -= stepLen, stepLen++) {
144149
toRetain.push(i);
@@ -148,8 +153,40 @@ class MyAutomator implements IMyAutomator {
148153
toRetain.forEach(item => {
149154
points.push(pointsOrigin[item]);
150155
});
151-
this.gesture(time, ...points);
152-
sleep(baseSleep + time + random(0, randomSleep));
156+
// 小于安卓8用普通gesture
157+
if (device.sdkInt < 26) {
158+
this.gesture(time, ...points);
159+
sleep(baseSleep + time + random(0, randomSleep));
160+
return
161+
}
162+
163+
// 大于安卓8,用优化版gesture,可以精控到每个点之间的时间
164+
const avgItemTime = Math.ceil(time / points.length);
165+
const strokes = [];
166+
let lastPoint = points[0];
167+
let currentStroke = null;
168+
for (let i = 1; i < points.length - 1; i++) {
169+
const currentPoint = points[i];
170+
const path = new android.graphics.Path();
171+
path.moveTo(lastPoint[0], lastPoint[1]);
172+
path.lineTo(currentPoint[0], currentPoint[1]);
173+
if (!currentStroke) {
174+
currentStroke = new android.accessibilityservice.GestureDescription.StrokeDescription(path, 0, avgItemTime, true);
175+
} else {
176+
currentStroke = currentStroke.continueStroke(path, 0, avgItemTime, true);
177+
}
178+
strokes.push(currentStroke);
179+
lastPoint = currentPoint;
180+
}
181+
const path = new android.graphics.Path();
182+
path.moveTo(lastPoint[0], lastPoint[1]);
183+
path.lineTo(points[points.length - 1][0], points[points.length - 1][1]);
184+
currentStroke = currentStroke.continueStroke(path, 0, avgItemTime, false);
185+
strokes.push(currentStroke);
186+
for (const stroke of strokes) {
187+
autojsGestures([stroke]);
188+
}
189+
sleep(baseSleep + random(0, randomSleep));
153190
}
154191

155192
constructor(tapType: number, dirctionReverse?: boolean) {
@@ -179,4 +216,131 @@ class MyAutomator implements IMyAutomator {
179216
}
180217
}
181218

182-
export default MyAutomator;
219+
export default MyAutomator;
220+
221+
222+
223+
224+
// function bezierCreate(x1, y1, x2, y2, x3, y3, x4, y4) {
225+
// // 构建参数
226+
// const h = 0;
227+
// const cp = [
228+
// { x: x1, y: y1 + h },
229+
// { x: x2, y: y2 + h },
230+
// { x: x3, y: y3 + h },
231+
// { x: x4, y: y4 + h },
232+
// ];
233+
// const numberOfPoints = 200;
234+
// const curve = [];
235+
// const dt = 1.0 / (numberOfPoints - 1);
236+
237+
// // 计算轨迹
238+
// for (let i = 0; i < numberOfPoints; i++) {
239+
// // const ax, bx, cx;
240+
// // const ay, by, cy;
241+
// // const tSquared, tCubed;
242+
// // const result_x, result_y;
243+
244+
// const cx = 3.0 * (cp[1].x - cp[0].x);
245+
// const bx = 3.0 * (cp[2].x - cp[1].x) - cx;
246+
// const ax = cp[3].x - cp[0].x - cx - bx;
247+
// const cy = 3.0 * (cp[1].y - cp[0].y);
248+
// const by = 3.0 * (cp[2].y - cp[1].y) - cy;
249+
// const ay = cp[3].y - cp[0].y - cy - by;
250+
251+
// const t = dt * i;
252+
// const tSquared = t * t;
253+
// const tCubed = tSquared * t;
254+
// const result_x = ax * tCubed + bx * tSquared + cx * t + cp[0].x;
255+
// const result_y = ay * tCubed + by * tSquared + cy * t + cp[0].y;
256+
// curve[i] = {
257+
// x: result_x,
258+
// y: result_y,
259+
// };
260+
// }
261+
262+
// // 轨迹转路数组
263+
// const array = [];
264+
// for (let i = 0; i < curve.length; i++) {
265+
// let xx, yy;
266+
// try {
267+
// const j = i < 100 ? i : 199 - i;
268+
// xx = Math.floor(curve[j].x);
269+
// yy = Math.floor(Math.abs(100 - curve[j].y));
270+
// } catch (e) {
271+
// break;
272+
// }
273+
// array.push([xx, yy]);
274+
// }
275+
276+
// return array;
277+
// }
278+
279+
function getRandomPoint(q1, q2, tMin, tMax) {
280+
// 计算从 q1 到 q2 的向量
281+
const vector = [q2[0] - q1[0], q2[1] - q1[1]];
282+
283+
// 生成一个随机的 t 值,确保点在 q1 和 q2 的线段内
284+
const t = Math.random() * (tMax - tMin) + tMin;
285+
286+
// 计算随机点的坐标
287+
const px = q1[0] + t * vector[0];
288+
const py = q1[1] + t * vector[1];
289+
290+
// 生成一个随机的偏移量,确保点不在连线上
291+
const offset = Math.random() * 0.4 - 0.2;
292+
293+
// 计算垂直向量
294+
const perpendicularVector = [-vector[1], vector[0]];
295+
296+
// 应用偏移量
297+
const finalPx = px + offset * perpendicularVector[0];
298+
const finalPy = py + offset * perpendicularVector[1];
299+
300+
return [finalPx, finalPy];
301+
}
302+
303+
// function isOnSameSide(p1, p2, q1, q2) {
304+
// // 计算向量 q1q2
305+
// const q1q2 = [q2[0] - q1[0], q2[1] - q1[1]];
306+
307+
// // 计算向量 q1p1 和 q1p2
308+
// const q1p1 = [p1[0] - q1[0], p1[1] - q1[1]];
309+
// const q1p2 = [p2[0] - q1[0], p2[1] - q1[1]];
310+
311+
// // 计算叉积
312+
// const crossProduct1 = q1q2[0] * q1p1[1] - q1q2[1] * q1p1[0];
313+
// const crossProduct2 = q1q2[0] * q1p2[1] - q1q2[1] * q1p2[0];
314+
315+
// // 判断叉积是否同号
316+
// return crossProduct1 * crossProduct2 > 0;
317+
// }
318+
319+
function generateRandomPoints(q1, q2) {
320+
// let p1, p2;
321+
// let attempts = 0;
322+
// do {
323+
const p1 = getRandomPoint(q1, q2, 0.0005, 0.3); // p1 更靠近 q1
324+
const p2 = getRandomPoint(q1, q2, 0.7, 0.9995); // p2 更靠近 q2
325+
// attempts++;
326+
// if (attempts > 1000) {
327+
// console.error("Too many attempts to generate points. Possible issue with logic.");
328+
// break;
329+
// }
330+
// } while (!isOnSameSide(p1, p2, q1, q2));
331+
332+
return [p1, p2];
333+
}
334+
335+
/**
336+
* copy from 抠脚本人:进阶手势录制,变速曲线滑动
337+
* @param strokes [x, y, duration][]
338+
*/
339+
340+
function autojsGestures(strokes) {
341+
const strokeDescription = java.lang.reflect.Array.newInstance(android.accessibilityservice.GestureDescription.StrokeDescription, strokes.length);
342+
for (let i = 0; i < strokes.length; i++) {
343+
strokeDescription[i] = strokes[i];
344+
}
345+
return runtime.automator.gestures.bind(runtime.automator)(strokeDescription);
346+
}

0 commit comments

Comments
 (0)