Flutterで作ったミニゲームをFlutter for Webに移植した

# Flutter for Web

Dartを使ってiOS/AndroidのUIが簡単に開発できるFlutterのWeb版が
Google I/O 2019で発表されました。

https://www.youtube.com/watch?v=IyFZznAk69U
以下、Google I/O 19のYoutube動画のスクリーンショットです。
<img width="800" alt="スクリーンショット 2019-05-16 23.11.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/503f61fb-c72b-30e0-56bc-b4ad162d7fe2.png">

やった！と思いましたが動画がアーキテクチャの図になるとムムムと思いました。
描画ライブラリなど[Flutterの低レイヤー部分](https://qiita.com/keidroid/items/ac213910980bc125995a)をゲーム制作で主に利用していたのにFlutter for Webではごっそり置き換わっていたからです。

iOS/Android向け
<img width="640" alt="スクリーンショット 2019-05-16 22.19.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/5d5cbf18-b92d-520f-9ddb-a2f766402644.png">

Web向け (Engineが置き換わる)
<img width="640" alt="スクリーンショット 2019-05-16 22.21.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/f805794d-fb7d-ce49-11f2-d73df0a02a3d.png">

# とはいえ移植した

flutter_webのバージョンは0.0.0を使用しました。

元のコード
https://github.com/keidroid/lights_out

移植したミニゲーム
https://fir-6c1ee.firebaseapp.com/

 - スマホ縦画面のみ対応。アクセスするとすぐ遊べます)
 - アプリ版時点ではコードサイズ5KBでした。

# 移植の工程

## プロジェクトをWeb対応した

公式ページの以下の通りの手順を行うと対応できました。

https://github.com/flutter/flutter_web
https://github.com/flutter/flutter_web/blob/master/docs/migration_guide.md

現時点ではクロスプラットフォームではなく、migrationの手順を終えると
iOS/Androidでは動作しないWeb専用アプリとなります。

ローカル実行すると `localhost:8080` で実行確認できます。
ビルドすると `build/`フォルダにweb実行ファイルが作成されるので`build/`フォルダを公開すれば完成です。

```
ローカル実行コマンド
$ webdev run
ビルドコマンド
$ webdev build
```

## ソースコードをWeb対応した
- dart:uiは動作せず。flutter_web:uiに変更する必要がありました。
- Widgetなしのアプリでは動作せず。Widgetを1つ以上用意しました。
- マスクフィルターや角丸描画など一部のflutter_web:uiは動作せず。他のAPIに置き換えました。

|アプリ版|Web版|
|:--|:--|
|<img width="320" alt="IMG_2307.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/91225786-9dc9-9b8c-5f45-914c306673a6.png">|<img width="320" alt="IMG_2308.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/b8eb68db-37f2-475f-2788-d53a2f85817f.png">|

## スタンドアローン対応した

以下Flutter for Webのページをスマホで開いてホーム画面に追加すると、全画面でゲームが遊べます。

https://fir-6c1ee.firebaseapp.com/

これはFlutterの機能でなく従来のChrome/Safariの機能です。
Flutter for Webではweb側の設定も自由に可能なので
ネイティブアプリっぽくするためメタタグ対応しました。

#### 変更前
https://github.com/flutter/flutter_web/blob/master/examples/hello_world/web/index.html

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <script defer src="main.dart.js" type="application/javascript"></script>
</head>
<body>
</body>
</html>
```

#### 変更後

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <!-- iOS -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <link rel="apple-touch-icon" href="./apple-touch-icon.png">
  <!-- Android -->
  <meta name="mobile-web-app-capable" content="yes">
  <link rel="manifest" href="./manifest.json">
  <title>Lights Out</title>
  <script defer src="main.dart.js" type="application/javascript"></script>
</head>
<body>
</body>
</html>
```

```manifest.json
{
  "lang": "en",
  "name": "Lights Out",
  "short_name": "Lights Out",
  "icons": [{
        "src": "/icon144.png",
        "sizes": "144x144",
        "type": "image/png"
      }],
  "start_url": "https://fir-6c1ee.firebaseapp.com/",
  "display": "standalone"
}
```

- https://developers.google.com/web/fundamentals/web-app-manifest/?hl=ja
- https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html

# 感想
- がっつりソースコード変えてやっと動いた
- まだバージョン0.0.0なので今後に期待 (現時点でもけっこう動作する)
- 今後は高レベルAPI使ってFlutterやる
- ネイティブもFlutterもWebアプリもすごいので、なにで作ったら良いのか迷う
- ゲームとかすぐ遊べて良いかもしれない