MENU

expo+React Nativeアプリ開発2日目!TypeScriptでノベルゲームを作ってみた話【作業報告4月12日】

expo+React Nativeアプリ開発2日目!TypeScriptでノベルゲームを作ってみた話【作業報告4月12日】今日もMLBの海外の反応と、犬の記事を更新しました。

今日は、山本由伸投手が6回無失点で9三振を奪う大活躍だったので、海外のコメントが沢山ありました。
また、まだ誰もその海外の反応の記事を出していないのか、ツイッター(拡散用)では1時間で300くらい閲覧のしるしが付いていました。

…ただ、実際にその記事には、8人位しか見ていなかったけど。

目次

今日のメインはアプリ開発!

今日のメインは、昨日に引き続き、expo + React Nativeでのアプリ開発です。

昨日のアプリは初めて作ったので、物凄くショボかったです。
コードもかなり短い。
でも、何も知らない初心者が、フォルダの場所の意味やコードの意味合い的な物が何となくわかってきました。(自分では全くコードを書けないけど)

今回のチャレンジ:ノベルゲーム(選択式)【asdと付き合う】

今日は、新しく**ノベルゲーム(選択式)【asdと付き合う】**を作ってみました。

ただ、chatgptにコードを書いてもらいましたが、エラー満載で何度も作り直し
さらに、chatgptとのやり取りが長くなり、画像なども見てもらったりしたので処理が重くなり、新しいスレッドに移行。

でも、なかなかうまくいかず、結局途中で妥協して中途半端なノベルゲームになってしまいました。

ChatGPTの違いに今更気づいた話

今更ながら気づいたのですが、コードはchatgpt4oを使うより、o3-mini-highの方が圧倒的に良いです。

o3-mini-highをほとんど使ったことが無かったので知らなかったのですが、コードを出力してもらう場合、文字数制限がchatgpt4oよりも長く出せる気がします。

さらに、無茶な画像やファイルをたくさん渡しても解読してくれる
4oには無い性能があるのではないかと感じました。

ただ、【推論しています】という長いロード時間があります。

コードの正確性についても、4oよりo3-mini-highの方が圧倒的?に優れている気がします。

📱 今回のasdノベルゲーム

今回は、React Native + TypeScript + Expo を使って、ノベルゲームアプリの制作に挑戦してみました。

簡単なテキストシーンの表示や分岐、キャラクター画像の切り替えなどを組み込みながら、Reactらしい構成でストーリーを展開させていく形です。

…が、途中で**「画像が表示されない」**という謎のバグに直面したので、その原因と対処も含めて振り返っていきます。

🔧 使用した技術・ライブラリ

  • React Native
  • TypeScript
  • Expo
  • JSONベースのシナリオ管理
  • コンポーネント構成によるシーンの切り替え

🏗️ 実装の構成

データ構造(TypeScript)

まず、ストーリーや選択肢の管理には types.ts を用意して型を定義しました。

export type Scene = {
  id: string;
  text: string[];
  image?: string;
  speaker?: string;
  bgm?: string;
  goto_ending?: boolean;
  next?: number;
  choices?: {
    text: string;
    next: number;
    kotori_gauge?: number;
  }[];
};

export type Chapter = {
  chapter: string;
  title: string;
  scenes: Scene[];
};

これで JSONファイルから安全にデータを読み込めるようにしています。

シナリオと画像

シナリオは chapter1.json, chapter2.json…のように分け、
シーンごとに image を指定してキャラ画像を出すようにしました。

{
  "id": "scene1",
  "image": "kotori_smile.png",
  "text": ["こんにちは、ことりです。", "今日も一日がんばろうね!"],
  "next": 1
}

画像の読み込みは getImageByName() を使って行います:

export const getImageByName = (name: string): any => {
  const images = {
    'kotori_smile.png': require('../assets/images/kotori_smile.png'),
    'kotori_fuan.png': require('../assets/images/kotori_fuan.png'),
    'kotori_paniku.png': require('../assets/images/kotori_paniku.png'),
    'kotori_yorokobi.png': require('../assets/images/kotori_yorokobi.png'),
    'happy_end.png': require('../assets/images/happy_end.png'),
    'bad_end.png': require('../assets/images/bad_end.png'),
    'nomarl_end.png': require('../assets/images/nomarl_end.png')
  };
  return images[name] || images['kotori_smile.png']; // fallback
};

🐛 ハマったところ:画像が表示されない!

問題点

  • 第3章から第4章にかけて画像が表示されなくなる
  • JSON の内容は "image": "kotori_yorokobi.png" など正しく見える
  • しかし UI 上では画像が出ず、fallback にすらならないときも…

原因

  • getImageByName() に渡される name" "(空白)や undefined の可能性
  • それにより images[name] が失敗して require() が機能しない
  • .png 拡張子が JSON にあるが、key に "kotori_yorokobi" のような拡張子なしを使っていた部分があり、キーの不一致が発生

解決法

  • getImageByName()images マップのキーを .png付きで統一
  • fallback を明示的に設定(kotori_smile.png
  • console.log(name) を入れて実行時の値をチェック

✅ 学んだこと

  • キーの整合性が超重要!
    JSONとロジック側で同じ文字列で管理しよう
  • fallbackは便利だけど油断禁物
    意図しないエラーが埋もれることもある
  • console.logは最強の味方
    React Native でもログでデバッグできる

最後に

今回は TypeScript を活用して型安全なノベルゲームの構築に挑戦し、
リアルタイムで画像切り替えを行う部分で多くの気づきがありました。

バグはつきものだけど、それを乗り越えるのが開発の楽しさ!
次はセーブ機能やエンディング分岐の強化にもチャレンジしてみたいですね。

追記:完成しました

ついに、2作目となるスマホアプリが完成しました!

今回も「React Native + Expo」を使い、ChatGPTの力を借りながら(全てchatgpt任せ)、ノベルゲーム風のアプリを作りました。途中で画像が表示されないトラブルなどもありましたが、なんとか最後まで動くものに仕上げることができました。

以下の動画は、実際にスマホでプレイした様子を録画したものです📱
ぜひご覧ください!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次