トップページ > 記事閲覧
サンプル
名前:にこよん 日時: 2018/02/11 00:53

Dxライブラリのサンプルコードについて 以下のサウンドノベル風ゲームのサンプルコードですが、 ttp://dxlib.o.oo7.jp/dxprogram.html#N20 半角文字を奇数打ち込むと表示がおかしくなってしまいます 他のゲームでも利用できるように改変したものになりますが、どのようにすれば半角文字も使えるようになるでしょうか? 改変内容は、複数の文字列を同時に扱えるようにクラスにまとめたのと、フォント付き文字で使えるようにしたのと 文字を開業するまでの幅を指定できるようにしたのと 改行文字(@)で改行できるので元の文章を複数の行の配列に分ける必要がないと思い、 複数行の文章を読み込めず、一行の文章しか読み込めなくしたぐらいです 描画速度は速いまま保ちたいのですができれば好きな速さに変更できるようにしたいと思っています // サウンドノベル風文字列描画、テキストバッファ使用バージョン #include "DxLib.h" #include <math.h> class Novel { private: //仮想テキストバッファの横サイズ縦サイズの最大値 #define STRBUF_WIDTH_MAX 50 #define STRBUF_HEIGHT_MAX 20 char OneMojiBuf[3]; // 1文字分一時記憶配列 char StringBuf[STRBUF_HEIGHT_MAX][STRBUF_WIDTH_MAX * 2 + 1] = {0}; //仮想テキストバッファ int CursorX = 0, CursorY = 0; //仮想画面上での文字表示カーソルの位置 int CP = 0; //参照する文字列番号と文字列中の文字ポインタ int EndFlag = 0; //終了フラグ int KeyWaitFlag = 0; //ボタン押し待ちフラグ int font_h; //描画するフォントのハンドル int x_max; //描画できる文字列の長さ(x) char String[1024]; void kaigyou() { CursorY++; //描画行位置を一つ下げる CursorX = 0; //描画列を最初に戻す if (CursorY >= STRBUF_HEIGHT_MAX) { //もしテキストバッファ縦幅からはみ出るならテキストバッファを縦スクロールさせる for (int i = 1; i < STRBUF_HEIGHT_MAX; i++) { for (int j = 0; j < STRBUF_WIDTH_MAX * 2; j++) { StringBuf[i - 1][j] = StringBuf[i][j]; } } CursorY--; // 描画行位置を一つあげる } } public: Novel(int X_max, int Font, const char string[]) { x_max = X_max; //フォントのサイズセット font_h = Font; strcpy_s(String, string); } void Calc() { //サウンドノベル風文字列描画処理を行う //ただし終了フラグが1だった場合は処理をしない if (EndFlag == 0){ char Moji; //ボタン押し待ちフラグがたっていた場合はボタンが押されるまでここで終了 if (KeyWaitFlag == 1){ if (CheckHitKeyAll() != 0){ KeyWaitFlag = 0; //ボタンが押されていたら解除 } else return; } else { //文字の描画 Moji = String[CP]; switch (Moji){ case '@': //改行文字 kaigyou();//改行処理および参照文字位置を一つ進める CP++; break; case 'B': //ボタン押し待ち文字 while (ProcessMessage() == 0 && CheckHitKeyAll() != 0) {}//ボタンが離されるまで待つ //ボタン押し待ちフラグをたてる KeyWaitFlag = 1; CP++; break; case 'E': //終了文字 EndFlag = 1; //終了フラグを立てるおよび参照文字位置を一つ進める CP++; break; case 'C': //クリア文字 for (int i = 0; i < STRBUF_HEIGHT_MAX; i++){//仮想テキストバッファを初期化して描画文字位置を初期位置に戻すおよび参照文字位置を一つ進める for (int j = 0; j < STRBUF_WIDTH_MAX * 2; j++){ StringBuf[i][j] = 0; } } CursorY = 0; CursorX = 0; CP++; break; default: //その他の文字 //1文字分抜き出す OneMojiBuf[0] = String[CP]; OneMojiBuf[1] = String[CP + 1]; OneMojiBuf[2] = '\0'; //1文字テキストバッファに代入 StringBuf[CursorY][CursorX * 2] = OneMojiBuf[0]; StringBuf[CursorY][CursorX * 2 + 1] = OneMojiBuf[1]; //参照文字位置を2バイト進める CP += 2; //カーソルを一文字文進める CursorX++; //テキストバッファ横幅からはみ出たら改行する if (GetDrawStringWidthToHandle(StringBuf[CursorY], strlen(StringBuf[CursorY]), font_h) >= x_max) kaigyou(); break; } //参照文字列の終端まで行っていたら参照文字列を進める if (String[CP] == '\0'){ CP = 0; EndFlag = 1; } } } } void Draw(int x, int y, int color) { //テキストバッファの描画 for (int i = 0; i < STRBUF_HEIGHT_MAX; i++) { DrawStringToHandle(x, i * GetFontSizeToHandle(font_h) + y, StringBuf[i], color, font_h); } } }; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ ChangeWindowMode(TRUE); SetGraphMode(640, 480, 16); if (DxLib_Init() == -1) //DXライブラリ初期化処理 return -1; //エラーが起きたら直ちに終了 //描画先を裏画面にセット SetDrawScreen(DX_SCREEN_BACK); Novel novel(630, CreateFontToHandle(NULL, 26, 3, DX_FONTTYPE_ANTIALIASING_EDGE_8X8), "これは元のDXライブラリ公式サイトのサンプルプログラムを様々なゲームで利用しやすいように\ 描画する位置、Bフォント、B色、B改行するまでの横幅などを指定できるようにしたものです。B@\ ただし文字が表示されていくスピードは変更できませんし、いくつかバグが存在します。E"); //ループ while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0){ novel.Calc(); ClearDrawScreen(); //画面のクリア DrawBox(0, 0, 640, 480, GetColor(0, 100, 0), TRUE); //背景エフェクトの描画 novel.Draw(0, 100, GetColor(255, 255, 255)); ScreenFlip(); //裏画面の内容を表画面に反映させる } DxLib_End(); //DXライブラリ使用の終了処理 return 0; //ソフトの終了 } あと、上のコードでビルドしたらわかるのですが一部の文字が描画する時におかしくなったり Bや@などのコードが正常に読み込まれずにそのまま描画されたりするのですが、これも半角文字の問題を修正すれば治ると思っています ただ直し方が分からないのでご教授願います
メンテ

