• 用Kotlin破解Android版微信小游戏跳一跳


    前言

    微信又更新了,从更新日志上来看,似乎只是一次不痛不痒的小更新.
    不过,很快就有人发现,原来微信这次搞了个大动作——在小程序里加入了小游戏。今天也是朋友圈被刷爆的缘故。

    看到网上 有人弄了一个破解版的,于是自己也跟着网上的案例整了一下,感觉挺有意思的。

    游戏如下:

    来玩游戏
    来玩游戏

    劳动成果

     用Kotlin破解Android版微信小游戏-跳一跳
    用Kotlin破解Android版微信小游戏-跳一跳

    跳一跳

    微信小程序可以玩游戏了,我们来破解一下《跳一跳》这个官方出品的小游戏吧。

    思路

    用usb调试安卓手机,用adb截图并用鼠标测量距离,然后计算按压时间后模拟按压。

    $ adb shell input swipe <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen) # 模拟长按
    $ adb shell screencap <filename> # 保存截屏到手机
    $ adb pull /sdcard/screen.png # 下载截屏文件到本地
    
    主要核心
    • 得到手指按的时间 t
    • 时间 = 距离 / 速度(常量) t = L / k
    • L = p2 - p1
    • 获取到起始点和结束点的坐标

    源码

    开发环境: Kotlin, IetelliJ IDEA

    https://github.com/iOSDevLog/JumpJump

    主要源码

    fun main(args: Array<String>) {
        val jumpjump = JumpJump()
        var isFirst = true
        var firstPoint: Point? = null
        var secondPoint: Point?
    
        val jPanel = object : JPanel() {
            override fun paintComponent(g: Graphics) {
                super.paintComponent(g)
                try {
                    var bufferedImage = ImageIO.read(File(SCREENSHOT_LOCATION))
                    val newImage = BufferedImage(675, 1200, bufferedImage.getType())
                    val gTemp = newImage.graphics
                    gTemp.drawImage(bufferedImage, 0, 0, 675, 1200, null)
                    gTemp.dispose()
                    bufferedImage = newImage
                    g.drawImage(bufferedImage, 0, 0, null)
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
        }
    
        jPanel.addMouseListener(object : MouseListener {
            override fun mouseReleased(e: MouseEvent?) {
            }
    
            override fun mouseEntered(e: MouseEvent?) {
            }
    
            override fun mouseClicked(e: MouseEvent?) {
            }
    
            override fun mouseExited(e: MouseEvent?) {
            }
    
            override fun mousePressed(e: MouseEvent?) {
                println("mousePressed")
                e.let {
                    if (isFirst) {
                        println("first {pomt" + e!!.x + " " + e.y)
                        firstPoint = e.point
                        isFirst = false
                    } else {
                        secondPoint = e!!.point
                        val distance = distance(firstPoint!!, secondPoint!!)
                        println("distance:" + distance)
                        isFirst = true
                        //magic number
                        call(distance * 2.2)
                        try {
                            // wait for screen cap
                            Thread.sleep(2500)
                        } catch (e1: InterruptedException) {
                            e1.printStackTrace()
                        }
    
                        printScreen()
    
                        jPanel.validate()
                        jPanel.repaint()
                    }
                }
            }
    
        })
    
        jumpjump.isVisible = true
        jumpjump.contentPane.add(jPanel)
    
        printScreen()
        jumpjump.repaint()
        jumpjump.validate()
    }
    
    fun distance(a: Point, b: Point): Int {
        return Math.sqrt((a.x - b.getX()) * (a.x - b.getX()) + (a.y - b.getY()) * (a.y - b.getY())).toInt()
    }
    

    在java中是如何操作的?

    BackgroundImage4Panel.java
    public class BackgroundImage4Panel extends javax.swing.JFrame {
        /**
         * serialVersionId
         */
        private static final long serialVersionUID = 1L;
    
        private static boolean isFirst = true;
    
        private static Point firstPoint;
        private static Point secondPoint;
    
        /**
         * Creates new form NewJFrame
         */
        public BackgroundImage4Panel() {
            setSize(675, 1200);
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        }
    
        /**
         * 测试入口
         *
         * @param args 参数列表
         */
        public static void main(String[] args) {
            AdbCaller.printScreen();
            final BackgroundImage4Panel backgroundImage4Panel = new BackgroundImage4Panel();
            backgroundImage4Panel.setVisible(true);
    
            JPanel jPanel = new JPanel() {
                /**
                 * serialVersionId
                 */
                private static final long serialVersionUID = -1183754274585001429L;
    
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    try {
                        BufferedImage bufferedImage = ImageIO.read(new File(Constants.SCREENSHOT_LOCATION));
                        BufferedImage newImage = new BufferedImage(675, 1200, bufferedImage.getType());
                        /**
                         * try to resize
                         */
                        Graphics gTemp = newImage.getGraphics();
                        gTemp.drawImage(bufferedImage, 0, 0, 675, 1200, null);
                        gTemp.dispose();
                        bufferedImage = newImage;
                        g.drawImage(bufferedImage, 0, 0, null);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            };
            backgroundImage4Panel.getContentPane().add(jPanel);
    
            backgroundImage4Panel.getContentPane().getComponent(0).addMouseListener(new MouseListener() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (isFirst) {
                        System.out.println("first " + e.getX() + " " + e.getY());
                        firstPoint = e.getPoint();
                        isFirst = false;
                    } else {
                        secondPoint = e.getPoint();
                        int distance = distance(firstPoint, secondPoint);
                        System.out.println("distance:" + distance);
                        isFirst = true;
                        AdbCaller.call(distance * 2.19);//magic number
                        try {
                            Thread.sleep(2500);// wait for screencap
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                        AdbCaller.printScreen();
                        JPanel jp = ((JPanel) backgroundImage4Panel.getContentPane().getComponent(0));
                        jp.validate();
                        jp.repaint();
                    }
    
                }
    
                @Override
                public void mousePressed(MouseEvent e) {
    
                }
    
                @Override
                public void mouseReleased(MouseEvent e) {
    
                }
    
                @Override
                public void mouseEntered(MouseEvent e) {
    
                }
    
                @Override
                public void mouseExited(MouseEvent e) {
    
                }
            });
        }
    
        /**
         * 实现图像的等比缩放
         *
         * @param source  待处理的图片流
         * @param targetW 宽度
         * @param targetH 高度
         * @return
         */
        public static BufferedImage resize(BufferedImage source, int targetW, int targetH) {
            int width = source.getWidth();// 图片宽度
            int height = source.getHeight();// 图片高度
            return zoomInImage(source, targetW, targetH);
        }
    
        /**
         * 对图片进行强制放大或缩小
         *
         * @param originalImage 原始图片
         * @return
         */
        public static BufferedImage zoomInImage(BufferedImage originalImage, int width, int height) {
            BufferedImage newImage = new BufferedImage(width, height, originalImage.getType());
    
            Graphics g = newImage.getGraphics();
            g.drawImage(originalImage, 0, 0, width, height, null);
            g.dispose();
            return newImage;
        }
    
        public static int distance(Point a, Point b) {//求两点距离
            return (int) Math.sqrt((a.x - b.getX()) * (a.x - b.getX()) + (a.y - b.getY()) * (a.y - b.getY()));
        }
    }
    
    

    AdbCaller.java

    public class AdbCaller {
    
        public static void call(double timeMilli) {
            try {
                Runtime.getRuntime().exec(Constants.ADB_PATH + " shell input touchscreen swipe 170 187 170 187 " + (int) timeMilli);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void printScreen() {
            try {
                Process p1 = Runtime.getRuntime().exec(Constants.ADB_PATH + " shell screencap -p /sdcard/screenshot.png");
                p1.waitFor();
                Process p2 = Runtime.getRuntime().exec(Constants.ADB_PATH + " pull /sdcard/screenshot.png " + Constants.SCREENSHOT_LOCATION);
                p2.waitFor();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    Constants.java
    public class Constants {
        /**
         * adb所在位置
         */
        public static final String ADB_PATH = "E:\\android_install_64\\sdk\\platform-tools\\adb.exe";
        /**
         * 截屏文件所在位置
         */
        public static final String SCREENSHOT_LOCATION = "E:\\android_install_64\\sdk\\platform-tools\\yyh.png";
    }
    
    

    使用方法

    • 在电脑上下载好adb
    • 打开安卓手机的usb调试模式并授权连接的电脑
    • 打开微信跳一跳,并点击开始
    • 在Constans.java中配置好adb路径与截图路径,运行
    • 在弹出的窗口中先点击小人底部适当位置,然后再点想要跳的箱子的位置即可完成

    参考

    https://github.com/easyworld/PlayJumpJumpWithMouse

    http://iosdevlog.com/2017/12/29/jump-jump.html

    关于更多

    分分钟教你学会正则表达式

    2017上半年技术文章集合—184篇文章分类汇总

    高级UI特效仿直播点赞效果—一个优美炫酷的点赞动画

    一个实现录音和播放的小案例

    NDK项目实战—高仿360手机助手之卸载监听

    相信自己,没有做不到的,只有想不到的

    微信公众号:终端研发部

    技术+职场
    技术+职场
  • 相关阅读:
    读书笔记 之《Thinking in Java》(对象、集合、异常)
    ArrayList 和 LinkedList的执行效率比较
    Hybris CronJob.
    C# 中的treeview绑定数据库(递归算法)
    identity_insert---实验性插入大批量数据和分页存储过程
    SQL Server 存储过程
    PL/SQL 在64位机上不能使用的问题解决
    登陆Oracle11g的企业管理器
    SQL在oracle和SQLserver将查询结果创建为新表的不同之处
    介绍一下内联、左联、右联
  • 原文地址:https://www.cnblogs.com/codeGoogler/p/8151078.html
Copyright © 2020-2023  润新知