CursorのComposerを使ってEbitengine製のオセロを自然言語だけで作る

# 要約
- CursorのComposerを使ってEbitengine製のゲームを作ってみた
- 1行もコードを書かずに30分程度で作りたかったゲームができてすごかった

# 背景
1年ほど前にCursorを使ってみようと思った時期があったのですが、WSL+Dockerの組み合わせで使ったときに上手くいかなかったのでVSCodeを使い続けていました。最近はそのあたりの問題も解決したという話を聞いたのと、Composerなる複数ファイルを同時に編集できる機能が便利という話を聞いたので改めてCursorの使い勝手を確認しようと思いました。

Cursorの機能を網羅的に紹介した記事はよく見かけましたが、プロジェクトを1から始めて、どのように実装が進んでいくのかがわかる記事がぱっと見つからなかったので、同じようなことを試そうとしている人が生成AIメインの開発がどのような感じになるのかイメージしやすいような記事があると良いのではと思い、手順をメモしておきました。

またGo言語製のゲームエンジンのEbitengineにも前々から興味があったので、合わせて試してみることにしました。
https://ebitengine.org/ja/
マルチプラットフォームで動くゲームを環境構築の手間がほぼ0で作れて、小さなゲームをさくっと作って公開するのにかなり向いていそうなライブラリです。

# 手順

## 準備

### Curosrのインストール
Ubuntuで試したので下記の記事を参考にさせていただきました。
https://zenn.dev/mizki/articles/36535a1b75ab81

### Cursorの設定
`Cursor Setting` → `Features` → `Allow agent composers to run tools ...` にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/60e39231-0360-bcb4-20a7-7b85a0e3c0c8.png)

### Go環境のインストール
使用しているPCにGoがインストールされていなかったので、ChatでGo言語の環境のインストール方法も確認しました。
```sh
wget https://go.dev/dl/go1.23.6.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.23.6.linux-amd64.tar.gz
echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bashrc
source ~/.bashrc
```

### Ebitengineのインストール

ebitenのインストールに関しても同様です。

```
sudo apt update
sudo apt install -y libgl1-mesa-dev xorg-dev
go get -u github.com/hajimehoshi/ebiten/v2
```

### 初期ファイルの作成

流石に何もない状態から作り始めるのは大変かと思ったので、最低限のhello worldくらいまでは用意することにしてみました。今思うと余計なお世話だったかもしれません。

```go
package main

import (
	"log"

	"github.com/hajimehoshi/ebiten/v2"
)

// ゲームの状態を管理するGame構造体
type Game struct{}

// Updateメソッド (毎フレーム更新処理)
func (g *Game) Update() error {
	return nil
}

// Drawメソッド (描画処理)
func (g *Game) Draw(screen *ebiten.Image) {
	// ここに描画処理を書く
}

// Layoutメソッド (画面のサイズ設定)
func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
	return 640, 480 // 画面サイズを640x480に設定
}

func main() {
	game := &Game{}
	if err := ebiten.RunGame(game); err != nil {
		log.Fatal(err)
	}
}
```

下記のコマンドで実行すると、黒いだけの画面が表示されます。

```sh
go mod init
go mod tidy
go run main.go
```

### プロジェクトをcursorで開く
main.goがあるディレクトリをcursorで開きます。
```
/opt/cursor/cursor.appimage .
```

## ゲームの開発

### agentモードに切り替える

Cursorの右側のタブからCOMPOSERを選択し、モードを`agent`に切り替えます。`agent`にするとコマンドを実行する部分を勝手にやってくれたりするようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/331348a3-3162-5c76-99fa-73f9a2ea92b1.png)

### ベースを作る

早速、agentにオセロの作り方を聞いてみます。
ebitenを使うのも初めてで、オセロも作ったことはないので段階を踏んでやっていった方がいいだろうと思い、まずは手順を教えてもらうことにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/88760a59-51bd-71e5-3cb1-a8830b7e16f3.png)

おお、手順を詳しくリストアップしてくれているな...と思ったのも束の間、勝手に実装に進み始めました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/72dbf580-12f1-491a-340d-de363b6df7a8.png)

そのまま見ていると、なんとゲームのロジックまで含めて全て完了してしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/23893882-5c55-7b4e-48b6-d7f03bf48c2c.png)

想像していたのは、
1. ボードを作る
1. 石を作る
1. 初期状態を作る
1. ...