Page: 1 |

Re: サンプル ( No.1 )
名前:にこよん 日時:2018/02/10 22:18

あとコメントの進めるのはずの場所が // 参照文字位置を2バイト勧める になってますよ
メンテ
Re: サンプル ( No.2 )
名前:管理人 日時:2018/02/11 01:54

> 他のゲームでも利用できるように改変したものになりますが、どのようにすれば半角文字も使えるようになるでしょうか? 『20.サウンドノベル風文字列描画、テキストバッファ使用バージョン』は、表示する文字は必ず全角文字であることを 前提としていますので、幾つかの箇所を変更する必要があります 『30.サウンドノベル風文字列描画、半角文字対応+テキストバッファ使用バージョン』を追加しましたので、よろしければご覧ください m(_ _)m <30.サウンドノベル風文字列描画、半角文字対応+テキストバッファ使用バージョン> http://dxlib.o.oo7.jp/dxprogram.html#N30 > あとコメントの進めるのはずの場所が >  > // 参照文字位置を2バイト勧める >  > になってますよ ご指摘ありがとうございます、修正しました
メンテ
Re: サンプル ( No.3 )
名前:にこよん 日時:2018/02/11 12:48

>『30.サウンドノベル風文字列描画、半角文字対応+テキストバッファ使用バージョン』を追加しましたので、よろしければご覧ください m(_ _)m 追加ありがとうございました ただURLをクリックしてもそのような記事は見つかりませんでした ↓↓ 時間のせいだったのでしょうか? 昨日の夜はなかったのですが、今日の昼頃にはつながるようになってましたm(__)m #30が2つあるのは仕様でしょうか? #32か#20 - 2 にしたほうがよさそうな気もします
メンテ
Re: サンプル ( No.4 )
名前:にこよん 日時:2018/02/11 15:44

