我创建了一个有趣的小项目,目标是记录我做出的自然鼠标动作,然后回放,但要朝向目标。
问:假设我制作并记录一个自然运动,结束于x:250,y:278,现在我想要的是让自然运动记录结束于我指定的目标坐标(ex:x:100,y:100)。
现在来看代码:(请注意,代码并不干净,但如果我可以这么说的话,它只是第一个原型,所以请在阅读时记住这一点)。
我如何记录动作:
当鼠标移动事件发生时,录制从按下鼠标开始到结束。
(main.recordmoves必须设置为true才能执行上述操作,我使用scanner系统输入将其设置为true/false。)
每当发生mouse\u moved事件时,mousemoved方法调用movesrecorder.record(mouseevent e)方法。
mousepressed方法将main.recordmoves布尔值设置为false,并将记录添加到记录列表中。
鼠标.java:
public class Mouse implements MouseListener, MouseMotionListener {
private Point location = new Point(0,0);
private boolean mouseOnScreen = false;
private Component c;
public Mouse(Component c) {
this.c = c;
}
public void pushStraight(int x, int y) {
if(!mouseOnScreen) {
c.dispatchEvent(new MouseEvent(c,MouseEvent.MOUSE_ENTERED, System.currentTimeMillis(),0,x,y,
0,false));
mouseOnScreen = true;
}
c.dispatchEvent(new MouseEvent(c,MouseEvent.MOUSE_MOVED,System.currentTimeMillis(),0,x,y,
0,false));
location.setLocation(x,y);
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {
if(Main.recordMoves) {
Main.recordMoves = false;
MovesRecorder.currentMove.time = System.currentTimeMillis() - MovesRecorder.startTime;
MousePatterns.moves.add(MovesRecorder.currentMove);
MovesRecorder.currentMove = null;
}
System.out.println("Pressed");
}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {
mouseOnScreen = true;
}
@Override
public void mouseExited(MouseEvent e) {
mouseOnScreen = false;
}
@Override
public void mouseDragged(MouseEvent e) {
location.setLocation(e.getPoint());
}
@Override
public void mouseMoved(MouseEvent e) {
location.setLocation(e.getPoint());
if(Main.recordMoves) MovesRecorder.record(e);
}
public Point getLocation() {
return location;
}
public boolean isMouseOnScreen() {
return mouseOnScreen;
}
public Component getC() {
return c;
}
}
mouserecorder.java文件:
public class MovesRecorder {
public static Move currentMove;
public static Point lastPos; //First lastPos (startingPos) is set here by Main.java
public static long startTime;
public static void record(MouseEvent e) {
if(currentMove == null) {
currentMove = new Move(Screen.mouse);
startTime = System.currentTimeMillis();
}
currentMove.movements.add(new Point(e.getPoint().x - lastPos.x,
e.getPoint().y - lastPos.y));
lastPos = e.getPoint();
}
}
move.java文件:
public class Move {
public List<Point> movements = new ArrayList<>();
public long time;
private Mouse m;
public Move(Mouse m) {
this.m = m;
}
public void executeEvents(int x, int y) { //This method as of now doesn't target the params.. it just does the recording
for(Point p : movements) {
execute(m.getLocation().x+p.x, m.getLocation().y+p.y, MouseEvent.MOUSE_MOVED);
try {
Thread.sleep(time / movements.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void execute(int x, int y, int event) {
m.getC().dispatchEvent(new MouseEvent(m.getC(),event,
System.currentTimeMillis(),0,
x,y,0,false));
}
}
main.java包含一个循环和一个scanner的switch语句,用于执行命令:
while(true) {
switch (s.next()) {
case "movesRec":
Main.recordMoves = true;
MovesRecorder.lastPos = Screen.mouse.getLocation();
break;
case "move":
MousePatterns.moves.get(0).executeEvents(100,100);
break;
}
}
mousepatterns.java包含一个用于添加移动的静态列表:
public static List<Move> moves = new ArrayList<>();
非常感谢您的帮助!
1条答案
按热度按时间zvms9eto1#
考虑下面的场景,在你记录的一个动作中(x1,y1)是你的起点,(x2,y2)是你的终点,你记录的这两点之间的唯一点是(xm1,ym1)。
当然,在真实场景中,在(x1,y1)和(x2,y2)之间有更多的点,但是为了简单起见,让我们假设只有一个点。
x1:0,y1:0
xm1:45:,ym1:60
x2:100,y2:100
现在你有了一个起点(x3,y3)并且想要按照你之前记录的同样的动作移动到(x4,y4)。为此,需要找到(xm2,ym2)。
x3:15,y3:45
xm2:?,ym2:?
x4:150,y4:200
考虑到xp1是xm1已经行驶的x1和x2之间距离的百分之多少,您可以执行以下操作来查找xm2和ym2:
xp1=xm1100/(x2-x1)
xm2=xp1(x4-x3)/100
yp1=ym1100/(y2-y1)
ym2=yp1(y4-y3)/100
(在(x1,y1)到(x2,y2)场景中,xp1=45%,yp1=60%,因为它们从(x1,y1)和(x2,y2)之间的距离“行驶”了45%和65%)
求解方程:
xp1=45100/100=45
xm1=45135/100=60.75
yp1=60100/(100-0)=60
ym2=60(200-45)/100=93
现在您只需对从(x1,y1)到(x2,y2)记录的每个点执行此操作,您将拥有从(x3,y3)到(x4,y4)的所有点