吉里吉里Zでのリリース

吉里吉里Zで作ったゲームを配布するにはリリース作業が必要です。吉里吉里Zにはリリーサなどの配布用ツールが同梱されていないため少し手間がかかります。

xp3にまとめる

吉里吉里2ではリリーサ(krkrrel.exe)を使いましたが吉里吉里Zには同梱されていません。吉里吉里2のリリーサをそのまま使えます。

アイコンを変える

吉里吉里2では吉里吉里設定ツール(krkrconf.exe)で変更できましたが吉里吉里Zでは使えません。

代わりに一般的なアイコン変更ツールが使えます。例えばResourceHackerなどが利用できます。

破損チェックツール

破損チェックツールを一緒に配布すると、ゲームが起動しないときにファイルが破損していないかチェックできます。
吉里吉里2のチェックツール(ファイル破損チェックツール.exe)と署名ツール(krkrsign.exe)がそのまま使えます。

エンジン設定ツール

吉里吉里2ではエンジン設定ツール(エンジン設定.exe)が使えましたが吉里吉里Zでは使えません。

代わりに、吉里吉里Z本体を起動する際に-userconfオプションを付けて起動すると設定ツールが開きます。配布する際は以下のようにするのが簡単です。

  1. ゲーム本体と同じフォルダに「ユーザ設定ツール.bat」というファイルを作成します。
  2. 作成したファイルをテキストエディタで開きます。
  3. 以下を書き込んで保存します。「tvpwin32.exe」の部分は自分のゲームのファイル名に書き換えてください。
    start "" %~dp0/tvpwin32.exe -userconf
    

以上で「ユーザ設定ツール.bat」を起動すると設定ツールが開くようになります。

近況報告

年も暮れるので近況報告です。

2015年9月、とあるプログラム会社に就職しました。すでに退職しましたが少しだけ会社の話を書きます。

主な仕事の内容は既存のソースコードをGPGPUで高速化することでした。正直にいうと私は高速化の価値を軽く見ていました。しかし処理時間を1ヶ月から数時間に縮めるような仕事を経験してその価値の一端に触れられました。誇張なく処理時間1/30が実現できるGPUの計算能力はすごいです。それを実装できるようになったのは収穫でした。

技術的にはC++も使えるようになりました。いままで自分で書く機会が少なかったので勉強し直しました。いわゆる名著が多く翻訳されているC++は勉強しやすくてよかったです。C#では中級者以上になると英語資料が避けられない印象があります。これは私のC++レベルが低くて日本語圏に収まっているだけの可能性も高いですね・・・・・。

退職したのはプログラミング環境が悪かったためです。メモリ4Gのノートパソコンでプログラミングをする姿はカルチャーショックでした。あのパソコンでVS2015は動くのでしょうか。これからセキュリティのための禁止事項が増えてさらに環境は悪化していきそうです。

不安だった人間関係の悩みは全くなく、いい職場だったと今でも思います。社会人経験ゼロの私に優しくご指導いただき感謝しております。大変お世話になりました。

エロゲの仕事も細々と続けています。最近は2Dから3D方面に興味が移っているので今後はそちらの仕事ができればと思っています。今年はVR元年とも言われましたが来年はさらに発展していくでしょう。その一端を担えればと思います。

今年はブログを6回しか更新できませんでした。フルタイムの仕事をしながら家でブログを書くのは大変です。吉里吉里関連は私が吉里吉里を触ることも少なくなったので難しいかもしれません。内容はともあれ来年は何か書くようにします。

私生活では大したことも起きていませんがアイマス沼にはまってしまいました。めんどくさくて手間のかかる天海春香さんが大好きです。春香一人のCDを揃えるだけでいくらかかるのでしょうか。10年も続くコンテンツ力は伊達ではありません。末永く楽しみたいと思います。

今後の具体的な予定は決まっていません。吉里吉里の人からVRの人に変身する、という方向で頑張りたいと思います。来年も皆さまよろしくお願いします。

