ページ 11

逆三角関数等々。。。

Posted: 2012年11月27日(火) 17:44
by ulllllr
お初に質問させていただきます。
現在、2Dのゲームを、このサイトを参考にさせていただきながら、作っているのですが、
プログラミング、そして数学の知識、経験ともに浅く、行き詰ってしまいました。

行き詰った処理というのは、プレイヤーの腕のスプライトの描画処理で、

  マウスの位置によって、腕の角度を変えるために胴体と腕のつなぎ目部分の座標値から、マウスの座標を引くなどして、
  直角三角形の底辺と垂直辺の長さを出して、それをタンジェントに変換 ( y/x) して、
  それをタンジェントから、ラジアンを出す、atan関数に渡し、戻り値を角度に直し、角度によって、スプライトのインデックスを変更し、スプライトの表示を変える。

という、処理です。

一応、コードは書けたのですが、結果が思うように動かず、四苦八苦しています。

ソース。

GetMousePoint( &mx, &my ); //// カーソル座標取得

if(( mx - ( px + 32 )) >= 0 ){ //// マウスカーソルがPlayerの右側にあるとき ////
tgx = mx - ( px + 32 );
tgsangle = 1; //// 表示するスプライトが右側のものか、否かのフラグ 1: 右 0: 左
}
else if((( px + 32 ) - mx) > 0 ){ //// マウスカーソルがPlayerの左側にあるとき ////
tgx = ( px + 32 ) - mx;
tgsangle = 0;            //// 表示するスプライトが右側のものか、否かのフラグ  1: 右 0: 左
}
else {
return 0;
}

if((( py + 16 ) - my ) >= 0 ){ //// マウスカーソルがPlayerの上側にあるとき ////
tgy = ( py + 16 ) - my;
tguangle = 1; //// 上か下か。 1: 上 0: 下
}
else if((my - ( py + 16 )) > 0 ){ //// マウスカーソルがPlayerの下側にあるとき ////
tgy = my - ( py + 16 );
tguangle = 0; //// 上か下か。 1: 上 0: 下
}
else {
return 0;
}

tgr = AngleOut( tgx, tgy ); //// tgr ( 角度格納用 ) に、AngleOut ( x,yの長さから、タンジェント出してラジアン。計算して角度を出す関数 ) に角度を格納。

if( tguangle ){

if( 90 >= tgr && tgr >= 65 ) wep_hgar_sprite = 0; //// 分かりやすいように、このときのスプライトを、 0_sprite とする。
else if( 65 > tgr && tgr >= 45 ) wep_hgar_sprite = 1; //// 同じく、 1_sprite
else if( 45 > tgr && tgr >= 25 ) wep_hgar_sprite = 2; //// 2_sprite
else if( 25 > tgr && tgr >= 5 ) wep_hgar_sprite = 3; //// 3_sprite
else if( 5 > tgr ) wep_hgar_sprite = 4; //// 4_sprite
}

else if( !tguangle ){

if( 5 > tgr ) wep_hgar_sprite = 4; //// 4_sprite 表示するスプライトは、上の4_spriteと同じため。
else if( 5 >= tgr && tgr > 25 ) wep_hgar_sprite = 5; //// 5_sprite
else if( 25 >= tgr && tgr > 45 ) wep_hgar_sprite = 6; //// 6_sprite
else if( 45 >= tgr && tgr > 65 ) wep_hgar_sprite = 7; //// 7_sprite
}


これで、どのようになるかというと、2_sprite, 3_sprite, 5_sprite, 6_sprite, 7_sprite は表示されず、ある程度すると、

  ○×.exe の 0x773915de でハンドルされていない例外が発生しました: 0xC0000094: Integer division by zero

と、表示されるか、

  ○×.ece は停止しました。

と出て、続行不可能になります。


どなたか、ご教示ください。


AngleOut関数 はこんなかんじです。

double AngleOut(
int x, int y //// それぞれ底辺、垂直線 ////
){

double r, tan; //// 角度、タンジェント 格納用 ////

tan = y / x; //// タンジェント格納 ////

r = atan( tan ) * ( 180.0 / 3.14159265358979 ); //// atan()でタンジェントからラジアンを出し、さらにラジアンを角度に変えて、r に格納 ////

return r;
}

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 18:27
by nil
コードタグを使用してください。
エラーの内容はint型変数が0で除算された、だと思うのですが、
とりあえずはデバッグモードなりを使ってどこでエラーが起こっているのかを調べましょう。

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 18:40
by softya(ソフト屋)
マルチポストですので相互リンクを行なって下さい。 → フォーラムルールhttp://dixq.net/board/board.html

