ONScripter on iOS

Since: Jan. 11, 2012
Last updated: Apr. 7, 2023 SDK を更新
更新内容はONScripter 開発日誌を参照

はじめに

iPhone や iPad など iOS 上で動作するノベルゲームエンジン ONScripter on iOS を使ったアプリの作成方法について説明します。

App Store で公開可能(要審査)な有償・無償のノベルゲームアプリを作成することができます。ゲームデータはアプリに内蔵できますが、アプリのインストール後に別途ダウンロードすることもできます(配布用Webサーバを別途用意)。

ここで説明する方法は macOS Ventura 13.5.1 以降で Xcode 14.3 (統合開発環境)以降を使っていることを想定していますが、古いバージョンでも動作すると思います。iPad Pro(iOS 16.6)の実機、および Xcode 14.3 のシミュレータ(iPhone 14 Pro Max)で正常に動作することを確認しています。

使用にあたって私に連絡する必要はありません。また、使用者に対して私から何か要求することもありません。自由に使ってください。

使用作品例

NOeSIS02 -羽化-
NOeSIS02 NOeSIS02
NOeSIS -嘘を吐いた記憶の物語-
NOeSIS01 NOeSIS01

アプリの開発方法

開発の流れ

  1. 製作
    NScripter (2011/12/15)(解説)を使用して Windows PC でゲームを製作します。ONScripter Launcher and Binary for Mac OS X を使って MacOSX 上で製作することも可能です(この場合 Windows PC は必要ありません)。以下の入門講座が参考になると思います。
  2. アプリの作成
    開発環境の構築アプリの作成を参考にして Xcode でアプリを作成します。実機で動作確認をする場合は、iPhone/iPad を USB で Mac に接続します。
  3. ゲームデータの動作確認(ゲームデータを内蔵する場合)
    ゲームデータが完成したら、ゲームデータの内蔵方法を参考にしてゲームデータを Xcode のリソースにドラッグし、HAVE_CONTENTS を定義してアプリを作成します。アプリを実行すると、初回にリソースから Library/Caches/ONS フォルダにゲームデータをコピーし、その後にゲームを開始します。
    Xcode からアプリを実行している場合は、Xcode の Windows → Devices から Installed Apps の ONScripter を選択し、Download Container でアプリのファイル一式を Mac 側にコピーし、Finder で中身を編集してから、Replace Container で端末に書き戻しても構いません。
  4. ダウンロードの動作確認(ゲームデータを初回にダウンロードする場合)
    ゲームデータが完成したら、zip ファイルに圧縮して自身で用意した WEB サーバ上に置きます。次に、その場所を ZIP_URL に設定してアプリを作成します。アプリを実行すると、ZIP_URL で指定した場所から zip をダウンロードし、ゲームデータを Library/Caches/ONS フォルダに展開してから実行します。正しくダウンロードしてゲームが開始されることを確認します。
  5. 公開 App Store でアプリを公開します。(要審査)

開発環境の構築

コマンドラインツールの導入

Xcode 4.3 以降ではビルドに必要なツールが入っていないため、以下の手順に従ってインストールします。

  1. Command Line Tools のインストール
    • Xcode 5.1.1 以降では、Xcode を起動し、メニューバーの「Xcode」→「Open Developer Tool」→「More Developer Tools」を選択してください。そうすると、Downloads for Apple Developers web site に接続するので、サインインして、お使いの Xcode 用の Command Line Tools をダウンロードしてインストールしてください。
    • うまく行かない場合は、ターミナルから以下のコマンドを実行し、現れたダイアログでインストールを選択してもインストールできます。
      $ xcode-select --install
      

      注意:先頭の $ はプロンプトなので入力しません。

    • Xcode 5.1.1 未満では、Xcode を起動し、メニューバーの「Xcode」→「Preferences」→「Downloads」の Components のうち Command line Tools の横の「Install」ボタンを押してインストールしてください。
  2. Mac Ports の「Quickstart」の中の macOS Ventura v13 をクリックし、MacPorts のインストーラをダウンロードしてインストールします。次に、ターミナルから以下のコマンドを入力してビルドに必要なツールをインストールします。関連ツールもインストールするため、終了するまで時間がかかります。
    $ sudo port install automake
    $ sudo port install autoconf
    $ sudo port install libtool
    $ sudo port install pkgconfig
    

    注意:先頭の $ はプロンプトなので入力しません。

SDK の導入

リリース日 SDK
最新版 https://github.com/ogapee/onscripter_ios
20230407 onscripter_ios-20230407.tar.gz 最新版
  Xcode 14.3 + iOS 11.0-16.4.1 用
  Apple シリコンを搭載した Mac でビルドできるようにしました。
20220831 onscripter_ios-20220831.tar.gz
  Xcode 13.4.1 + iOS 9.0-15.6.1 用
  TestFlightで内部テストができることを確認しました。
20220705 onscripter_ios-20220705.tar.gz
  Xcode 13.4.1 + iOS 9.0-15.5 用
20210819 onscripter_ios-20210819.tar.gz
  Xcode 12.5.1 + iOS 9.0-14.7.1 用
  1. ファインダーを起動し、メニューバーから「移動」→「ホーム」を選択してホームディレクトリに移動します。次に、src という名前のフォルダを作成し、上から最新の SDK (onscripter_ios-*.tar.gz)をダウンロードして src フォルダの中に展開します。
  2. macOS の「アプリケーション」→「ユーティリティ」→「ターミナル.app」を起動し、以下のコマンドを実行します。
    $ cd ~/src/onscripter_ios
    $ source dev_iPhoneOS.sh
    $ make clean
    $ make
    $ source dev_iPhoneSimulator.sh
    $ make clean
    $ make
    
    注意:先頭の $ はプロンプトなので入力しません。また、初回の make clean はエラーで終了しますが、そのまま make に進んでください。
    これによって、以下のライブラリが実機用とシミュレータ用にそれぞれ作成されます。

アプリの作成

以下のワークスペースファイルをダブルクリックして Xcode で開きます。

onscripter_ios/ONScripter.xcworkspace
Fig.1
図1:ONScripter のソースコードの導入

図1の上部に示すように、対象を「ONScripter」に変更します。実機用に作成する場合は、その右をAny iOS Device (図1では Generic iOS Device になっています、端末が接続されている場合は端末名に設定しても構いません) に、シミュレータ用に作成する場合は iOS Simulators の中のいずれか(iPhone 14 Pro Max など)に変更します。

最新の ONScripter の導入

ONScripter のページから最新の ONScripter のソースコード(onscripter-????????.tar.gz)をダウンロードして適当な場所に展開します。

図1の1をクリックし、展開したソースコードの内全ての *.cpp, *.h ファイルをファインダーを使って Sources (図1の2)にドラッグします(ドラッグ前にファインダー側で「種類」を押してソートしておくと楽です)。そのときにダイアログが出ますが、Add to targets で ONScripter にチェックを入れてから「Finish」ボタンを押してください(これをしないとドラッグしたファイルがビルドされません)。さらに、ドラッグしたファイルの内、不必要な以下のファイルを Sources から(Delete キーで)削除します(図1は削除後の状態)。

AVIWrapper.h
AVIWrapper.cpp
conv_shared.cpp 
nsaconv.cpp
nsadec.cpp 
nscriptdecode.cpp
sarconv.cpp 
sardec.cpp
simple_aviplay.cpp

Sources の以下のファイルを右クリックして Show File Inspector を選択し、Xcode ウィンドウの右側に表示される Identiy and Type の File Type を Objective-C++ source に変更します。

onscripter_main.cpp

プロジェクトの設定

図1の 3 をクリックし、さらに上図の TARGETS の下の ONScripter をクリックして、以下のようにプロジェクトの設定を変更します。赤字の部分は適宜変更してください。Product Nameの文字列がアプリ名になります。

Info の項目 設定値
Bundle version string (short) 1.0
Bundle version 1.0
App Transport Security Settings
Exception Domains
onscripter.osdn.jp
Build Settings の項目 設定値
Product Bundle Identifier jp.ogapee.ONScripter
Product Name ONScripter
Preprocessor Macros IOS
UTF8_FILESYSTEMS
USE_LUA
USE_SMPEG
MP3_MAD
PDA_AUTOSIZE
USE_SDL_RENDERER
HAVE_CONTENTS
RENDER_FONT_OUTLINE
ZIP_URL=\"http://*.*/*/*.zip\"
MAGIC_FILE=\".20230407\"
USE_SELECTOR

ゲームデータの配布方法

ゲームデータを内蔵する場合(推奨

ゲームデータを内蔵する場合は HAVE_CONTENTS を定義してください。この場合、ZIP_URL は指定しません。

Fig.2
図2:ゲームデータの内蔵

HAVE_CONTENTS を定義した場合のゲームデータの内蔵方法について説明します。まず、ゲームデータをまとめたフォルダの名前を ONS にします。次に、ファインダーで ONS フォルダを Xcode の Resources にドラッグします。このときに、ダイアログが表示されるので、必ず Create folder references for any added folders にチェックを入れてください。こうすることで、図2の例に示すようにフォルダの階層構造を保ったまま Resources にコピーすることができます。

アプリを実行すると、もし Library/Caches/ONS が存在しない場合、もしくは Library/Caches/ONS/ 以下に MAGIC_FILE が存在しない場合に、Resources から ONS を Library/Caches/ONS にコピーし、Library/Caches/ONS/ 以下に MAGIC_FILE を作成した後にゲームを開始します。このとき、セーブデータなど後から生成されるファイルは、ゲームデータの中に元々含まれていない限り消されずに残ります。

ゲームデータを初回にダウンロードする場合

ゲームデータを初回にダウンロードする場合は、ご自身でサーバを用意し、ZIP_URL にゲームの構成ファイルを全てまとめた単一の zip ファイルの URL を指定してください。URL の左右両方にバックスラッシュ(\)とダブルクオート(")を入れる点に注意してください。この場合、HAVE_CONTENTS は指定せず削除します。ゲームの構成ファイルのうち nscript.dat, arc.nsa, default.ttf 等は zip 内の(フォルダを挟まない)直下に置いてください。例えば、Lhaca デラックス版ExplzhWinZipなどのzip作成ソフトを起動し、nscript.dat, arc.nsa, default.ttf などのファイルを直接ドラッグ&ドロップすれば正しく zip ファイルが作成されます。

また、「Info の項目」→「NSAppTransportSecurity」→「NSExceptionDomains」のドメイン(デフォルトは onscripter.osdn.jp)を、ZIP_URL で指定した URL のドメインに変更してください。変更しないとダウンロードできません。

MAGIC_FILE にはゲームデータのバージョン管理用のファイル名を指定します。ファイル名の左右両方にバックスラッシュ(\)とダブルクオート(")を入れる点に注意してくださいです。HAVE_CONTENTS もしくは ZIP_URL が指定された状態で、ゲーム起動時にこのファイルが存在しない場合に、ゲームデータのコピーもしくはダウンロードを実行し、最後に MAGIC_FILE で指定した空のファイルを作成してゲームを開始します。ゲームの構成ファイルを更新するときに変更してください。ファイル名は、ゲームの構成ファイルと重ならない名前であれば任意の名前を指定できますが、上の例のようにリリースした日付などにしておくと管理しやすいと思います。

アプリを更新する際に、エンジン部分(ONScripter)だけを変更してゲームデータは変更しない場合は、MAGIC_FILE を更新する必要はありません。

ゲームの選択機能

USE_SELECTOR を定義すると、起動時にゲームを選択できるようになります。ゲームデータは、アプリをインストールした後に、端末のアプリの Library/Caches 直下に任意の名前のフォルダを作成してその中に置いてください。ただし、ゲームデータがあるフォルダが Library/Caches 直下に1つしかない場合は、無条件にそのフォルダにあるゲームが実行されます。また、Documents の下にも同じ名前の空のフォルダを作成してください。セーブデータはこちらに保存されます。

Library/Caches 直下にアクセスするには、現状では、Xcode 上でアプリを実行することによってインストールし、Xcode の Windows → Devices and Simulators から Installed Apps の ONScripter を選択し、Download Container でアプリのファイル一式を Mac 側にコピーして、Finder で中身を編集してから、Replace Container で端末に書き戻す必要があるようです。すなわち、App Store からアプリを配布した場合は、ゲームの選択機能を活用することはできないようです。

HAVE_CONTENTS と USE_SELECTOR、もしくは ZIP_URL と USE_SELECTOR を併用することもできます。内蔵ゲームデータもしくは ZIP_URL で指定されたゲームデータは Library/Caches/ONS フォルダに展開されます。併用した場合、もし Library/Caches 直下に他にフォルダがなければ、内蔵したもしくはダウンロードしたゲームが無条件に実行されます。ユーザがフォルダを追加した場合は、起動時にゲーム選択画面が表示されます。

文字の輪郭描画

RENDER_FONT_OUTLINE を定義すると、起動オプションで --render-font-outline を指定した場合と同じになります。文字が見やすくなるのでおすすめです。

アイコン

アプリのアイコンを変更するには、ONScripter → Resources → Images.xcassets → AppIcon のアイコン画像を差し替えてください。

作成

実機向けにビルドする場合は、図1の右上の欄に「ONScripter Any iOS Device (arm64)」(実機を接続していない場合)と表示されていることを確認してください。ここに「testsdl」や「libSDL」などと表示されている場合は、この欄をクリックして正しい項目を選択してください。

メニューバーの「Product」→「Scheme」→「Edit Scheme」の Run ONScripter.app の Build Configuration を Debug から Release に変更します。

メニューバーの「Product」→「Build」を実行します。

アプリの作成に成功したら、メニューバーの「Product」→「Run」を実行するとプログラムが起動します。

Xcode で "Signing for "ONScripter" requires a development team. Select a development team in the Signing & Capabilities editor." というエラーが出る場合には、プロジェクトの設定の Signing & Capabilities の Signing 項で、Automatically manage signing のチェックを一度外してから再度チェックを入れ、続いてその直下の Team を設定してください。

Apple シリコンを搭載した Mac でシミュレータ向けにビルドする場合は、Build Settings → Architectures → Excluded Architectures の Debug と Release に Any iOS Simulator SDK の項目を追加して arm64 を設定してから、シミュレータ向けにビルドしてください。

アプリの申請

アプリのArchive作成とアップロード

Xcode から App Store にアプリを登録するには以下のようにします。

  1. メニューバーの「Product」→「Archive」を実行して申請用にアプリを作成します。
  2. 成功するとArchives一覧が表示されるので、今回作成したアーカイブが選択されていることを確認して「Distribute App」をクリックします。
  3. ダイアログがいくつか表示されますが、すべてデフォルトのまま「Next」を押します。
  4. 最後に Review ONScripter.ipa content: のダイアログが表示されるので、「Upload」を押します。

正常にアップロードされると、App "ONScripter" successfully uploaded. と表示されます。

アプリのテスト

公開前に TestFlight によって内部テストを行う方法について説明します。

  1. App Store Connectにログインして、マイAppからアップロードしたアプリを選択します。
  2. 「TestFlight」をクリックしてから「内部テスト」の横の+をクリックします。新規内部グループを作成して、テスター(たとえば自分自身)を追加します。
  3. 「ビルド」→「iOS」をクリックし、アップロードしたアプリのステータスが「コンプライアンスがありません」に変わったら、「管理」をクリックし、輸出コンプライアンス情報で「上記のアルゴリズムのどれでもない」を選択して、「内部テストを開始」をクリックします。
  4. アプリのステータスが「提出準備完了」に変わったら、上で作成した内部テストのグループをグループに追加します。
  5. テスターは、iPhoneもしくは iPad にApp StoreからTestFlightアプリをインストールしておきます。テスターにメールが送られてくるので、メール本文にあるTestFlightのURLにアクセスし、表示された招待コードをTestFlightアプリで入力すると、作成したアプリをインストールして実行できるようになります。
  6. 作成したアプリを一度インストールすると、以降のアップデートはTestFlightアプリの中から実行できます。

アプリの公開

  1. App Store ConnectのマイAppからアップロードしたアプリを選択します。
  2. 「App Store」をクリックして、必要な項目を記入してから「審査用に追加」を押します。以降の手順は未確認です。

zip 内のゲームデータの配置方法

ゲームデータを初回にダウンロードする場合に、スクリプトファイル(nscript.dat や 00.txt)、アーカイブファイル(arc?.nsa や ??.ns2), フォントファイル(default.ttf)は zip 内の(フォルダを挟まない)直下に置いてください。その他のファイルはサブフォルダの下にあっても構いません。Android 版でも同じ zip ファイルが使用できます。

nscript.dat   (ゲームの構成ファイル)
arc.nsa       (ゲームの構成ファイル)
default.ttf   (自分で用意するフォントファイル)
...           (その他のゲームの構成ファイル (基本的に全てコピー))
  • ゲームの構成ファイル(arc.nsa など) は解像度変更などはせずに元のファイル(サブフォルダを含む)をそのままコピーしてください。
  • TrueType font による文字表示を参考にフォントファイルを default.ttf という名前で同じ場所に置いてください。
    例えばM+とIPAの合成フォントの Migu 2M の太字 (Migu-2M-bold.ttf) が、きれいな太字で見やすくお勧めです。

実行方法

実機と MacOSX を接続して Xcode から実行するか、もしくは ONScripter のアイコンをタップして ONScripter を起動してください。

画面をタップすることによってゲームが進行します。同時にタップする指の本数によって機能が変わります。同時にタップする場合は、1本ずつ順に画面に触れてください。

タップ方法 機能
指1本 左クリック
指2本 右クリック
指3本 早送り(ctrl キー)

制限・注意事項

  • ディスプレイの解像度に合うようにゲーム画面の解像度が自動調整されます。色深度は 32bit です。
  • 電源ボタンもしくはホームボタンを押すと処理を中断して他のアプリを実行できるようになります。アイコンをタップするとゲームを再開します。
  • 動画ファイルの再生は MPEG1, H.264, MPEG4 フォーマットに対応しています。
  • 使用する音楽のサンプリング周波数は 22.05KHz か 44.1KHz のどちらかにしてください(混在可)。MP3, Ogg Vorbis, WAV をサポートしています。48 KHz などの音源は正常に再生されないので、えこでこツールなどを使って 44.1 KHz に変換してください。
  • 画像は BMP, JPEG, PNG, GIF をサポートしています。

その他

使用しているライブラリの修正箇所を以下に記します。

SDL

  • Retina display に対応するために、「Bug 1394 - Fixes for SDL's handling of "Retina" display on iOS devices」のパッチをあてています。
  • iOS 6.0 に対応するため、src/video/uikit 以下を、2012/10/29 時点のリポジトリ上の SDL のものと差し替えています。
  • Xcode 6.1.1 に対応するために、以下のように修正しています。
    --- SDL-old/src/video/uikit/SDL_uikitappdelegate.m    2012-10-30 01:05:43.000000000 +0900
    +++ SDL-new/src/video/uikit/SDL_uikitappdelegate.m   2015-01-11 17:12:36.000000000 +0900
    @@ -38,6 +38,7 @@
     #endif
     
     extern int SDL_main(int argc, char *argv[]);
    +extern void SDL_iPhoneSetEventPump(SDL_bool     enabled);
     static int forward_argc;
     static char **forward_argv;
     static int exit_status;
    

SDL_image

  • IMG_bmp.c, IMG_gif.c, IMG_jpg.c, IMG_png.c の Target Membership にチェックを入れて使用されるようにしています。
  • iOS 9.3.3 で読み込んだ画像が乱れる場合があるので、SDL_image 2.0 を参考に、IMG_ImageIO.m の CGColorSpaceCreateCalibrateRGB を CGColorSpaceCreateDeviceRGB に変更しました。

SDL_mixer

  • music_mad.c, music_mad.h の Target Membership にチェックを入れて使用されるようにしています。
  • Build Settings の Preprocessor Macros に以下の定数を追加しています。
    MP3_MAD_MUSIC
    
  • Build Settings の Header Search Paths に以下のパスを追加しています。
    $(SRCROOT)/../../Release-iphoneos/include
    

SDL_ttf

  • 現時点(2012/01/11)でリポジトリにある SDL_ttf.c の TTF_RenderGlyph_Shaded 関数には文字が全く描画されないバグがあるため、以下のように修正しています。
    --- a/SDL_ttf.c Fri Jan 20 20:35:28 2012 -0500
    +++ b/SDL_ttf.c Mon Jan 23 00:17:59 2012 +0900
    @@ -1747,7 +1747,7 @@
            /* Copy the character from the pixmap */
            src = glyph->pixmap.buffer;
            dst = (Uint8*) textbuf->pixels;
    -       for ( row = 0; row < glyph->bitmap.rows; ++row ) {
    +       for ( row = 0; row < glyph->pixmap.rows; ++row ) {
                    memcpy( dst, src, glyph->pixmap.width );
                    src += glyph->pixmap.pitch;
                    dst += textbuf->pitch;
    
  • Build Settings の Header Search Paths に以下のパスを追加しています。
    $(SRCROOT)/../../Release-iphoneos/include
    $(SRCROOT)/../../Release-iphoneos/include/freetype2
    

その他のライブラリ