概要
VRをつけて24時間疑似マラソンをしよう!
モバイルで位置情報を取得して、取得したコースを走れます。
座標を取得すれば好きな景色で走れます。
遊び方
- ①ログインする。
- ➁ホーム画面に遷移したらマラソンでスタートを押す
- ③VRをつけて走ろう!
GitHubリポジトリ
アーキテクチャ図
フロントエンド

バックエンド

モバイル

使用技術
フロントエンド
- React.ts
- アプリ全体のUI構築。
画面遷移や状態管理、各種コンポーネント(ログイン、プロフィール作成、ゲーム画面など)を実装
- Vite
- 用途: 開発環境・ビルドツール。
高速な開発サーバーとビルド、ホットリロードを提供。
- @react-three/fiber
- 3D描画のためのReactラッパー。
Three.jsをReactコンポーネントとして扱い、駅や地図などの3Dビューを実装。
- @react-three/drei
- @react-three/fiber用の便利な3Dユーティリティ。
カメラコントロールやライト、プリミティブなどの補助機能を提供。
- @react-three/xr
- WebXR(VR/AR)対応。
VRモードやXRデバイスでの体験をReactで実装。
- Street View Static API
- 用途: Google Street View画像の取得。駅周辺や地図の静的画像表示に利用。
r3f/xrの最新のバージョンは、記事が皆無なので、この二日間ぐらいはDocsを読み込んだよ
ドキュメントこそ至高
機能
パノラマ画像取得
RepeatWrappingをいい感じに4つの画像を繋ぎ合わせをしています。
一箇所につき画像を4つ取得していてリクエスト数が4なので何もうれしくないですね
VRコントローラーでY軸の交差をカウント
左右のコントローラーのY軸の交差をカウントし一定数(今回は10)回すれば、場所が更新されます
代替手段
マイクロサービスのデプロイ待ちの間
HonoとCloudflareで構築

フロントのインフラ

