# スマホゲームの bot の作り方: MAS で自動化

> Macro Automation Studio で Android のスマホゲーム bot を作る方法: Marketplace から入れる、MAS Agent に頼む、BlueStacks 上で Python で書く、の 3 通りです。

Source: https://automationmacro.com/ja/docs/make-a-bot-for-any-game (ガイド, updated 2026-09-05)

このチュートリアルでは、Macro Automation Studio (MAS) で Android のスマホゲームの bot の作り方を、インストール済みのゲームから、1 つまたは複数のアカウントでスケジュール実行する bot まで説明します。MAS の bot は画面から動きます: 画像でボタンを見つけ、OCR でカウンターを読み、人間らしいタイミングでタップします。Windows または Mac で初めて bot を作る方向けです。

<div class="doc-video" data-video="SDrdMIV49a8" data-title="How to make a bot for any game"></div>

## 始める前に

- MAS がインストール済みで、無料トライアルかプランでサインインしていること。[MAS のインストール](/docs/install) を参照してください。
- ゲームが MAS の操作できるデバイスで動いていること: このコンピューター上のエミュレータ、クラウドデバイス、またはお手持ちのスマホ。[デバイス](/docs/devices) を参照してください。
- デバイスがデバイスグループに入っていて、カードが Error ではなく Stopped を表示していること。追加の手順は [はじめに](/docs/getting-started) ページで説明しています。
- Python の経路では他に何も要りません。MAS は `mas` パッケージ入りの独自の Python 環境を同梱しています。

## スマホゲームの bot の作り方: 3 つの方法

### Marketplace からインストールする

すでに誰かがあなたのゲーム用の bot を作っている場合の最速の方法です。

1. **Marketplace** を開き、ゲームを検索します。
2. 項目を開き、**ダウンロード** をクリックします。bot は **マクロ** に表示されます。
3. **デバイスグループ** でグループを開き、デバイスの **マクロ** セレクターで bot を選んで **開始** をクリックします。

スクリーンショット付きの詳しい手順は [Marketplace からマクロを実行する方法](/docs/run-macro-from-marketplace) にあります。既製の bot は [Whiteout Survival](/whiteout-survival-bot)、[Kingshot](/kingshot-bot)、[Last Asylum: Plague](/last-asylum-plague-bot) 向けにあります。

### MAS Agent に依頼する

一覧にないゲーム向けの、コード不要の方法です。

1. **エージェント** を開き、デバイスを選びます。
2. いつ止まるべきかを含めて、ルーチンを 1 文で説明し、**作成** をクリックします。
3. エージェントが質問したら答えます。推測せず、止まって質問します。
4. マクロが 3 回の検証実行に合格したら、**マイマクロに追加** をクリックします。

作成には AI クレジットを使いますが、完成したマクロの実行にはかかりません。結果は開いて編集できる普通の Python プロジェクトです。[MAS Agent](/docs/agent) を参照してください。

### Python で作る

bot のすべての判断を完全に制御できます。このページの残りはこの経路です。

## Python でスマホゲームを自動化する

### 1. bot が見るべきものを書き出す

ルーチンを 1 度手で遊び、触れるすべての画面を書き出します。押すボタン、割り込むポップアップ、エネルギーを示すカウンター、終わったことを意味するメッセージです。各項目がテンプレート画像か OCR 領域になります。停止状態を知っている bot は、目隠しで走ることがありません。

### 2. プロジェクトを作る

1. **マクロ** を開き、**新しいプロジェクトを作成** をクリックします。
2. **コードベース** を選び、**対象デバイス** をモバイルにし、プロジェクト名を付けて **プロジェクトを作成** をクリックします。
3. プロジェクトを開きます。Code Editor に MAS が実行するファイル `src/app.py` が表示されます。

### 3. Asset Lab でテンプレートを取り込む

1. デバイスでゲームを起動し、ボタンのある画面に移動します。
2. Code Editor で **アセット** パネルを開き、**Asset Helper を開く** をクリックします。Asset Lab がライブ画面で開きます。
3. ボタンの周りをぴったり囲む長方形を切り出して保存します。数値の ID 付きで画像ライブラリに入ります。
4. ポップアップの閉じるボタン、確認ボタン、「エネルギー切れ」のメッセージについて繰り返します。
5. **アセット** パネルに戻り、各画像で **ID をコピー** を使い、スクリプト先頭の `mas.images` に ID を貼り付けます。