#30を参考にプログラムを修正したところ無事動くようになりました ありがとうございました ただ、以下の関数を読んだ時にメモリ侵害が起きてしまいます。 GetDrawStringWidthToHandle(StringBuf[CursorY], strlen(StringBuf[CursorY]), font_h) 使い方が悪いのでしょうか? ただ、もう一つ引数を指定できそうだったので GetDrawStringWidthToHandle(StringBuf[CursorY], strlen(StringBuf[CursorY]), font_h, TRUE) とかにしてみたらちゃんと動きました 最後の引数の意味も教えていだだけると嬉しいですm(__)m
メンテ
Re: サンプル ( No.5 )
名前:管理人 日時:2018/02/12 00:11

> ただURLをクリックしてもそのような記事は見つかりませんでした > ↓↓ > 時間のせいだったのでしょうか? 原因は分かりませんが、確かにご返信時点でサーバーにファイルはアップしていましたので、 そうかもしれません > #30が2つあるのは仕様でしょうか? > #32か#20 - 2 にしたほうがよさそうな気もします ご指摘ありがとうございます、凡ミスをしてしまいました orz 後続の項目の番号を全部書き換えるとミスが起こりそうだったので一番下に追加していましたが ご提案の通り『20−2』に変更しました http://dxlib.o.oo7.jp/dxprogram.html#N20_2 > GetDrawStringWidthToHandle(StringBuf[CursorY], strlen(StringBuf[CursorY]), font_h) > 使い方が悪いのでしょうか? エラー発生時の strlen(StringBuf[CursorY]) の戻り値はどのような値になっていますでしょうか? 推測ですが、にこよんさんは元のプログラムを変更して 『「文字数が STRBUF_WIDTH_MAX を超えたら改行」ではなく、GetDrawStringWidthToHandle の戻り値が 規定以上の大きさになったら改行する』 という処理をされているので、StringBuf の1行分の配列サイズである STRBUF_WIDTH_MAX を超えて 文字データを StringBuf に書き込んでしまっている可能性があります 仮にそれが原因の場合、STRBUF_WIDTH_MAX の値を大きくすることでこの問題は発生しなくなりますので、 よろしければ STRBUF_WIDTH_MAX の値を大きくしてみてください > ただ、もう一つ引数を指定できそうだったので > GetDrawStringWidthToHandle(StringBuf[CursorY], strlen(StringBuf[CursorY]), font_h, TRUE) > とかにしてみたらちゃんと動きました > 最後の引数の意味も教えていだだけると嬉しいですm(__)m 通常が DrawStringToHandle の描画横幅を取得する機能であるのに対して、第4引数を TRUE にすると DrawVStringToHandle の描画縦幅を取得する機能となります メモリの不正なアクセスを防いだりするための引数ではないので、なぜこの引数を TRUE にすると エラーが発生しなくなるのかはわかりません ( 改良後のソースを拝見させていただければ原因が分かるかもしれません )
メンテ
Re: サンプル ( No.6 )
名前:にこよん 日時:2018/02/12 01:03

> 『「文字数が STRBUF_WIDTH_MAX を超えたら改行」ではなく、GetDrawStringWidthToHandle の戻り値が > 規定以上の大きさになったら改行する』 おっしゃる通りです > という処理をされているので、StringBuf の1行分の配列サイズである STRBUF_WIDTH_MAX を超えて > 文字データを StringBuf に書き込んでしまっている可能性があります > 仮にそれが原因の場合、STRBUF_WIDTH_MAX の値を大きくすることでこの問題は発生しなくなりますので、 > よろしければ STRBUF_WIDTH_MAX の値を大きくしてみてください その危険性は十分理解していたつもりなので 200 と、もとよりだいぶ大きな数を指定しておりました 1行で3,40文字程度しか描画していないのでその可能性はないと思われます そもそもエラーが発生するのは1文字目も描画できてない最初の時です(説明不足ですみません) デバッグで確認したところちょうどGetDrawStringWidthToHandle(StringBuf[CursorY], strlen(StringBuf[CursorY]), font_h) を読んだ時に(1行前までは動いててこの関数の次の行に来る前にERROR)止まってるようでした > DrawVStringToHandle の描画縦幅を取得する機能となります そのような機能だったのですね! TRUEにしても問題ない長さが返ってきたので何が変わってるのかなと、 だから割と正常に動いていたのですか...(TRUE時) > エラー発生時の strlen(StringBuf[CursorY]) の戻り値はどのような値になっていますでしょうか? int型で確認していいのかどうかはわかりませんがint型で取得してみると 1 でした
メンテ
Re: サンプル ( No.7 )
名前:にこよん 日時:2018/02/12 01:15

