Love2D のゲームをスマホで遊ばせるまで|バーチャルゲームパッドと Retina 対応を AI に全部書かせる
この記事で分かること
Love2D で作ったゲームを、ブラウザ経由でスマホで遊ばせるまでの手順を AI 駆動開発で一発通しするテンプレです。
- LÖVE 11.5 を
love.jsで Web ビルドすればブラウザで動く - スマホにはキーが無いので、バーチャルゲームパッド JS をインジェクトしてタッチを
keydown/keyupに変換する - Retina と Emscripten の canvas スケーリングで必ず詰まる。罠を先に AI へ渡せば一発で通る
僕(大森翔吾)が Love2D × AI駆動開発の入門記事 で触れた FLAPPY_BIRD などのプロトで検証し、そのまま _template_love2d に落とし込んだ知見を共有します。
なぜ Love2D は「そのまま」ではスマホで遊べないのか
LÖVE(Love2D)は Lua で 2D ゲームを書ける軽量エンジン。love.graphics でコードオンリー描画ができて、AI 駆動開発との相性が抜群です。ただし本来は PC デスクトップ前提で、スマホ対応は自前で用意する必要があります。
壁は3つ。
- 入力:PC は矢印キー + Z/X(A/B ボタン)想定。スマホにはキーが無い
- Retina / 高 DPI:
highdpi = trueにすると論理 960x540 でもピクセルバッファが実 2倍に膨らむ - Web canvas スケーリング:Emscripten SDL2 は canvas の CSS サイズと描画バッファを勝手に同期するので、スマホ画面に合わせて CSS を変えると描画が壊れる
この3つに最初から釘を刺したプロンプトを AI に渡せば、余計な往復なく通ります。Godot でのゲーム開発は Godot × AI駆動開発で2Dゲームを作る、Love2D で AI にコードを書かせる基本は Love2D × AI駆動開発|Lua はむしろ AI と相性がいい にまとめています。
問題1:入力をどうするか(バーチャルゲームパッド)
love.keyboard.isDown("up") のような既存コードを 書き換えずに スマホ対応したい。解は「タッチイベントを KeyboardEvent に変換して document にディスパッチする」こと。Emscripten SDL2 がキーイベントを拾うので、Lua 側のコードはそのまま動きます。
// web/gamepad.js(抜粋)
var KEY_MAP = {
up: { key: "ArrowUp", code: "ArrowUp", keyCode: 38 },
a: { key: "z", code: "KeyZ", keyCode: 90 },
b: { key: "x", code: "KeyX", keyCode: 88 },
// ...
};
function sendKey(button, pressed) {
var km = KEY_MAP[button];
var evt = new KeyboardEvent(pressed ? "keydown" : "keyup", {
key: km.key, code: km.code, keyCode: km.keyCode,
bubbles: true, cancelable: true,
});
document.dispatchEvent(evt);
}
DOM 側に D-pad と A/B ボタンを組み、touchstart / touchend で sendKey を呼ぶだけ。これで Lua のゲームロジックには一切手を入れず、スマホで love.keyboard.isDown("z") が反応します。
問題2:Retina / 高 DPI で絵が右下にズレる
conf.lua で t.window.highdpi = true を入れると、Retina ディスプレイでは love.graphics.getWidth() が論理幅(960)より大きい値を返します。何も対策しないと「960x540 向けに描いたのに画面の左上1/4しか使われない」状態になります。
対処は SCALE パターン。love.load で比率を計算し、love.draw の先頭で love.graphics.scale を効かせるだけ。
local SCALE = 1
function love.load()
SCALE = love.graphics.getWidth() / 960
end
function love.draw()
love.graphics.scale(SCALE, SCALE)
-- 以降は 960x540 の論理座標で描画してOK
end
-- マウス座標を使う場合は論理座標へ戻す
local mx, my = love.mouse.getPosition()
mx, my = mx / SCALE, my / SCALE
これを毎回忘れるので、僕は AGENTS.md / CLAUDE.md のプロジェクトテンプレに埋め込んでいます。新規ゲームを scaffold した瞬間から AI が勝手にこのパターンで書いてくれる状態がゴール。
問題3:Emscripten canvas のスケーリングで全員ハマる
ここが一番深い罠。Emscripten SDL2 は canvas の CSS 表示サイズを読み取って、描画バッファ(canvas.width / canvas.height)をそれに同期する 仕様です。
つまりスマホ画面に合わせるつもりで、
// NG: これをやると描画バッファも 390x219 にされて絵が崩れる
gameCanvas.style.width = "390px";
gameCanvas.style.height = "219px";
とすると、Lua 側は 960x540 のつもりなのに実際の描画先が狭くなって、左上の一部しか描画されない。さらに canvas.width を直接上書きすると WebGL コンテキストがリセット されて画面が真っ黒になります。
正解は CSS transform: scale() を使うこと。transform は width / height の算出値を変えないので、Emscripten のバッファ同期が発火しません。
var scale = window.innerWidth / 960;
gameCanvas.style.transformOrigin = "top left";
gameCanvas.style.transform = "scale(" + scale + ")";
さらにレースコンディション対策として、Emscripten の初期化完了を Module.postMainLoop フックで待ちます。gamepad.js が love.js より先に走ると、canvas のデフォルト 300x150 を読んでおかしな状態で固まるため。
var orig = Module.postMainLoop;
Module.postMainLoop = function () {
Module.postMainLoop = orig || null; // ワンショット
applyMobileLayout(); // この時点で love.load 完了・バッファ 960x540 確定
};
ここは検証で7〜8手法ダメ出しした結果の結論です。詳しくは Love2D を love.js でスマホ公開するまで で手順側からも書きました。
問題4:love.js は Lua 5.1 ベースという地雷
ネイティブの LÖVE は LuaJIT(5.1 + 拡張)で動くので goto 文や bit ライブラリが普通に使えます。ところが love.js は 素の Lua 5.1 ベース。PC で動いていたコードが Web ビルドでだけ落ちる、という事故が頻発します。
gotoラベル(::continue::)→if not ... then ... endで代替- ビット演算ライブラリ
bit→ 自前で実装するか使わない設計に寄せる
AI に最初からこう伝えておけば、goto を書かれない。Lua の書き癖の入口は AI駆動開発のスマホ1台ワークフロー でも触れています。
AI 駆動開発 Tip:罠をテンプレ化してプロジェクトに常駐させる
ここまでの4問題、全部「知っていれば回避できる」ものです。なので CLAUDE.md / AGENTS.md に以下を固定で書いておく。
- 対象は LÖVE 11.5 + love.js。12.x の API は使わない
love.drawの冒頭でlove.graphics.scale(SCALE, SCALE)を呼ぶ- Web canvas のスケーリングは
transform: scale()のみ。canvas.style.width/canvas.widthの直接変更禁止 Module.postMainLoopで初期化待ち してからレイアウト適用gotoとbitは love.js で動かない。使わない
これを置いた状態で Claude Code に「_template_love2d で scaffold して、Web ビルドとバーチャルゲームパッド対応まで入れて」と頼めば、ほぼ一発で通ります。毎回の試行錯誤をゼロにするのが AI 駆動開発の本質。Claude Code 自体の使い方は Claude Code 完全ガイド を参照してください。
関連する記事
- Love2D × AI駆動開発|Lua はむしろ AI と相性がいい
- Love2D を love.js でスマホ公開するまで
- スマホ1台でAI駆動開発する方法
- Claude Code 完全ガイド|AI駆動開発の主戦力
- Godot × AI駆動開発で2Dゲームを作る
AI駆動開発のご相談・お仕事のご依頼
株式会社CAEN(代表:大森翔吾)では、Love2D や Godot を使った個人ゲーム開発の AI 駆動化、Web ビルドとスマホ公開のテンプレ整備、CLAUDE.md / AGENTS.md を使ったプロジェクト常駐ルール設計などのご相談を承ります。
- お問い合わせ:info@caen.co.jp
- ポッドキャスト:AI駆動開発ラボ(stand.fm)
- YouTube:@aidd-lab
- X:@shogo_oomori
「Love2D で作ったプロト版をスマホでも遊べるようにしたい」「自社ゲームの Web ビルドを AI 駆動で整備したい」など、お気軽にご相談ください。