Market-Dungeon

https://github.com/sato07f-ui/58hack-Takajo

React

JavaScript

スーパーをダンジョンみたいに攻略?!

ふぇふぇ

sato07f-ui

YUME TAKANO

推しアイデア

買い物につきあう「待ち時間」を、スーパーならではの商品を利用してゲームをする「遊び時間」に変えること

作った背景

親の買い物に付き合う時間は退屈。その時間を楽しめるよう、店にあるモノを認識してバトルするゲームにした。

推し技術

Three.js の 3D をカメラ映像に重ねて AR にし、敵の出現には物体認識(YOLOv8n)を使用した。親子の位置は Supabase Realtime で共有し、50m 離れると「脱出」、10m 以内に戻ると親の端末から「復活の鍵」が自動で届く。

プロジェクト詳細

マーケットダンジョン

image

概要

スーパーをダンジョンに見立てて遊ぶ スマホ向けWeb ARゲーム です。 カメラに食材を映すと3Dの敵が出てきて、魔法で倒すとアイテムを落とします。親子で遊ぶ想定で、子どもが親から離れすぎると「脱出」扱いになる見守り機能も付いています。

作った背景

子供にとってスーパーでの買い物は退屈で、飽きると走り回ったり、親から離れて迷子になったりしがち。そこで、買い物そのものを遊びに変えれば、子供も楽しく付いて来られると考えた。さらに、親から離れすぎるとダンジョンから追い出される仕組みにし、遊びながら自然と親のそばにいられるようにした。

遊び方

  1. 親子それぞれのスマホでアプリを開き、タイトル画面をタップする
  2. 親は「親として使う」で復活の鍵になるコード(英数字 6〜12 文字)を決め、子供に伝える
  3. 子供は「子供として使う」でコードを入力し、親とつながったら「ダンジョンへ入る」。チュートリアルで操作を覚えたら冒険スタート
  4. 食材にカメラを向けるとモンスターが出現。「魔法を撃つ」で攻撃し、頭上の HP ゲージを削る(1 秒ごとに何度でも撃てる)
  5. 倒すとアイテムがドロップし、自動で手持ちに入る
  6. 親から 50m 以上離れるとダンジョンから脱出して攻撃できなくなる。親の 10m 以内に戻ると、鍵が届いて復活 image

見どころ

  • 食材がモンスターに: にんじん・ピーマンの画像や本物のバナナにカメラを向けると、映った方向に顔のある野菜モンスターが AR で現れる。スマホの向きを変えても、その場所に浮かび続ける
  • ヒット・撃破演出: 魔法が当たると敵が白く光ってつぶれ、衝撃波のリングと火花がはじけ、スマホも震える。頭上の HP ゲージは緑→黄→赤とすり減り、ゼロになると回転しながら消滅する
  • ドロップアイテム: 倒した場所に、にんじんソードやバナナブーメランの 3D モデルがくるくる回って現れ、手元へ吸い込まれて「手に入れた!」
  • 脱出と復活の鍵: 親から離れすぎると「ダンジョンから脱出してしまった!」の画面に。親に近づくほど「もう少し!」「鍵がもうすぐ届く…!」と変わり、そばに戻ると親の端末から鍵が届いて復活する

技術スタック

フロント(JavaScript / React / Three.js)

画面(スタート画面、ダンジョン入口、バトルHUD、親子の画面)と状態管理

AR 描画(Three.js / DeviceOrientation)

カメラ映像に 3D の敵を重ねる。WebXR がない iPhone Safari でも動くよう、端末の向きセンサーでカメラを回す

物体認識(YOLOv8n / ONNX Runtime Web)

本物のバナナを映すと敵が出現。ブラウザの中で推論し、カメラ映像を外部に送らない

見守り通信(Supabase Realtime)

親子の位置を Supabase Realtime で共有。データベースには保存しない

位置・距離(Geolocation API / Haversine 公式)

親子の距離を計算し、「脱出」と「復活」を判定 15m以上の距離差 => 「脱出」状態(ゲームできない) => 親にも知らせがきている 1m以内の距離 => 復活判定 (復活のカギを入手) => ゲーム可能に!!

距離と位置の算出はGeolocation APIでお互いの緯度・経度を入手してsupabaseに一時保存する(3秒ごとに値を算出) 一時保存された緯度・経度をHaversine公式をもとに距離を算出

Haversine公式

image

システム

アーキテクチャ

image

特に苦労した点・工夫した点

  1. 中間発表で「お店では本物の食材を認識できないと遊べないのでは」と指摘を受け、MindAR の画像認識に加えて YOLO(onnx runtime) による物体認識を取り入れた。開発時間が限られていたため、認識する対象はバナナ1つに絞った。 => つまり画像認識の精度をあげた!!(バナナ特化)

読み込み精度の詳細について

image

person : 人のこと(もし人がカメラに写っていもそれ以外のものを認識して3Dキャラを作成できるために学習済みの配列に入れた)

banana : 実行中のyoloのしきい値を.060を超えたら3Dオブジェクトthree.jsのキャンバスに描画 spawnEnemie !== nullのときはyoloを物体認識をストップしています。 そして敵を倒す => ドロップアイテムを入手の裏でもyoloをキャッシュから呼び出して物体認識を再稼働するような仕組みにしてます。

  1. yolo,wasm,supabase realtime(websocket)の読み込み時間が長い

起動時の読み込みで平均して600 ~ 800msかかっていたのでUXとして悪いな~と思った。 山西先生の「神の一言」によってチュートリアルステージをyolo等の本番環境に必要なツールなしでつくってユーザーの待ち時間をなくす そして裏で非同期処理で読み込み処理を走らせてUXの向上をしました

今後の展望

  • YOLOに他の野菜や果物も学習させる(にんじん、ピーマンなど)
  • アイテムを増やす(にんじんソード、ピーマンシールドなど)
  • リアルタイムでの距離抽出の精度を上げる
  • ラスボス出現とクリア画面実装

話し合い履歴↓ https://docs.google.com/document/d/1pDoyN4_cIO84QhV9NP8gAhrdfsx79s6AuyFDLjLazO0/edit?usp=sharing

おまけ

  • 3Dオブジェクトについて 着想は子供が苦手な食品をモンスターにして倒そう、というものでした。 まずiPadで原画を描いてそれをGeminiに投げてプロンプトを考えてもらい、ClaudecodeにPythonでBlenderによるモデリングを実装してもらい、時短で作りました。本当は各モンスターを倒したらそれぞれ個別のドロップ品を落とす予定でしたがそこまでは実装できませんでした。個人的なお気に入りはほうれん草と報連相ペンです。あと南国おちゃらけバナナの原画ちょっと可愛くないですか。供養させてください。 image image image image

チームワーク 今回のチームは、チーム開発が右も左もわからない初学者2人と経験豊富なハッカソン常連客1人で開発しました。 Githubを教えてもらい、main、develop、featureを使用して機能ごとにbranchを切って作業をしました。issueをGithub上であげ、各メンバーが何をやっているのか明確化しました。 今まで適当なチーム開発しかしてこなかったので、大変学びになるハッカソンでした!

ふぇふぇ

@1a57abffd020c2c3