誰か教えてください。

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

誰か教えてください。

#1

投稿記事 by 蒼空(初心者) » 16年前

東方風のSTGを作っているんですが、
「東方永夜抄」の夢符「封魔陣」の弾幕を真似したいんですけど、
どうしても、途中で5つの角度に分かれる弾幕の作り方がわからないんです。
弾が5つ重なって真下に下りてきて、途中に真ん中の1つはそのままの角度。
あとの二つは、まっすぐから±45度で、
もう二つは、まっすぐから±22.5度なんですけど、
誰か、教えてください。

環境は、VC++ 2008EEで、XPをつかっています。
知識は、興味本位でやり始めたばっかりなので、
簡単な文は分かるぐらいです。
よろしくお願いします。

チルチル

Re:誰か教えてください。

#2

投稿記事 by チルチル » 16年前

弾に番号でも渡しておいて移動パターン内で時間が来たら条件分岐すれば良いんじゃないですか?

それとも条件分岐の具体的な内容ですか?

蒼空(初心者)

Re:誰か教えてください。

#3

投稿記事 by 蒼空(初心者) » 16年前

うまく説明が出来ないんですけど、
まず、8way弾で、その弾には5つ弾が重なっていて、
発射された後、弾一つ一つに、発射されてある一定時間以上たったなら、
弾の角度を変える。ってやつなんですけど、

一気じゃなくて、弾一つ一つで連続して変化するという弾幕です。

>それとも条件分岐の具体的な内容ですか?

はい、できればそれでお願いします。

b

Re:誰か教えてください。

#4

投稿記事 by b » 16年前

弾を発射するときに、動く方向の角度と、一定時間経ったときに加算する角度の2つの角度情報を持たせれば条件分岐を使用しなくても実装できると思います。

蒼空(初心者)

Re:誰か教えてください。

#5

投稿記事 by 蒼空(初心者) » 16年前

bさん、返答ありがとうございます。

でも、できればソースを載せてほしいです。
正直、自分の知識的にちょっと危ないので、

龍神録のソースを使っていますので、ぜひともお願いします。

b

Re:誰か教えてください。

#6

投稿記事 by b » 16年前

龍神録のソースは使ってないのでわかりませんが、ぱぱっと書いてみますわ。
その間弾を実装するための設計書とか自分で組んでみてはいかがでしょう?

蒼空(初心者)

Re:誰か教えてください。

#7

投稿記事 by 蒼空(初心者) » 16年前

はい、指摘?ありがとうございます。

一応自分でも、軽く分かる範囲で作ってみました。
ですが、やはり知識不足で理想にはぜんぜん遠くて
そのために、投稿しました。良い返答を期待しています。

チルチル

Re:誰か教えてください。

#8

投稿記事 by チルチル » 16年前

まあ永夜抄やった事があるのでどんな弾幕かはわかりますけどね

封魔陣は二回曲がると思いますけど
一回も二回もそれほど変わらないので省略します

bさんの方法でも良いですがパッと思いついた方法を書きます



まず弾の構造体に角度を格納するAngleと言う変数と
多目的に使えるDATAと言う変数があるとします

弾を一度に五個登録する時にfor文でも使って
DATA変数に何でも良いんですが
とりあえず 0 1 2 3 4 の順番に数値を入れます
それ以外の数値は同じなので
重なって飛んで行きます

そして弾の移動パターンの中で
弾のカウンタが指定した時間になったら
Angle変数に角度を加算します

45度と22.5度を導く効率の良い式が浮かばないので

#define PI 3.1415926535898

と言う宣言が行われているとして

PI=180度なので

45度=PI/180*45
22.5度=PI/180*22.5

で求めます

そして

if( Shot.Count==60 ){

if( Shot.DATA==0 )Shot.Angle+=PI/180*45;

if( Shot.DATA==1 )Shot.Angle+=PI/180*22.5;

if( Shot.DATA==3 )Shot.Angle-=PI/180*22.5;

if( Shot.DATA==4 )Shot.Angle-=PI/180*45;

}

のような処理で実現します

これで発射されてから一秒後に五方向に別れる・・と思う

簡単にするために無駄が多くなってるので
慣れて来たら効率化してみてください

bさんのように登録時に角度を求めて時間になったら
角度に足す事で曲げる事もできます

私は説明では不十分かもしれないので
わからない事があったら言って下さい
サンプルとかも作りますよ

蒼空(初心者)

Re:誰か教えてください。

#9

投稿記事 by 蒼空(初心者) » 16年前

チルチルさんどうもありがとうございます。

ぜひ、ソレを参考にさせていただきます。

チルチル

Re:誰か教えてください。

#10

投稿記事 by チルチル » 16年前

書いている間に更新されましたね

私は龍神録のコードが理解できなかったので
オリジナルのコードを使っています

