14章の弾幕(2)

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
<kor

14章の弾幕(2)

#1

投稿記事 by <kor » 17年前

どうも。
この前の弾幕の作成方法でたくさんの方にお世話になりました。<korです。
前回教えていただいた方法で2~7way弾を作って実行してみたのですが、パターン000から006までは正常に
実行されるのですが、それ以降の自分で作ったものはなぜか実行されません。
ちなみに、エクセルファイルとshot.cppも変更しました。エラーも出てません。

なぜ実行されないのか、教えていただけないでしょうか?

管理人

Re:14章の弾幕(2)

#2

投稿記事 by 管理人 » 17年前

恐らく関数ポインタを追加していないからじゃないでしょうか。
弾幕の関数は似たような関数が大量に出てくるので、
ポインタでその関数をさせるようにしてあります。
例えば感覚的に表現するならば

int *p[4];

p[0]=弾幕0の関数のポインタ;
p[1]=弾幕1の関数のポインタ;
p[2]=弾幕2の関数のポインタ;
p[3]=弾幕3の関数のポインタ;

と格納しておけば、3番の弾幕の処理をさせたいときp[処理をさせたい番号=3]を示せばいい事になり
楽が出来ます。
その為、新しく弾幕4を追加した時は

int *p[5];

p[0]=弾幕0の関数のポインタ;
p[1]=弾幕1の関数のポインタ;
p[2]=弾幕2の関数のポインタ;
p[3]=弾幕3の関数のポインタ;
p[4]=弾幕4の関数のポインタ;

のように新しく追加しなければなりません。

これをやってみましょう。

shot.cppファイルの上に

extern void shot_bullet_H000(int);
extern void shot_bullet_H001(int);
extern void shot_bullet_H002(int);
extern void shot_bullet_H003(int);
extern void shot_bullet_H004(int);
extern void shot_bullet_H005(int);
extern void shot_bullet_H006(int);

と長々と書いているところがありますね。
もし今007をshotH.cppに追加したのならば、上の続きに

extern void shot_bullet_H007(int);

を追加して下さい。そして上で言う
p[4]=弾幕4の関数のポインタ;
の作業をしてやります。

void (*shot_bullet[SHOT_KND_MAX])(int) ={
	shot_bullet_H000,
	shot_bullet_H001,
	shot_bullet_H002,
	shot_bullet_H003,
	shot_bullet_H004,
	shot_bullet_H005,
	shot_bullet_H006,
};

これがそのポインタの格納ですから

void (*shot_bullet[SHOT_KND_MAX])(int) ={
	shot_bullet_H000,
	shot_bullet_H001,
	shot_bullet_H002,
	shot_bullet_H003,
	shot_bullet_H004,
	shot_bullet_H005,
	shot_bullet_H006,
	shot_bullet_H007,
};

を追加して下さい。この時SHOT_KND_MAXが
上限を超えていないか注意して下さい。
例えば今の場合は8以上になっている事を確認して下さい。

もしこれで解決しない場合はまたお聞き下さい。

Justy

Re:14章の弾幕(2)

#3

投稿記事 by Justy » 17年前

 便乗ですが、ふと疑問に。


>この時SHOT_KND_MAXが上限を超えていないか注意して下さい。

 SHOT_KND_MAXの定義って必要なのでしょうか?
 37章のソースを見る限り、無くてもいいような気がするのですが。

管理人

Re:14章の弾幕(2)

#4

投稿記事 by 管理人 » 17年前

そうですね~、恐らくここでしか使わないので特に定義はしなくてもいいのかもしれません。

void (*shot_bullet[SHOT_KND_MAX])(int)

とかかなくても

void (*shot_bullet[18])(int)

と書けばいいということですよね?
まぁ今回は解らなくはならないと思いますが、
一応後から見たときに、どの数字が何の意味なのかわからなくならないように、
shotの種類を増やしたい時は

#define SHOT_KND_MAX 18

の値を変更したらいいだけにした方がわかりやすいかな?と思い、このようにしました。
あまり必要性の低い定義はしない方がいいでしょうか?

Justy

Re:14章の弾幕(2)

#5

投稿記事 by Justy » 17年前


>void (*shot_bullet[18])(int)
>と書けばいいということですよね?

 あ、いえ
