Search code examples
javamathinputrpa

Smoothing out lines on direction change , simulating user input from pattern with java Robot


So im creating application that simulate mouse movement of a user.

I have pattern in a format of [number of steps,direction]

 pattern.put(Weapon.NAME_TEST_DOWN2, new int[][]{ //sens: 1.0 steps:5,10ms delay
            {600, DOWN},
            {100, RIGHT | DOWN},
            {400, LEFT | DOWN},
            {100, LEFT},
            {200, NONE},
            {600, RIGHT},
            {400, NONE},
            {400, LEFT}
        });

Things work fine bud obviously mosue movement is snappy , needs to be smoothened out so it looks human like , image of that :

enter image description here

Function for whole mouse movement is :

private final int stepAmount = 1;
@SuppressWarnings("FieldMayBeFinal")
private int delay = (int) (2 * CsgoRr.getModel().getAppPrefs().getIngameSensitivity()); // increments of 1 1.5 2 2.5 etc
   @SuppressWarnings("CallToPrintStackTrace")
    public void reduceRecoil() {

        @SuppressWarnings("UnusedAssignment")
        int directionFlag = 0;
        int previousDirectionFlag;
        int nextDirectionFlag = RecoilPatternInfo.NONE;
        for (int row = 0; row < recoilPattern.length; row++) {

            if (weapon.isTriggerPulled()) {
                int duration = recoilPattern[row][0];
                directionFlag = recoilPattern[row][1];
                previousDirectionFlag = (row != 0) ? recoilPattern[row - 1][1] : RecoilPatternInfo.NONE;
                try {
                    nextDirectionFlag = recoilPattern[row + 1][1];
                } catch (IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
                switch (directionFlag) {
                    case (RecoilPatternInfo.DOWN): {
                        while ((duration -= delay) > 0) {
                            if (weapon.isTriggerPulled()) {
                                mouseMove(MouseInfo.getPointerInfo().getLocation().x,
                                        MouseInfo.getPointerInfo().getLocation().y + stepAmount);
                            } else {
                                return;
                            }
                            this.delay(delay);
                        }
                        break;
                    }
                    case (RecoilPatternInfo.DOWN | RecoilPatternInfo.LEFT): {
                        while ((duration -= delay) > 0) {
                            if (weapon.isTriggerPulled()) {
                                mouseMove(MouseInfo.getPointerInfo().getLocation().x - stepAmount,
                                        MouseInfo.getPointerInfo().getLocation().y + stepAmount);
                            } else {
                                return;
                            }
                            this.delay(delay);
                        }
                        break;
                    }
                    case (RecoilPatternInfo.DOWN | RecoilPatternInfo.RIGHT): {
                        while ((duration -= delay) > 0) {
                            if (weapon.isTriggerPulled()) {
                                mouseMove(MouseInfo.getPointerInfo().getLocation().x + stepAmount,
                                        MouseInfo.getPointerInfo().getLocation().y + stepAmount);
                            } else {
                                return;
                            }
                            this.delay(delay);
                        }
                        break;
                    }
                    case (RecoilPatternInfo.LEFT): {
                        while ((duration -= delay) > 0) {
                            if (weapon.isTriggerPulled()) {
                                mouseMove(MouseInfo.getPointerInfo().getLocation().x - stepAmount,
                                        MouseInfo.getPointerInfo().getLocation().y);
                            } else {
                                return;
                            }
                            this.delay(delay);
                        }
                        break;
                    }
                    case (RecoilPatternInfo.RIGHT): {
                        while ((duration -= delay) > 0) {
                            if (weapon.isTriggerPulled()) {
                                mouseMove(MouseInfo.getPointerInfo().getLocation().x + stepAmount,
                                        MouseInfo.getPointerInfo().getLocation().y);
                            } else {
                                return;
                            }
                            this.delay(delay);
                        }
                        break;
                    }

                    case (RecoilPatternInfo.UP): {
                        while ((duration -= delay) > 0) {
                            if (weapon.isTriggerPulled()) {
                                mouseMove(MouseInfo.getPointerInfo().getLocation().x,
                                        MouseInfo.getPointerInfo().getLocation().y - stepAmount);
                            } else {
                                return;
                            }
                            this.delay(delay);
                        }
                        break;
                    }
                    case (RecoilPatternInfo.UP | RecoilPatternInfo.LEFT): {
                        while ((duration -= delay) > 0) {
                            if (weapon.isTriggerPulled()) {
                                mouseMove(MouseInfo.getPointerInfo().getLocation().x - stepAmount,
                                        MouseInfo.getPointerInfo().getLocation().y - stepAmount);
                            } else {
                                return;
                            }
                            this.delay(delay);
                        }
                        break;
                    }
                    case (RecoilPatternInfo.UP | RecoilPatternInfo.RIGHT): {
                        while ((duration -= delay) > 0) {
                            if (weapon.isTriggerPulled()) {
                                mouseMove(MouseInfo.getPointerInfo().getLocation().x + stepAmount,
                                        MouseInfo.getPointerInfo().getLocation().y - stepAmount);
                            } else {
                                return;
                            }
                            this.delay(delay);
                        }
                        break;
                    }
                    default: {//RecoilPatternInfo.NONE
                        while ((duration -= delay) > 0) {
                            if (weapon.isTriggerPulled()) {
                                mouseMove(MouseInfo.getPointerInfo().getLocation().x,
                                        MouseInfo.getPointerInfo().getLocation().y);
                            } else {
                                return;
                            }
                            this.delay(delay);
                        }
                    }
                }
            }
        }
    }

As i know which direction im going to move next and i know how many steps remain till direction change i should be able to do that.

What i was thinking is incrementing/decrementing value of movement to side/up/down of next/previous movement direction only last/first 20% of steps.Then incrementaly increasing/decreasing this movement bud whole thing woud be insanely big SWITCH statement , lot of work and not efficient.

Is there any better way of doing this? Or will i be forced into my first idea?

Any ideas for most efficient working solution?


Solution

  • Ok so after a lot of paper work(yes i drew it on paper) , i managed to do this without using some complex math or spline api etc.

    What i did was followed on my first idea , taken in mind next direction and pre turn slowly , using deviation with smoothing factor based on percentages of patern and steps that has been made so far.

    This approach is really effective and performance gains outweight lesser detail in curves.

    Its by no means perfect bud with additional user input , random number addition its pretty much what i had in mind.