吉里吉里のループチューナで開けないwavファイル

たまに吉里吉里本体では再生できるのにループチューナでは開けないwavファイルがあります。

どうやらループチューナでは最初のチャンクがfmtチャンクでないと読み込めないようです。
普通はそうなっているので問題ないのですが、Cubaseで書き出したwavファイルがjunkチャンクから始まるため読み込めません。
このようなファイルはAudacityなど他のソフトで開いて保存しなおせば読み込めるようになります。

たくさんある場合はSoXでコマンドラインで処理するのが楽だと思います。

linq.tjs公開しました

TJSでLINQ to Objectsが使えるようになるライブラリlinq.tjsを公開しました。
https://github.com/sakano/linq.tjs

LINQ to ObjectsはC#の強力なコレクション操作ライブラリです。foreachすらないtjsではfor文を回すしかありませんでしたが、linq.tjsではより簡潔に複雑な処理を記述出来ます。

吉里吉里2/Zどちらでも使えます。

使用方法

  1. releaseページからSource codeをダウンロードします。
  2. linqフォルダに入っているlinq.tjs, linq_utility.tjs, linq__order.tjs, linq_generate.tjsを自分のプロジェクトフォルダに入れます。
  3. 最新のScriptsEx.dllをダウンロードして吉里吉里と同じフォルダに入れます。
  4. 以下のコードのようにlinq.tjsを読み込みます。
    Scripts.execStorage("linq.tjs");
    

使用例

例えば以下のように使えます。

Enumerable.range(1, 10)
    .where(function(x) { return x % 2 == 0;})
    .select(function(x) { return x * 2; })
    .forEach(function(x) { System.inform(x); });
// 4,8,12,16,20 が表示される

使い方はC#のLINQと全く同じです。簡単に説明すると次のように動作します。
1. Enumerable.range(1, 10)で1~10の整数を生成
2. .where(function(x) { return x % 2 == 0;}) で偶数のみ抽出
3. .select(function(x) { return x * 2; }) で抽出した偶数を2倍
4. .forEach(function(x) { System.inform(x); }); でダイアログを表示

文字列関数

function(x) { return ~; }が鬱陶しいのでlinq.jsを見習って文字列で指定できるようにしています。
“XXX => YYY”を”function(XXX) { return YYY; }”に変換するだけですが結構便利です。先の例は以下のようになります。

Enumerable.range(1, 10)
    .where("x => x % 2 == 0")
    .select("x => x * 2")
    .forEach("x => System.inform(x);");
// =>,4,8,12,16,20

さらに省略してYYY部分のみでも使えます。この場合は第1引数が_、第2引数が_2、第3引数が_3、…のようになります。つまり”function(_, _2, _3, _4, _5, _6, _7, _8, _9) { return YYY; }”に変換されます。

Enumerable.range(1, 10)
    .where("_ % 2 == 0")
    .select("_ * 2")
    .forEach("System.inform(_);");
// =>,4,8,12,16,20

引数の受け渡し

tjsにはjavascriptと異なりレキシカルスコープがありません。つまりfunctionの中で外にある変数が参照できずLINQを使う上で非常に不便です。なのでselectやwhereなどコールバックを引数にとる関数では、通常の引数の後ろに渡された引数をそのままコールバックに渡すようにしています。

以下の例ではargやcaptionとして引数を受け取っています。indexはここでは使っていませんが現在のインデックス番号です。

Enumerable.range(1, 10)
    .where("x, index, arg => x % arg == 0", 2)
    .select("x, index, arg => x * arg", 2)
    .forEach("x, index, caption => System.inform(x, caption);", "結果表示");
// =>,4,8,12,16,20

Enumerable.from

Enumerable.fromに配列、辞書配列、文字列を渡すとLINQが使えるようになります。

配列の場合はそれぞれの要素が順番に列挙されるだけです。また、toArray()を使うと列挙中のシーケンスを配列に変換できます。

var array = Enumerable.from([10, 20, 30])
    .select("x => x * x")
    .toArray();
