サンプルプログラムにて
サンプルプログラムにて
サンプルプログラムのサウンドノベル風文字列描画、テキストバッファ使用バージョンが
自分には難解です。
こんな初歩的なところでつまずいている自分のために
改行の他にmainで読み込んだ文字列を別の関数で表示などといった
ユーザ関数を多用した同じことができるプログラムが欲しいです。
どなたか作ってください!
お願いします!お願いします!
自分には難解です。
こんな初歩的なところでつまずいている自分のために
改行の他にmainで読み込んだ文字列を別の関数で表示などといった
ユーザ関数を多用した同じことができるプログラムが欲しいです。
どなたか作ってください!
お願いします!お願いします!
Re:サンプルプログラムにて
>どなたか作ってください!
いやいや、誰かに作ってもらってたんじゃ夏天さんのスキルが上がりませんよ^^
少しずつ作ってみませんか?
まず、半角が無いテキストデータだとして考えましょう。
char txt[128]="今日からサウンドノベル風文字列表示の勉強をします";
これを時間差で表示させて見ます。
まず、時間差で表示させるには、
1、1文字格納、表示
2、2文字格納、表示
3、3文字格納、表示
これを延々と繰り返せばいいですね。
また繰り返すまでの区間は、配列に\0が見つかるまでです。
txt2というもともとの配列のほかにtxt2という描画用の配列を用意します。
txt2にtxtから必要な分だけコピーして、常にtxt2を表示するようにしてみます。
まず、
txt[0],txt[1]をtxt2[0],txt[1]にコピーし、txt2[2]に\0を格納します。
つまり
txt2[0] = txt[0];
txt2[1] = txt[1];
txt2[2]='\0';
こういうことです。
すると%sでtxt2を表示させれば「今」が表示できますね。
どうように、
txt2[0] = txt[0];
txt2[1] = txt[1];
txt2[2] = txt[2];
txt2[3] = txt[3];
txt2[4]='\0';
としてやり、同様に表示すると今度は「今日」が表示できます。
txt2[0] = txt[0];
txt2[1] = txt[1];
txt2[2] = txt[2];
txt2[3] = txt[3];
txt2[4] = txt[4];
txt2[5] = txt[5];
txt2[6]='\0';
とすると「今日は」になります。
常にtxt2を表示させれば段々1文字ずつ増えていきますね?
このコピーをコピー元の配列の中身が\0になるまでしていけば、サウンドノベル風になりますね?
つまり2要素ずつコピーしては、終端記号をいれていけばいいわけです。
ただこれを毎回2ずつ増やしていると早すぎるので、特定ターンに一回処理をするようにプログラムするとよいでしょう。
やり方つかめてきましたかね?
いやいや、誰かに作ってもらってたんじゃ夏天さんのスキルが上がりませんよ^^
少しずつ作ってみませんか?
まず、半角が無いテキストデータだとして考えましょう。
char txt[128]="今日からサウンドノベル風文字列表示の勉強をします";
これを時間差で表示させて見ます。
まず、時間差で表示させるには、
1、1文字格納、表示
2、2文字格納、表示
3、3文字格納、表示
これを延々と繰り返せばいいですね。
また繰り返すまでの区間は、配列に\0が見つかるまでです。
txt2というもともとの配列のほかにtxt2という描画用の配列を用意します。
txt2にtxtから必要な分だけコピーして、常にtxt2を表示するようにしてみます。
まず、
txt[0],txt[1]をtxt2[0],txt[1]にコピーし、txt2[2]に\0を格納します。
つまり
txt2[0] = txt[0];
txt2[1] = txt[1];
txt2[2]='\0';
こういうことです。
すると%sでtxt2を表示させれば「今」が表示できますね。
どうように、
txt2[0] = txt[0];
txt2[1] = txt[1];
txt2[2] = txt[2];
txt2[3] = txt[3];
txt2[4]='\0';
としてやり、同様に表示すると今度は「今日」が表示できます。
txt2[0] = txt[0];
txt2[1] = txt[1];
txt2[2] = txt[2];
txt2[3] = txt[3];
txt2[4] = txt[4];
txt2[5] = txt[5];
txt2[6]='\0';
とすると「今日は」になります。
常にtxt2を表示させれば段々1文字ずつ増えていきますね?
このコピーをコピー元の配列の中身が\0になるまでしていけば、サウンドノベル風になりますね?
つまり2要素ずつコピーしては、終端記号をいれていけばいいわけです。
ただこれを毎回2ずつ増やしていると早すぎるので、特定ターンに一回処理をするようにプログラムするとよいでしょう。
やり方つかめてきましたかね?
Re:サンプルプログラムにて
txt[p2][p1]で管理しています。
こんな感じでどうでしょうか?
人のプログラムを読むのになれていらっしゃらないようなので、極力コードの直接記述はさけました。
/* */の部分は自分で作ってください。
無駄な部分もありますが、わかりやすさ最優先で書きました。
半角が混ざるともうちっとテクが必要です。
次はそのテクの話をします。
int i,p1=0,p2=0,counter=0; char txt2,txt[10][128]={ "今日はサウンドノベル風文字列表示法を勉強しています。", "色々人の書いたプログラムを理解するのは難しいですが", "わからなくとも、どんなプログラムでもいいので試行錯誤しながら自分で", "いろんなプログラムを書いてみることで", "自分の力となります。", "がんばってください。", }; if(エンターが今の瞬間押されたら){ p2++; p1=0;//次の文章へ } if(counter%3==0)//3周に1回処理をする if( /*次の要素が\0でなければ*/ ) p1+=2;//表示する文字を全角1つ増やす for(i=0;i<p1;i++){ txt2=txt[p2]//コピー /*もし用意した配列よりp1が大きければブレイク*/ } txt2='\0';//終端記号格納 DrawFormatString( /* txt2を表示 */ ); counter++;
こんな感じでどうでしょうか?
人のプログラムを読むのになれていらっしゃらないようなので、極力コードの直接記述はさけました。
/* */の部分は自分で作ってください。
無駄な部分もありますが、わかりやすさ最優先で書きました。
半角が混ざるともうちっとテクが必要です。
次はそのテクの話をします。
Re:サンプルプログラムにて
まず、
char txt_a[3]="AB";
char txt_b[3]="あ";
において、
printf("%d\n",txt_a[0]);
printf("%d\n",txt_b[0]);
をしてみてください。何か違いに気づくはずです。
全角はsignedでは1バイト目がかならずマイナスになります。
半角はプラスになります。
以下サンプルを書いてみました。
tbの偶数配列要素というのは、文字の1バイト目を表しています。赤字の部分です。
つまり、全角は1バイト目がマイナスであることを利用すれば
半角か、全角かが判定できます。
ですから調べた要素がプラスなら1つ配列要素をずらせばよく、
調べた要素がマイナスなら2つ要素をずらせばいいわけですね。
わかります?
char txt_a[3]="AB";
char txt_b[3]="あ";
において、
printf("%d\n",txt_a[0]);
printf("%d\n",txt_b[0]);
をしてみてください。何か違いに気づくはずです。
全角はsignedでは1バイト目がかならずマイナスになります。
半角はプラスになります。
以下サンプルを書いてみました。
#include<stdio.h> void main(){ int i; char ta[11]="abcdeABCDE"; char tb[11]="あイ言○Z"; for(i=0;i<10;i+=2) printf("ta[%d]=%d\tta[%d]=%d\ttb[%d]=%d\ttb[%d]=%d\t\n",i,ta,i+1,ta[i+1],i,tb,i+1,tb[i+1]); } 実行結果 ta[0]=97 ta[1]=98 tb[0]=-126 tb[1]=-96 ta[2]=99 ta[3]=100 tb[2]=-125 tb[3]=67 ta[4]=101 ta[5]=65 tb[4]=-116 tb[5]=-66 ta[6]=66 ta[7]=67 tb[6]=-127 tb[7]=-101 ta[8]=68 ta[9]=69 tb[8]=-126 tb[9]=121
tbの偶数配列要素というのは、文字の1バイト目を表しています。赤字の部分です。
つまり、全角は1バイト目がマイナスであることを利用すれば
半角か、全角かが判定できます。
ですから調べた要素がプラスなら1つ配列要素をずらせばよく、
調べた要素がマイナスなら2つ要素をずらせばいいわけですね。
わかります?
Re:サンプルプログラムにて
文字コードはこちらにこれでもかと載っているので
http://ash.jp/code/
参考にしてください。
半角の文字コードはこちらが見やすいかな?
http://e-words.jp/p/r-ascii.html
http://ash.jp/code/
参考にしてください。
半角の文字コードはこちらが見やすいかな?
http://e-words.jp/p/r-ascii.html
Re:サンプルプログラムにて
一応念の為捕捉を。
char型は singedなのか unsignedのどちらかになりますが、どちらになると決められないので
負になるかどうかのチェックは必ず signedにキャストしてから行って下さい。
次にシフト JISにおける2バイト文字の判定は 負であるかだけのテストだけでは
半角カタカナを誤認するので不十分です。
半角カタカナを外して判定する必要があります。
char型は singedなのか unsignedのどちらかになりますが、どちらになると決められないので
負になるかどうかのチェックは必ず signedにキャストしてから行って下さい。
次にシフト JISにおける2バイト文字の判定は 負であるかだけのテストだけでは
半角カタカナを誤認するので不十分です。
半角カタカナを外して判定する必要があります。
Re:サンプルプログラムにて
そういえば昔、文字コードがどうなっているのかかたっぱしから出力してみたことがあり、
半角カタカナも負であることを知りました。
半角カタカナを使うとバグがおきるとよくいわれるのはこのためなんですかね?
半角カタカナを想定したエラー処理をしていないシステムがあるということでしょうか。
半角カタカナも負であることを知りました。
半角カタカナを使うとバグがおきるとよくいわれるのはこのためなんですかね?
半角カタカナを想定したエラー処理をしていないシステムがあるということでしょうか。
Re:サンプルプログラムにて
>半角カタカナを使うとバグがおきるとよくいわれるのはこのためなんですかね
まぁそうですね。
昔はデータ量を減らす為に1バイトで表現できるカタカナということで、重宝されたのですが
今では過去との互換の為だけに存在する、本来は不要な文字です。
インターネットとかだと使われる文字コードは非常に多いので
半角カタカナを使用されると文字コードの判定が難しくなって文字化け発生率が高くなりますし、
昔のメールでは 7bitしか扱わないので即文字化けでした。
とはいえ、最近は UnicodeとかMIMEとか ESMTPとかで回避できるので、大分半角カタカナの
トラブルも減りましたよね。
まぁそうですね。
昔はデータ量を減らす為に1バイトで表現できるカタカナということで、重宝されたのですが
今では過去との互換の為だけに存在する、本来は不要な文字です。
インターネットとかだと使われる文字コードは非常に多いので
半角カタカナを使用されると文字コードの判定が難しくなって文字化け発生率が高くなりますし、
昔のメールでは 7bitしか扱わないので即文字化けでした。
とはいえ、最近は UnicodeとかMIMEとか ESMTPとかで回避できるので、大分半角カタカナの
トラブルも減りましたよね。
Re:サンプルプログラムにて
不要な文字ですかぁ、と言う事は将来なくなる可能性も?
でも結構顔文字に使ったり、コメントとか突っ込みに半角カタカナって結構重宝しますよねw
昔のメールは7bitですかぁ、、残りの1bitは何かのフラグだったんですか?
でも結構顔文字に使ったり、コメントとか突っ込みに半角カタカナって結構重宝しますよねw
昔のメールは7bitですかぁ、、残りの1bitは何かのフラグだったんですか?
Re:サンプルプログラムにて
>と言う事は将来なくなる可能性も
もうここまで来てしまうと、その可能性は大幅な改訂でもない限りいですね。
Unicodeにもちゃっかり入ってますし。
>残りの1bitは何かのフラグだったんですか?
いえ、もともとメールのプロトコル(SMTP)は 7bitしか扱わない(1バイトが 8ビットとは限らない)ので、
どうするかはサーバー次第です。
8bitのメールを送ってしまった場合、経由する全てのメールサーバーが 8bitを通すものなら
大丈夫かもしれませんが、8bit目を削除してしまう仕様のものが1つでもあれば
データは破損します。
日本語をメールで送る場合、本文なら ISO-2022-JPに、ヘッダなら Base64とかのコードに
変換して 7bitで収まるようにしてから送っているので日本語がメールで扱えているわけです。
でも半角カナは ISO-2022-JPには入っていないんですよね。だからそのまま流すと
どうなるかは状況次第です。
半角カナをどう扱うかはメーラーによって対応が違っていて、うちのメーラーから
半角カナメールを送るとメーラー側で半角カナを判定して全角に直してから
送っているようです。
今は ESMTPという 8bitを扱えるプロトコルがあり、大分普及してきているので
8bitで送ってしまっても大丈夫な確率は高くなっているのですが、
それでも半角カナは使わないのがマナーというものですね。
もうここまで来てしまうと、その可能性は大幅な改訂でもない限りいですね。
Unicodeにもちゃっかり入ってますし。
>残りの1bitは何かのフラグだったんですか?
いえ、もともとメールのプロトコル(SMTP)は 7bitしか扱わない(1バイトが 8ビットとは限らない)ので、
どうするかはサーバー次第です。
8bitのメールを送ってしまった場合、経由する全てのメールサーバーが 8bitを通すものなら
大丈夫かもしれませんが、8bit目を削除してしまう仕様のものが1つでもあれば
データは破損します。
日本語をメールで送る場合、本文なら ISO-2022-JPに、ヘッダなら Base64とかのコードに
変換して 7bitで収まるようにしてから送っているので日本語がメールで扱えているわけです。
でも半角カナは ISO-2022-JPには入っていないんですよね。だからそのまま流すと
どうなるかは状況次第です。
半角カナをどう扱うかはメーラーによって対応が違っていて、うちのメーラーから
半角カナメールを送るとメーラー側で半角カナを判定して全角に直してから
送っているようです。
今は ESMTPという 8bitを扱えるプロトコルがあり、大分普及してきているので
8bitで送ってしまっても大丈夫な確率は高くなっているのですが、
それでも半角カナは使わないのがマナーというものですね。
Re:サンプルプログラムにて
管理人様のソースのコメント欄を考えて見ました
しかしコンパイルエラーが出てきます
どこが間違っているのでしょうか
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
//ChangeWindowMode( TRUE ) ;
int i,p1=0,p2=0,counter=0;
int Cr;
char txt2,txt[10][128]={
"今日はサウンドノベル風文字列表示法を勉強しています。",
"色々人の書いたプログラムを理解するのは難しいですが",
"わからなくとも、どんなプログラムでもいいので試行錯誤しながら自分で",
"いろんなプログラムを書いてみることで",
"自分の力となります。",
"がんばってください。",
};
if(CheckHitKey( KEY_INPUT_RETURN )){
p2++; p1=0;//次の文章へ
}
if(counter%3==0){//3周に1回処理をする
if( txt[p2][p1+1] != '\0' ){
p1+=2;//表示する文字を全角1つ増やす
}
}
for(i=0;i<p1;i++){
txt2=txt[p2];//コピー
/*もし用意した配列よりp1が大きければブレイク*/
if(txt2 < p1){
break;
}
}
txt2='\0';//終端記号格納
Cr = GetColor( 255 , 255 , 255 );
DrawFormatString( 0, 0, Cr, "%s", txt2);
counter++;
}
c:\program files\microsoft visual studio 8\vc\platformsdk\include\mmreg.h : warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。
c:\documents and settings\tenka\デスクトップ\vcqma\dxlib.h(1529) : warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。
c:\documents and settings\tenka\デスクトップ\vcqma\str.cpp(32) : error C2109: 配列または、ポインタでない変数に添字が使われました。
c:\documents and settings\tenka\デスクトップ\vcqma\str.cpp(34) : error C2109: 配列または、ポインタでない変数に添字が使われました。
c:\documents and settings\tenka\デスクトップ\vcqma\str.cpp(38) : error C2109: 配列または、ポインタでない変数に添字が使われました。
ビルドログは "file://c:\Documents and Settings\Tenka\デスクトップ\vcqma\Debug\BuildLog.htm" に保存されました。
vcqma - エラー 3、警告 2
========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========
しかしコンパイルエラーが出てきます
どこが間違っているのでしょうか
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
//ChangeWindowMode( TRUE ) ;
int i,p1=0,p2=0,counter=0;
int Cr;
char txt2,txt[10][128]={
"今日はサウンドノベル風文字列表示法を勉強しています。",
"色々人の書いたプログラムを理解するのは難しいですが",
"わからなくとも、どんなプログラムでもいいので試行錯誤しながら自分で",
"いろんなプログラムを書いてみることで",
"自分の力となります。",
"がんばってください。",
};
if(CheckHitKey( KEY_INPUT_RETURN )){
p2++; p1=0;//次の文章へ
}
if(counter%3==0){//3周に1回処理をする
if( txt[p2][p1+1] != '\0' ){
p1+=2;//表示する文字を全角1つ増やす
}
}
for(i=0;i<p1;i++){
txt2=txt[p2];//コピー
/*もし用意した配列よりp1が大きければブレイク*/
if(txt2 < p1){
break;
}
}
txt2='\0';//終端記号格納
Cr = GetColor( 255 , 255 , 255 );
DrawFormatString( 0, 0, Cr, "%s", txt2);
counter++;
}
c:\program files\microsoft visual studio 8\vc\platformsdk\include\mmreg.h : warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。
c:\documents and settings\tenka\デスクトップ\vcqma\dxlib.h(1529) : warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。
c:\documents and settings\tenka\デスクトップ\vcqma\str.cpp(32) : error C2109: 配列または、ポインタでない変数に添字が使われました。
c:\documents and settings\tenka\デスクトップ\vcqma\str.cpp(34) : error C2109: 配列または、ポインタでない変数に添字が使われました。
c:\documents and settings\tenka\デスクトップ\vcqma\str.cpp(38) : error C2109: 配列または、ポインタでない変数に添字が使われました。
ビルドログは "file://c:\Documents and Settings\Tenka\デスクトップ\vcqma\Debug\BuildLog.htm" に保存されました。
vcqma - エラー 3、警告 2
========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========
Re:サンプルプログラムにて
> 管理人様のソースのコメント欄を考えて見ました > しかしコンパイルエラーが出てきます > どこが間違っているのでしょうか Unicode形式云々の件は、よくわかりません。 他の件は、 > char txt2,txt[10][128]={ txt2が配列ではないのに > txt2=txt[p2];//コピー > if(txt2 < p1){ > txt2='\0';//終端記号格納 配列のごとく扱っているためです。
Re:サンプルプログラムにて
あらら・・すみません、txt2は配列のコピー先の配列なので、配列でなくてはなりません。
txtの一番低い次元の要素数用意してください。
つまり、今は
txt2[128]ということになります。
これでどうですか?
txtの一番低い次元の要素数用意してください。
つまり、今は
txt2[128]ということになります。
#include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){ if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; SetDrawScreen( DX_SCREEN_BACK ); int i,p1=0,p2=0,counter=0; int Cr; char Key[256],oldKey[256]={},txt2[128],txt[10][128]={ "今日はサウンドノベル風文字列表示法を勉強しています。", "色々人の書いたプログラムを理解するのは難しいですが", "わからなくとも、どんなプログラムでもいいので試行錯誤しながら自分で", "いろんなプログラムを書いてみることで", "自分の力となります。", "がんばってください。", }; Cr = GetColor( 255 , 255 , 255 ); while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && Key[KEY_INPUT_ESCAPE]==0){ if( oldKey[KEY_INPUT_RETURN]==0 && Key[KEY_INPUT_RETURN]==1 ){//1回前の時入力してなくて、今入力していたら p2++; p1=0;//次の文章へ } if(counter%3==0){//3周に1回処理をする if( txt[p2][p1+1] != '\0' ){ p1+=2;//表示する文字を全角1つ増やす } } for(i=0;i<p1;i++){ txt2=txt[p2];//コピー /*もし用意した配列よりiが大きければブレイク*/ if(128-1 <= i){ break; } } txt2='\0';//終端記号格納 DrawFormatString( 0, 0, Cr, "%s", txt2); for(i=0;i<256;i++)//今の入力情報を記憶 oldKey=Key; counter++; ScreenFlip(); } DxLib_End(); return 0; }
これでどうですか?
Re:サンプルプログラムにて
なんとか理解できそうです
いろいろわかりやすき教えていただきありがたく思っています
最初に誰か作ってくださいとわがままを言ったにもかかわらず
こんなにわかりやすく教えていただき本当にありがたいです
コレで野望にまた一歩近づいたような気がします
ありがとうございました!
いろいろわかりやすき教えていただきありがたく思っています
最初に誰か作ってくださいとわがままを言ったにもかかわらず
こんなにわかりやすく教えていただき本当にありがたいです
コレで野望にまた一歩近づいたような気がします
ありがとうございました!
Re:サンプルプログラムにて
夏天さん、
人の書いたプログラムって理解するのは難しいものですよね。
だからこそ、ゲームプログラミングの館では、直接コードを見ることを目的とせず、概念を理解する事を目的としてご利用下さい。
頑張ってくださいね☆
Justyさん、
逆に私が質問したような形になってしまい、すみません^^;
なるほど、7というと中途半端な数字に見えますけど、特に8である必要はないですものね。
ありがとうございます。
人の書いたプログラムって理解するのは難しいものですよね。
だからこそ、ゲームプログラミングの館では、直接コードを見ることを目的とせず、概念を理解する事を目的としてご利用下さい。
頑張ってくださいね☆
Justyさん、
逆に私が質問したような形になってしまい、すみません^^;
なるほど、7というと中途半端な数字に見えますけど、特に8である必要はないですものね。
ありがとうございます。