Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xyx0no646/16913d4407cdd4729cb2d5cf189a7095 to your computer and use it in GitHub Desktop.
Save xyx0no646/16913d4407cdd4729cb2d5cf189a7095 to your computer and use it in GitHub Desktop.

吉里吉里ZのKAG3を吉里吉里SDL2でも動作するように書き換えるメモ

あれ?吉里吉里Zのプロジェクトがそのまま動作しないぞ?

実は「吉里吉里SDL2」には以下の2つのものが足りません。

MenuItem
コンテキストメニューが実装されていません。(※吉里吉里Z2の段階で非推奨でした)
標準フォント
吉里吉里Zなら必ずWindowsなのでMSゴシックとかつかえるんでしょうが
クロスプラットフォームなのでデフォルトフォントは用意してやる必要があります
KAGParser.dllの廃止
KAGParser.dllは廃止され、TJS2で再実装されました。

そこで、少し手を加えてやります。

書き換え

2023/12/17 追記:

以下のリンク先を見て「なるほど、つまり吉里吉里Zのプロジェクトにsystem_polyfillを入れればいいんだな?」と思った方、正解です。 https://github.com/krkrsdl2/kag3/blob/b21b16ea684a3274488282687ca4184df49bec9f/data/startup.tjs

以下はいくらか古い情報です。あとで情報を削ります。


以下のURLから2つのファイルをダウンロードしてきます。