// arrayは[100, 400, 900]になる

辞書の場合はkeyにキー、valueにその値が入った辞書配列として列挙されます。

Enumerable.from(%["hoge" => 100, "moge" => 200])
    .forEach(function(x) {
        System.inform(@"キー:${x.key}, 値:${x.value}");
    });
// "キー:hoge, 値:100"
// "キー:moge, 値:200"
// と表示される。

文字列の場合は先頭から1文字ずつ列挙されます。toString()でシーケンスを文字列に変換できます。

var str = Enumerable.from("StRinG")
    .where("_ == _.toUpperCase()") // 大文字のみ抽出
    .toString();
// strはSRGになる。

Enumerable.extendTo

LINQを頻繁に使う場合、Enumerable.fromを毎回呼び出すのは面倒です。今のところ配列限定ですが、一度Enumerable.extendTo(Array);を呼び出せば配列からselectなどの関数を直接呼び出せるようになります。

Enumerable.extendTo(Array);

var array = [1,2,3,4,5];
array = array.select("_ * 10").toArray();
// arrayは[10,20,30,40,50]になる

関数一覧

C#のLINQ to Objectsにある関数は全て移植済みです。その他にもInteractive Extensionsやlinq.jsなどから必要そうな関数を追加しています。

クエリ関数一覧

aggregate, aggregateWithSeed, all, any, average, buffer, concat, contains, count, defaultIfEmpty, distinct, do, elementAt, elementAtOrDefault, except, first, firstOrDefault, forEach, force, groupBy, groupJoin, indexOf, innerJoin, intersect, isEmpty, last, lastOrDefault, max, min, orderBy, orderByDescending, outerJoin, repeat, reverse, scan, scanWithSeed, select, selectMany, sequenceEqual, single, singleOrDefault, skip, skipWhile, startsWith, sum, take, takeWhile, thenBy, thenByDescending, toArray, toDictionary, toLookup, toString, trace, union, where, zip

生成関数一覧

Enumerable.from, Enumerable.empty, Enumerable.range, Enumerable.repeat, Enumerable.return, Enumerable.matches, Enumerable.random, Enumerable.randomInt, Enumerable.generate

Enumerable.matches

linq.tjs独自の関数としてEnumerable.matchesを追加しています。TJSではRegExpクラスで正規表現を使えますが癖があっていまいち使いづらいです。Enumerable.matchesでは正規表現のマッチ結果を扱えます。

Enumerable.matches(/([a-zA-Z]+)=([0-9]+)/g, "foo=100 bar=200")
    .forEach(function (matches) {
        System.inform(@"0:${matches[0]}, 1:${matches[1]}, 2:${matches[2]}");
    });
// "0:foo=100, 1:foo, 2:100"
// "0:bar=200, 1:bar, 2:200"
// が表示される

第1引数は使用する正規表現です。gフラグは必須です。第2引数は正規表現の対象となる文字列です。
このようにするとRegExp.matchesの結果が列挙されます。もう正規表現を使うのにfor文は必要ありません。

吉里吉里のバージョンを調べる

吉里吉里の質問をする時は使用している吉里吉里のバージョンを最初に伝えましょう。
単に吉里吉里といっても吉里吉里2安定版/吉里吉里2開発版と吉里吉里Zの各種バージョンで様々な違いがあります。
さらにKAG3/KAGEX2/KAGEX3などKAGのバージョンの違いがあります。
これらを書かない場合、バージョンを質問し返すのが面倒なためにスルーされる確率が上がります。

吉里吉里のバージョン

吉里吉里を起動してCtrl+F12を押すと以下のような画面が表示されます。
一番最初の行の「吉里吉里[きりきり] 2 実行コア version 2.31.2012.831 ( TJS version 2.4.28 )」が吉里吉里のバージョンになります。
自分の吉里吉里の同じ部分をコピーして送れば大体わかります。
krkr-version

KAGのバージョン

