数日も間が開かない質問失礼します。
今、3Dでアクションゲームを作っています。
自機がロックオンした敵を中心にコントローラーの右を押すと反時計回りに、左で時計回りに円を描いて動くようにしたいです。
http://dixq.net/forum/viewtopic.php?f=3&t=5036
http://dixq.net/forum/viewtopic.php?t=9605&p=77514
http://dixq.net/forum/viewtopic.php?f=3&t=4050#wrap
このあたりが参考になるとは思うのですが(特に3つ目)「現在の角度」「回転させたい角度」「オプションの角度」
など「角度」という言葉がよく出てきますが、これがどこの角度を指し、どのように求めるのかわかりません。
自機座標をJ(Jx,Jy,Jz)、敵座標をT(Tx,Ty,Tz)しています。
また、敵と自機との距離は別のトピックに掲載されていた「距離^2=(x-x2)^2+(y-y2)^2」を使って求めることができています。これをKyoriとしています。
また、動く速さはSpeedです。また、Y軸については考慮せずxz平面で考えています。
これらの変数から、敵座標を中心とした自機の回転運動をさせることは可能でしょうか?
また、その方法のご教授お願いします。
環境:Windows7 C++ VisualStudio2008 DXライブラリ
敵を中心とした自機の回転運動
Re: 敵を中心とした自機の回転運動
まずは自分で問題を簡単にしていくことが大事だと思います。
3Dとありますが、
リンクされたトピックにはカメラワークに関する記述があるようですが、
与えられた情報(自機の座標及び敵の座標)をもとにして
「敵の座標を中心として自機の座標を回転させる」
ということのみを考えるのであれば関係ないことです。
2Dにおいて、任意の座標を中心として他の任意の座標を任意の角度で回転させる手法というのは
それこそ調べればたくさん出てくると思いますが、
まずは簡略化された以下の問題は解けますでしょうか?
問:点J(3,5)がある。原点を中心にしてPを右回りに30°回転させた座標を求めよ。
まずは可能か限り問題を簡単にして、一つづつクリアしていくとよいかと。
(この場合なら3D→2D、 任意の座標を中心とする→原点を中心とするなど)
3Dとありますが、
とした時点で1自由度減っているのでこれは2Dの問題です。Y軸については考慮せずxz平面で考えています
リンクされたトピックにはカメラワークに関する記述があるようですが、
与えられた情報(自機の座標及び敵の座標)をもとにして
「敵の座標を中心として自機の座標を回転させる」
ということのみを考えるのであれば関係ないことです。
2Dにおいて、任意の座標を中心として他の任意の座標を任意の角度で回転させる手法というのは
それこそ調べればたくさん出てくると思いますが、
まずは簡略化された以下の問題は解けますでしょうか?
問:点J(3,5)がある。原点を中心にしてPを右回りに30°回転させた座標を求めよ。
まずは可能か限り問題を簡単にして、一つづつクリアしていくとよいかと。
(この場合なら3D→2D、 任意の座標を中心とする→原点を中心とするなど)
Re: 敵を中心とした自機の回転運動
返信遅くなってしまって申し訳ありません。
おかげ様で角度が何かという点や実際の計算の仕方も実装することができました。
しかしまた違った問題が出てきました。
現在、”右をしばらく押してから左を押す、またはその逆”をすると自機がワープしてしまいます。
敵を中心とした円の座標のどこかへ行ってしまいます。
「計算に使っている変数がいきなりプラス・マイナスを切り替えるからか?」
と思って改造したのですがどうにもうまくいきません。
どのあたりがおかしいのでしょうか?
ソースの関係あるところを抜き出して掲載します。
ヘッダーファイル
cppファイル
おかげ様で角度が何かという点や実際の計算の仕方も実装することができました。
しかしまた違った問題が出てきました。
現在、”右をしばらく押してから左を押す、またはその逆”をすると自機がワープしてしまいます。
敵を中心とした円の座標のどこかへ行ってしまいます。
「計算に使っている変数がいきなりプラス・マイナスを切り替えるからか?」
と思って改造したのですがどうにもうまくいきません。
どのあたりがおかしいのでしょうか?
ソースの関係あるところを抜き出して掲載します。
ヘッダーファイル
//自機クラス
#ifndef JIKI_H
#define JIKI_H
#include "Object.h"
class Jiki : public Object
{
private:
int Pad;//ボタンの入力状態格納用変数
float ChangeS;//現在の自機の敵に対する角度
float ActionChangeS;//自機が敵に対して動く角度
float JikiX,JikiZ;//自機のX,Z座標を計算用に代入する変数
float TekiX,TekiZ;//敵のX,Z座標を計算用に代入する変数
float Kyori;//自機と敵の距離
int RLflg;//右、左入力感知用フラグ
int SaveRLflg;//前回のフラグを保存
public:
Jiki();//コンストラクタ
void ModelLoad();//モデルのロード
void FirstPos();//モデルの初期位置
void Action(int JoyPad,VECTOR TekiPos);//モデルの操作、動作
void StickPoint(int jSX,int jSY,int JoyPad);//スティックの入力値を簡易数に変換する
void Update(int Joypad,VECTOR TekiPos,int SX,int SY);//アップデート
~Jiki();//デストラクタ
};
#endif
//自機クラス
#include "Jiki.h"
#include<math.h>//平方根やべき乗の計算
Jiki::Jiki()//コンストラクタ
{
ModelLoad();
FirstPos();
ChangeS = -(DX_PI_F / 2.0f);
ActionChangeS = 0;
RLflg = 0;
SaveRLflg = 0;
}
//モデルのロード
void Jiki::ModelLoad()
{
ModelHandle = MV1LoadModel("3DGraphics/jiki1.mqo");
}
//モデルの初期位置
void Jiki::FirstPos()
{
ModelPos = VGet(0.0f,0.0f,-150.0f);//初期位置
}
//スティックの入力値から移動速度を出す
void Jiki::StickPoint(int jSX, int jSY,int JoyPad)
{
///////////////////////////////////////////////////////////////////////
//ここで移動角度をリセットしようとしてみましたがこれでもやはりワープしてしまいます
///////////////////////////////////////////////////////////////////////
//右ボタンを押した時フラグ
if(JoyPad & PAD_INPUT_RIGHT)//→ボタン
{
RLflg = 1;
}
//左ボタンを押した時フラグ
else if(JoyPad & PAD_INPUT_LEFT)//←ボタン
{
RLflg = 0;
}
//フラグを前回のフラグと比べる
if(RLflg != SaveRLflg)
{
//前回の入力と逆なら移動角度をリセット
ActionChangeS = 0;
}
//フラグ保存
SaveRLflg = RLflg;
////////////////////////////////////////////////////////////////////////////
//スティック入力角度に対する移動量
if((jSX>=1 && jSX<=700)||(jSY>=1 && jSY<=700))
{
ActionChangeS += DX_PI_F / 72.0f;
}
if((jSX>=701 && jSX<=999) || (jSY>=701 && jSY<=999))
{
ActionChangeS += DX_PI_F / 36.0f;
}
if(jSX == 1000 || jSY==1000)
{
ActionChangeS += DX_PI_F / 18.0f;
}
}
////////////////////////////////////////////////////////
//モデルの操作、動作
////////////////////////////////////////////////////////
void Jiki::Action(int Joypad,VECTOR TekiPos)
{
//自機、敵座標を計算しやすい型に変換
JikiX = ModelPos.x;
JikiZ = ModelPos.z;
TekiX = TekiPos.x;
TekiZ = TekiPos.z;
//敵と自機の距離
Kyori = pow((TekiX - JikiX),2)+pow((TekiZ-JikiZ),2);
Kyori = sqrt(Kyori);
//右ボタンを押した時反時計回り
if(Joypad & PAD_INPUT_RIGHT)//→ボタン
{
JikiX = Kyori*cos(ChangeS+ActionChangeS)+TekiX;
JikiZ = Kyori*sin(ChangeS+ActionChangeS)+TekiZ;
}
//左ボタンを押した時時計回り
if(Joypad & PAD_INPUT_LEFT)//←ボタン
{
JikiX = Kyori*cos(ChangeS-ActionChangeS)+TekiX;
JikiZ = Kyori*sin(ChangeS-ActionChangeS)+TekiZ;
}
//位置をセット
ModelPos.x = JikiX;
ModelPos.z = JikiZ;
MV1SetPosition(ModelHandle,ModelPos);
}
////////////////////////////////////////////////////////
void Jiki::Update(int Joypad,VECTOR TekiPos,int jSX,int jSY)
{
StickPoint(jSX,jSY,Joypad);
Action(Joypad,TekiPos);
}
//デストラクタ
Jiki::~Jiki()
{
//モデルの開放
MV1DeleteModel(ModelHandle);
}
Re: 敵を中心とした自機の回転運動
すみません。自己解決しました。
ChangeSやActionChangeSの値を思ったとおりに動かせるまで苦労しました。
いちおう、ちゃんとできたソース貼っておきます。
ありがとうございました。
Jiki.cpp
ChangeSやActionChangeSの値を思ったとおりに動かせるまで苦労しました。
いちおう、ちゃんとできたソース貼っておきます。
ありがとうございました。
Jiki.cpp
//スティックの入力値から移動速度を出す
void Jiki::StickPoint(int jSX, int jSY,int JoyPad)
{
//右ボタンを押した時フラグ
if(JoyPad & PAD_INPUT_RIGHT)//→ボタン
{
RLflg = 1;
}
//左ボタンを押した時フラグ
else if(JoyPad & PAD_INPUT_LEFT)//←ボタン
{
RLflg = 0;
}
//フラグを前回のフラグと比べる
if(RLflg != SaveRLflg)
{
//前回の入力と逆なら移動角度をリセット
ActionChangeS = 0;
}
//フラグ保存
SaveRLflg = RLflg;
//スティック入力角度に対する移動量
if((jSX>=1 && jSX<=700)||(jSY>=1 && jSY<=700))
{
ActionChangeS = DX_PI_F / 72.0f;
}
if((jSX>=701 && jSX<=999) || (jSY>=701 && jSY<=999))
{
ActionChangeS = DX_PI_F / 36.0f;
}
if(jSX == 1000 || jSY==1000)
{
ActionChangeS = DX_PI_F / 18.0f;
}
}
////////////////////////////////////////////////////////
//モデルの操作、動作
////////////////////////////////////////////////////////
void Jiki::Action(int Joypad,VECTOR TekiPos)
{
//自機、敵座標を計算しやすい型に変換
JikiX = ModelPos.x;
JikiZ = ModelPos.z;
TekiX = TekiPos.x;
TekiZ = TekiPos.z;
//敵と自機の距離
Kyori = pow((TekiX - JikiX),2)+pow((TekiZ-JikiZ),2);
Kyori = sqrt(Kyori);
//右ボタンを押した時反時計回り
if(Joypad & PAD_INPUT_RIGHT)//→ボタン
{
ChangeS = ChangeS+ActionChangeS;
JikiX = Kyori*cos(ChangeS)+TekiX;
JikiZ = Kyori*sin(ChangeS)+TekiZ;
}
//左ボタンを押した時時計回り
if(Joypad & PAD_INPUT_LEFT)//←ボタン
{
ChangeS = ChangeS-ActionChangeS;
JikiX = Kyori*cos(ChangeS)+TekiX;
JikiZ = Kyori*sin(ChangeS)+TekiZ;
}
//一周回ったらリセット
if(ChangeS >= DX_PI_F*2 || ChangeS <= DX_PI_F*-2)
{
ChangeS = 0;
}
//位置をセット
ModelPos.x = JikiX;
ModelPos.z = JikiZ;
MV1SetPosition(ModelHandle,ModelPos);
}