Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f6bbf6a
Optimize runtime loops and refresh brawler/game config data
Copilot May 11, 2026
5e8bf2e
Address review feedback for wording and brawler aliases
Copilot May 11, 2026
b7e2b47
Upgrade vulnerable pip dependencies to patched versions
Copilot May 11, 2026
d96dc9f
Apply review cleanup for detection variable naming
Copilot May 11, 2026
142c9bf
Upgrade Pillow to 12.2.0 for security fixes
Copilot May 11, 2026
1ad69ea
Fix detection temp list initialization style
Copilot May 11, 2026
a28d0ca
Align detection variable naming with file style
Copilot May 11, 2026
1f2d14b
Merge pull request #1 from bebabinlarsson-blip/copilot/update-all-for…
bebabinlarsson-blip May 11, 2026
f00a6ef
Add multi-mode/team-aware foundations with prediction support
Copilot May 11, 2026
ea4264e
Address validation review nits for robustness and clarity
Copilot May 11, 2026
628a150
Polish team-mode behavior comments and threshold clarity
Copilot May 11, 2026
0a18509
Tune mode profile knobs and use deque for enemy history
Copilot May 11, 2026
e2b16e8
Clarify active game mode naming and prediction intent
Copilot May 11, 2026
6ac345c
Merge pull request #2 from bebabinlarsson-blip/copilot/enhance-game-m…
bebabinlarsson-blip May 11, 2026
23332c8
feat: stabilize bot behavior and reduce detection jitter
Copilot May 11, 2026
04ad09d
fix: address validation feedback on thread consistency
Copilot May 11, 2026
aeaa378
chore: incorporate final code review suggestions
Copilot May 11, 2026
fa381c7
docs: clarify deterministic fallback and cooldown semantics
Copilot May 11, 2026
2847833
docs: align movement docstrings with deterministic logic
Copilot May 11, 2026
05b195e
refactor: clarify enemy grace tracking and move-key naming
Copilot May 11, 2026
c5e5744
refactor: polish idle polling and deterministic movement naming
Copilot May 11, 2026
5f291dd
Merge pull request #3 from bebabinlarsson-blip/copilot/fix-buggy-and-…
bebabinlarsson-blip May 11, 2026
18e84bb
Improve mode-aware objective logic beyond solo-only behavior
Copilot May 11, 2026
0c5e637
Apply review fixes for objective logic update
Copilot May 11, 2026
3e44584
Merge pull request #4 from bebabinlarsson-blip/copilot/update-logic-e…
bebabinlarsson-blip May 11, 2026
7359c8c
Update README to reference this repo (bebabinlarsson-blip/BrawlStarsB…
Copilot May 11, 2026
588940a
Merge pull request #5 from bebabinlarsson-blip/copilot/update-readme-…
bebabinlarsson-blip May 11, 2026
aee7e9f
Update requirements.txt for Python 3.14 compatibility
Copilot May 11, 2026
7868cc7
Merge pull request #6 from bebabinlarsson-blip/copilot/fix-contourpy-…
bebabinlarsson-blip May 11, 2026
1032b86
fix: remove pandas/seaborn, add cubebox attack, auto player position …
Copilot May 11, 2026
d913ce7
refactor: avoid redundant tile_distance call in is_cubebox_in_range
Copilot May 11, 2026
9dc067d
Merge pull request #7 from bebabinlarsson-blip/copilot/update-readme-…
bebabinlarsson-blip May 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# BrawlStarsBot
⚠️ **DISCLAIMER!!** ****You can lose trophies while using the bot!! The bot's goal is to farm mastery**** ⚠️

Brawl stars bot for farming mastery through solo showdown. The bot will find bushes and hide, it also attacks enemies if they are within range. Macro is integrated into the code to automate when defeated, it will queue up for another match automatically.
Brawl stars bot for farming mastery through solo showdown (and now configurable team-mode profiles). The bot will find bushes and hide (or play more aggressively in team profiles), and attack enemies if they are within range. Macro is integrated into the code to automate when defeated, it will queue up for another match automatically.

## Info
Inspired by [OpenCV Object Detection in Games Python Tutorial playlist by "Learn Code By Gaming"](https://www.youtube.com/watch?v=KecMlLUuiE4&list=PL1m2M8LQlzfKtkKq2lK5xko4X-8EZzFPI) and ["How To Train YOLOv5 For Recognizing Game Objects In Real-Time" by "Jes Fink-Jensen"](https://betterprogramming.pub/how-to-train-yolov5-for-recognizing-custom-game-objects-in-real-time-9d78369928a8).
Expand All @@ -16,44 +16,60 @@ A recommended map to run the bot on is island invasion, using short/medium range
- Start the bot when loading in
- Find the closest bush and hide in it
- Attack the enemy when they are in the range
- Enemy movement prediction (short-term) to react earlier in fights
- Optional teammate-aware behavior (when your model includes a `Teammate` class)
- Configurable game mode profiles: `solo_showdown`, `team_3v3`, `team_5v5`
- Mode-aware objective search priorities (bush, cubebox, enemy) with capped reposition times for team modes
- Rank push context fields (`current_rank` / `target_rank`) for session tracking output
- Activate gadget when the enemy is closer to the player
- Custom Bluestack game control for the bot


## Demo of the bot
[![Watch the video](https://github.com/Jooi025/BrawlStarsBot/blob/main/misc/image/youtube_thumbnail.jpg)](https://youtu.be/TWmNfkQBVYk?si=CXaSBoAV-YknJPLt)
[![Watch the video](https://github.com/bebabinlarsson-blip/BrawlStarsBotPrompt/blob/main/misc/image/youtube_thumbnail.jpg)](https://youtu.be/TWmNfkQBVYk?si=CXaSBoAV-YknJPLt)

## Requirement
* Windows OS
* [Bluestacks 5](https://www.bluestacks.com/download.html) to run Brawl Star and for custom control
* Python version 3.11.6
* Python version 3.11.6 or newer (3.14 supported)

## How to install and run the bot?
### [Watch the tutorial and common error fix playlist](https://youtube.com/playlist?list=PLD9X_geub8rmkcpJSWzvoqmB9VZk-9TfO&si=7vrCV9s1kLviRaTL)
### Clone Repo
1. Clone the repository
```
git clone https://github.com/Jooi025/BrawlStarsBot.git
git clone https://github.com/bebabinlarsson-blip/BrawlStarsBotPrompt.git
```
2. Install the required library
```
cd BrawlStarsBot
cd BrawlStarsBotPrompt
pip install -r requirements.txt
```
[Writing instruction](https://github.com/Jooi025/BrawlStarsBot/blob/main/misc/textInstruction.md)
[Writing instruction](https://github.com/bebabinlarsson-blip/BrawlStarsBotPrompt/blob/main/misc/textInstruction.md)
### Update Repo
```
cd BrawlStarsBot
cd BrawlStarsBotPrompt
git pull
```
## Recent updates
- Improved runtime performance by reducing busy-wait CPU loops in capture/detection threads.
- Improved detection throughput by using faster list handling and model confidence pre-filtering.
- Improved brawler lookup robustness (`Mr. P`, `mr p`, `mrp` now resolve to same key format).
- Expanded `brawler_stats.json` with newer and missing brawlers for current roster coverage.
- Added configurable mode profiles for solo and team modes (`3v3`, `5v5`) with different bot behavior.
- Added class-name based detection mapping so custom models can be extended more safely.
- Added short-horizon enemy movement prediction and optional teammate-support aggression.
- Improved non-solo behavior with profile-based objective priorities and faster reposition loops.
- Added manual rank-push context fields for current/target rank visibility.
- Added cubebox attack: bot now attacks power cube boxes in range during search and movement phases.
- Player position is now estimated automatically from the detection bounding box — `heightScaleFactor` and `hsf_finder.py` are no longer required.
- Removed `pandas` and `seaborn` from `requirements.txt`; both were unused by the bot and prevented installation on Python 3.14.

## Improvement to be made
- [ ] bot can attack power cube boxes and collect them
- [x] bot can attack power cube boxes and collect them
- [x] improve detection of enemy (less false detect)
- [ ] change player detection and don't need to measure HSF
- [x] change player detection and don't need to measure HSF
- [x] improve storm direction function
- [x] improve the screen detection of "defeated"
- [x] fix spam printing of "stop bot"
- [x] improve fps for lower performance computer



35 changes: 34 additions & 1 deletion brawler_stats.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,39 @@

"sandy":[2.57,6,0.157],

"spike":[2.4,7.67],
"crow":[2.73,8.67],
"leon":[2.73,9.33],
"amber":[2.4,8.67],
"meg":[2.4,7.33],
"gale":[2.4,8.33],
"surge":[2.4,8],
"colette":[2.4,9],
"belle":[2.4,10],
"ash":[2.57,4.67],
"lola":[2.4,8],
"fang":[2.57,3.33],
"janet":[2.4,8.67],
"sam":[2.57,3.33],
"buster":[2.57,6.67],
"chester":[2.4,7.67],
"mandy":[2.4,12],
"maisie":[2.4,8.67],
"cordelius":[2.57,5.67],
"larrylawrie":[2.4,8],
"larryandlawrie":[2.4,8],
"melodie":[2.73,6.67],
"lily":[2.73,3.67],
"angelo":[2.4,10],
"draco":[2.57,3.67],
"berry":[2.4,7.67],
"clancy":[2.4,8],
"moe":[2.57,6],
"kenji":[2.73,3.67],
"juju":[2.4,8.33],
"shade":[2.57,4],
"ollie":[2.57,4.67],
"meeple":[2.4,8.67],
"mico":[2.73,4]

}
}
109 changes: 94 additions & 15 deletions constants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import json
import re
from pathlib import Path
from modules.print import bcolors
brawler_stats_dict = json.load(open("brawler_stats.json"))

REPO_ROOT = Path(__file__).resolve().parent
with open(REPO_ROOT / "brawler_stats.json", encoding="utf-8") as stats_file:
brawler_stats_dict = json.load(stats_file)


def normalize_brawler_name(name):
"""
Normalize user-provided brawler names for robust lookup.
e.g. "Mr. P", "MrP", "mr p" -> "mrp"
"""
return re.sub(r"[^a-z0-9]+", "", name.lower().strip())

class Constants:
#! Brawler's stats
Expand All @@ -12,10 +25,13 @@ class Constants:

"""
go to https://pixelcrux.com/Brawl_Stars/Brawlers/ to find your
brawler's speed and attack range and use hsf_finder.py
to get the brawler's height scale factor

eg. eve's speed (2.4), attack_range (9.33) and heightScaleFactor (0.158)
brawler's speed and attack range.

heightScaleFactor is no longer required — player position is now
estimated automatically from the detection bounding box.
It is kept here for backward compatibility but ignored by the detector.

eg. eve's speed (2.4) and attack_range (9.33)
"""
speed = 2.4 # units: (tiles per second)
attack_range = 9.33 # units: (tiles)
Expand All @@ -29,6 +45,56 @@ class Constants:
"""
sharpCorner = True
centerOrder = True

#! Gameplay mode profile
"""
Supported:
- solo_showdown
- team_3v3
- team_5v5
"""
game_mode = "solo_showdown"
game_mode_profiles = {
"solo_showdown": {
"hide_in_bush": True,
"centerOrder": True,
"aggression": 1.0,
"prediction_seconds": 0.35,
"teammate_support_range": 6,
"team_aggression_distance_multiplier": 0.9,
"search_priority": ["Bush", "Cubebox", "Enemy"],
"objective_move_cap_seconds": 2.6,
},
"team_3v3": {
"hide_in_bush": False,
"centerOrder": False,
"aggression": 1.15,
"prediction_seconds": 0.35,
"teammate_support_range": 6,
"team_aggression_distance_multiplier": 0.9,
"search_priority": ["Enemy", "Bush", "Cubebox"],
"objective_move_cap_seconds": 1.4,
},
"team_5v5": {
"hide_in_bush": False,
"centerOrder": False,
"aggression": 1.2,
"prediction_seconds": 0.4,
"teammate_support_range": 7,
"team_aggression_distance_multiplier": 0.88,
"search_priority": ["Enemy", "Bush", "Cubebox"],
"objective_move_cap_seconds": 1.2,
},
}

#! Rank pushing context (manual)
"""
This is used for rank push context/output.
Current and target rank are intentionally manual values.
"""
rank_push_enabled = False
current_rank = None
target_rank = None

#! Window Capture
"""
Expand All @@ -52,16 +118,29 @@ class Constants:

#! Do not change these
# Detector constants
classes = ["Player","Bush","Enemy","Cubebox"]
"""
Threshold's index correspond with classes's index.
e.g. First element of classes is player so the first
element of threshold is threshold for player.
"""
threshold = [0.37,0.47,0.57,0.65]
classes = ["Player", "Bush", "Enemy", "Cubebox", "Teammate"]
class_threshold = {
"Player": 0.37,
"Bush": 0.47,
"Enemy": 0.57,
"Cubebox": 0.65,
"Teammate": 0.57,
}
default_class_threshold = min(class_threshold.values())
# Backward-compatible index-based thresholds for any existing code paths.
# This list intentionally follows only the `classes` array order.
threshold = [class_threshold.get(class_name, default_class_threshold) for class_name in classes]

normalized_game_mode = game_mode.lower().strip()
if normalized_game_mode not in game_mode_profiles:
print(bcolors.WARNING + f"Unknown game_mode '{game_mode}', defaulting to solo_showdown." + bcolors.ENDC)
normalized_game_mode = "solo_showdown"
active_game_mode = normalized_game_mode
selected_game_mode = game_mode_profiles[active_game_mode]
centerOrder = selected_game_mode["centerOrder"]

try:
brawler_stats = brawler_stats_dict[brawler_name.lower().strip()]
brawler_stats = brawler_stats_dict[normalize_brawler_name(brawler_name)]
display_str = f"Using {brawler_name.upper()}'s stats if your selected brawler is not {brawler_name.upper()},\nplease manually modify at constants.py."
standard_hsf = 0.15
if len(brawler_stats) == 2:
Expand All @@ -71,7 +150,7 @@ class Constants:
brawler_stats = 3*[None]
except KeyError:
brawler_stats = 3*[None]
display_str = f"{brawler_name.upper()}'s stats is not found in the JSON. \nUsing speed, attack_range and heightScaleFactor in constant.py.\nPlease manually modify at constants.py if you have not."
display_str = f"{brawler_name.upper()}'s stats are not found in the JSON. \nUsing speed, attack_range and heightScaleFactor in constants.py.\nPlease manually modify at constants.py if you have not."
print("")
print(bcolors.BOLD + bcolors.OKGREEN + "Original Creator: https://github.com/Jooi025/BrawlStarsBot" + bcolors.ENDC)
print("")
Expand Down Expand Up @@ -120,4 +199,4 @@ class Constants:
assert type(bool_dict[key]) == bool,f"{key.upper()} should be True or False"

if __name__ == "__main__":
pass
pass
4 changes: 2 additions & 2 deletions detection_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
wincap.set_window()

# initialize detection class
detector = Detection(windowSize,Constants.model_file_path,Constants.classes,Constants.heightScaleFactor)
detector = Detection(windowSize,Constants.model_file_path,Constants.classes,Constants.heightScaleFactor,Constants.class_threshold)

wincap.start()
detector.start()
Expand All @@ -37,4 +37,4 @@
detector.stop()
cv.destroyAllWindows()
break
print('Done.')
print('Done.')
16 changes: 13 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,13 @@ def main():
wincap.set_window()

# initialize detection class
detector = Detection(windowSize,Constants.model_file_path,Constants.classes,Constants.heightScaleFactor)
detector = Detection(
windowSize,
Constants.model_file_path,
Constants.classes,
Constants.heightScaleFactor,
Constants.class_threshold
)
# initialize screendectect class
screendetect = Screendetect(windowSize,wincap.offsets)
# initialize bot class
Expand All @@ -55,6 +61,9 @@ def main():
print(f"Resolution: {wincap.screen_resolution}")
print(f"Window Size: {windowSize}")
print(f"Scaling: {wincap.scaling*100}%")
print(f"Mode: {Constants.active_game_mode}")
if Constants.rank_push_enabled:
print(f"Rank push: current={Constants.current_rank}, target={Constants.target_rank}")

aspect_ratio = windowSize[0]/windowSize[1]
if aspect_ratio > 1.79:
Expand All @@ -63,6 +72,7 @@ def main():
while True:
screenshot = wincap.screenshot
if screenshot is None:
sleep(0.001)
continue
# update screenshot for dectector
detector.update(screenshot)
Expand Down Expand Up @@ -127,7 +137,7 @@ def main():
if __name__ == "__main__":
print(" ")
print(bcolors.HEADER + bcolors.BOLD +
"Before starting the bot, make sure you have Brawl Stars open \non Bluestacks and selected solo showdown gamemode.")
"Before starting the bot, make sure you have Brawl Stars open \non Bluestacks and selected your intended game mode.")
print("")
print("Also make sure to change the speed, attack_range and HeightScaleFactor"
+"\nfor you selected brawler at constants.py (instruction there as well).")
Expand Down Expand Up @@ -162,4 +172,4 @@ def main():
# exit
elif user_input =="4" or user_input == "exit":
print("Exitting...")
break
break
4 changes: 2 additions & 2 deletions misc/textInstruction.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
### Testing and changing values
**Important - please disable Bluestacks' ads and close the left sidebar for the bot to work as intended**
1. Run "detection_test.py" to check if object detection is working
2. Change the brawler_name in "constants.py" to your selected Brawler's name and run "constant.py".
2. Change the brawler_name in "constants.py" to your selected brawler's name and run "constants.py" (spaces/punctuation are handled, e.g. "Mr. P" or "mr p").
3. If the brawler's stats in not found manually change the speed, attack range and height scale factor located below brawler_name at "constant.py" to the brawler's [speed and range](https://pixelcrux.com/Brawl_Stars/Brawlers/) and to find the height scale factor run "hsf_finder". Also modify sharpCorner (True if the map has many walls, otherwise False) and centerOrder ( True if brawler spawns in the middle of the map, otherwise False).

4. Run "main.py"

5. Select solo showdown and "start bot" (enter 1)
5. Select your configured mode in-game (matching `game_mode` in `constants.py`) and "start bot" (enter 1). Solo profiles prioritize bush/cubebox play; team profiles prioritize enemy repositioning.
Loading