KAGのバージョンは簡単に調べる方法がありません。
しかし最後に更新されたのが5年前になるので普通は最新版だと思います。
KAGとだけ分かれば十分です。

KAGEXの場合は以下の3つのどこからダウンロードしたかでバージョンが変わります。
kag3ex3が最新版です。自分がどれを使っているかくらいは覚えておきましょう。
https://sv.kikyou.info/svn/kirikiri2/branches/kag3ex3/
https://sv.kikyou.info/svn/kirikiri2/branches/kag3ex2/
https://sv.kikyou.info/svn/kirikiri2/branches/kag3ex1/

吉里吉里でフォルダ/アーカイブの選択を省略する方法

吉里吉里を普通に起動すると以下のようなウィンドウが表示されます。
フォルダ/アーカイブの選択

ゲーム開発中は、この画面でプロジェクトフォルダを選択してOKをクリックしてゲームを起動します。
起動するたびに毎回選択するのは面倒です。
自動的にプロジェクトフォルダを選択する方法を紹介します。
2つあるので好きな方を使ってください。

方法1.フォルダ名をdataにする

プロジェクトフォルダをdataという名前にして、krkr.exeと同じ場所に置きます。
そうするとdataフォルダを自動的に選択してゲームを起動してくれます。

dataの代わりにcontent-dataという名前でも大丈夫です。
好きな方を使ってください。

方法2.コマンドライン引数を使う

フォルダの名前を変えずに「コマンドライン引数」でも設定できます。
実際に以下の手順でコマンド引数を指定できます。

1.krkr.exeを右クリックしてショートカットを作成します。

2.作成されたショートカットを右クリックしてプロパティを開きます。

3.ショートカットタブのリンク先の欄に、krkr.eXeの場所が書かれています。
その直後に半角スペースを付けて、さらに””で囲んだプロジェクトフォルダのパスを書き込みます。

下の画像の赤矢印の部分です。
ここでは”F:\project”フォルダをプロジェクトフォルダとして使っています。
shortcut-property

あとはOKをクリックして、設定したショートカットをダブルクリックすればゲームが起動します。

OBS Studio + Viqoでニコ生配信

ニコ生の放送環境をOBS StudioViqoに変更しました。
インストールなど結構面倒だったのでその方法をメモ。

OBS Studioを使うメリット

・Windows以外でも動く
Macでも配信できます。ただしこの記事ではWindows版を使っています。

・放送に使えるソフトが減る
OBS StudioとViqo(コメビュ)の連携が便利で5つから3つに減らせました。

元の環境
Open Broadcaster Software/OBSutil/FME Automator/やります!アンコちゃん/棒読みちゃん
 ↓
新しい環境
OBS Studio/Viqo/棒読みちゃん

・無料で使える
もちろん日本語にも対応してます。

OBS Studioのインストール

インストーラを公式ページのGet OBS Studioの下のWidnows 7/8//10からダウンロードしてインストール。

次にOBS Studioのニコ生用プラグインをダウンロードします。
githubのページからobs-rtmp-nicolive_2.0-win.7zをダウンロード。
7z形式で圧縮されているので解凍します。解凍方法
するとdataフォルダとobs-pluginsフォルダが入っているので、OBS Studioのインストール先の同じフォルダに上書きします。

上手くいけばOBS Studioの「設定」⇒「配信」⇒「配信種別」の部分にニコニコ生放送が追加されます。
下の画像の矢印の部分です。
OBS Studio setting
「ログインタイプ」をViqoの設定を読み込む、にしておくと次にインストールするViqoと連携できます。
OBS Studio上でのアカウント設定などが不要になります。
「映像ビットレートを自動調整」にチェックを入れると、映像ビットレートを放送時に自動的にニコ生の上限に設定してくれます。
音声ビットレートは調整されないので先に「出力」設定画面から設定しておきます。
「自動で配信開始と枠移動を行う」にチェックを入れると、Viqoで枠取りをしたときに自動的に映像配信を開始してくれます。