なのでサンプルを作るのが難しいですが
できる限り善処します

b

Re:誰か教えてください。

#11

投稿記事 by b » 16年前

簡単に書いてみました。間違いとかあるかもしれませんが(^^;)
さすがに初見で龍神録の変数の仕様とかはわからないので、要所のみ書いてみました。

仕様は封魔陣ノーマルのスぺカを基準で。
//弾の発射フラグ立て=============================
int i , j ;
double angle1 , angle2 ;//第一、第二動作角度
const double addangle1 = 2 * PI / 弾の数(8WAYなら8) ;
const double addangle2 = 弾の間隔の角度(ラジアンで22.5度) ;

angle1 = 起点となる角度、自機狙いなら自機の角度を入れておく

for( i = 0 ; i < 弾の数(8WAYなら8) ; i++ )//すみません、抜けてました
{
	angle1 += addangle1 ;

	//↓どちらかを使ってください、今回は5Wayということで上の方のみで
	//Nway弾が奇数のとき
	angle2 = -(double)( nWay / 2 ) * addangle2 ;
	//Nway弾が偶数のとき
	angle2 = -(double)( nWay - 1 ) / 2.0 * addangle2 ;

	for( j = 0 ; j < 弾の数(5方向に弾を分けるなら5) ; j++ )
	{
		//発射されていない弾のフラグを探す
		{
			第一動作角度にangle1を代入

			第二動作角度にangle2を代入

			angle2 += addangle2 ;
		}
	}
}

b

Re:誰か教えてください。

#12

投稿記事 by b » 16年前

追記:ちるちるさんの方法ですが、弾の発射個数の分岐が7個に変わった場合にソースを書き換える個所が多数出ると思います。
また、0,1,2,3,4と弾に番号を振っていますが、それが何を指し示すのかわからない数字、マジックナンバーになってしまっているのではないでしょうか?

自分の方法ですと、弾を何個発射するかの変数、const int shotnum = 5 ;とかを弾を発射する関数に用意すれば、その数値を変えるだけで角度調節、発射個数変更が効きます。

Dixq (管理人)

Re:誰か教えてください。

#13

投稿記事 by Dixq (管理人) » 16年前

龍神録では、弾の「状態」を表すために「.state」が用意してあります。
このstateに好きな数字を入れて、その数字で条件わけしてやればいいと思います。
今、1箇所から同じ方向に5つ弾が出て、途中でその5つが分岐するなら、
その5つに0~4の数字でもふってやり、その数字に応じてあるカウント数になったら、
角度を変えてみてはどうでしょう?

チルチル

Re:誰か教えてください。

#14

投稿記事 by チルチル » 16年前

そう言えばそうですね
私は定数項を変更する方法を使う事が多いのでこのような処理にしました

どうも私は例外処理に対して排他的な処理を行ってしまう癖が・・

やはり登録時に変更角度を渡した方が良いかもしれませんね・・

「マジックナンバー」と言う言葉の意味がよく分りませんが確かに脈絡は無いですね・・
私のコードはこんな感じの処理ばっかりですけど
気付かないうちにマジックナンバーだらけになってしまっていたのか・・

b

Re:誰か教えてください。

#15

投稿記事 by b » 16年前

マジックナンバーとは でググってみるといいですよ

チルチル

Re:誰か教えてください。

#16

投稿記事 by チルチル » 16年前

そういえば私のコードはスイッチ文の脈絡がわかりにくい事が多い・・
いやそれは関係無いか・・
処理全体がもうマジックナンバーみたいなもんだし・・

Dixq (管理人)

Re:誰か教えてください。

#17

投稿記事 by Dixq (管理人) » 16年前