void (*shot_bullet[/url])(int)
 こうです。

 で、後はshot.knd<SHOT_KND_MAXなところはshot.knd<sizeof(shot_bullet)/sizeof(shot_bullet[0])
感じにしておけば配列の要素数を自分で管理する必要が無くなるので、shotの種類を増やしたい時に
楽かなと思いまして。
(sizeof~の部分はマクロ化した方がいいでしょうけど)



>必要性の低い定義はしない方がいいでしょうか

 必要性があるなら定義した方がいいと思いますよ。

 ただ、今回のケースで言うと sizeofで要素数をわかるので
敢えて配列の要素数と SHOT_KND_MAXの数を手動で一致させる必要はないかな、と。
 特に数が多くなったり幾つか弾の種類をコメントアウトして削ったときとか
修正が面倒で、しかもミスに気付きにくいですし。

 でももしこの方式で進めるなら要素数と SHOT_KND_MAXが違っていたら
コンパイル時か実行時に知らせるコードを入れておくとミスに気付けるので
いいのかもしれません。

管理人

Re:14章の弾幕(2)

#6

投稿記事 by 管理人 » 17年前

>あ、いえ
>void (*shot_bullet[/url])(int)
>こうです。

ご、、ごもっとも( ̄▽ ̄;)

そうか~なぜイチイチ定義してたんでしょう;
龍神録もそうなっているので、何も考えずに館のコードもそうしてしまいました。

いや~しかし館のサンプルはホントに、後から変更が効かない構造ですねorz

Justy

Re:14章の弾幕(2)

#7

投稿記事 by Justy » 17年前


>いや~しかし館のサンプルはホントに、後から変更が効かない構造ですねorz

 あー、なかなか難しいですね、それは。
 時系列で複数のプロジェクトが作られてますから、最初の頃からあるコードですと・・・ね。

<kor

Re:14章の弾幕(2)

#8

投稿記事 by <kor » 17年前

今確認してみたら、define.cppのSHOT_KND_MAXもちゃんと13になってましたし、shot.cppも上の通りになってました。

管理人

Re:14章の弾幕(2)

#9

投稿記事 by 管理人 » 17年前

あれ?そうなんですか。
では以下の点をご確認のうえ、それでも原因が解らなかったらこちらに送って下さい。
こちらでバグの原因を見つけてみます。

・今出現させたい弾幕がshot_bullet_H007だとしたら、shot_bullet_H007がshot.cppでextern宣言されているか。
・ポインタ配列にその関数のアドレスが入れてあるか
・エクセルデータの弾幕の呼び出しが7番になっているか
・shot_bullet_H007がshotH.cpp内で正確に実装されているか

<kor

Re:14章の弾幕(2)

#10

投稿記事 by <kor » 17年前

すいません、いろんなところをよくわからないのに変更してたからだと思ってプロジェクトをDLしなおして、
shotH.cppとshot.cpp、define.hだけを変更してやってみたらshotH.cppで
識別子が見つかりませんでした
というエラーが弾幕の数だけ出てしまうんですけど、なぜですか?
とりあえず、1つエラーの出たところを載せておきます。龍神録プログラミングも見てみましたが間違ったところはなかったのですが・・・
//1発だけ、自機に向かって直線発射
void shot_bullet_H000(int n){
        int k;
        if(shot[n].cnt==0){
                if(shot[n].flag!=2 && (k=shot_serch(n))!=-1){  //←ここでエラーが起きたらしいです。
                        shot[n].bullet[k].knd   =enemy[shot[n].num].blknd2;
                        shot[n].bullet[k].angle =shotatan2(n);
                        shot[n].bullet[k].flag  =1;
                        shot[n].bullet[k].x     =enemy[shot[n].num].x;
                        shot[n].bullet[k].y     =enemy[shot[n].num].y;
                        shot[n].bullet[k].col   =enemy[shot[n].num].col;
                        shot[n].bullet[k].cnt   =0;
                        shot[n].bullet[k].spd   =3;
                        se_flag[0]=1;
                }
        }
}

Justy

Re:14章の弾幕(2)

#11

投稿記事 by Justy » 17年前


