ページ 1 / 1
既読文 判定
Posted: 2010年5月04日(火) 04:20
by Ma
ふと思ったので質問です。
昔作っていたノベルゲームで開発時間の都合上、既読文書のスキップ機能を諦めました。
もし、ビジュアルノベルゲームを作っているとして、既読文書かどうかの判定を作るとしたら、どのように実装しますか?
(今何か開発しているわけではありません。)
【条件】
・既読の判定は一ページごと。
・ノベルシステム部分(システム上の文章の記録方法/読み込み方法)は、制限されていません。
【オプション】(この項目はできればです)
シナリオ情報が途中で修正されたり追加されたりしても誤作動がなかったら理想的ですよね。
-つまり、既読文の間に未読文が追加されても対応できそうなような仕様。
アイディアだけでOKです。
私なら、各ページにIDとフラグを与えますが、ちょっと非効率な気もします。
(IDはシナリオを作るソフトが被らないように自動生成。)
*一応
もしプログラムをお書き込みになる場合、C++ か java だと助かります。

Re:既読文 判定
Posted: 2010年5月04日(火) 10:31
by lbfuvab
セーブデータに含めて管理します(しました)
昔需要も無いのにノベルゲ用のプログラムを作っていた時はそうしました。
Re:既読文 判定
Posted: 2010年5月04日(火) 11:34
by softya
シナリオですから何らかの分岐点はありますよね。
条件文の分岐点のIDで管理するってのはどうでしょうか?
ただし、IDの自動付与は
>シナリオ情報が途中で修正されたり追加されたりしても誤作動がなかったら理想的ですよね。
の条件に反するので無理そうな気がします。
Re:既読文 判定
Posted: 2010年5月04日(火) 12:04
by Ma
> lbfuvab さん
>セーブデータに含めて管理します(しました) >セーブデータに含めて管理します(しました)
すいません。もちろん、そうなると思うのでですが、どのように・・・というところがお聞きしたいです。
> softya さん
>条件文の分岐点のIDで管理するってのはどうでしょうか?
分岐点だけを記録するのでは、分岐後、どれだけ読んだかがわからないですよね。
となると、通り過ぎた条件分の分岐点IDのすべてと、枝分かれの可能性の数だけ合わせた分岐点後のどこまでかって情報を記録するということになりますかね?
たとえば、簡単な3つ枝の分岐点が一つで、終着点が3点だとしたら、その分岐を通ったかどうか、
その後の枝3つそれぞれに、何ページ読んだかどうかの記録。
でも、この方法、途中でページが増えたら対応できないです。。。
>ただし、IDの自動付与は
>>シナリオ情報が途中で修正されたり追加されたりしても誤作動がなかったら理想的ですよね。
>の条件に反するので無理そうな気がします。
毎ページ、必ず異なるIDを、そしてすでに与えたIDは被らないようにIDを与えるようにする、
という仕様にすれば途中でシナリオに変更があっても誤作動が起きないような気がします。
ただ、1ページ、1ページに、シナリオ情報にIDを付加したら、セーブデータは、
すでに読んだページのID一覧を記録。
もちろん、IDはすべて順序にそっていて、分岐点があるなら分岐ごとのIDにセクションわけするとか。
・例
[(ID名)]
(ページID)-(フラグ)
(ページID)-(フラグ)
(ページID)-(フラグ)
・具体例
[共通シナリオ/イントロ]
00001-1
00002-1
00003-1
00005-1
[ルートA]
00007-1
[ルートB]
00009-1
00010-0
[ルートC]
00013-0
ただ、毎回読みこまないといけないので、章ごとにファイルを別々にしたほうがよさそうです。
問題点は見てもわかるように、かなり無駄が出そうなところです。

Re:既読文 判定
Posted: 2010年5月04日(火) 12:12
by softya
素朴なギモンなんですが、読んでいる途中で中断した場合も保存するって方向でしょうか?そうすると読み進んだら自動セーブ、あるいは中断時はセーブして終わると言った感じでしょうか。分岐点まで読んだかどうかの保存で十分な気がしますが。
Re:既読文 判定
Posted: 2010年5月04日(火) 12:15
by Justy
> すでに読んだページのID一覧を記録
ゲーム中に存在するページ IDが連番に(表示順は問わない)なっていれば
セーブデータとしては読んだかどうかは1ページあたり 1bitあれば管理できると思います。
10000ページあっても 1.2KBちょっとです。
Re:既読文 判定
Posted: 2010年5月04日(火) 12:32
by Ma
>読んでいる途中で中断した場合も保存するって方向でしょうか?そうすると読み進んだら自動セーブ、あるいは中断時はセーブして終わると言った感じでしょうか。
はい、そのとおりです。
言葉足らずだったようですいません。
>分岐点まで読んだかどうかの保存で十分な気がしますが。
たしかにアマチュアが作るゲームならシナリオはそんな長くないし、セーブ機能があれば十分なのですが、
企業のを見ると、既読文に上手く対応しているので、それを真似る知識があるといいかな、って思ったのです。
>Justy さん
>ゲーム中に存在するページ IDが連番に(表示順は問わない)なっていれば
そうですよね、私も最初はビット単位で記録しようと思いました。
それに、シナリオ修正にも対応できそうだし。
ただ、それだと分岐点の処理が難しそうだと思いました。
というのは、ビットごとだと途中で分岐IDをいれるのも困難だと思ったからです。
何かいい案がありますか?
*訂正
いや、分岐も何も関係なく、分岐IDを含めてシナリオを直線にすれば(シナリオは分岐してもその情報は分岐しないなら)いいのか。
あとは、シナリオが毎回更新されるたびに、途中でビットを加えるかどうかの処理をすればいいだけですからね。

Re:既読文 判定
Posted: 2010年5月04日(火) 12:41
by Justy
> ビットごとだと途中で分岐IDをいれるのも
既読ページフラグとは別に持ってはどうでしょう。
分岐毎にユニーク且つ連番な分岐 IDを割り振って、分岐選択済みフラグとして
既読ページフラグとおなじような感じでセーブデータに保存すればいいのでは、と。
Re:既読文 判定
Posted: 2010年5月04日(火) 12:48
by softya
私なら一行毎に自動ID付与するツールを作るでしょうね。そのIDで読んだかどうか管理。
シナリオを修正する度にツールを通過させて追加変更された部分に新しいIDを付与。
この場合はシナリオの並びとID番号の順番は一致しない。
まぁ、セーブサイズはビットにするほど気にしなくて良いのでは?
デバッグが面倒なだけだと思いますが。
Re:既読文 判定
Posted: 2010年5月04日(火) 13:04
by Ma
なるほど。
Justy さんの方針もいいと思いました。
この方法は、自分が勝手に困難だと思い込んでいたようです。
具体的には、シナリオ情報が以下のようになっていたとすると。。。
(//はコメントとします。#はスクリプト的目的です。[/url]は分岐処理です。)
#sceario 000
「共通シナリオです。あああああああああ」//0ビット目
「きょうつう(ryいいいいいいいいいい」//1ビット目
[分岐001:(選択肢1),(選択肢2)]//(選択肢:0ビット目/1ビット目)
[選択肢1]
「ああああああああああああああ」//2ビット目
#jumpTo 001
[end]
[選択肢2]
「いいいいいいいいいいいいいい」//3ビット目
[end]
「選択肢が終わりました。」//4ビット目
#scenario 001
「分岐で選択肢1を選んだ場合発生するシナリオです。」//5ビット目
(即興で考えたシナリオ情報ファイルの仕様です。)
のようになっていたとしたら、
6ビットで既読文を読んだかどうかを保存。
2ビットで、選択肢用の別ファイルに選んだかどうかを保存。
途中でシナリオが更新される場合は、前シナリオファイルと比較して足りないビットを付け足す感じです。
残る問題点は、修正のレベルによりますがシナリオ修正後に的確な場所にビットを付け足したり消去する処理が難しそうですね…。
これについては、シナリオ編集用のソフトを自前で作成して、ひとつひとつ修正するたびにどこのビット位置にどのようにビットの修正を行うのか記録するのが理想的と思いました。
(というのは、パッチみたいなことができるのを考えてです。)
あー、でもいろいろミスが起きて大変なことになりそうですね…。
これについて、なにか言及はないでしょうか?
>softyaさん。
やはり、そこに落ち着きそうですかね。
ビット単位での記録について考えていたら、おっしゃるとおりデバッグが難しい事になりそうな気がしてきました。
ID記録方針やっぱりいいのかな。

Re:既読文 判定
Posted: 2010年5月04日(火) 13:48
by Justy
>6ビットで既読文を読んだかどうかを
~
>足りないビットを付け足す感じです
このあたりは、ビット毎に用途が分かれていたり、選択肢用の別ファイルとか
ちょっと意味がわからなかったんですけど……。
>ビット位置にどのようにビットの修正を行うのか記録するのが理想的と思いました
どのビットというか、理想はページIDから……ID 10だったら、オフセット 1バイト 2ビット目とか
計算で求めるのがいいでしょうね。
>でもいろいろミスが起きて大変なことになりそうですね
しっかりとしたツールを作ればそういうこともないように思うんですけど、
どういうミスを想定されていますか?
>ビット
>ID記録方針やっぱりいいのかな
既読フラグをビットにしただけでいうほどデバッグが難しくなるとは
思えないのですが、特にビットである必要はないのでそのあたりは環境とお好みで。
結局のところその環境で動けばいいので、ID記録の方がやりやすいのであれば
それで問題ないとは思います。
Re:既読文 判定
Posted: 2010年5月04日(火) 14:57
by Ma
> どのビットというか、理想はページIDから……ID 10だったら、オフセット 1バイト 2ビット目とか
>計算で求めるのがいいでしょうね。
なるほど、そういうことでしたか。
誤解していました。すいません。
それなら、↑のよくわからないと言っていたのは、気にしないでください。
私の早とちりとかってな想像でしたw
>どういうミスを想定されていますか?
ビットがずれたり、とかって考えてましたが、私が誤解していたようなので、解決しました。
たしかに、ID割り振って、保存するときは、IDのビットに行けばいいというわけですね。
すごく効率的に思えてきました。
あとは、IDがかぶらなければOKですね。
この方法が最善だと思います、ありがとうございました。
主目的が達成できたので解決にします。
ところで、ビット単位の計算って、char型配列が一般的でしょうか?
char配列だったとして、何百何十何ビット目のフラグをオンにする場合、
int flag = 1;
flag = flag << (ビット数%8);
char[ビット数/8] = char[ビット数/8] | flag;
↓//だから
char[ビット数/8] = char[ビット数/8] | (1 << (ビット数%8));
↓
char[ビット数/8] |= (1 << (ビット数%8));
こんな感じでいいんでしょうか?
(ビット数は0から始まります。)
間違いがあればご指摘よろしくお願いします。

Re:既読文 判定
Posted: 2010年5月04日(火) 15:29
by Justy
>char型配列
unsigned char型で。
エンディアンの問題がないなら unsigned intでも。
あとはリリースまでにきっちりと将来必要なフラグの数が決められるなら配列でいいですし、
そうでないなら vectorなどの可変長で(その場合セーブデータには要素数も書き込む)。
>計算
それで問題ないです。
ただ 8という定数は CHAR_BITを使った方がよりいいですね。
Re:既読文 判定
Posted: 2010年5月05日(水) 01:15
by Ma
なるほど、よくわかりました。vector もよさそうですね。
次の機会があった時はこの方針にしてみます。
ありがとうございました。