没機能:空間を8分割にしてそれらに写真を貼り付け
https://youtu.be/ZlXMbJ5Ibo0
デメリット:
- なんかきもい
- APIのリクエストが倍増える
メリット:
- 解像度がいい
バックエンド
- grpc
- redis
- Dynamodb
- websocket
- axum
- utoipa
- cargo watch
- sqlx
- redisを使ってゲーム中のタイマーをカウント。Websocket接続が切れた場合などに、キャッシュを確認して残っていたら再接続してゲームを途中化から開始できる。
- grpcのサーバーストリームとWebsocketを使って試合中のタイマーをフロントで表示させる。(リアルタイム性)
- bffをモバイル用とWeb用で作成。それぞれに必要なデータをbffで提供。
- OpneAPIスキーマ定義
- ドメイン駆動設計(軽量)を活用した、コード設計。詳細実装に依存するのではなく、抽象に依存する。(依存性逆転の法則)
- ドメインのビジネスロジックを通して不変条件を定義、変更する。常に整合性のとれたデータを生成。
- バックエンドのデプロイは、ecs fargateを使ってデプロイ。
- 外部からのリクエストをdtoでラップすることで疎結合を促進。外部の変更に依存せずに変更が最小限になるようにする。
- DIで内部実装(リポジトリ)や生成のロジックを注入することでモックでテストできるようにしてテストが容易になる。
モバイル
このモバイルアプリケーションは、以下の主要技術を組み合わせて開発されています。
- Kotlin: Androidの公式開発言語。
- Coroutines (コルーチン) を活用し、位置情報のバックグラウンド取得、ネットワーク通信、データベースアクセスといった複数の非同期処理を効率的に管理し、アプリの応答性を高めています。
- Jetpack Compose: 最新のAndroid UIを構築するための宣言型UIツールキット。
- UIコードの記述量を削減し、より直感的でリアクティブな画面開発を実現。状態の変化に応じてUIが必要な部分だけ再描画されるため、パフォーマンスの向上とバッテリー消費の抑制に貢献します。
- MVVM (Model-View-ViewModel) アーキテクチャ: UIロジックとビジネスロジックを分離する設計パターン。
- ViewModel でUIに関連するデータを保持・管理し、StateFlow を用いてUIに変更を効率的に通知します。これにより、関心事が分離され、コードの可読性、テスト容易性、保守性が向上します。
- Hilt: Android向けの依存性注入(DI)ライブラリ。
- ViewModel、Service、Repositoryといった各コンポーネントへの依存性の提供を簡潔に記述でき、コードの結合度を下げてテスト容易性や保守性を高めています。
- Retrofit & OkHttp: タイプセーフなHTTPクライアントライブラリとその基盤。
- サーバーAPI(認証API、ゲームAPI、地図API)との通信を容易に実装。OkHttp の Interceptor を利用して、認証が必要なリクエストにJWT(アクセストークン)を自動で付与したり、通信ログを記録したりする共通処理を一元化しています。
- Gson: JavaオブジェクトとJSONデータ間のシリアライズ/デシリアライズを行うライブラリ。
- APIリクエストのボディやレスポンスとしてやり取りされるJSONデータを、Kotlinのデータクラスへ簡単に変換するために使用しています。
- Room: SQLiteデータベースの上に構築された抽象化レイヤーを提供する永続性ライブラリ。
- 収集した生のGPS座標(緯度、経度、タイムスタンプ)を
LocationPointEntity
として効率的かつ安全に端末ローカルに保存します。これにより、オフライン時やデータ送信前の一時保管場所として機能します。
- Google Play Services Location API: 高精度かつバッテリー効率の良い位置情報アクセスを提供。
FusedLocationProviderClient
を使用し、ユーザーの現在位置を継続的に取得してルート記録の基礎データとします。
- 外部 Maps API (snapToRoads): 収集したGPS座標を実際の道路形状に沿って補正(スナップ)する機能。
- ユーザーの移動軌跡の精度を向上させ、より自然で正確なルートデータを生成し、サーバーに記録するために利用します。
- Android Foreground Service (
LocationService
): アプリがバックグラウンドや非アクティブ状態でも処理を継続するための仕組み。
- ユーザーがアプリを閉じた後も、位置情報の追跡をバックグラウンドで続行。ステータスバーに常時通知を表示することで、OSによるプロセスの強制終了リスクを低減し、安定したルート記録を実現します。
- Jetpack Navigation Compose: Jetpack Composeアプリ内の画面遷移を管理。
- ログイン画面からメイン画面への遷移など、アプリ内のナビゲーションをタイプセーフかつ宣言的に定義します。
- Android Security Crypto (Jetpack Security): 機密データを安全に保存・管理するためのライブラリ。
- ログイン後に取得するアクセストークンやリフレッシュトークンといった機密情報を、暗号化して端末内に安全に保管するために使用しています。
- リポジトリパターン (
LocationRepository
, AuthRepository
など): データアクセスロジックを抽象化し、データソースへのアクセスを一元管理する設計パターン。
- ViewModelなどの上位レイヤーは、データの取得元(ローカルDBかリモートAPIかなど)を意識することなく、必要なデータ操作をリクエストできます。例えば
LocationRepository
では、位置情報のローカル保存、Maps APIによるスナップ処理、Game APIへの送信といった一連の処理をカプセル化しています。
工夫ポイント
- フロントエンド
- Street View Static APIを1度に前後左右計4枚呼び出すことで自然な画像を取得
- バックエンド
- 具体実装とインターフェースで分けたり、状態変更をモデルを通して行うことで、どこに何があるか分かりやすく変更を加えやすいようにした。
- grpcのプロトファイルのからコードを生成する部分を簡略化するために専用のビルダーを用意した。
- bffをモバイル用とウェブ用で分けた。
- モバイル
- 安定した位置情報の取得
- バックグラウンドでも途切れないようにフォアグラウンドサービスで追跡
- 高精度な経路生成
- 外部の地図APIを利用し、GPSデータを実際の道路に補正
- データ保護とオフライン対応
- ローカルDBに保存することで通信切断に強くデータを保護
- 安全な認証
- 暗号化ストレージと通信インターセプターで安全で効率的に認証情報を管理
技術の無駄づかいポイント
- フロントエンド
擬似的に360度のパラノマを生成。
一箇所につき、リクエスト数が4なのでうれしくないね、やったね
- バックエンド
- わざわざdbを全部違うものにした。
- モバイル
- セキュリティ
- Jetpack Securityで認証情報を本格的に暗号化保存
- 設計基盤!
- Hiltによって完全な依存性注入で保守性と拡張性を確保!
- データ処理!
- 単なるGPS記録だけでなく、経路補正APIで品質を向上!
demo
こいつが出たら、完走です

今後実装したいこと
ランニングマシーンと接続して、VRで景色を見ながら走る