トップページ > 過去ログ > 記事閲覧
atan2関数をつかったプログラムについて
名前:クラウン 日時: 2008/01/06 11:56

こんにちは! 今、こちらのゲーム→http://www.vector.co.jp/soft/win95/game/se271698.htmlの照準の合わせ方や腕の回転方法をまねてプログラムを作っているのですが、回転がうまくいきません。プログラムは下記になります。 void Player_Show( int pj_flag , int myship_x ) { double PI=3.14; // 円周率設定 static int rad=PI*2/1; // 角度変数 int aim_image_sagyo , *aim_img; aim_image_sagyo=LoadGraph("aim.bmp"); //   自機照準画像取得 aim_img=&aim_image_sagyo; if( pj_flag==0 ) //歩行状態である myship.body_img=&( myship.image[myship.muki][(myship_x%32)/2] ); //現在の方向とx座標にあったボディー画像を取得 else //飛行状態である myship.body_img=&( myship.image[myship.muki][17] ); //方向にあったボディー画像を取得 myship.hand_img1=&( myship.image[myship.muki][18] ); //方向にあった腕の画像を取得 myship.hand_img2=&( myship.image[myship.muki][19] ); // DrawRotaGraph2( myship.x+75 , myship.y+35 , 75 , 20 , 1 , rad*2/1 , *myship.hand_img1 , TRUE ); //腕の画像表示 DrawGraph( myship.x , myship.y , *myship.body_img , TRUE ); //ボディー画像表示 DrawRotaGraph2( myship.x+75 , myship.y+35 , 75 , 20 , 1 , rad*2/1 , *myship.hand_img2 , TRUE ); //腕の画像表示 DrawGraph( Mouse_X , Mouse_Y , *aim_img , TRUE ); //照準の表示 rad=atan2( (double)myship.x+75-Mouse_X , (double)myship.y+35-Mouse_Y ); } 変数の『MouseXとMouseY』はマウスの座標取得をし値を格納しています。 どのようなプログラムを組めばいいか教えていただけると幸いです。 よろしくおねがいします。 開発環境 OS:WindowsXP 使用ソフト:VisualC++ 2005 Express Edision ライブラリ:DXライブラリ 使用言語:C言語

Page: 1 |

Re: atan2関数をつかったプログラムについて ( No.1 )
名前:TNT 日時:2008/01/06 15:30