よく回答の流れを見ずに書き込んだら思いっきり不適切なコメントしてしまいました(汗

確かにマジックナンバーを多用すると効率が悪くなる場面が多いと思いますが、
まずは弾幕が作れるようになってから、効率面を考えてもいいのでは無いかなと思います。

そして効率面を追及していくと解り易いと思います。
まぁ今回位の規模でしたらどちらでもいいかもしれませんね。

Tatu

Re:封魔陣の作り方

#18

投稿記事 by Tatu » 16年前

封魔陣に挑戦してみました。
//弾を発射する関数
void boss_bullet_on(int way,int knd,int col,int flag,double x,double y,double size,double b_angle,double d_angle,double spd,int state,int till){
    int i=0,k;
    for(i=0;i<way;i++){
        if((k=search_boss_shot())!=-1){
            boss_shot.bullet[k].knd   = knd;//弾の種類
            if(knd==7) boss_shot.bullet[k].kaiten=1;
            else boss_shot.bullet[k].kaiten=0;
            boss_shot.bullet[k].col   = col;//弾の色
            boss_shot.bullet[k].flag  = 1;//flag;1だと当たり判定あり、2だと当たり判定なし
            boss_shot.bullet[k].cnt   = 0;
            boss_shot.bullet[k].x     = x;//座標
            boss_shot.bullet[k].y     = y;
            //boss_shot.bullet[k].size  = size;弾の大きさ(今は意味なし)
            boss_shot.bullet[k].angle = b_angle+d_angle*(i - way/2);//角度:bが基準、dが間隔
            boss_shot.bullet[k].spd   = spd;//スピード
            boss_shot.bullet[k].state = state;//弾の状態
            boss_shot.bullet[k].till  = till;//弾が画面外に出ても消えない時間
            se_flag[0]=1;
        }
    }
}
//封魔陣のようなもの
void boss_shot_bulletH000(){
    int i,t=boss_shot.cnt;
    static double ang=PI/16;
    if(t==0){
        boss.hp_max=150000;
        boss.hp    =30000;
    }
    if(t%15==0){
        for(i=0;i<5;i++){
            boss_bullet_on(8,5,1,1,boss.x,boss.y,1,ang,PI2/8,3,i+1,0);
        }
    }
    if(t>100){
        if((t+100)%800<400) ang+=PI/(32*60);
        else          ang-=PI/(32*60);
        if(t%150==0){
            boss_bullet_on(32,10,1,1,boss.x,boss.y,1,bossatan2(),PI2/32,6,6,0);
        }
        if(t%100==0){
            boss_bullet_on(16,1,0,1,boss.x,boss.y,1,bossatan2()+PI,PI/16,3,7,0);
        }
    }
    for(i=0;i<BOSS_BULLET_MAX;i++){
        if(boss_shot.bullet.flag>0){
            switch(boss_shot.bullet.state){
                case 1:
                    if(boss_shot.bullet.cnt==30 || boss_shot.bullet.cnt==60)
                        boss_shot.bullet.angle-=PI/4;
                    break;
                case 2:
                    if(boss_shot.bullet.cnt==30 || boss_shot.bullet.cnt==60)
                        boss_shot.bullet.angle-=PI/8;
                    break;
                case 4:
                    if(boss_shot.bullet.cnt==30 || boss_shot.bullet.cnt==60)
                        boss_shot.bullet[i].angle+=PI/8;
                    break;
                case 5:
                    if(boss_shot.bullet[i].cnt==30 || boss_shot.bullet[i].cnt==60)
                        boss_shot.bullet[i].angle+=PI/4;
                    break;
                case 6:
                    if(boss_shot.bullet[i].cnt<30){
                        boss_shot.bullet[i].spd-=0.2;
                    }
                    if(boss_shot.bullet[i].cnt==120){
                        boss_shot.bullet[i].knd=6;
                        boss_shot.bullet[i].spd=2;
                    }
                    break;
                //陰陽玉の代わり
                //通常時は赤く、当たり判定があるが
                //低速時は青く、当たり判定がない
                case 7:
                    if(CheckStatePad(configpad.slow)==0){
                        boss_shot.bullet[i].flag=1;
                        boss_shot.bullet[i].col=0;
                    }
                    else{
                        boss_shot.bullet[i].flag=2;//当たり判定がない
                        boss_shot.bullet[i].col=1;
                    }
                    if(boss_shot.bullet[i].cnt<60){
                        if(cos(boss_shot.bullet[i].angle)>0){
                            boss_shot.bullet[i].angle+=PI*2/(3*60);
                        }
                        else{
                            boss_shot.bullet[i].angle-=PI*2/(3*60);
                        }
                    }
                    if(boss_shot.bullet[i].x<16 || FMX-16<boss_shot.bullet[i].x){
                        boss_shot.bullet[i].angle=PI-boss_shot.bullet[i].angle;
                    }
                    break;
            }
        }
    }

}

yu

Re:封魔陣の作り方

#19

投稿記事 by yu » 16年前

・・・被ってしまいました><
すみません;

自分も作ってみました。
変な処理をしているかもしれませんw
妥協したところが多々有りです・・・

60章を元に作成しました。
boss_shotH.cppにこの関数を追加し、func.hを少し変更すると動くと思います。

後、Tatu様のようにstateはswitchで扱ったほうが良いですね;

どこか分からないところ、おかしなところがあったら言ってください;

#追記
#一部編集しました

チルチル

Re:封魔陣の作り方

#20

投稿記事 by チルチル » 16年前

なかなかよさそうなサンプルですね
とりあえず私の出る幕は無さそうですね

蒼空(初心者)

Re:封魔陣の作り方

#21

投稿記事 by 蒼空(初心者) » 16年前

少し見ぬ間に、いろいろ返信ありがとうございます。

コレを見てもう少しがんばってみます。

閉鎖

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