自機狙いが自機狙いされない

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

自機狙いが自機狙いされない

#1

投稿記事 by カレンレン » 7年前

現在c++でSTGを作っているのですが、自機狙いの座標取得の際、プレイヤーの座標を正しく読み込みませんでした。
過去ログに解決策があり、そちらを試したところ今度はcontrolクラスが生成されないようになりました

main.cppには  CONTROL* control = &CONTROL::GetInstance();

CONTROL.h には

コード:

class CONTROL
{
private:
	PLAYER *player;
	ENE *enemy;
private:
	CONTROL();
public:
	~CONTROL();
	void GetPlayerPosition(double *x, double *y);
	void GetEnemyPosition(double *x, double *y);
	bool CircleJudge(double, double, double, double, double, double);
	void JudgeAll();
	static CONTROL& GetInstance() {
		static CONTROL control;
		return control;
	}
	void ALL();
};
と書いてます。
ブレークポイントを追うと
1 static CONTROL& GetInstance() {
2 static CONTROL control;
3 static CONTROL& GetInstance() {
4 static CONTROL control;
となり、これ以上は進みません(コンパイル自体はとおります)
c++は最近知ったばかりで時間もなく困ってます、どなたか原因がわかる方ご指導お願いします。

fm

Re: 自機狙いが自機狙いされない

#2

投稿記事 by fm » 7年前

あー、これは、publicになってれば外部関数でもクラスを宣言することで
容易に取得できますが、あるいはprotectedか、virtualかどうか自機のクラスのメンバの
状態を確認してください。privateだと、外部から取得は出来ないと思います。

自分はC++は入門レベルなので、あまり言えないですが、自機狙いのプログラムは
いくつか研究したことがあります。

で、自分の感覚で言うと、自機の座標に向かって移動するアルゴリズムをいくつか紹介したいと思います。

1.ベクトルとベクトルの正規化を使う
(50,20)から(100,200)に弾を発射したい場合、
(100-50,200-20)とすれば差分が求まります。
すると、差分は、(50,180)となりますが、そのまま足したら1フレーム後に到着してしまいます。
なので、ベクトルというか差分を大きさの1のベクトルの大きさにしてから速さを決めてやれば
良いと思います。(ただし、これは某書籍にも載ってました)
そのため、50,180を50*50+180*180として、34900で50と180を割ってやる必要が出てきます。
すると正規化したベクトルは(0.0014,0.00515)となります。これを1000倍すると、
(1.4,5.15)となり、確かに、正確な移動量となります。(これを固定小数点で表せないか???)

2.アークタンジェントを使う
tan(タンジェント)という関数を知っているかと思いますが、これは単に半径r=1のY/Xの1次関数で
いうところの、傾きでしかありません。その傾きの角度アルファが分かっている場合に、tanの傾きが分かります。
逆に、角度アルファが分からない場合、どうするかというと、Y/Xの傾きから角度を導きだすのが、
tan(タンジェント)の逆関数であるアークタンジェントです。その場合は、0度~359度を出すためにc言語などでは
atan2関数を使います。角度が分かればあとは、
x+=cos(角度をラジアンに変換してください);、y+=sin(角度をラジアンに変換してください);
とすれば、目的の座標に到達できると思います。

3.自作アークタンジェントを使う
YとXの差分が分かるなら、敵の座標を中心として、自機の座標がどこの象限にいるのかを確認したうえで
DY/DXを求めると、案外、簡単に求まります。その際には、tan0°~tan359°までをテーブル化したうえで
傾きとDY/DXを誤差を確認したうえで求める事ができますが、2分探索もしくは線形探索で求めると
良いと思います。

4.線形補完を使う
何かの画像処理のウェブサイトともう1つの情報源から分かったことですが、
変数Nが0から1まで小数点で表すか固定小数点として式を変形する必要がありますが、
X'=X1*(1-N)+X2*Nとし、Y'をY1とY2から同様も求められます。
として計算すると求まります。固定小数点で求めたい場合もあると思いますが、自分は8ビット整数で行いたい
のです。しかし、2バイト整数で求めたいというもしもその際は、S=64としてX3=X1*(S-N)/S+X2*N/Sとして、
yにも適応させると8ビットより上の固定小数でもいけます。

5.線分描画のアルゴリズムを使う
8ビットでも可能な値で使いたいなら、精度を甘くても良いならおススメです。
(0)スピードを1にする(誤差を最小限にしたいのと、ゆっくり確認したいため)
(1)X方向、Y方向の差分の絶対値をそれぞれ求めて2で割り、大きい方を変数Distanceとする
 (マイナスならプラスにすればいい
(2)VX=(JikiX-TekiX)/(Distance/2)*スピード;
VYも同様に求める

6.1次関数を変形する
直線の関数は中学校で習ったと思いますが、傾きはY座標の差分/X座標の差分で求まります。
しかし、式を変形しないと出来ません。
y=(Y2-y1)/(X2-X1)*x+y切片だったはずです。

int px,px1,px2;
int py,py1,py2;
double a;
px=px1
a=(py2-py1)/(px2-px1);py=py1;
while(1){
px+=1;
DrawPixel(px,py,c);
py=py+a;
}

上記の計算式はまだ8ビットの固定小数に精度は悪いですが直せるほど簡単です。

7:あってるかどうかは未定です。
自機に向かって移動する弾は精度をよくするためには、ゆっくりと動かさないと8ビット整数に
適応できません。
極端にYとXそれぞれの差分の差が大きすぎない限り、右シフトを行えば、いつかは8以下になります。
(50,28)から(128,224)に移動したい場合、差分は(78,196)となり、8以下にするためには、/2を何回やれば
良いかを検討を付けると、DXの方が小さいのを考慮して、/16すればいい事がわかります。
そのため、X座標かY座標の差分の小さい方が8以下になるまで右シフトをすれば移動量の増分が求まるはず
です。
しかし、極端な例を出すのは忍びないのですが、(100,3)から(105,255)に移動したい場合、
差分は(5,252)となり、あきらかに小さいXの差分は8以下なのに、そううまく動いてくれません。
ものごとには例外はありますが、ゲームプログラム内で例外を作る事はちょっとあまり良くないです。

8:sinとcosのテーブル化
まず、前提となる条件は8ビットでは360°周期の三角関数のテーブルは収まらないということです。
まず、三角関数は、画面の上にいる自機に弾を動かしてはならないという一種のルールを設けたり、
360°周期の三角関数のテーブルを2°刻みずつ与えてやればなんと90°周期分ですみます。あるいは、
4°刻みなら45°周期ですみます。
あるいは、360°周期の三角関数を255+104として、2バイトで扱うなら、テーブルが複雑化して
しまいますが、確実に360°周期の三角関数を扱えます。あるいは、256度周期にしたりする場合は、
for(int i=0;i<255;i++)
{
CT=COS(I*(3.14159265/128))
ST=SIN(I*(3.14159265/128))
}
で良いと思います。
あとは、シフト演算との兼ね合いで2のN乗の振幅で与えたりすれば
収まってしまいます。
このソースコードと線分描画アルゴリズムを使えば三角関数をできるだけ振幅を大きくしてやれば任意の座標に
x,yを指定できます。

たいちう
記事: 418
登録日時: 13年前

Re: 自機狙いが自機狙いされない

#3

投稿記事 by たいちう » 7年前

> c++は最近知ったばかりで時間もなく困ってます、どなたか原因がわかる方ご指導お願いします。

提示された部分には問題がないと思います。
実行できるよう最低限の追加をしたのが次のプログラムです。

コード:

class PLAYER;
class ENE;

class CONTROL
{
private:
	PLAYER *player;
	ENE *enemy;
private:
	CONTROL() {}
public:
	virtual ~CONTROL() {}
	void GetPlayerPosition(double *x, double *y);
	void GetEnemyPosition(double *x, double *y);
	bool CircleJudge(double, double, double, double, double, double);
	void JudgeAll();
	static CONTROL& GetInstance() {
		static CONTROL control;
		return control;
	}
	void ALL();
};

int main() {
	CONTROL* control = &CONTROL::GetInstance();
	return 0;
}
> 1 static CONTROL& GetInstance() {
> 2 static CONTROL control;
> 3 static CONTROL& GetInstance() {
> 4 static CONTROL control;

と書かれているので、CONTROLのコンストラクタで余計なことをしていませんか?

カレンレン

Re: 自機狙いが自機狙いされない

#4

投稿記事 by カレンレン » 7年前

>CONTROLのコンストラクタで余計なことをしていませんか?
調べたところENEのコンストラクタでCONTROLのインスタンスをよんでいました・・・
たいちうさんありがとうございます。
fmさんの情報も参考にします。

閉鎖

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