http://dixq.net/g/56.html
s13. sin,cosって何? シューティングの基本概念
を読ませて頂き気づいたことが一つあります。
現在、私もシューティングゲームを作っております。
多分、私のプログラムでは斜め移動の時に
普段より多い移動量が発生している気がします。
(説明が下手で申し訳ないです。)
Px,Py … 現在位置
Dx,Dy … フレームごとの移動量
speed … 速度
・各キー操作がなければ移動量は0になる。(ようは押している時だけ動く)
・キー操作ごとに毎フレームで現在位置に移動量(speed)を足しております。
ここからが本題なのですがspeedが3だと仮定します。
この時、斜め(右と上など)が押されている場合
移動量は3√2になりませんか?
違ったらすみません・・・。
もしそうならサイン、コサインを使うのかと思うのですが
角度がわからない場合はどうするのでしょうか?
例えば(10,420)から(500,100)に移動するといった場合など
角度がわかれば下記でいんですよね?
Dx += cos( angle ) * speed ; //x座標計算
Dy += sin( angle ) * speed ; //y座標計算
斜めの移動量について
Re:斜めの移動量について
移動前の座標と移動後の座標がわかっているならば,sin,cosは計算で求めることができます.
移動前の座標をA,移動後の座標をBとする時(例ならばA=(10,420),B=(500,100)),
cos = (Bx-Ax)/|AB|
sin = (By-Ay)/|AB|
Ax,BxはそれぞれA,Bのx座標を,Ay,ByはA,Bのy座標を表します.
|AB|はAとBの距離です.
角度(ラジアン)を求めたい場合は,
上式で求めた値をacos,asinなどの引数にすれば良いのではないでしょうか.
質問を取り違えていたり,計算式を間違えていたらすみません…….
それと,実装方法がわからないので私の勘違いである可能性が高いのですが,
「フレームごとの移動量」に加算する方法で合っていますか?
「現在位置」に加算する方が自然な気がするのですが…….
ちなみに,意図的にかどうかはわかりませんが,
ゲームによっては斜め方向の移動量を多くしたままのものもあります.
(私の知る限りではロックマンDASHがそうでした)
移動前の座標をA,移動後の座標をBとする時(例ならばA=(10,420),B=(500,100)),
cos = (Bx-Ax)/|AB|
sin = (By-Ay)/|AB|
Ax,BxはそれぞれA,Bのx座標を,Ay,ByはA,Bのy座標を表します.
|AB|はAとBの距離です.
角度(ラジアン)を求めたい場合は,
上式で求めた値をacos,asinなどの引数にすれば良いのではないでしょうか.
質問を取り違えていたり,計算式を間違えていたらすみません…….
それと,実装方法がわからないので私の勘違いである可能性が高いのですが,
「フレームごとの移動量」に加算する方法で合っていますか?
「現在位置」に加算する方が自然な気がするのですが…….
ちなみに,意図的にかどうかはわかりませんが,
ゲームによっては斜め方向の移動量を多くしたままのものもあります.
(私の知る限りではロックマンDASHがそうでした)
Re:斜めの移動量について
移動で角度が解らないような仕様なら仕方ないですが、
一般的な移動だけならsin,cosいらないんじゃないですか?
斜めといっても、45°だけなら(90+45°などは除く)
×√2ほど多いとわかっているなら、÷√2すればいいだけです。
龍神録の館でまさに同じ解説をしています。
http://dixq.net/rp/9.html
また、2点から角度を求める時はatan2が便利ですよ。
これも館に書いてあります。
http://dixq.net/rp/13.html
atan2で検索かけてもらえたらどこに書いてあるか解ると思います。
一般的な移動だけならsin,cosいらないんじゃないですか?
斜めといっても、45°だけなら(90+45°などは除く)
×√2ほど多いとわかっているなら、÷√2すればいいだけです。
龍神録の館でまさに同じ解説をしています。
http://dixq.net/rp/9.html
また、2点から角度を求める時はatan2が便利ですよ。
これも館に書いてあります。
http://dixq.net/rp/13.html
atan2で検索かけてもらえたらどこに書いてあるか解ると思います。
Re:斜めの移動量について
やはり移動量が多いんですか・・・。
知らなかった・・・ww
>>mats 様
すみません。現在位置に加算しております。
whileの最後に
Px += Dx;
Py += Dy;
と書いて移動させているように見せております。
>>Dixq (管理人) 様
管理人様からご回答頂けるとは感激です><
いつも制作したゲームをプレイさせて頂いております。
話はそれますがエアロビート面白かったです。
ただ一つ問題が御座いまして
私が以前購入したノートパソコンでは画像が乱れてしまいます。
※多分グラフィックボードの問題です。
そのPCではDXライブラリを使うと画像がおかしくなります。
但し3D機能のフラグをfalseにすると使えました。
(実家にあるのでご興味が御座いましたら型番調べます。)
atan2をみたのですが引数が2つしかなくないでしょうか?
(10,420)から(500,100)の角度を求める場合
4つ必要ではないでしょうか?
あまりsin,cosが得意ではないのですが
具体的にDx,Dyの移動量はどう変化するのでしょうか?
知らなかった・・・ww
>>mats 様
すみません。現在位置に加算しております。
whileの最後に
Px += Dx;
Py += Dy;
と書いて移動させているように見せております。
>>Dixq (管理人) 様
管理人様からご回答頂けるとは感激です><
いつも制作したゲームをプレイさせて頂いております。
話はそれますがエアロビート面白かったです。
ただ一つ問題が御座いまして
私が以前購入したノートパソコンでは画像が乱れてしまいます。
※多分グラフィックボードの問題です。
そのPCではDXライブラリを使うと画像がおかしくなります。
但し3D機能のフラグをfalseにすると使えました。
(実家にあるのでご興味が御座いましたら型番調べます。)
atan2をみたのですが引数が2つしかなくないでしょうか?
(10,420)から(500,100)の角度を求める場合
4つ必要ではないでしょうか?
あまりsin,cosが得意ではないのですが
具体的にDx,Dyの移動量はどう変化するのでしょうか?
Re:斜めの移動量について
>やはり移動量を求めるのはできないのでしょうか・・・。
三角関数をちゃんと使えば求められますよ。
>あまりsin,cosが得意ではないのですが
シューティングにおいて重要すぎる知識ですので、この機会にちゃんと理解された方が良いでしょう。
ここの管理人さんが書かれたsin,cosの説明です。
http://dixq.net/g/56.html
こちらとかも。
http://www8.plala.or.jp/ap2/suugaku/san ... shoho.html
>atan2をみたのですが引数が2つしかなくないでしょうか?
>(10,420)から(500,100)の角度を求める場合
>4つ必要ではないでしょうか?
まずtanを理解することから始めましょう。
さきほど紹介したサイトの下のほうにtanがありますね。
http://www8.plala.or.jp/ap2/suugaku/san ... shoho.html
tanθ=a/bって事が分かると思います。
わかりやすく書くとtanθ=y/xってことですね。
角度θからxとyの座標の比率が分かります。
atanはアークタンジェントって事でtanの逆三角関数です。
逆三角関数を単純に言うとy/xからθを求めることが出来る関数なんですが、yの距離、xの距離から角度θを求めることが出来ます。
なので、atan2に与えるパラメータは、ぞれぞれxとyの距離です。
atan2(y2-y1,x2-x1)
って事ですね。2つしかパラメータがいらない理由は分かりましたか?
それとベクトルと言う概念も重要です。
すでに、
Px += Dx;
Py += Dy;
のDx,Dyと言う形で利用されている訳ですけどね。
http://w3e.kanazawa-it.ac.jp/math/categ ... ector.html
http://w3e.kanazawa-it.ac.jp/math/categ ... okisa.html
色々書きましたが、分からなかったら聞いてください。
三角関数をちゃんと使えば求められますよ。
>あまりsin,cosが得意ではないのですが
シューティングにおいて重要すぎる知識ですので、この機会にちゃんと理解された方が良いでしょう。
ここの管理人さんが書かれたsin,cosの説明です。
http://dixq.net/g/56.html
こちらとかも。
http://www8.plala.or.jp/ap2/suugaku/san ... shoho.html
>atan2をみたのですが引数が2つしかなくないでしょうか?
>(10,420)から(500,100)の角度を求める場合
>4つ必要ではないでしょうか?
まずtanを理解することから始めましょう。
さきほど紹介したサイトの下のほうにtanがありますね。
http://www8.plala.or.jp/ap2/suugaku/san ... shoho.html
tanθ=a/bって事が分かると思います。
わかりやすく書くとtanθ=y/xってことですね。
角度θからxとyの座標の比率が分かります。
atanはアークタンジェントって事でtanの逆三角関数です。
逆三角関数を単純に言うとy/xからθを求めることが出来る関数なんですが、yの距離、xの距離から角度θを求めることが出来ます。
なので、atan2に与えるパラメータは、ぞれぞれxとyの距離です。
atan2(y2-y1,x2-x1)
って事ですね。2つしかパラメータがいらない理由は分かりましたか?
それとベクトルと言う概念も重要です。
すでに、
Px += Dx;
Py += Dy;
のDx,Dyと言う形で利用されている訳ですけどね。
http://w3e.kanazawa-it.ac.jp/math/categ ... ector.html
http://w3e.kanazawa-it.ac.jp/math/categ ... okisa.html
色々書きましたが、分からなかったら聞いてください。
Re:斜めの移動量について
回答ありがとうございます。
引数の意味はそういうことでしたか・・・。
かなり難しいですね。というか複雑・・・。
理解できたかわからないのですが
現在位置から(600,40) へspeedで移動する場合は
下記の移動量ということであっているでしょうか?
// (Play.Px,Play.Py) から(600,40) へ移動する
float tan = atan2(40-Play.Py,600-Play.Px);
Play.Mx = cos(tan) * Play.Speed;
Play.My = sin(tan) * Play.Speed;
引数の意味はそういうことでしたか・・・。
かなり難しいですね。というか複雑・・・。
理解できたかわからないのですが
現在位置から(600,40) へspeedで移動する場合は
下記の移動量ということであっているでしょうか?
// (Play.Px,Play.Py) から(600,40) へ移動する
float tan = atan2(40-Play.Py,600-Play.Px);
Play.Mx = cos(tan) * Play.Speed;
Play.My = sin(tan) * Play.Speed;
Re:斜めの移動量について
>float tan = atan2(40-Play.Py,600-Play.Px);
>Play.Mx = cos(tan) * Play.Speed;
>Play.My = sin(tan) * Play.Speed;
あって良ると思います。
ただ、tanは関数名とかぶるので、rとかradianとか角度を表す名前にした方が良いでしょう。
>Play.Mx = cos(tan) * Play.Speed;
>Play.My = sin(tan) * Play.Speed;
あって良ると思います。
ただ、tanは関数名とかぶるので、rとかradianとか角度を表す名前にした方が良いでしょう。
Re:斜めの移動量について
> 話はそれますがエアロビート面白かったです。
プレイして頂きありがとうございます^^
最近更新が出来ていませんが、時間を見つけて更新したいと思います;
> かなり難しいですね。というか複雑・・・。
あ~こういう場合は、関数をある種のブラックボックス化して考えてしまえばいいんですよ^^
中身の動作アルゴリズムはわからなくとも「これを渡したらあれが返ってくる」という仕組みだけわかればよいのです。
そのもの自身の仕組みを全て理解して利用することが一番良いことですが、そんなこと現実的に不可能な場合が多いです。
全て理解するまでそれが使えないより、使い方さえ理解して、出来る事の幅を広げた方が良いですよね?
例えばシャープシューターさんがテレビを見ていたとしましょう。
チャンネルを変える時、電源ボタンを押せばTVのスイッチが入りますが、
リモコンにどのような信号が走って、TVの電子回路にどのような電気信号が流れるか、全て理解していなくても使えていますよね?
仕組みを全て理解するより、その使い方を理解することの方が大事なこともあります。
ということで、今回、「移動元」と「移動先」を渡したらその方向の角度を返す関数を作ってみます。
仰っている内容から4つ引数を渡す方が解りやすそうなので、こんな感じで用意しました
これから先はatan2がアークタンジェントを利用してて、アークタンジェントっていうのは逆正弦と逆余弦が・・なんて考えなくても今作ったGetAtan2Angle関数に移動元の座標と移動先の座標を渡せばそちらの方向の角度が返るのだとだけ解っていればいいのです。
プレイして頂きありがとうございます^^
最近更新が出来ていませんが、時間を見つけて更新したいと思います;
> かなり難しいですね。というか複雑・・・。
あ~こういう場合は、関数をある種のブラックボックス化して考えてしまえばいいんですよ^^
中身の動作アルゴリズムはわからなくとも「これを渡したらあれが返ってくる」という仕組みだけわかればよいのです。
そのもの自身の仕組みを全て理解して利用することが一番良いことですが、そんなこと現実的に不可能な場合が多いです。
全て理解するまでそれが使えないより、使い方さえ理解して、出来る事の幅を広げた方が良いですよね?
例えばシャープシューターさんがテレビを見ていたとしましょう。
チャンネルを変える時、電源ボタンを押せばTVのスイッチが入りますが、
リモコンにどのような信号が走って、TVの電子回路にどのような電気信号が流れるか、全て理解していなくても使えていますよね?
仕組みを全て理解するより、その使い方を理解することの方が大事なこともあります。
ということで、今回、「移動元」と「移動先」を渡したらその方向の角度を返す関数を作ってみます。
仰っている内容から4つ引数を渡す方が解りやすそうなので、こんな感じで用意しました
#include <stdio.h> #include <math.h> float GetAtan2Angle( float FromX, float FromY, float ToX, float ToY ){ return atan2( (ToY-FromY), (ToX-FromX) ); } int main(){ float ang; ang = GetAtan2Angle( 10, 420, 500, 100 ); printf("%f\n",ang); return 0; }
これから先はatan2がアークタンジェントを利用してて、アークタンジェントっていうのは逆正弦と逆余弦が・・なんて考えなくても今作ったGetAtan2Angle関数に移動元の座標と移動先の座標を渡せばそちらの方向の角度が返るのだとだけ解っていればいいのです。