というようなフローだったのですが、一足飛びに進んだ形でした。
本当にできているのか...？と思い、`go run main.go`したところ無事立ち上がりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/9b4958b0-1944-e478-07d4-57e5b686cf07.png)

各マスをクリックした場合、置ける場所であれば石が置かれ、挟まれている石は色が変わります。置けない場所であればクリックは無効になります。というわけでゲームロジックも含めて完璧に実装されていました。盤の色が緑なのもオセロの商品の色に合わせてあって気が利いています。

### 改変してみる

オセロを作るだけであれば最初の1回だけで終わってしまったので、Cursor自体の使い勝手はわからないのと、メジャーなゲームなのでほぼほぼ近いソースコードがあったのだろうなと思われたので、追加の仕様を実装させてみることにしました。

見た目をリッチにできれば面白みが出るのではという安直な考えから、オセロの石をアプリのアイコンにしてみることを試してみます。(昔[ねとらぼで紹介されていたゲーム](https://nlab.itmedia.co.jp/nl/articles/2405/20/news157.html)の再現です)

twitterとxのアイコンをpngでmain.goと同じディレクトリに保存し、それを石代わりに表示するようにお願いしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/4a5cd420-c41e-09d0-c744-1ad9a8bcc301.png)

あっさり表示できてしまいました...自分でライブラリの仕様を調べたりしながらだとかなり時間がかかっていたと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/4b35ad66-18f0-0330-178f-28bb30fb41e1.png)

### さらに改変してみる

ここまでできるのであれば、自分が思いつく範囲のことはやってもらえそうです。その場で思いついた内容をCOMPOSERに指示していきます。

↓が実際に指示に使った文面です。
- 今がtwitterとXどちらの手番かを画面上に表示するようにしてください
- 盤面を縦8マス、横6マスにしてください
- tablet.jpgを背景に表示するようにしてください
- エラーが出ます
- 次に石が置ける場所を、透過したグレーの四角で塗りつぶすことはできますか？

面白いのはjpgファイルを表示するコードを追加したあと、`go run main.go`がエラーを出すようになってしまったのですが、エラーメッセージを渡してあげると自分でエラー内容を修正してくれたところです。偉い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/8e9b2f7e-eee0-a5c6-559b-bb833a278783.png)

### 完成

そんなこんなで、タブレット上で繰り広げられるXとTwitterのオセロが30分ほどで完成しました。

![othello.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/a5f9ab9d-5a5a-95a2-da9b-96a90f35de83.gif)

コードの生成や実行結果を確認する時間はほとんど無く、プロンプトを考える時間や素材を探している時間がほとんどでした。こうすれば遊び勝手が良くなるのでは？と思ったことも、言葉で指示するだけで実装をやってもらって、実際に遊びやすくなるのかをすぐに確認できるので非常に快適でした

### Webへのデプロイ

ブラウザから遊べるようにできるとスマホからでも実行できて面白いのではないかと思い、続けてやり方を聞いてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/758e0c22-4d0d-06a6-8397-1180e357cc24.png)

wasmでビルドして`index.html`に埋め込んであげれば遊べるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407118/20c185a2-16a5-d1c6-47e5-160872657383.png)

agentモードというだけあって、`index.html`や`build.sh`を勝手にディレクトリ内に作成してくれます。コード補完の用途でしか生成AIを使っていなかったので、これはかなり便利だなと思いました。
また、COMPOSERの画面に表示されたコマンドを1クリックで実行できるも便利です。これまではやり方を聞いてコマンドをコピペしていました。条件はわかりませんが、指示によってはコマンドの実行までやってくれたり、コマンドを実行していいか聞いてきたりします。

# 感想
実装のスピードがこれまでとは次元が違うところが体験できて良かったです。自然言語だけでプログラミングというのは、頭で考えている内容を言葉で伝える過程で認識の差が生じて上手くいかないイメージでしたが、少なくとも今回扱ったくらいのボリュームであれば問題ないのは以外でした。

Github Copilotよりも性能が断然良いように感じたのと、細かい入力の手間が少なくなるように細部まで気を使って作られているように感じたので、Cursorへ乗り換えるモチベーションになりました。

2つ目の目的だったEbitengineに触ってみるというところは、Cursorがコードを全て書いてしまったし特におかしい挙動もなかったので、コードを読むタイミングが無く、始める前後で理解が深まった感触は全くありませんでした...とはいえ、成果物を見る限り記述の量が少なく、各関数がやっていることがわかりやすいので、非常にとっつきやすそうには感じました。