あとは「映像」設定画面で出力解像度を640×360にしておけば配信設定は完了です。

Viqoのインストール

ViqoはOBS Studioと連携できるコメントビューアです。
自動枠取りなどもできます。

まずはVisual Studio 2013 の Visual C++ 再頒布可能パッケージが必要なのでダウンロード+インストールします。

次にViqoをダウンロードします。
このページからViqo-2-3-3_windows_64_portable.zipをダウンロードします。
インストールは必要ないので解凍したファイルは適当な場所に置いておきます。

この段階で”viqo.exe”から起動できますが正常に動作しません。
OpenSSLをダウンロードする必要があります。

このページからopenssl-1.0.2g-x64_86-win64.zipがダウンロードできます。
解凍して”libeay32.dll”, “ssleay32.dll”, “openssl.exe”を”viqo.exe”と同じ場所に移動します。
これでviqoが動作するようになりました。

Viqoの設定

「編集」メニューの「設定」から設定画面が開けます。
Viqo account setting
MailとPassの部分にニコニコのIDとパスワードを入力、ログイン方法では「ブラウザを指定」を選択+普段使っているブラウザを選択します。
ここで「取得」ボタンをクリックして「正常にセッションが取得されました」と表示されればOKです。
ただしブラウザ側でニコニコにログインしている必要があります。

さらに「編集」メニューの「放送開始サーチ」から放送開始サーチ画面が開けます。
「有効にする」にチェックを入れて、「コミュニティ追加」で放送するコミュニティ番号を追加しておきます。

この状態では設定が保存されていません。
次に起動したときにまた設定し直しになってしまいます。
「ファイル」メニュー⇒「状態セーブ」⇒「デフォルト」をクリックすれば設定を保存できます。
これで次回起動時にも現在の設定が引き継がれるようになります。

Viqoと棒読みちゃんの設定

Viqoで取得したコメントを棒読みちゃんで読み上げできます。
Viqoの下の方にある「コマンド」タブを選択して「コメント受信時」にチェックを入れます。
さらに「”棒読みちゃんのパス\RemoteTalk\RemoteTalk.exe” /Talk %comment%」を入力します。
棒読みちゃんのパスというのは”BouyomiChan.exe”があるフォルダのパスになります。

設定したら状態セーブから設定を保存するのを忘れないようにしましょう。

放送時には棒読みちゃんは自分で起動する必要があります。

Viqoとコメジェネの設定

よく分からない。知ってる人がいたら教えてください。

放送開始

Viqoの「放送」メニューの「次枠設定」から枠設定画面が開けます。
この画面で放送タイトルやカテゴリなどの設定ができます。

あとは放送メニューの「今すぐ取得」をクリックすれば設定した枠が取得できます。
OBS Studioが起動されていればViqoと連携して自動的に配信が開始されます。

配信停止機能は無いようなのでニコ生の配信画面から停止してください。

吉里吉里LanczosフィルタをGPU化した

吉里吉里ZではLanczos2,Lanczos3による画像の拡大縮小ができるのですが枚数が多いと非常に時間がかかります。
なのでGPU上で動作するように書き換えて高速化しました。
krLanczosGPU.zip
ソースコード(github)

現在の最新バージョンの吉里吉里Z本体にはLanczos拡縮の機能が含まれていません。(コードはdev_lanczosブランチにありますがマージされていません)
このdllにはCPU版も同梱されているので単純にLanczosを使いたいだけの場合にも便利だと思います。

何も考えずにPhotoShop等でリサイズするよりかなり画質よくなるので出来るなら使った方がいいです。

速度的にはGTX770上でCPU版に比べて3~8倍速まで確認しています。
画像サイズが大きくなるほど差が広がっていくと思われます。
頑張ればもっと速くなりそうですが動作したので一区切り。
それよりpng保存で時間かかるのが何とかならんものか・・・・・・。

吉里吉里からC#を使うメモ