「DXライブラリを用いた、ゲーム制作での三角関数等について。 こんにちは。私は、趣... - Yahoo!知恵袋」
http://detail.chiebukuro.yahoo.co.jp/qa ... 1297835247
補足は使ってしまっているので、向こうにはお礼を書いて、お礼にこちらで質問していることを書き添えて下さい。

向こうでatan2がヒントに出てますが使っていない理由ありますか?
※ こちらは相互リンクするまで回答を控えさせて頂きます。

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 19:10
by ulllllllr
すみません。
焦っていたもので、つい読み飛ばしてしまっていたようです。
ご指摘ありがとうございます。ただいま、知恵袋の http://detail.chiebukuro.yahoo.co.jp/qa ... 1297835247 のほうでも、お礼とリンクを張ってきました。

atan2 を使用しない理由ですが、ほかのプロジェクトで試しに使ってみた際、上手くいかなかったので、使用していません。
おそらく、自分の使い方がおかしかったのでしょうが、時間が惜しかったため、上手くいった、 atan を使っています。


コードタグも、すっかり忘れていました。申し訳ないです。
もう一度、コードタグをつけて、コードをあげたほうがいいでしょうか?


いまさらですが、OSは windows7 IDEは、 VisualStudio Express 2010 DXライブラリを使って開発をしています。

本当にいろいろと申し訳ないです。
深く反省して、次はないようにしていきたいです。

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 19:19
by softya(ソフト屋)
atan2を使ったほうがすっきりするのでatan2をオススメします。
そのまま使わずにx,yを逆にしたり+-をひっくり返す必要性があるかもしれません。

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 19:23
by ulllllllr
そうですか、ありがとうございます
今から、エラー箇所の特定など含めて、取り組みます。

大体、書き終わったら、今度はコードタグをしっかりつけて、コードを載せたいと思います。

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 19:36
by ulllllllr
atan2 に換えてみたところ、いつものようなエラーが起きなくなりました!
ありがとうございます!

変えた部分は、AngleOut 内部のみです。

コード:

double AngleOut(
	double x, double y		//// それぞれ底辺、垂直線 ////
){

	double r;		//// 角度 格納用 ////

	r = atan2( y, x ) * ( 180.0 / 3.14159265358979 );		//// atan()でタンジェントからラジアンを出し、さらにラジアンを角度に変えて、r に格納 ////

return r;
}
ただ、相変わらず、5, 6, 7_sprite は表示されないままです。
もうちょっと調べてきます。なにか、気になるところがありましたら、ぜひ教えてください。

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 20:09
by box
ulllllr さんが書きました:

コード:

		else if( 5  >= tgr && tgr > 25 ) wep_hgar_sprite = 5;            //// 5_sprite
		else if( 25 >= tgr && tgr > 45 ) wep_hgar_sprite = 6;           //// 6_sprite
		else if( 45 >= tgr && tgr > 65 ) wep_hgar_sprite = 7;           //// 7_sprite
5以下で、かつ、25より大きいなどという状況は起きるはずがないように思います。

あと、私だったら、もっと見やすくなるように下のように書きます。
まあ、好みの問題ですけど。
少なくとも、三角関数を使っているからには math.h をインクルードしているわけで、
処理系がせっかく用意してくれている円周率の値を使うのが筋ではないか、と。
バグを出さない最善と思われる方法は「自分でよけいなコードを書かないこと」だと思います。

コード:

#include <math.h>

double AngleOut(double x, double y)      //// それぞれ底辺、垂直線 ////
{
    return atan2(y, x) * 180.0 / M_PI;       //// atan()でタンジェントからラジアンを出し、さらにラジアンを角度に変えて、r に格納 ////
}

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 20:38
by ulllllllr
ありがとうございます!

本当ですね。今思えば、何でこんなミスを。。。


戻り値として、関数呼び出し等するやり方があるのですね。勉強になりました。
M_PIですが、私の環境だと、定義されていないと出てしまいます。


これまで、回答してくださった方々、本当にありがとうございました。
初めてのトピック(?)で、迷惑をかけてしまうこともありましたが、大変勉強になりました。
いつか、回答できるような立場になりたいです。
では。

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 20:45
by nil
M_PIはmath.hをincludeする前に
_USE_MATH_DEFINES
をdefineしないと定義されません。

Re: 逆三角関数等々。。。

Posted: 2012年11月27日(火) 20:54
by ulllllllr
ありがとうございます。