strlen(StringBuf[CursorY]) の戻り値を調べているときに分かったのですがエラーが発生していた時、 Font_hが 0 でした 原因はフォントの生成失敗でDXライブラリから 0 が返ってきたのをそのまま渡していたことでした 推測ですがGetDrawStringWidthToHandleの引数のフォントハンドルが0だった場合、 最後の引数がFALSEの時の処理はでは特に対策しておらず 最後の引数がTRUEの時の処理にはフォントハンドルがなかった場合のエラー処理(既定のフォントで計算する処理)があった みたいな事が原因でしょうか? それならフォントの生成部分を修正すればいいだけなのですが...
メンテ
Re: サンプル ( No.8 )
名前:管理人 日時:2018/02/13 00:45

> strlen(StringBuf[CursorY]) の戻り値を調べているときに分かったのですがエラーが発生していた時、 > Font_hが 0 でした > 原因はフォントの生成失敗でDXライブラリから 0 が返ってきたのをそのまま渡していたことでした 調べていただきありがとうございます すみません、GetDrawStringWidthToHandle に無効なフォントハンドルが渡された場合にメモリの不正なアクセスが 発生してしまうバグがありました、これがエラーになる原因だと思います 修正版をアップしましたので、よろしければお試しください m(_ _;m http://dxlib.o.oo7.jp/temp/DxLibVCTest.exe // Windows版 VisualC++ 用 http://dxlib.o.oo7.jp/temp/DxLibBCCTest.exe // Windows版 BorlandC++ 用 http://dxlib.o.oo7.jp/temp/DxLibBCC2Test.exe // Windows版 C++ Builder 10.1 Berlin 用 http://dxlib.o.oo7.jp/temp/DxLibGCC_MinGWTest.exe // Windows版 MinGW 用 http://dxlib.o.oo7.jp/temp/DxLibDotNet.zip // Windows版 .NET用 http://dxlib.o.oo7.jp/temp/DxLibAndroidTest_ARM.exe // Android版 ARM用 http://dxlib.o.oo7.jp/temp/DxLibAndroidTest_x86.exe // Android版 x86用 http://dxlib.o.oo7.jp/temp/DxLibMakeTest.exe // ソース ( 中身を既存のライブラリのファイルに上書きして、VisualStudioをお使いの場合は『リビルド』を、  BCCをお使いの場合は『再構築』をして下さい ) > 推測ですがGetDrawStringWidthToHandleの引数のフォントハンドルが0だった場合、 > 最後の引数がFALSEの時の処理はでは特に対策しておらず > 最後の引数がTRUEの時の処理にはフォントハンドルがなかった場合のエラー処理(既定のフォントで計算する処理)があった > みたいな事が原因でしょうか? いえ、最後の引数が TRUE でも FALSE でも今回修正したメモリの不正なアクセスの箇所は実行され、且つエラー判定によって 最後の引数が使用される前に関数から抜けるので、最後の引数が TRUE のときにエラーが発生しなかったのは、やはりたまたまだと思います ( メモリの不正なアクセスの場合、アクセスするアドレスによってはエラーにならなかったりするので、たまたま最後の引数が TRUE のときはアクセスする位置が少しずれてエラーにならなかったのだと思います )
メンテ
Re: サンプル ( No.9 )
名前:にこよん 日時:2018/02/13 23:22

修正ありがとうございます 平日は試せそうにないので終末に試してみようと思います
メンテ
Re: サンプル ( No.10 )
名前:にこよん (解決) 日時:2018/02/23 14:26

特に問題が発生することはなくなってました ありがとうございましたm(__)m
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存