いつもお世話になっております。
特定の弾幕を発動する際に、画像とスペルカード名を表示してみたいと思い、プログラムを改造しているのですが、行き詰ってしまいました。下の動画の1分08秒に表れるようなエフェクトにしたいと思っています。[youtube][/youtube]
過去のトピックを参考にさせて頂いて、構造体のヘッダにcnt,x、y座標、弾幕名の配列を用意したものの、コードに描き表せません。
スペルカードのフラグ=1→boss_shotH.cpp内のそれぞれの弾幕で弾幕名の文字列を実引数として関数を呼ぶ という流れになるのは想像できるのですが・・・
ご指導、ご鞭撻のほど宜しくお願い致します。
struct.h
東方のようなスペカ表示について
Re: 東方のようなスペカ表示について
ここまで分かっているのならば後はそれをプログラムに書き起こすだけなのですけれどねクラバック さんが書きました:スペルカードのフラグ=1→boss_shotH.cpp内のそれぞれの弾幕で弾幕名の文字列を実引数として関数を呼ぶ という流れになるのは想像できるのですが・・・
まぁ、ある程度経験を積むまではそれが難しいのですけど(苦笑)
そうですね、龍神録をベースにするならば
effect.cpp内のcalc_effect関数にエフェクト本体の仕様を書くとあとで分かりやすいと思います。
スペルカードのフラグが1になった時に、boss_shot.cpp内にあるboss_shot_main関数から最初の呼び出し(登録)をするようにします
boss_shot_main関数から呼び出す登録用の関数に弾幕の名前を文字列の引数として渡してやればいいでしょうね。
今回の場合spell_name_t構造体の中の文字列spell_nameに渡してやって、それを元に弾幕の名前を表示させてやればいいと思います。
calc_effect関数は毎フレーム毎に呼び出されるので、一度スイッチを入れてやれば自動的に処理してくれます(処理の内容は当然自分で書く必要がありますが)
あとはエフェクトが終了した時点で弾幕が開始されるようにしてやればいいと思います。
とりあえず全体の流れを書いてみましたが、これも一つの方法であって別のやり方もあると思います。
でももう少し具体的な事を聞きたければまた聞いてくださいね
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ
Re: 東方のようなスペカ表示について
ごめんなさい。考えたのですが、全くと言っていいほど分かりませんでした。
作成した弾幕を、通常攻撃とスペルカードとを区別させるやり方がまず分かりません。
また、boss_shot_main()関数で登録用の関数enter_spell(char name)を呼ぶようにしたのですが、enter_spell(char name)側で渡された文字列をどう扱えばいいのか、分かりません。
理解力に乏しくて申し訳御座いません。再び、ご指導頂けませんでしょうか。
スペカ名を格納する構造体のメンバ名をspell_nameからspell_cardへ変更しました。タグ名とメンバ名が同一だった為です。
struct.h
GV.h
ini.cpp void ini内
boss_shot.cpp void boss_shot_main()内
effect.cpp
作成した弾幕を、通常攻撃とスペルカードとを区別させるやり方がまず分かりません。
また、boss_shot_main()関数で登録用の関数enter_spell(char name)を呼ぶようにしたのですが、enter_spell(char name)側で渡された文字列をどう扱えばいいのか、分かりません。
理解力に乏しくて申し訳御座いません。再び、ご指導頂けませんでしょうか。
スペカ名を格納する構造体のメンバ名をspell_nameからspell_cardへ変更しました。タグ名とメンバ名が同一だった為です。
struct.h
//スペカ名を格納する構造体
typedef struct{
int flag,cnt,to_cnt;//表示するフラグ、カウンタ、何カウントで表現するか
double x,y;//表示する座標
char *spell_card[DANMAKU_MAX];//弾幕名を格納する配列
}spell_name_t;
void ini(){
/*・・・*/
spell_name.spell_card[0] = "月符「サイレントセレナ」";
spell_name.spell_card[1] = "凍符「パーフェクトフリーズ」";
spell_name.spell_card[2] = "禁忌「恋の迷路」";
}
//ボスの弾幕メイン
void boss_shot_main(){
if((stage_count==boss.appear_count[0] || stage_count==boss.appear_count[1]) && boss.flag==0){//開始時間なら
enter_boss(0);//開始
enter_spell(*spell_name.spell_card[0]);//登録用の関数。スペルカード名を渡す
}
if(boss.flag==0)//ボスが登録されて無ければ戻る
return;
calc_boss();
if(boss.phy.flag==1)//物理演算移動オンなら
calc_phy();//物理計算を
if(boss.state==2 && (boss.hp<=0 || boss.endtime<=0)){//弾幕中で体力が無くなったら
se_flag[1]=1;//敵のピチュリ音
se_flag[11]=1;
input_phy(30);//30カウントで定位置に戻す
memset(&boss_shot,0,sizeof(boss_shot_t));//ボスの弾幕情報を初期化
memset(&lazer,0,sizeof(lazer_t)*LAZER_MAX);//ボスのレーザー情報を初期化
flash.flag=0;//フラッシュを消す
if(boss.knd==boss.danmaku_num[0] || boss.knd==boss.danmaku_num[1]||boss.knd==boss.danmaku_num[2] || boss.knd==boss.danmaku_num[3] || boss.knd==boss.danmaku_num[4]){//弾幕をだしきったら
boss.flag=0;//消す
enter_dn(10,40);//(45)ドガーン処理
se_flag[9]=1;//ボスが死んだ音
return ;
}else{
enter_boss(1);//次の弾幕を登録
}
}
if(boss.state==1){//弾幕間の待機時間
waitandenter();
}
if(boss.state==2){//弾幕中なら
boss_shot_bullet[boss.knd]();//弾幕関数へ
boss_shot_calc();//弾幕計算
}
boss.cnt++;
}
Re: 東方のようなスペカ表示について
聞きたいことがあれば聞いて
とか自分で言った手前助けない訳にはいきませんね!
一気に全部片付けようとするとごちゃごちゃするので一つずつやって行ってくださいね(←受け売り)
まず通常攻撃とスペルカードとの区別ですが
龍神録でも通常攻撃とスペルカードとで背景を変える仕様になっていましたね
詳しくはこちら参照http://dixq.net/rp/25.html
そんな訳でコレを利用させてもらえばいいと思います
boss.back_knd[boss.knd]==1ならばスペルカードのエフェクトを表示させる、といった具合ですね。
文字列の扱いに関しては、これもやり方がいくつかあります
どちらにしろ配列とかポインタとかある程度理解していないと扱いは難しいですね
今回の場合
spell_name構造体の中のspell_cardがchar型の配列なので、ここに画面上に表示させる名前を入れる訳ですね
でも配列のポインタとか考えるとややこしくなるので、宣言を
char spell_card[DANMAKU_MAX];//弾幕名を格納する配列
こう変えた方がいいと思います
そして文字列操作関数であらかじめ用意していた文字列をコピーしてやるのがいいでしょうね。
文字列操作関数に関してはこの辺りを
http://tkmakwins15.tuzikaze.com/contents/string1.htm
もちろん文字列のポインタを渡す方法でもいいのですが、読み解くのが難しいですからね(苦笑)
とか自分で言った手前助けない訳にはいきませんね!
一気に全部片付けようとするとごちゃごちゃするので一つずつやって行ってくださいね(←受け売り)
まず通常攻撃とスペルカードとの区別ですが
龍神録でも通常攻撃とスペルカードとで背景を変える仕様になっていましたね
詳しくはこちら参照http://dixq.net/rp/25.html
そんな訳でコレを利用させてもらえばいいと思います
boss.back_knd[boss.knd]==1ならばスペルカードのエフェクトを表示させる、といった具合ですね。
文字列の扱いに関しては、これもやり方がいくつかあります
どちらにしろ配列とかポインタとかある程度理解していないと扱いは難しいですね
今回の場合
spell_name構造体の中のspell_cardがchar型の配列なので、ここに画面上に表示させる名前を入れる訳ですね
でも配列のポインタとか考えるとややこしくなるので、宣言を
char spell_card[DANMAKU_MAX];//弾幕名を格納する配列
こう変えた方がいいと思います
そして文字列操作関数であらかじめ用意していた文字列をコピーしてやるのがいいでしょうね。
文字列操作関数に関してはこの辺りを
http://tkmakwins15.tuzikaze.com/contents/string1.htm
もちろん文字列のポインタを渡す方法でもいいのですが、読み解くのが難しいですからね(苦笑)
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ
Re: 東方のようなスペカ表示について
ご指導有難う御座います・・・!
教えて頂いたのを元に、ソースコードを改変してみました。しかし、boss_shot.cppとeffect.cpp内のenter_spell()関数の引数に疑問を覚えます。また、enter_spell()関数の定義で未だに躓いています・・・申し訳御座いません。
引き続き教えて頂ければ幸いです。
struct.h
GV.h
ini.cpp void ini()内
boss_shot.cpp void boss_shot_main()内
effect.cpp
教えて頂いたのを元に、ソースコードを改変してみました。しかし、boss_shot.cppとeffect.cpp内のenter_spell()関数の引数に疑問を覚えます。また、enter_spell()関数の定義で未だに躓いています・・・申し訳御座いません。
引き続き教えて頂ければ幸いです。
struct.h
//スペカ名を格納する構造体
typedef struct{
int flag,cnt,to_cnt;//表示するフラグ、カウンタ、何カウントで表現するか
double x,y;//表示する座標
char spell_card[31];//弾幕名を格納する配列 ひとまずスペカ名を30文字以内に収める
}spell_name_t;
void ini(){
/*・・・*/
strcpy(spell_name[0].spell_card, "月符「サイレントセレナ」");
strcpy(spell_name[1].spell_card, "凍符「パーフェクトフリーズ」");
strcpy(spell_name[2].spell_card, "禁忌「恋の迷路」");
}
//ボスの弾幕メイン
void boss_shot_main(){
static int i=0;//前回からの変更点
if((stage_count==boss.appear_count[0] || stage_count==boss.appear_count[1]) && boss.flag==0){//開始時間なら
enter_boss(0);//開始
//前回からの変更点
if(boss.back_knd[boss.knd]==1){
enter_spell(spell_name[i].spell_card[31]);//登録用の関数。スペルカード名を渡す
i++;
}
}
if(boss.flag==0){//ボスが登録されて無ければ戻る
return;
}
calc_boss();
if(boss.phy.flag==1){//物理演算移動オンなら
calc_phy();//物理計算を
}
if(boss.state==2 && (boss.hp<=0 || boss.endtime<=0)){//弾幕中で体力が無くなったら
se_flag[1]=1;//敵のピチュリ音
se_flag[11]=1;
input_phy(30);//30カウントで定位置に戻す
memset(&boss_shot,0,sizeof(boss_shot_t));//ボスの弾幕情報を初期化
memset(&lazer,0,sizeof(lazer_t)*LAZER_MAX);//ボスのレーザー情報を初期化
flash.flag=0;//フラッシュを消す
if(boss.knd==boss.danmaku_num[0] || boss.knd==boss.danmaku_num[1]||boss.knd==boss.danmaku_num[2] || boss.knd==boss.danmaku_num[3] || boss.knd==boss.danmaku_num[4]){//弾幕をだしきったら
boss.flag=0;//消す
enter_dn(10,40);//(45)ドガーン処理
se_flag[9]=1;//ボスが死んだ音
return ;
}else{
enter_boss(1);//次の弾幕を登録
//前回からの変更点
if(boss.back_knd[boss.knd]==1){
enter_spell(spell_name[i].spell_card[31]);//登録用の関数。スペルカード名を渡す
i++;
}
}
}
if(boss.state==1){//弾幕間の待機時間
waitandenter();
}
if(boss.state==2){//弾幕中なら
boss_shot_bullet[boss.knd]();//弾幕関数へ
boss_shot_calc();//弾幕計算
}
boss.cnt++;
}
Re: 東方のようなスペカ表示について
う~ん…。
どうやらあの内容を文字だけで伝えようとした僕が間違っていたようですね(苦笑)
でも詳しいコードを書くのは面倒ですし(オイ)
もっと簡単に実装できそうな気もしたのでちょっとだけ書いてみます
いっそのこと登録関数で文字列渡すのはやめにしてしまいましょう
boss_shotH.cpp
こうして弾幕毎に名前を設定してやればどうでしょう?
これですでにchar型の配列spell_cardには、スペルカードの名前が格納されているのであとはエフェクトを表示させるだけです。
まぁこの方法にも登録関数を呼び出すタイミングなど問題があるのですけど
上手くやらないと最悪エフェクトが表示されてる間に弾幕が始まって、ボスの画像がいい感じに邪魔すると思います。 ちょっと細工すればそれも解決できますけど。
まぁ、これも一つの方法と言うことで
で、今までクラバックさんが頑張って来た方法についての補足はここからです
クラバックさんがやっているようにしても実装できるとは思いますが
spell_name_t構造体が必要以上に宣言されてしまっているので、無駄に容量を取ると思います。
どうで処理する内容はボスの画像と名前を表示させるだけなので、spell_name_t構造体の宣言は一つでいいと思いますね。
配列で宣言した方が分かりやすいと言えば分かりやすいですが…
まぁ、お好きなようにしてください
登録関数についてはこんな感じでいいと思いますね
スペルの番号って何? となると思いますが
ini.cppにて
と書いてますよね
つまりspell_name構造体型配列の0番にはサイレントセレナが1番にはパーフェクトフリーズが既に入っている訳ですね。
だからあとは0を渡せばサイレントセレナが、1を渡せばパーフェクトフリーズが、2を渡せば恋の迷路が、それぞれ呼び出されるようにすればいいと思いますよ。
3番はグレイソーマタージ辺りで(黙れ)
こんどはサイレントセレナの時にはちゃんと0という数字を渡すように呼び出す側(boss_shot_main関数)で仕込んで置かなければならない訳ですが
これもini.cppで こんな感じの配列を作ってやって、それぞれに合った処理をするようにしてやればいいでしょうね
0以上なら番号にあったスペル宣言のエフェクトを表示させる、-1なら通常弾幕なのでエフェクトはなし
といった具合に。
ふむ、前半に余計なこと書いたせいで無駄に長文になってしまいましたね。
失礼しました
追記:
10/19午前10時頃
学校からちょっぴり訂正しました
どうやらあの内容を文字だけで伝えようとした僕が間違っていたようですね(苦笑)
でも詳しいコードを書くのは面倒ですし(オイ)
もっと簡単に実装できそうな気もしたのでちょっとだけ書いてみます
いっそのこと登録関数で文字列渡すのはやめにしてしまいましょう
boss_shotH.cpp
//サイレントセレナ
void boss_shot_bulletH001(){
#define TM001 60
int i,k,t=boss_shot.cnt%TM001,t2=boss_shot.cnt;
static int cnum;
double angle;
strcpy(spell_name.spell_card,"月符「サイレントセレナ」");
if(t2==0)//最初の初期化
cnum=0;
if(t==0){//1ターンの最初の初期化
//以下略
}
これですでにchar型の配列spell_cardには、スペルカードの名前が格納されているのであとはエフェクトを表示させるだけです。
まぁこの方法にも登録関数を呼び出すタイミングなど問題があるのですけど
上手くやらないと最悪エフェクトが表示されてる間に弾幕が始まって、ボスの画像がいい感じに邪魔すると思います。 ちょっと細工すればそれも解決できますけど。
まぁ、これも一つの方法と言うことで
で、今までクラバックさんが頑張って来た方法についての補足はここからです
クラバックさんがやっているようにしても実装できるとは思いますが
spell_name_t構造体が必要以上に宣言されてしまっているので、無駄に容量を取ると思います。
どうで処理する内容はボスの画像と名前を表示させるだけなので、spell_name_t構造体の宣言は一つでいいと思いますね。
配列で宣言した方が分かりやすいと言えば分かりやすいですが…
まぁ、お好きなようにしてください
登録関数についてはこんな感じでいいと思いますね
//スペルカードの名前を登録する関数
void enter_spell(int num) //表示するスペル名の番号を渡す
{
spell_name[num].spell_flag=1;
//必要な情報があれば登録したり処理したりしておく
//文字列を表示させるときの初期座標とか書いておくといいかも?
}
ini.cppにて
void ini()
{
/*・・・*/
strcpy(spell_name[0].spell_card, "月符「サイレントセレナ」");
strcpy(spell_name[1].spell_card, "凍符「パーフェクトフリーズ」");
strcpy(spell_name[2].spell_card, "禁忌「恋の迷路」");
}
つまりspell_name構造体型配列の0番にはサイレントセレナが1番にはパーフェクトフリーズが既に入っている訳ですね。
だからあとは0を渡せばサイレントセレナが、1を渡せばパーフェクトフリーズが、2を渡せば恋の迷路が、それぞれ呼び出されるようにすればいいと思いますよ。
3番はグレイソーマタージ辺りで(黙れ)
こんどはサイレントセレナの時にはちゃんと0という数字を渡すように呼び出す側(boss_shot_main関数)で仕込んで置かなければならない訳ですが
これもini.cppで こんな感じの配列を作ってやって、それぞれに合った処理をするようにしてやればいいでしょうね
0以上なら番号にあったスペル宣言のエフェクトを表示させる、-1なら通常弾幕なのでエフェクトはなし
といった具合に。
ふむ、前半に余計なこと書いたせいで無駄に長文になってしまいましたね。
失礼しました
追記:
10/19午前10時頃
学校からちょっぴり訂正しました
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ
Re: 東方のようなスペカ表示について
お手を煩わせてしまい申し訳御座いません。
成程、登録関数を使わない方法もあるんですね・・・!
しかし、烏滸がましいのですが、登録関数を使って実装してみたいと思っています。
ご指摘頂いたとおり、構造体をスペカ分用意するのは無駄と思い直し、一つだけ宣言しました。
また、spell_name_t構造体のメンバをchar spell_card[DANMAKU_MAX][41]としました。
effect.cpp内部の各種関数、MakeScreen関数やSetDrawScreen関数等を殆どいじったことがないので、試行錯誤しながら実装していきます・・・!
struct.h
GV.h
ini.cpp void ini()内
boss_shot.cpp boss_shot_main()内
effect.cpp
成程、登録関数を使わない方法もあるんですね・・・!
しかし、烏滸がましいのですが、登録関数を使って実装してみたいと思っています。
ご指摘頂いたとおり、構造体をスペカ分用意するのは無駄と思い直し、一つだけ宣言しました。
また、spell_name_t構造体のメンバをchar spell_card[DANMAKU_MAX][41]としました。
effect.cpp内部の各種関数、MakeScreen関数やSetDrawScreen関数等を殆どいじったことがないので、試行錯誤しながら実装していきます・・・!
struct.h
//スペカ名を格納する構造体
typedef struct{
int flag,cnt,to_cnt;//表示するフラグ、カウンタ、何カウントで表現するか
double x,y;//表示する座標
char spell_card[DANMAKU_MAX][41];//弾幕名を格納する配列 弾幕の個数分×弾幕の名前の最大文字数用意する
}spell_name_t;
/*省略・・・*/
strcpy(spell_name.spell_card[0], "月符「サイレントセレナ」");
strcpy(spell_name.spell_card[1], "凍符「パーフェクトフリーズ」");
strcpy(spell_name.spell_card[2], "禁忌「恋の迷路」");
//スペル名の番号を格納する。 通常弾幕の場合は-1にする
spell_num[0] = -1;//通常弾幕
spell_num[1] = 0;//
spell_num[2] = -1;
spell_num[3] = 1;
spell_num[4] = 2;
//ボスの弾幕メイン
void boss_shot_main(){
static int i=0;
if((stage_count==boss.appear_count[0] || stage_count==boss.appear_count[1]) && boss.flag==0){//開始時間なら
enter_boss(0);//開始
//前回からの変更点
if(boss.back_knd[boss.knd]==1){//もし背景がスペカ用背景ならば、
if(spell_num[i]!=-1){//もしi番目の弾幕が、通常弾幕でなければ
enter_spell(spell_num[i]);//i番目の弾幕を登録。
}
}
i++;
}
if(boss.flag==0){//ボスが登録されて無ければ戻る
return;
}
calc_boss();
if(boss.phy.flag==1){//物理演算移動オンなら
calc_phy();//物理計算を
}
if(boss.state==2 && (boss.hp<=0 || boss.endtime<=0)){//弾幕中で体力が無くなったら
se_flag[1]=1;//敵のピチュリ音
se_flag[11]=1;
input_phy(30);//30カウントで定位置に戻す
memset(&boss_shot,0,sizeof(boss_shot_t));//ボスの弾幕情報を初期化
memset(&lazer,0,sizeof(lazer_t)*LAZER_MAX);//ボスのレーザー情報を初期化
flash.flag=0;//フラッシュを消す
if(boss.knd==boss.danmaku_num[0] || boss.knd==boss.danmaku_num[1]||boss.knd==boss.danmaku_num[2] || boss.knd==boss.danmaku_num[3] || boss.knd==boss.danmaku_num[4]){//弾幕をだしきったら
boss.flag=0;//消す
enter_dn(10,40);//(45)ドガーン処理
se_flag[9]=1;//ボスが死んだ音
return ;
}else{
enter_boss(1);//次の弾幕を登録
//前回からの変更点
if(boss.back_knd[boss.knd]==1){//もし背景がスペカ用背景ならば、
if(spell_num[i]!=-1){//もしi番目の弾幕が通常弾幕でなければ、
enter_spell(spell_num[i]);//i番目の弾幕を登録。
}
}
i++;
}
}
if(boss.state==1){//弾幕間の待機時間
waitandenter();
}
if(boss.state==2){//弾幕中なら
boss_shot_bullet[boss.knd]();//弾幕関数へ
boss_shot_calc();//弾幕計算
}
boss.cnt++;
}
//スペルカードの名前を登録する関数
void enter_spell(int num){//boss_shot_main()からスペルカード名が渡されてくる
int k;
spell_name.flag=1;
spell_name.spell_card[num];//←文字列が格納されている
spell_name.x = FMX-50;//ひとまずの初期x座標
spell_name.y = FMY-50;//ひとまずの初期y座標
spell_name.cnt = 0;
if((k=search_effect())!=-1){
effect[k].flag=1;//エフェクトを登録
effect[k].cnt=0;
effect[k].knd=5;//スペルカード発動エフェクト(文字)
effect[k].brt=0;
effect[k].ang=0;
effect[k].mvang=-PI/2;
effect[k].spd=1;
effect[k].r=1;
effect[k].eff=2;
effect[k].img=handle;//[s]たぶん文字列を画像にしてここにいれる[/s]
effect[k].x=70;
effect[k].y=300;
}
//必要な情報があれば登録したり処理したりしておく
//文字列を表示させるときの初期座標とか書いておくといいかも?
}
//スペルカードの名前の計算
void spell_calc(){
//if(spell_name.flag>0){
//}
}
//エフェクトを計算する
void calc_effect(){
for(int i=0;i<EFFECT_MAX;i++){
if(effect[i].flag>0){//エフェクトが登録されていたら
effect[i].x+=cos(effect[i].mvang)*effect[i].spd;
effect[i].y+=sin(effect[i].mvang)*effect[i].spd;
switch(effect[i].knd){//エフェクトの種類によって分岐
/*省略・・・*/
case 5 ://スペルカード発動エフェクト(文字)
if(effect[i].cnt>=10){
effect[i].brt-=255/10;
}
effect[i].r+=0.12;
effect[i].cnt++;
if(effect[i].cnt>12 || ch.flag!=1){
effect[i].flag=0;
}
break;
default:
printfDx("effect設定エラー\n");
break;
}
}
}
}
Re: 東方のようなスペカ表示について
無事、スペカ名と画像のエフェクト、両方の実装を終えることが出来ました・・・!
細部の再現は到底叶いませんが、ひとまず原型は出来たように思います。
エフェクトの使い方も大体は理解出来ましたし、これから更なる拡張に努めたいと思います。
jayさん、助けて頂いたこと深く御礼申し上げます。また機会が有りましたら、宜しくお願い致します。
ini.cpp
boss_shot.cpp
effect.cpp
graph.cpp
細部の再現は到底叶いませんが、ひとまず原型は出来たように思います。
エフェクトの使い方も大体は理解出来ましたし、これから更なる拡張に努めたいと思います。
jayさん、助けて頂いたこと深く御礼申し上げます。また機会が有りましたら、宜しくお願い致します。
ini.cpp
void ini(){
strcpy(spell_name.spell_card[0], "月符「サイレントセレナ」");
strcpy(spell_name.spell_card[1], "凍符「パーフェクトフリーズ」");
strcpy(spell_name.spell_card[2], "禁忌「恋の迷路」");
//スペル名の番号を格納する。 通常弾幕の場合は-1にする
spell_num[0] = 0;//通常弾幕
spell_num[1] = 0;//
spell_num[2] = -1;
spell_num[3] = 1;
spell_num[4] = 2;
SetDrawValidAlphaChannelGraphCreateFlag(TRUE);
spell_name_handle = MakeScreen(300, 20);
SetDrawValidAlphaChannelGraphCreateFlag(FALSE);
}
//ボスの弾幕メイン
void boss_shot_main(){
static int i=0;
if((stage_count==boss.appear_count[0] || stage_count==boss.appear_count[1]) && boss.flag==0){//開始時間なら
enter_boss(0);//開始
//前回からの変更点
if(boss.back_knd[boss.knd]==1){//もし背景がスペカ用背景ならば、
if(spell_num[i]!=-1){//もしi番目の弾幕が、通常弾幕でなければ
enter_spell_name(spell_num[i]);//i番目の弾幕を登録。
enter_spell_graph(img_dot_bossImage[4]);
}
}
i++;
}
if(boss.flag==0){//ボスが登録されて無ければ戻る
return;
}
calc_boss();
if(boss.phy.flag==1){//物理演算移動オンなら
calc_phy();//物理計算を
}
if(boss.state==2 && (boss.hp<=0 || boss.endtime<=0)){//弾幕中で体力が無くなったら
se_flag[1]=1;//敵のピチュリ音
se_flag[11]=1;
input_phy(30);//30カウントで定位置に戻す
memset(&boss_shot,0,sizeof(boss_shot_t));//ボスの弾幕情報を初期化
memset(&lazer,0,sizeof(lazer_t)*LAZER_MAX);//ボスのレーザー情報を初期化
flash.flag=0;//フラッシュを消す
if(boss.knd==boss.danmaku_num[0] || boss.knd==boss.danmaku_num[1]||boss.knd==boss.danmaku_num[2] || boss.knd==boss.danmaku_num[3] || boss.knd==boss.danmaku_num[4]){//弾幕をだしきったら
boss.flag=0;//消す
enter_dn(10,40);//(45)ドガーン処理
se_flag[9]=1;//ボスが死んだ音
return ;
}else{
enter_boss(1);//次の弾幕を登録
//前回からの変更点
if(boss.back_knd[boss.knd]==1){//もし背景がスペカ用背景ならば、
if(spell_num[i]!=-1){//もしi番目の弾幕が通常弾幕でなければ、
enter_spell_name(spell_num[i]);//i番目の弾幕を登録。
}
}
i++;
}
}
if(boss.state==1){//弾幕間の待機時間
waitandenter();
}
if(boss.state==2){//弾幕中なら
boss_shot_bullet[boss.knd]();//弾幕関数へ
boss_shot_calc();//弾幕計算
}
boss.cnt++;
}
//スペルカードの名前を登録する関数
void enter_spell_name(int num){//boss_shot_main()からスペルカード名が渡されてくる
int k;
spell_name.flag=1;
make_spell_graph(num);//画像作成
if((k=search_effect())!=-1){
effect[k].ang = 0;
effect[k].brt = 0;
effect[k].cnt = 0;
effect[k].eff = 2;
effect[k].flag = 1;//エフェクトを登録
effect[k].img = spell_name_handle;
effect[k].knd = 5;//スペルカード発動エフェクト(文字)
effect[k].mvang = PI/2*3;//↑方向
effect[k].r = 6.0;
effect[k].spd = 0;
effect[k].x = FMX-55;
effect[k].y = FMY-10;
}
//必要な情報があれば登録したり処理したりしておく
//文字列を表示させるときの初期座標とか書いておくといいかも?
}
//スペルカードの画像を登録する関数
void enter_spell_graph(int graph){//ボスの画像graphが渡されてくる
int k;
if((k=search_effect())!=-1){
effect[k].ang = 0;
effect[k].brt = 125;
effect[k].cnt = 0;
effect[k].eff = 2;
effect[k].flag = 1;
effect[k].img = graph;
effect[k].knd = 6;
effect[k].mvang = PI/6*5;
effect[k].r = 1;
effect[k].spd = 7;
effect[k].x = FMX+50;
effect[k].y = FY+30;
}
}
//エフェクトを計算する
void calc_effect(){
for(int i=0;i<EFFECT_MAX;i++){
if(effect[i].flag>0){//エフェクトが登録されていたら
effect[i].x+=cos(effect[i].mvang)*effect[i].spd;
effect[i].y+=sin(effect[i].mvang)*effect[i].spd;
switch(effect[i].knd){//エフェクトの種類によって分岐
case 5 ://スペルカード発動エフェクト(文字)
if(effect[i].cnt<=25){
effect[i].brt+=255/25;
effect[i].r -= 0.192;//1.2倍へ
}
if(effect[i].cnt>=30 && effect[i].y > FY){
effect[i].spd += 0.08;
}
if(effect[i].y <= FY){
effect[i].spd = 0;
}
effect[i].cnt++;
/*if(effect[i].cnt>12 || ch.flag!=1){
effect[i].flag=0;
}*/
break;
case 6 ://スペルカード発動エフェクト(画像)
if(effect[i].x<FMX/6*4 && effect[i].x>FMX/6*3 ){
effect[i].spd = 2;
}
if(effect[i].x<=FMX/6*3){
effect[i].spd = 7;
}
break;
default:
printfDx("effect設定エラー\n");
break;
}
}
}
}
//スペカ名が記述された画像作成
void make_spell_graph(int k){//strcpy(spell_name.spell_card[0], "月符「サイレントセレナ」");の[]内のこと
if(spell_name.flag>0){
SetDrawScreen(spell_name_handle);//ini()で作成した画像を描画対象にする
ClearDrawScreen();
ChangeFontType(DX_FONTTYPE_ANTIALIASING);
ChangeFont("MS ゴシック");
DrawString(5, 2.5, spell_name.spell_card[k], color[0]);//画像に対して、スペルカード名を描画する
SetDrawScreen(DX_SCREEN_BACK);
}
}