>shotH.cppとshot.cpp、define.hだけを変更してやってみたらshotH.cppで
>識別子が見つかりませんでした
>というエラーが弾幕の数だけ出てしまうんですけど、なぜですか?

 えーと、一番肝心の「見つからなかった識別子」の名前は何なのでしょうか。



>ここでエラーが起きたらしいです

 shot_serch -> shot_searchだとかいうことは?

管理人

Re:14章の弾幕(2)

#12

投稿記事 by 管理人 » 17年前

エラーが出たら、そのエラーメッセージをダブルクリックしたらエラーの出た行に飛びます。
その行のどこでエラーが出ているのかそのエラーメッセージから推測します。
例えば「"shot_serch"が見つかりませんでした」のようなエラーメッセージなら
shot_serchを右クリックして「定義に移動」してみて下さい。
恐らくどこにも飛べないと思います。
そうするとスペルミスだとわかります。
こんな感じで一つずつつぶしてみてはどうでしょうか。

<kor

Re:14章の弾幕(2)

#13

投稿記事 by <kor » 17年前

今管理人様の方法で見てみたら、shot_searchがshot_serchになってました。ちまちま a を打ち続ける作業に…
で、実行してみたらできたんですけど、やっぱりあとから自分で作ったものが出てきません。
エクセルファイルが悪いんですかね?なんか保存するときに、

story0.csvには、CSV(カンマ区切り)と互換性のない機能が含まれている可能性があります。
この形式でブックを保存しますか。

っていう警告が出てしまいます。
それに、csvで保存できたはいいんですが、60カウントのところを7番に変更してるのに変更前の1番が出てしまいます。いったい何が悪いのか・・・?

管理人

Re:14章の弾幕(2)

#14

投稿記事 by 管理人 » 17年前

警告はこちらでもでますよ。理由はよく知りませんが・・。
保存して、閉じて、また開いて、保存した時の状態になっていれば、
無事保存できている事が確認できると思います。

(これから何か途中わからない事があれば言って下さい)

これからする作業は本来反対からするべきですが、順番がわからなくなってはいけないので、
最初から書きますね。(1)~(4)でそれぞれ値がきちんとはいっているか確認してください。


(1)
まず、エクセルデータにおいて、弾幕種類(blknd)にあたるのが弾幕の番号ですね。
これはload.cppのload_story()にて

case 7:	enemy_order[n].blknd	=atoi(inputc);break;

でenemy_order[*].blkndに読み込まれます。
この時ちゃんと7が入っているかブレイクポイントを用いて確認して下さい。
(printfDxでもいいですが)


(2)
このデータは敵が出現する時刻になったらenemy_enter()関数内で

enemy[*].blkndに格納されるはずです。

またここに7が入っていることを確認して下さい。


(3)
そしてenemy.cpp内のenter_shot(int)関数内で

void enter_shot(int i){
	int j;
	for(j=0;j<SHOT_MAX;j++){//フラグのたって無いenemyを探す
		if(shot[j].flag==0){//未使用の弾幕データがあれば
			memset(&shot[j],0,sizeof(shot_t));//初期化して登録
			shot[j].flag=1;//フラグをたてる
			shot[j].knd=enemy.blknd;//弾の種類

shot[j].kndに7が渡されます。
ここも確認してください。


(4)
後は、shot.cpp内の

void shot_main(){
	int i;
	for(i=0;i<SHOT_MAX;i++){//弾幕データ計算
		//フラグが立っていて、設定した種類が間違っていなければ(オーバーフロー対策)
		if(shot.flag!=0 && 0<=shot.knd && shot.knd<SHOT_KND_MAX){
			shot_bullet[shot.knd](i);//.kndの弾幕計算関数を呼ぶ関数ポインタ

shot.kndが7なら
shot_bullet[shot.knd](i)で
配列の[7]が呼ばれるはずですからenemy_pattern7が呼ばれるはずです。
ここも確認してください。

これらが全てうまくいっていて、それでも、弾幕7が実行されないのなら、
アドバイスだけでは解りませんので、こちらに送って下さい。

<kor

Re:14章の弾幕(2)

#15

投稿記事 by <kor » 17年前

>>管理人様
ごめんなさい。load.cpp内で、story.csvの場所の定義を間違ってただけでした。
迷惑かけちゃってすいませんm(__)m

閉鎖

“C言語何でも質問掲示板” へ戻る