切り抜きは小さく特徴的にしてください。画面全体はその画面だけにしか一致しませんが、ボタンならボタンが出る場所ならどこでも一致します。テンプレートは jpg、png、gif、webp で、1 枚 10 MB までです。[Asset Lab](/docs/asset-lab) ページでツールを詳しく説明しています。

### 4. OCR 領域を取り込む

1. Asset Lab で、読みたいカウンターの周りに枠を描きます。
2. ライブの OCR テストを実行し、数字がきれいに読めるまで枠を詰めます。
3. 座標をスクリプトの `Region(x1, y1, x2, y2)` にコピーします。

文字がうまく読めない場合のセグメンテーションモードと色変換は、[OCR ガイド](/docs/guides/ocr-text-reading) で説明しています。

### 5. ループを書く

下のループは、すべてのゲーム bot に共通する形です。各行が SDK の呼び出しに対応します:

- `find_object_retry` はボタンを `time_sleep=2.0` 秒間隔で最大 `total_tries=3` 回探し、何も一致しなければ `None` を返します。
- `click(x, y, delay_ms=1000)` は一致の中心をタップし、ゲームが反応するまで 1 秒待ちます。
- `read_text(region, psm=7)` はカウンターを 1 行として読みます。
- `time.sleep(random.uniform(0.8, 2.0))` は周回の間に人間らしい間を入れます。
- `mas.save` と `mas.retrieve` は周回数を保持するので、止まった実行は続きから再開します。
- 停止条件がループを終えます。例では 5 つ使います: 最大周回数、時間の予算、「エネルギー切れ」のテンプレート、低いカウンター、連続した見失い。

### 6. 実行してログを読む

Code Editor でデバイスを選び、**実行** (<kbd>F5</kbd>) をクリックします。すべての `mas.log` の行が実行コンソールに表示されます。**停止** は <kbd>Shift</kbd>+<kbd>F5</kbd> です。一度に 1 つずつ直してください。テンプレートが見つからないときは、ロジックに触る前に切り出し直します。

### 7. スケジュールする

1. **スケジューラー** を開き、**新しいスケジュールを作成** をクリックします。
2. **名前** を入力し、**マクロ** と **エミュレータポート** を選び、**日付** と **時刻** を設定します。
3. **繰り返し** を **毎日** にして、**スケジュールを作成** をクリックします。

アプリは開いたままにする必要があります。スケジューラーはアプリの中で動きます。[スケジューラー](/docs/scheduler) と [ループとスケジュール実行](/docs/guides/loops-and-scheduling) を参照してください。

### 8. デバイスグループで実行する

すべてのアカウントのエミュレータインスタンスを 1 つのグループにデバイスとして追加し、各デバイスに bot を割り当てて **すべて開始** をクリックします。アカウント名などデバイスごとの値は設定プロファイルから来ます。[多重起動での周回](/docs/guides/multi-instance) を参照してください。

## 完全な bot の例

画像 ID と領域を、取り込んだものに置き換えてください。このスクリプトは、エネルギーが少なくなるか、時間の予算を過ぎるか、30 周を終えるまで資源を集め、再起動しても続きから動きます。

