記事検索

検索ワードを入力してください。
Sky Tech Blog
Flutter × Flameで​“ゲーム的インタラクション”を​設計・​実装してみた

Flutter × Flameで​“ゲーム的インタラクション”を​設計・​実装してみた

Flutterのゲームエンジン「Flame」を用いて、モバイルゲームのような操作体験を持つUIの試作を通じて得た知見を紹介します。入力処理の設計、フレームベースの状態管理、フィードバック設計などを整理し、Flameを活用するメリットや注意点を解説します。

はじめに

「ちょっとした操作なのに、なぜか気持ちいいアプリ」と、「ちゃんと動いているはずなのに、どこか触っていて楽しくないアプリ」。

この差は何なのか、と考えることがあります。

アニメーション?レスポンス速度?それとも設計の問題?

色々ありますが、その一つは
“インタラクションの作り込み”だと考えております。

今回、Flutter向けゲームエンジンであるFlameを使って、モバイルゲームのような操作体験を持つUIを試作しました。

この記事では単なるデモではなく、
入力処理の設計
フレーム更新ベースの状態管理
視覚・触覚フィードバックの設計

といった観点で、どのように構築したかを整理します。

【参考】Flutter​(公式サイト)に​基づき制作

背景と​目的

当初はFluoriteの活用も検討していましたが、本記事では、まずFlame Engineを用いて「どこまで実現できるか」を検証します。

今回の目的は以下です:

  • モバイルゲーム的な操作体験の実現
  • Flutterでのインタラクション表現の拡張可能性の検証
  • 将来的なフレームワーク選定のための知見蓄積
【参考】Fluorite​(公式サイト)に​基づき制作

https://fluorite.game/

なぜFlameを​使うのか​(設計視点)

Flutter単体でもGestureやAnimationは扱えますが、以下のようなケースでは設計が複雑になりがちです:

  • 継続的な入力(ドラッグ・押しっぱなし)
  • フレーム単位で変化する状態
  • 複数オブジェクトの相互作用

Flameを使うことで、

  • update(dt) による状態更新
  • 明確なゲームループ
  • 入力と描画の分離

が自然に実現できます。
特に「状態が時間に応じて変化する」処理は、Flameのモデルと非常に相性が良いと感じました。

【参考】Flame Engine​(公式サイト)に​基づき制作

全体​アーキテクチャ

今回の構成は以下のように分離しています:

Game (FlameGame) ├── PlayerComponent ├── FieldComponent └── InputController

設計意図

  • PlayerComponent
    → 移動・回転・内部状態を管理
  • FieldComponent
    → フィールド状態および接触判定
  • InputController
    → 入力イベントを状態として正規化

「入力 → 状態 → 表示」の流れを明確に分離することで、拡張性と可読性を担保しています。

処理内容に​ついて

入力処理:イベント駆動から状態駆動へ
Flutter標準のGestureはイベント駆動ですが、ゲーム的な挙動では「入力状態を保持する」方が扱いやすくなります。

  • 実装方針
    入力イベントを直接処理しない
    状態として保持し、update内で参照する
class InputState {
  Vector2 moveVector = Vector2.zero();
  bool isLeftActive = false;
  bool isRightActive = false;
}


@override
void update(double dt) {
  position += input.moveVector * speed * dt;
}

これにより、フレーム単位での一貫した制御が可能になります。

仮想スティック:ベクトル正規化

ドラッグ量をそのまま使うと、入力がデバイスや操作量に依存してしまいます。

final direction = dragVector.normalized();
velocity = direction * maxSpeed;

入力を正規化することで、操作感の一貫性を保っています。

回転制御:状態遷移と​して​扱う

画面下部の左右入力によって回転を制御し、非入力時には減衰させます。

if (input.isLeftActive) {
  angularVelocity = -rotationSpeed;
} else if (input.isRightActive) {
  angularVelocity = rotationSpeed;
} else {
  angularVelocity *= 0.9;
}

入力を直接回転に反映するのではなく、「速度」として扱うことで自然な挙動になります。

フィードバック設計(視覚+触覚)
今回特に重視したのがフィードバック設計です。

HapticFeedback.selectionClick();

単一のフィードバックでは認知しづらいケースでも、視覚と触覚を組み合わせることで、ユーザーの理解を補助できます。

Flameを​使って​感じた​メリット

1. updateループに​よる​一元管理

Flutter単体ではTimerやAnimationControllerで分散しがちな処理を、1つのループで管理できます。

2. コンポーネント指向設計

Widgetツリーとは異なり、「振る舞い単位」で分割できるため、再利用性、テスト容易性が向上します。

3. 入力処理との​親和性

Drag・Tap・Holdといった入力を、自然に状態へ落とし込めます。

ハマりどころ

Flutterとの責務分離

  • UI(Flutter)
  • ゲームロジック(Flame)

を明確に分けないと、設計が破綻しやすくなります。
Overlayなどを活用した分離が有効です。

状態管理の境界

RiverpodやBlocと併用する場合、

  • アプリ状態
  • ゲーム内状態

の責務を明確にする必要があります。

今後の​展望

fluoriteが公開・成熟した場合には、実装コスト、表現力、保守性
といった観点で比較検証を行いたいと考えています。

特に、

  • 入力の状態管理
  • フィードバック設計
  • インタラクションの抽象化

がどのように変化するかは注目しています。

まとめ

Flameを使うことで、

  • フレームベースの状態管理
  • 入力の状態化
  • リッチなフィードバック設計

を比較的シンプルに実装できました。

Flutterは単なるUIフレームワークにとどまらず、インタラクション設計のプラットフォームとしても十分に強力だと感じています。
今回の内容はあくまでプロトタイプですが、

  • 操作体験の向上
  • UX改善
  • ゲーミフィケーション

といった領域での応用可能性があると考えています。

Flutterでの表現の幅を広げる一つの選択肢として、Flameは有効なツールでした。


\シェアをお願いします!/
  • X
  • Facebook
  • LINE
キャリア採用募集中!

入社後にスキルアップを目指す若手の方も、ご自身の経験を幅広いフィールドで生かしたいベテランの方も、お一人おひとりの経験に応じたキャリア採用を行っています。

Sky株式会社のソフトウェア開発や製品、採用に関するお問い合わせについては、下記のリンクをご確認ください。
お問い合わせ
ホーム