自分の場合こういうのは組みながらバグを潰していくので、間の抜けたアドバイスをしてしまうかもしれませんが…(^_^; まず画像表示、"rad*2/1"の"2/1"は余計だと思います。atan2で取得した時点でradianになっています。 (意図が分からないため、言い切れない部分でもあるのですが…) 次に最後の行ですが、atan2の引数の渡し方が2点において誤っています。 ・atan2の関数型は atan2(double y, double x); ・動径をしめすベクトルの向きが逆 ということで、まずxとyが逆なので入れ替えます。 ( (double)myship.y+35-Mouse_Y , (double)myship.x+75-Mouse_X); しかし、これは「マウスから腕に向かうベクトル」を動径とした偏角を意味しますので、 実行すると腕はマウスと正反対の方向を向くはずです。 なので、ひっくり返します。 ( (double)Mouse_Y-(myship.y+35) , (double)Mouse_X-(myship.x+75) ); 他に見落としが無ければ、計算面での誤りは以上だと思います。 ただ、atan2を最後に呼び出しているのには何か意図があるのでしょうか? 通常は描画する前に角度計算として呼び出すので、計算→描画といった手順が普通だと思うのですが… そうすれば、radをstaticにする必要も無くなりますし、描画遅延(1フレーム)も無くなります。 あと、atan2は垂直/水平を取るときに動作が怪しくなりますので、引数のうちxかyが0の時は 例外処理を設けておく必要があるかもしれません。
Re: atan2関数をつかったプログラムについて ( No.2 )
名前:クラウン 日時:2008/01/06 17:33

TNTさん!いつもありがとうございます! ご指摘どおり、直してみました。でもなかなか、思ったようになおりません。すこしマシにはなったのですが根本的におかしいのでしょうか? もう一つ質問したいことが、これは、まったくプログラムが思いつかないのですが、キーボードを使って、キー↑を押すと腕が上がり、キー↓を押すと腕が下がる・・・というようなプログラムを組む場合は、いったいどのようにすればいいのでしょうか?
Re: atan2関数をつかったプログラムについて ( No.3 )
名前:TNT 日時:2008/01/06 18:10

まず、マウスカーソルの方向を向くプログラムのサンプルを載せてみますね。 計算部分はこれで問題なく動きます。 クラウンさんのプログラムで、もし意図しない角度を指したりするとすれば、 画像の扱いそのものにどこか問題があるのかもしれません。 一つ考えられるのは、ロードする画像そのものの向きでしょうか。 スクリーン座標系は数学的直交座標のy軸を反転させたものですので、0度は右方向になります。 つまり、読み込む画像は右向きを基準として作成することになります。 (もし、元の画像が違う方向:上や下などを向いている場合、角度の初期値を持たせて処理する必要があります) 以下のプログラムで、右向き矢印画像「arrow.png」を作成して実行してみてください。 #include "DxLib.h" #include <math.h> int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { double rad; int arrow; int Mouse_X, Mouse_Y; int Arrow_X, Arrow_Y; ChangeWindowMode(TRUE); if( DxLib_Init() == -1 ) return -1 ; SetDrawScreen(DX_SCREEN_BACK); arrow = LoadGraph("arrow.png"); Arrow_X = 320; Arrow_Y = 240; while(true){ if(ProcessMessage() == -1) break; ClearDrawScreen(); GetMousePoint(&Mouse_X, &Mouse_Y); rad = atan2(double(Mouse_Y - Arrow_Y), double(Mouse_X - Arrow_X)); DrawRotaGraph(Arrow_X, Arrow_Y, 1, rad, arrow, TRUE); ScreenFlip(); } DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } と、次はキー入力に関してですが…
Re: atan2関数をつかったプログラムについて ( No.4 )
名前:TNT 日時:2008/01/06 18:24

腕の角度を変数として用意し、キー入力によってそれを増減させることで上げ下げが可能です。 角度変数はradianでも良いのですが、操作するのに直感的では無いのでdegreeを利用した方が楽かと思います。 (変換式は radian = degree * PI / 180) と、これもサンプルを #include "DxLib.h" #include <math.h> int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { double PI = 3.14159; double rad; int Arrow_X, Arrow_Y; int Arrow_Angle; int arrow; ChangeWindowMode(TRUE); if( DxLib_Init() == -1 ) return -1 ; SetDrawScreen(DX_SCREEN_BACK); arrow = LoadGraph("arrow.png"); Arrow_X = 32; Arrow_Y = 240; Arrow_Angle = 0; while(true){ if(ProcessMessage() == -1) break; ClearDrawScreen(); if(CheckHitKey(KEY_INPUT_UP )) Arrow_Angle -= 1; if(CheckHitKey(KEY_INPUT_DOWN)) Arrow_Angle += 1; if(Arrow_Angle <= -80) Arrow_Angle = -80; if(Arrow_Angle >= 80) Arrow_Angle = 80; rad = (double)Arrow_Angle * PI / 180; DrawRotaGraph(Arrow_X, Arrow_Y, 1, rad, arrow, TRUE); ScreenFlip(); } DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } 上キーを入れると矢印が上に1度ずつ、下キーを入れると下に1度ずつ動きます。
Re: atan2関数をつかったプログラムについて ( No.5 )
名前:クラウン 日時:2008/01/06 23:48

TNTさん!ありがとうございました! TNTさんのプログラムを参考に腕の回転と、弾の発射を考えてみました。↓ //腕の回転 void Player_Show( int pj_flag , int myship_x ) { static int Arrow_Angle; double PI=3.14; // 円周率設定(double)Mouse_X-myship.x+105 //static double rad=PI*2/1; // 角度変数 if(myship.muki==0 ) { if( key[KEY_INPUT_UP]==1 ) Arrow_Angle -= 1; if( key[KEY_INPUT_DOWN]==1 ) Arrow_Angle += 1; } if( myship.muki==1 ) { if( key[KEY_INPUT_UP]==1 ) Arrow_Angle += 1; if( key[KEY_INPUT_DOWN]==1 ) Arrow_Angle -= 1; } if(Arrow_Angle <=-80) Arrow_Angle =-80; if(Arrow_Angle >=80) Arrow_Angle =80; myship_rad=(double)Arrow_Angle * PI / 180; if( pj_flag==0 ) //歩行状態である myship.body_img=&( myship.image[myship.muki][(myship_x%32)/2] ); //現在の方向とx座標にあったボディー画像を取得 else //飛行状態である myship.body_img=&( myship.image[myship.muki][17] ); //方向にあったボディー画像を取得 myship.hand_img1=&( myship.image[myship.muki][18] ); //方向にあった腕の画像を取得 myship.hand_img2=&( myship.image[myship.muki][19] ); // if( weapon_id==0 ) { // 腕とボディーの表示 if( myship.muki==0 ) { DrawRotaGraph2( myship.x+75 , myship.y+40 , 75 , 20 , 1 , myship_rad , *myship.hand_img1 , TRUE ); DrawGraph( myship.x , myship.y , *myship.body_img , TRUE ); DrawGraph( myship.x , myship.y+15 , *myship.hand_img2 , TRUE ); } if( myship.muki==1 ) { DrawGraph( myship.x , myship.y+15 , *myship.hand_img1 , TRUE ); DrawGraph( myship.x , myship.y , *myship.body_img , TRUE ); DrawRotaGraph2( myship.x+75 , myship.y+35 , 75 , 20 , 1 , myship_rad , *myship.hand_img2 , TRUE ); } } if( weapon_id==1 ) { // 腕とボディーの表示 if( myship.muki==0 ) { DrawGraph( myship.x , myship.y+15 , *myship.hand_img1 , TRUE ); DrawGraph( myship.x , myship.y , *myship.body_img , TRUE ); DrawRotaGraph2( myship.x+75 , myship.y+35 , 75 , 20 , 1 , myship_rad , *myship.hand_img2 , TRUE ); } if( myship.muki==1 ) { DrawRotaGraph2( myship.x+75 , myship.y+30 , 75 , 20 , 1 , myship_rad , *myship.hand_img1 , TRUE ); DrawGraph( myship.x , myship.y , *myship.body_img , TRUE ); DrawGraph( myship.x , myship.y+15 , *myship.hand_img2 , TRUE ); } } if( weapon_id==2 ) { // 腕とボディーの表示 DrawGraph( myship.x , myship.y+15 , *myship.hand_img1 , TRUE ); DrawGraph( myship.x , myship.y , *myship.body_img , TRUE ); DrawGraph( myship.x , myship.y+15 , *myship.hand_img2 , TRUE ); } } //弾の発射 static int i , NewSpace=0 , OldSpace=0 , InputSpace=0 ,rad ; int *myshotbulletimg; if( key[KEY_INPUT_SPACE]==1 ) NewSpace=1; else NewSpace=0; if( OldSpace==0 && NewSpace==1 ) InputSpace=1; else InputSpace=0; if( InputSpace==1 ) { for( i=0 ; i<20 ; i++ ) { if( myshot[i].shotbulletflag==0 ) { myshot[i].sb_speedx=cos((double)rad)*10; myshot[i].sb_speedx=sin((double)rad)*10; myshot[i].shotbulletx=myship.x+70; myshot[i].shotbullety=myship.y+35; myshot[i].shotbulletflag=1; break; } } } OldSpace=NewSpace; for( i=0 ; i<20 ; i++) { myshotbulletimg=&(myshot[i].shotbullet); if( myshot[i].shotbulletflag==1 ) { myshot[i].shotbulletx+=myshot[i].sb_speedx; myshot[i].shotbullety+=myshot[i].sb_speedy; DrawGraph( myshot[i].shotbulletx , myshot[i].shotbullety , *myshotbulletimg ,TRUE); DrawFormatString(0,0,GetColor(255,0,0),"%d %d",cos(myship_rad)*10,sin(myship_rad)*10); if( myshot[i].shotbullety > 600 || myshot[i].shotbullety < -120 || myshot[i].shotbulletx >780 ||myshot[i].shotbulletx < -160 ) myshot[i].shotbulletflag=0; } } } ここで、弾の発射だけ、思った方向に飛ばないのですが、よろしければ、おしえていただけますか? 何度もすみません!(>_<)
Re: atan2関数をつかったプログラムについて ( No.6 )
名前:クラウン 日時:2008/01/06 23:49

弾の発射プログラムだけ、上が抜けて今しました・・・。 引数などはありません。
Re: atan2関数をつかったプログラムについて ( No.7 )
名前:TNT 日時:2008/01/07 00:16

下から20行目あたりの myshot[i].sb_speedx=cos((double)rad)*10; myshot[i].sb_speedx=sin((double)rad)*10; この2行目はsb_speedyの誤りですね。 多分、これでちゃんと飛ぶ…と思います。
Re: atan2関数をつかったプログラムについて ( No.8 )
名前:クラウン 日時:2008/01/07 10:39

! お恥ずかしい間違いすみませんでした。

Page: 1 |