C++/CLIのdllを作ってそこからC#を呼ぶ。それだけ。ncbindも問題なく動作します。
サンプルコード

吉里吉里のウィンドウ(左上)とC#のウィンドウ(右下)の間でメッセージのやりとりができます。
krkr-cli-test

吉里吉里でもkwidgetsを利用するとUI含めて結構作れますが、本格的な物ならC#と.NETが使えると便利です。試してないですがVisualBasicやF#, IronPythonなども同じく使えると思います。

吉里吉里とC#のアプリを別々にするとプロセスが分かれて面倒くさかったのが色々解消される・・・・・・といいなあ。

RoslynのCode Analyzerを作ってみるメモ

Visual Studio 2015ではAnalyzeなるものを自作して独自のエラーや警告を出せます。Metro.cs #1でそんな話をしていたので試してみた。

参考資料

VS2015のRoslynでCode Analyzerを自作する(ついでにUnityコードも解析する)
新しいコンパイラー“Roslyn”を用いたプログラミングを体験!
Roslyn を使用した API 向けライブ コード アナライザーの作成
Roslyn アナライザーへのコード修正の追加
Working with Types in Your Analyzer

必要な情報探すのにかなり時間かかった。検索するとほとんど英語で出てきて大変。上4つは貴重な日本語情報でまとまっているので読むべき。

準備

Visual Studio 2015をインストールする。このとき共通ツールのVisual Studio拡張性ツールもインストール。
それと.NET Compiler Platform SDKもインストールする。

プロジェクトを作る

メニューの ファイル>新規作成>プロジェクト を開いて Visual C#>Extensibility>Analyzer with Code Fix を選んで新規作成する。
そうすると説明書(ReadMe.txt)とサンプル(DiagnosticAnalyzer.cs, CodeFixProvicer.cs)が入ったプロジェクトが自動作成される。

コードを書く

DiagnositcAnalyzer.csで問題箇所を見つけてエラーや警告を出す。CodeFixProvider.csではその修正案を作る。
詳しくは参考資料を参照。Syntax Visualizerとデバッグ実行のウォッチ式などを見ながら気合いで何とかするのがデフォっぽい。
今日は調べるだけで力尽きたので、とりあえず非ジェネリックのIEnumearbleを見つけたら警告を出すAnalyzerを書いた。

using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace ForbidIEnumerable
{
    [DiagnosticAnalyzer(LanguageNames.CSharp)]
    public class ForbidIEnumerableAnalyzer : DiagnosticAnalyzer
    {
        public const string DiagnosticId = "ForbidIEnumerable";

        private static readonly LocalizableString Title = "Forbit to use IEnumerable";
        private static readonly LocalizableString MessageFormat = "IEnumerable is forbidden. Please use IEnumerable<T>.";
        private static readonly LocalizableString Description = "IEnumerable error {0}";
        private const string Category = "Prohibition";

        private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);

        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        { get { return ImmutableArray.Create(Rule); } }

        public override void Initialize(AnalysisContext context)
        {
            context.RegisterSyntaxNodeAction(syntaxContext =>
            {
                var declarationSyntax = (VariableDeclarationSyntax)syntaxContext.Node;
                var typeInfo = syntaxContext.SemanticModel.GetTypeInfo(declarationSyntax.Type);
                if (typeInfo.ConvertedType.SpecialType == SpecialType.System_Collections_IEnumerable) {
                    syntaxContext.ReportDiagnostic(Diagnostic.Create(Rule, syntaxContext.Node.GetLocation()));
                }
            }, SyntaxKind.VariableDeclaration);
        }
    }
}

実行してみる

デバッグ実行するとアナライザを読み込んだVisualStudioが起動されるのでそれでテストできる。
完成したものを実際に使うには組み込むプロジェクトの「参照」を右クリックして「アナライザーの追加」からビルドされたdllを読み込む。

roslyn-code-analyzer
実行してみたところ。警告が出て何か変なことを教えてくれる。なぜか警告メッセージが二重で出ているが原因は不明。