https://github.com/krkrsdl2/kag3/tree/krkrsdl2/data

  • MenuItem_stub.tjs (※コンテキストメニューがあるように見せかけるtjsファイルです)
  • font.otf(※IPAフォントです。すみません。Adobe Han Sansです:https://github.com/adobe-fonts/source-han-sans/tree/release梅ゴシックに切り変わりました。詳しくはコメントで

を既存の吉里吉里Zのプロジェクトのdataフォルダにコピーしてください。

その後、以下のようなコードをstartup.tjsに追加してください

// MenuItemがない場合、MenuItemがあるように見せかける
if (typeof(global.MenuItem) !== "Object")
{
Scripts.execStorage("MenuItem_stub.tjs");
}

// デフォルトフォントを指定する
if (typeof(global.Font) === "Object" && typeof(global.Font.addFont) === "Object")
{
System.setArgument("-deffont", global.Font.addFont("font.otf")[0]);
}

参考:https://github.com/krkrsdl2/kag3/blob/krkrsdl2/data/startup.tjs


2023/9/2 KAGParser.dllは最新の吉里吉里SDL2で廃止されました。

移行方法はこちらhttps://twitter.com/pnfqno646/status/1630669557169029121


これでKAG3ベースなら一応動作するはずです。

吉里吉里のリリーサーでdata.xp3を作成し 吉里吉里Z/吉里吉里SDL2両方で動作することをいったん確認してください

※Web版使用する方は、「Web版で音の再生がおかしくなることがある(Web版)」項目/「足りない機能がある(Web版)」項目もご覧ください。

まだ動かない……orz

セーブでコケる(MacOS/iOS)

「Cannot open storage よくわからない文字列/datasc.ksd」というエラーが出る場合

MainWIndow.tjsに以下の記述がある場合は

// saveDataLocation がフルパスでないようならば System.exePath を
// 付け加える
if(saveDataLocation.indexOf(":") == -1)
       saveDataLocation = System.exePath + saveDataLocation;

https://github.com/krkrz/kag3/blob/master/data/system/MainWindow.tjs#L288

このように書き換えてください

// saveDataLocation がフルパスでないようならば System.dataPath にする
if(saveDataLocation.indexOf(":") == -1)
     saveDataLocation = System.dataPath;

iOSなど一部の環境は「System.exePath」とはアプリ本体(が入っているフォルダ)のことを指します。

Appleのセキリティポリシーなどの理由により、アプリ本体を書き換えることは許可されていません。

System.dataPathは「書き換えても良い場所」を指すので吉里吉里Zでもこちらのほうがベターだと思います。

モーダルWindowが死ぬ(Web/Android/iOS)

「Windowの概念がない環境下ではモーダルWindowが動かない」ですよね。

具体的に困るのは「WebやAndroidやiOSでYesNoDialog.tjsが動かない」という症状です。

一応、WebだけならJavaScriptに逃がすという方法があります。

※21/8/28 追記

文字列をそのままEvalするのは色々と危険だというご指摘いただきました。そのとおりですorz 以下サンプルはjavascriptのwindowコンテキストを持ってくる方法に書き換えました。

https://gist.github.com/xyx0no646/16913d4407cdd4729cb2d5cf189a7095#gistcomment-3872405

// Yes か No かはっきりさせる関数
function askYesNo(message, caption = "確認")
{
    // Webはこちらに分岐 JavaScriptのconfirm関数を使う
    if(typeof(global.KirikiriEmscriptenInterface) == "Object"){
	var js = KirikiriEmscriptenInterface.evalJS('window');
	return js.confirm(message);
    }
    // 他の吉里吉里SDL2環境や吉里吉里Zはこちらに分岐
    else{
        var win = new YesNoDialogWindow(message, caption);
        win.showModal();
        var res = win.result;
        invalidate win;
        return res;
    }
}

参考:Web版吉里吉里SDL2 JS⇔TJS Interface メモ
https://gist.github.com/xyx0no646/03cab2d139df0616fa73dd9a168ac282

参考:TJS<->JS interface information
https://gist.github.com/uyjulian/66bb0466136d04bc1920d55894edb8c0

AndroidやiOSではアラートを表示する吉里吉里プラグインをC++で書けば良いです。 こちらにソース置いときます。 https://gist.github.com/xyx0no646/5521bf6c61ee54db5bd1343b2c364bcf

XCodeならkrkrsdl2フォルダのSource Filesにファイルを作ってから、Build PhasesのCompile Sourcesに突っ込めば動きます。 Androidならmesonツールチェーンに突っ込んでください。

吉里吉里プラグイン(.dll)はどう動いているのか / 吉里吉里プラグインを追加するには?(全環境)

「なんちゃら.dll」はご存知、Windowsにしか存在しない動的リンクの仕組みです。
DLL内部に書かれている機械語もx86のものであり、MacOSやiOSやWebAssemblyで動かせるわけでは当然ないです。

でも現に、json.dllなどの一部のプラグインは動作しています。
では、どうやっているのかというと、ソースコードからビルドして静的リンクしています。

……早い話が、自力でC++からビルドすれば動くってことです!
ソースコードの修正やビルドの煩わしさを乗り越えれば動くかもしれません!

本気の方は、奥付まで。(そのうち全部入りWeb版ビルドを配布するかもしれません)

  • 追記(2021/9/14)

吉里吉里SDL2の動的リンクプラグイン対応が近いうちにされそうです!!!
https://twitter.com/uyjulian/status/1437737889035587584

公式にあるプラグインは対応しそうな感
https://twitter.com/uyjulian/status/1450064331253628929

Web版で音の再生がおかしくなることがある(Web版)

[playse]が無限ループする、などなど

対応中……
→対応されました!!以下はすでに必要ありません。 2023/08/27

WebAssembly上でのWaveSoundBufferの実装はかなりナイーブらしく @uyjulianさんはこの部分だけWebAssemblyではなくJavaScriptに移せないか考えているようです。

その間、一次対応を考えています。思いついたら追記します。

一次対応

一次対応→[playse] [stopse] [playbgm] [stopbgm]の代替品ができました。 https://gist.github.com/xyx0no646/e9c4ddad70f0db64a87cfefd87dd3eb9

一次対応2 → 完全版ではありませんが、JavaScriptで実装されたWaveSoundBufferの代替品ができました。

上記のものはメモリリークする可能性があったり、タグを書き換える手間があったりで大変なので、こちらのほうがより良い代替実装になっています。
ループチューナーとか色々動かないのですが、そのへんは一次対応なので許してください……

JSWaveSoundBuffer.tjs
https://gist.github.com/xyx0no646/71363ab2b47dcfdcc920afe0570abd8d

上記をdataフォルダに保存した後、startup.tjsに以下のように記述してください。

// JavaScript実装のWaveSoundBuffer(機能限定版)
if (System.platformName === 'Emscripten') {
	//Safariは適用を除外する(ogg再生時のAudioタグが使い物にならないため.代替策は考え中……)
	var isSafari = KirikiriEmscriptenInterface.evalJS('navigator.vendor.indexOf("Apple")') != -1;
	// なお、mp3を使う場合は上記判定はいらないので
	isSafari = false;
	// としてください
	if (!isSafari) {
		Scripts.execStorage("JSWaveSoundBuffer.tjs");
	}
}

詳細はJSWaveSoundBuffer.tjsの上部のコメントを見てください。

※2021/9/20 [ws]タグを使うとフリーズしてしまう問題を修正

Web版で「System.exit();」が動かない(Web版)

吉里吉里Zや他の吉里吉里SDL2環境では「アプリを閉じる」という挙動をするこの関数

Web版吉里吉里SDL2では画面がフリーズして終わります。

ブラウザでJavaScriptを動かしたことがある方はご存知かもしれませんが、 自分自身のタブを閉じることはセキリティ上できないのです……

私はlocation.reloadで画面を再読み込みさせてお茶を濁しています。

    var isClose = askYesNo("終了しますか?");
    super.onCloseQuery(isClose);
    // Webの場合はこちら
    if(typeof(global.KirikiriEmscriptenInterface) == "Object" && isClose){
	KirikiriEmscriptenInterface.evalJS('try{window.close();}catch(e){}'); // PWAならこれで閉じられます
        KirikiriEmscriptenInterface.evalJS('location.reload()');//JavaScriptのlocation.reloadを呼び出しています
        return;
    }
    // それ以外はこちら
    if (isClose)
      try{System.exit();}catch(){}

Web版でeditタグの日本語入力ができない(Web版)

EmscriptenのSDL2の問題です。極東の島国は後回しらしい。

editタグをクリックしたらJavaScriptのpromptを出す一次対応です。 LinkEditLayerの拡張です。

以下macro.ksに貼り付けてください。

https://gist.github.com/xyx0no646/b4049970c16dcd4ab526706fdf4a6a8a

Web版でフルスクリーンしたい(Web版)

……やめといたほうがいいです。多分、いいことなんてないと思います。
「onWindowedMenuItemClick」と「onFullScreenMenuItemClick」をHTML5 FullScreen APIで上書きすればできます。

以下、macro.ksに貼り付けてください。
https://gist.github.com/xyx0no646/787d5f800b262ac0f4297f1950ebef06

一応、挙動は確認しておいたほうがいいと思います。

動画が再生できない(全環境)

……そうです。大人の事情により動画が再生できないんです。

良い代替手段は今考えていますが、Web版ならhtml5のvideoタグをTJS2内部に召喚することで動画再生できるはずです。

(※スニペットは作成中です。少々お待ち下さい)

足りない機能がある(Web版)

吉里吉里Zや他の吉里吉里SDL2環境と違い、Web版吉里吉里SDL2はTJS2上でJavaScriptが使えます。
JavaScriptが書ける方は、足りない機能や不具合をJavaScriptで上書きして使うことができます。

JSONとかはC++からプラグインをビルドするよりJavaScriptで書いちゃったほうが楽かもしれません。

※「吉里吉里Zや他の吉里吉里SDL2環境」にはない機能です。Web版以外も出す方はほどほどに……!

// 対応しているのはWeb版吉里吉里SDL2だけなので以下のような分岐を入れます……
if(typeof(global.KirikiriEmscriptenInterface) == "Object"){
   // windowコンテキストを呼び出すと……
   var js = KirikiriEmscriptenInterface.evalJS('window');
   // JavaScriptのalertがそのまま呼べる!
   js.alert("alert");
  // こんなこともできるし……
  var array =js.JSON.parse("[1,2,3,4]");
  //こんなことまでできます!
  js.alert(array[0]);
}

参考:Web版吉里吉里SDL2 JS⇔TJS Interface メモ
https://gist.github.com/xyx0no646/03cab2d139df0616fa73dd9a168ac282

参考:TJS<->JS interface information
https://gist.github.com/uyjulian/66bb0466136d04bc1920d55894edb8c0

PWAアプリにしたい(Web版)

PWA化すれば、Webページから直接インストール出来たり、オフラインでゲームをプレイできたりします。
……というわけで、今!私(ぷり)はPWA版を作っています。乞うご期待です!

純粋な不具合(主にWeb版)

ともに戦いましょう。

周りの吉里吉里使いと解決策を考えましょう。 ソースを修正してプルリクエストしたりフォークしたりしてもよいのです。

コミュニティベースのオープンソースってそういうものです。
皆が吉里吉里の製作者であり所有者です。そして不具合の修正への責任もまた各々が持っています。

なお、私はずっと吉里吉里SDL2のデバッグやっているので 奥付的なものにリプ飛ばせばなにかわかるかもしれません。

もしそれでもわからない場合はともに戦いましょう……orz

関連記事

吉里吉里SDL2とはなにか
https://writening.net/page?dsGMBX

奥付的なもの

ぷり@xyx0no646
https://twitter.com/xyx0no646

@yasuoohno
Copy link

こんにちは!

    // Webはこちらに分岐 JavaScriptのconfirm関数を使う
    if(typeof(global.KirikiriEmscriptenInterface) == "Object"){
        return KirikiriEmscriptenInterface.evalJS('confirm("'+message+'")');
    }

こちらですが、messageに改行、ダブルクォート、エスケープ文字等入ってたときに例外あがってしまう事があります。
互換性上、エスケープ処理が必要になりましたので念のためお知らせしておきます。

jsを evalしているので security上も エスケープしたほうが良いかなと 🔒

@xyx0no646
Copy link
Author

こんにちは!

    // Webはこちらに分岐 JavaScriptのconfirm関数を使う
    if(typeof(global.KirikiriEmscriptenInterface) == "Object"){
        return KirikiriEmscriptenInterface.evalJS('confirm("'+message+'")');
    }

こちらですが、messageに改行、ダブルクォート、エスケープ文字等入ってたときに例外あがってしまう事があります。
互換性上、エスケープ処理が必要になりましたので念のためお知らせしておきます。

jsを evalしているので security上も エスケープしたほうが良いかなと 🔒

@yasuo_ohnoさん

文字列をそのままevalしてしまうのは大変うかつでした……
以下のように書き換えました。ありがとうございますm(_ _)m

        // Webはこちらに分岐 JavaScriptのconfirm関数を使う
        if(typeof(global.KirikiriEmscriptenInterface) == "Object"){
		var js = KirikiriEmscriptenInterface.evalJS('window');
		return js.confirm(message);
	}

@xyx0no646
Copy link
Author

xyx0no646 commented Nov 28, 2021

gistが編集できなくなったのでコメントで失礼します。

font.otf(※IPAフォントです。すみません。Adobe Han Sansです:https://github.com/adobe-fonts/source-han-sans/tree/release)

font.otfが「梅ゴシックO5」に切り替わりました。フォントのライセンスは「これらのフォントはフリー(自由な)ソフトウエアです。あらゆる改変の有無に関わらず、また商業的な利用であっても、自由にご利用、複製、再配布することができますが、全て無保証とさせていただきます。」です。

https://osdn.net/projects/ume-font/wiki/FrontPage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment