トップページ > 過去ログ > 記事閲覧
ADV風の会話表示
名前:播磨宿 日時: 2008/12/13 13:32

初めまして、播磨宿という者です。 アドベンチャーゲームの様な会話のやり方について質問です。 【サウンドノベル風文字列描画基本】 これを基本にして会話を表示させているのですが、会話A.B.Cの様に複数の会話を用意し 会話A終了→二択→選択によって会話B or Cを表示 といった感じにしたいのです。 ですが、【サウンドノベル風文字列描画基本】のやり方を弄っているだけの私では、複数の会話を用意し、フラグによって表示する会話を入れ替えるといったやり方が分かりません。 もし良ければ、ソース等も交えて教えて貰えないでしょうか。

Page: 1 |

Re: ADV風の会話表示 ( No.1 )
名前:wakahage 日時:2008/12/13 16:15

機能とフラグを足してみました。 追加機能 機能:ラベル フラグ:*文字列 会話にインデックスを付けます。 String[]中に*〜 があっても表示しません 機能:選択 フラグ:S文字列1:文字列2:... 入力が1の場合文字、String[][]から文字列1を探します。 同じように入力が2の場合は文字列2のところに移ります。 機能:跳躍 フラグ:G "**"を以下から探して移ります。 フラグ:G*文字列 *文字列を最初からさがして移ります。 こんな感じです↓ char String[][ 256 ] = { "*START", "選んでください", "@ 1, Cがしゃべる 2, Bがしゃべる 3, 終わる@S*C1:*B1:*END", "*C1 Cです。@", "つぎは AがしゃべりますBG", "*B1 Bです。@", "次は AがしゃべりますBG", "ここは表示されません", "**", "@ Aです。@G*START", "*END おわりですBE" } ; そして switch 構文の中に以下を追加します。 case 'S': //選択 { char n,serch[10]={0};//検索文字列 int j; re:; n=input(); //入力 if(n<=0) goto re; //再入力 j=CP+1; for(int i=1;i<n;++i) { for(1;String[SP][j]!=':';++j)if( String[SP][j]=='\0')goto re; //再入力 ++j; } for(int i=j;String[SP][i]!='\0' && String[SP][i]!=':';++i) serch[i-j]=String[SP][i]; for(int i=SP+1;i<sizeof(String)/sizeof(*String);++i) if(strstr(String[i],serch)==String[i]) SP=i,CP=strlen(serch); } break; case 'G': //跳躍 { char serch[10]="**"; //基本は "**"を検索 if(String[ SP ][ CP+1 ]=='*') { //もしGの後が*だったら、うしろの文字列を最初から検索します。 for (int i=CP+1;String[SP][i]!='\0';++i) serch[i-CP-1]=String[SP][i]; SP=0; //最初から } for(int i=SP;i<sizeof(String)/sizeof(*String);++i) if(strstr(String[i],serch)==String[i]) SP=i,CP=strlen(serch); } break; case '*': //*があったらスペースか最後まで飛ばす { while(String[SP][CP]!=' ' && String[SP][CP]!='\0') ++CP; } break; 最後に入力用の関数です char input() { // テンポラリグラフィックの作成 int TempGraph = MakeGraph( 640 , 480 ) ; // 画面の内容を丸々コピーする GetDrawScreenGraph( 0 , 0 , 640 , 480 , TempGraph ) ; int n=KeyInputNumber(DrawPointX *MOJI_SIZE,DrawPointY *MOJI_SIZE,127,1,0); DrawGraph(0,0, TempGraph,0); // グラフィックを削除する DeleteGraph( TempGraph ) ; return n; } 長くなってしまいましたが、要らない機能があれば削除してください。 以上はあくまでも参考ですので、イメージと違うかもしれません。 解説ですが、 まず、選択フラグSを検知したら入力関数を呼びます。 入力すると画面に数値が描画されてしまうので改行の要領で処理します。 入力値に応じてSの後ろの : で区切られた検索文字列を取得します。0以下の場合は再入力してもらいます。 上の例で もし4以上だと '\0' を超えてしまったので再入力してもらいます。 検索文字列が取得できたら以下から最後までのString[]から検索文字列が頭にくる行に SP を設定します。 次に G ですが、これは選択によって分かれた会話を一つに戻すためにあります。 上の例だと 1を入力した後 Cがしゃべり、終わったら、次の行に行かずに"**"に飛ぶようになっています。 先の S の要領で飛ばしています。 G*START は Gのすぐ後ろが'*' なのでStringの最初から "*START"を検索します。 もしヒットしない場合無限ループが生まれます。 又 "*START" のように最初が '*' の場合は会話で無いので表示しないようにしています。
Re: ADV風の会話表示 ( No.2 )
名前:播磨宿 日時:2008/12/13 20:37

wakahageさん、丁寧に有難うございます。 ↑の「G」「G*」「*」の様な機能はとても有難いです。 ただ「S」についてなのですが、こちらの説明が足りていなかった事に気付きました。 私が述べた「二択」なのですが、これは「あるフラグAがたっている時に会話Aを表示し、あるフラグBが立っている時に会話Bを表示する」 というのを略した訳ですが、実際に組んでいるプログラムでは 「会話Aが終わると(フラグA→Bへ)⇒会話終了⇒(ゲーム本編)⇒会話発生。会話Aが終わっているので次に会話B開始」 この様な感じとなっているのです。 「S」の機能を「入力=フラグ」にすればよいと思うのですが、ゲーム本編を間に挟む際。どうすれば良いのか分かりませんでした。 もし、良ければこちらも教えて貰えないでしょうか?
Re: ADV風の会話表示 ( No.3 )
名前:wakahage 日時:2008/12/14 02:39

そういうフラグでしたか。早とちりしてすみません では「入力=フラグ」のとおり入力関数を、フラグ変数にしてみてはいかがでしょうか。 /*グローバル変数*/ char flag[10]={1}; //この値はゲーム本編中で変える /*switch 内*/ case 'F': //フラグによる場合分け { char n,serch[10]={0}; n=flag[String[SP][CP+1]-'A']; //入力関数ではなくフラグをそのまま代入 if(n<=0) {MessageBox(0,"フラグの値がおかしいです",0,0);return -1;} int j=CP+2; for(int i=1;i<n;++i) { for(1;String[SP][j]!=':';++j)if( String[SP][j]=='\0') {MessageBox(0,"フラグの値がおかしいです",0,0);return -1;} ++j; } for(int i=j;String[SP][i]!='\0' && String[SP][i]!=':';++i) serch[i-j]=String[SP][i]; for(int i=SP+1;i<sizeof(String)/sizeof(*String);++i) if(strstr(String[i],serch)==String[i]) SP=i,CP=strlen(serch); } break; 機能としては Fアルファベット文字列1:文字列2:... フラグが一個だけだと足りないので、上の例だとFA〜FJまでの10フラグ設定可。 すると、こんな感じになります。 char *String[]={ "以上会話AでしたBE", /*ここでゲーム本編を間に挟むのですね?*/ //flag[0]がゲーム中で1か2に設定される "@FA*B:*C", "*B会話BをはじめますB", "@・・・", "@・・・G", "*C会話Cを始めますB", "@・・・", "@・・・G", "**おわりですBE" } これはFAしか使っていませんがFB,FC..と複雑に分けることもできます。
Re: ADV風の会話表示 ( No.4 )
名前:播磨宿 日時:2008/12/14 14:50

早い返答有難うございます。 「F」の機能を使うことで、今まで複雑かつ雑だった処理がスッキリしました。 フラグの立て方は色々と試行錯誤していたので本当に助かりました。 お陰様で微調整は必要ながら、大枠を完成させる目処が立ちました。 色々と教えてくださって有難うございました。

Page: 1 |