```python
import random
import sys
import time

import mas
from mas import Region

images = mas.images({
    "attack_button": 101,
    "confirm_button": 102,
    "close_popup": 103,
    "out_of_energy": 104,
})

ENERGY_REGION = Region(x1=380, y1=20, x2=520, y2=60)
TASK = "farm_bot"
MAX_ROUNDS = 30
TIME_BUDGET_S = 20 * 60
MIN_ENERGY = 10


def pause(low=0.8, high=2.0):
    time.sleep(random.uniform(low, high))


def read_energy():
    result = mas.read_text(region=ENERGY_REGION, psm=7)
    digits = "".join(ch for ch in result.text if ch.isdigit())
    return int(digits) if digits else None


def clear_popups():
    popup = mas.find_any_object([images.close_popup, images.confirm_button])
    if popup:
        mas.click(popup.x, popup.y, delay_ms=800)
        return True
    return False


def main():
    rounds = mas.retrieve(TASK).get("rounds", 0)
    misses = 0
    started = time.monotonic()
    mas.log(f"Starting at round {rounds}")

    while rounds < MAX_ROUNDS:
        if time.monotonic() - started > TIME_BUDGET_S:
            mas.log("Time budget reached", level="warning")
            break
        if clear_popups():
            continue
        if mas.find_object(images.out_of_energy):
            mas.log("Out of energy, stopping")
            break
        energy = read_energy()
        if energy is not None and energy < MIN_ENERGY:
            mas.log(f"Energy {energy} is below {MIN_ENERGY}, stopping")
            break
        button = mas.find_object_retry(images.attack_button, total_tries=3, time_sleep=2.0)
        if button is None:
            misses += 1
            mas.log(f"Attack button not found ({misses})", level="warning")
            if misses >= 5:
                mas.log("Giving up after 5 misses", level="error")
                sys.exit(2)
            continue
        misses = 0
        mas.click(button.x, button.y, delay_ms=1000)
        pause()
        rounds += 1
        mas.save(TASK, {"rounds": rounds})
        mas.log(f"Round {rounds} of {MAX_ROUNDS}")

    if rounds >= MAX_ROUNDS:
        mas.clear(TASK)
    mas.log(f"Finished with {rounds} rounds")


if __name__ == "__main__":
    main()
```

`sys.exit(2)` は実行を失敗としてマークするので、`macro.failed` を購読する Webhook に通知されます。正常終了は `macro.completed` を報告します。[Webhook](/docs/webhooks) を参照してください。

## bot を安定させるコツ

- **解像度。** テンプレートと領域は、取り込んだときの解像度と DPI に属します。bot を動かすすべてのデバイスを同じ設定にしてください。エミュレータのガイドは縦向きの 540x960、240 DPI を基準にしています。
- **テンプレートの衛生。** ボタンだけを切り出し、周りの背景は含めないでください。ゲームのアップデートで見た目が変わったら切り出し直します。ボタンに 2 つの見た目があるときは両方を取り込み、`find_any_object` で探します。
- **停止条件。** すべてのループに最低 2 つ必要です: カウンターか時間の予算と、「完了」を意味する画面の状態。それがない bot は、気づくまで走り続けます。
- **ゆっくり動かす。** 周回の間に 1 から 2 秒の間を入れてもコストはわずかで、機械的に見えにくくなります。
- **タップではなく判断を記録する。** `mas.log("Energy 8, stopping")` は実行がなぜ終わったかを教えてくれますが、100 回のクリックのログは教えてくれません。

## うまくいかないとき

### ボタンがまったく見つからない

切り抜きが大きすぎる、しきい値が見た目に対して厳しすぎる、またはデバイスが取り込んだときと違う解像度で動いています。より小さく切り出し直し、呼び出しで `threshold=0.7` を試してください。完全なチェックリストは [画像認識ガイド](/docs/guides/image-recognition-macros) にあります。

### カウンターが違う数字を読む

領域に隣のアイコンが含まれているか、文字が暗い背景に明るい色です。Asset Lab で枠を詰め、`color_conversion=ColorConversion.BLACK_WHITE` を渡してください。信頼度の確認方法は [OCR ガイド](/docs/guides/ocr-text-reading) で説明しています。

### 2 日目に bot がすぐ止まる

保存されたカウンターがすでに上限です。例は `MAX_ROUNDS` に達するとストレージを消去します。それを変えた場合は、使い捨てのスクリプトから `mas.clear("farm_bot")` を 1 度呼んでください。

### クリックがボタンの横に落ちる

取り込み後にエミュレータの解像度か DPI が変わったか、ウィンドウが縦向きではありません。エミュレータのディスプレイを取り込み時の設定に戻し、まだ外れるものを取り込み直してください。

100%リスクのない自動化ツールは存在しないため、自動化は責任を持って、ご自身の判断で行ってください。
