{"id":23406963,"url":"https://github.com/njurquet/zigzag","last_synced_at":"2026-04-24T21:33:09.387Z","repository":{"id":266570626,"uuid":"897553105","full_name":"NJurquet/ZigZag","owner":"NJurquet","description":"Computer Vision bot for the ZigZag mobile game developped by Ketchapp","archived":false,"fork":false,"pushed_at":"2025-01-04T02:06:55.000Z","size":458,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T00:07:18.058Z","etag":null,"topics":["computer-vision","opencv","python"],"latest_commit_sha":null,"homepage":"https://youtu.be/rpwYOtp9QeU","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NJurquet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-02T20:36:22.000Z","updated_at":"2025-01-21T11:02:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"eb3c045c-1ad4-49a0-952b-090bcca192d1","html_url":"https://github.com/NJurquet/ZigZag","commit_stats":null,"previous_names":["njurquet/zigzag"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NJurquet%2FZigZag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NJurquet%2FZigZag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NJurquet%2FZigZag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NJurquet%2FZigZag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NJurquet","download_url":"https://codeload.github.com/NJurquet/ZigZag/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247947859,"owners_count":21023066,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["computer-vision","opencv","python"],"created_at":"2024-12-22T14:16:29.940Z","updated_at":"2026-04-24T21:33:09.337Z","avatar_url":"https://github.com/NJurquet.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eZigZag\u003c/h1\u003e\u003cbr\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"https://play-lh.googleusercontent.com/6pyha8P40IH8Yn7ets-yr-sDmze-lif7Lh80ZMffdBojvhAtGTk88zHru3UHeipNhA\" width=\"300\" /\u003e\u003cbr\u003e\n\u003c/div\u003e\n\n## Introduction\n\n### Game\n\n**ZigZag** is a popular mobile game with over 50M downloads on the _Google Play Store_.\nThe game is simple: players control a ball moving along an isometric zigzag path and changing its direction by tapping on the screen.\nEach tap causes the ball to move diagonally to the left or right.\nThe primary objective is to stay on the path as long as possible without falling off the edges while collecting diamonds found along the way.\n\nThe game incorporates a scoring system where each direction change increases the score by 1 point.\nWhen collecting a diamond, the score will increase by 2.\nDiamonds can also be used to unlock various ball skins, adding a customization element to the game. \n\nThe game has 5 _Google Play Games_ achievements:\n\n-   Get a score of 50 points! (Uncommon)\n-   Get a score of 125 points! (Uncommon)\n-   Get a score of 250 points! (Rare)\n-   Get a score of 1000 points! (Ultra Rare)\n-   Play 1000 rounds of ZigZag! (Rare)\n\n### Project\n\nThis project aims to create an autonomous bot to play the game on behalf of the player using `Python` image processing.\n`OpenCV` and `NumPy` are used for every image processing task.\nSince ZigZag is a mobile game, it is run on a computer using an Android emulator such as _Bluestacks_ or _LDPlayer_.\n\nThe bot is designed to detect the ball and path edges in real time and simulating screen taps when the ball approaches an edge.\nThe ultimate goal is to enable the bot to consistently achieve all game score milestones and maximize the high score potential to eventually reach the actual limit of 100k points.\n\n\u003e [!NOTE]\n\u003e The bot is only working on **Windows** at the moment, and has been tested on **Visual Studio Code** (even though it should work on any IDE) and **Bluestacks 5** Android emulator.\n\n\u003e [!NOTE]\n\u003e A view of AI usage whithin the project can be found in the [AI.md](AI.md) file.\n\n## Depedencies\n\nThis project uses depedencies that require `Python 3.10` or above.\n\n\u003cdiv align=\"center\"\u003e\n  \n|    **Name**    | **Version Used** |\n|----------------|:----------------:|\n| Python         | 3.12.4           |\n| opencv-python  | 4.10.0.84        |\n| numpy          | 2.1.3            |\n| pywin32        | 308              |\n| PyAutoGUI      | 0.9.54           |\n\u003c/div\u003e\n\n## Installation\n\n\u003e [!WARNING]\n\u003e **MacOS** is not supported at the moment.\n\n1. Clone the repository and navigate to the project root folder `ZigZag`:\n\n```bash\ngit clone https://github.com/NJurquet/ZigZag.git\n```\n\n2. Install the required dependencies:\n\n```bash\npip install -r requirements.txt\n```\n\n3. Install an Android emulator on your computer.\n   [Bluestacks 5](https://www.bluestacks.com/) or [LDPlayer](https://www.ldplayer.net/) are recommended.\n\n4. Go to the Google Play Store, sign in with your Google account and download **ZigZag**.\n\n5. In the emulator settings, remove eventual ads.\n   Minimize the right sidebar to remove a maximum of distractions.\n\n6. Open the game and test a few games to make sure the game is running correctly (the emulator can be put in airplane mode for less ads, but it should not affect the bot).\n\n7. Change the `src/config.py` file to configure the project as needed.\n\n    Make sure to set the `WINDOW_NAME` constant to your game window name, and `VISION_EN` to either `True` or `False` depending on if you want to enable or disable the image processing window.\n    A list of all opened windows can be obtained by running:\n\n```bash\npython -m src.capture.screen_capture\n```\n\n\u003e [!TIP]\n\u003e Set `VISION_EN` to `False` to minimize the time used for frame drawing and display.\n\n8. Make sure you have done the following before running the bot for the best results:\n\n    - Have the game on the main screen\n    - Your PC is charging (for better performance)\n    - Any heavy other programs are closed (for better performance)\n\n9. Run the bot:\n\n```bash\npython -m src.main\n```\n\n\u003e [!NOTE]\n\u003e The window should automatically be resized to `WINDOW_HEIGHT` provided in the `config.py` file, and the mouse be moved to the center of the window.\n\n## Goals\n\n1. Process a frame image so it detects the ball and path edges.\n\n2. Process the real-time game screen so it detects the ball and path edges.\n\n3. Be able to simulate a click that results from the ball being close to an edge.\n\n4. Have an average FPS of at least 30 with vision window enabled and when the PC is charging.\n\n5. Achieve an average score of 500 points.\n\n6. Achieve a score of 1000 points.\n\n7. The game window should be captured no matter its initial position or size, and without causing more disturbances.\n\n8. The bot should meet the 500 average points objective on any Windows computer, regardless of its performance or resolution.\n\n9. The bot should be robust and give reproducible results. It should be independant to time, randomness, and other external factors.\n\n## Strategy\n\n1. Find the emulator window, resize it and move the mouse to its center.\n2. Capture the window using DPI awareness for being able to capture DPI aware applications, and for screen scale independence.\n3. Find optimal detection parameters \u0026 mask out interfering objects to keep the necessary ones.\n4. Detect the player ball and draw a circle on the frame with OpenCV.\n5. Detect path edges and draw the lines on the frame with OpenCV.\n6. Use 2 points for edge proximity detection: horizontal front point \u0026 isometric front point. If the ball is close enough to a detected edge, it simulates a click.\n7. When changing direction, vertically mirror the 2 points to only detect one side of the edges lines.\n8. Also simulate a click when the white background is detected, in case edges are not detected properly.\n9. All or most calculations are performed using matrix operations or Numpy arrays for processing time optimization.\n10. Every position, distance or size are calculated in relative units to the screen height for window size \u0026 screen resolution independence.\n\n## Difficulties\n\n### Dynamic color changes\n\nAs the player progresses through one game, the theme colors transition randomly within a predefined palette.\nAdditionally, the ball can be customized with various skins, each having unique color patterns.\nThis project cannot therefore rely on color-based detection methods to identify game elements.\n\n### Accuracy in detection\n\nOpenCV-based image processing is prone to imperfections in detecting edges or circles.\nInsufficient detection accuracy could result in the ball being lost or misidentified, or the path edge detection failing for a set of time.\nSuch errors may lead to the ball falling off the edges.\n\n### Diamonds interference\n\nAlthough diamonds are important to collect to reach higher scores, they are not part of the game mechanics.\nThese pink diamonds are isometric shapes composed of lines that could interfere with lines detection and may cause unwanted change in ball direction.\n\n### Real-time game\n\nObjects detection, screen processing and actions are performed in real-time using the live game window.\nWithout proper optimization, these operations could lead to high latency and low reaction times, resulting in delayed direction changes or missed edge detections, negatively affecting performance.\n\n### Window capture\n\nThe game window capture may introduce disturbances or noise that can affect performance or gameplay.\nIf the window is not captured correctly, the bot will not be able to properly detect the ball/edges.\nFor example, variations in some emulator configurations such as UI elements (e.g., borders or sidebars) may cause the bot to misinterpret the game frame.\n\nThe window will not be placed at the exact same position every time, so capturing the window based on its position will not work.\n\n### Computer independence\n\nThe bot is intended to run on computers with diverse performance, screen resolutions and scaling.\nVariability in system performance may result in more delays, glitches or processing inconsistencies.\nFixed pixel-based sizes and positions will also cause failings in game elements detection or being out of the screen area.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnjurquet%2Fzigzag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnjurquet%2Fzigzag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnjurquet%2Fzigzag/lists"}