自機の座標の取得について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kar
記事: 15
登録日時: 10年前

自機の座標の取得について

#1

投稿記事 by kar » 10年前

STG制作での質問です。今私はこちらのサイトhttp://bituse.info/game/shot/13と龍神禄を参考にC++でのSTG制作を勉強しているのですが、
自機(Player)の座標が正確に取得できず困っています。
自分で色々と調べてみたところ以下のコードのPLAYER::GetPositionが自機の初期位置(x=180,y=420)を代入してしまっている事が分かりました。
おそらくこれが原因だと思うのですが、解決方法が分かりませんでした。
私のイメージではPLAYER::GetPositionは自機の今現在の座標を*x,*yに代入するものだと思っていたのですが、上記のように意図した座標とは違う値が代入されていました。
どのようにすれば正確な自機の座標が取得できるのでしょうか?。稚拙な文章で申し訳ありませんがどなたかアドバイスをお願いします。

コード:

#include "pch.h"
#include "player.h"
#include "control.h"

PLAYER::PLAYER(){ 
	 
	gh=LoadGraph("dat/画像/自機/001.png");
	psgh=LoadGraph("dat/画像/自機/ショット/0.png");

	memset(shot,0,sizeof(shot));

    speed=3.0; //スピード

	count=0;//カウント

	//初期位置
    x=180; 
	y=420; 
	//移動制御
	sayu=zyoge=0;
	naname=1.0;

    life=true;// 生きてるかどうか

	for(int i=0;i<PSHOT_MAX;i++){
		shot[i].flag=false;
		shot[i].gh=psgh;
	}
} 
//現在のplayerの位置を代入//(バグ)初期位置が代入されている
void PLAYER::GetPosition(double *x,double *y){
	
	*x=this->x;
	*y=this->y;
	//DrawFormatString(50,50,GetColor(255,255,255),"player差出座標(%f,%f)",this->x,this->y);
}

void PLAYER::Move(){
	sayu=zyoge=0;
	naname=1.0;
	//左右どちらかの入力があったら
	if(key[KEY_INPUT_RIGHT]==1 || key[KEY_INPUT_LEFT]==1){
		sayu=1;
	}
	//上下どちらかの入力があったら
	if(key[KEY_INPUT_UP]==1 || key[KEY_INPUT_DOWN]==1){
		zyoge=1;
	}
	//左右、上下どちらも押されていたら
	if(sayu == 1 && zyoge == 1){
		naname=sqrt(2.0);
	}
	
	//キャラの移動
	if(key[KEY_INPUT_RIGHT]==1){
		x+=speed/naname;
	}
	if(key[KEY_INPUT_LEFT]==1){
		x-=speed/naname;
	}
	if(key[KEY_INPUT_UP]==1){
		y-=speed/naname;
	}
	if(key[KEY_INPUT_DOWN]==1){
		y+=speed/naname;
	}

	//キャラの移動制御
	if(x<FIELD_START_X){
		x+=speed/naname;
	}
	if(x>FIELD_MAX_X){
		x-=speed/naname;
	}
	if(y<FIELD_START_Y){
		y+=speed/naname;
	}
	if(y>FIELD_MAX_Y){
		y-=speed/naname;
	}

}

void PLAYER::Shot(){
	//発射出来る弾を探しフラグを立てる
	if(key[KEY_INPUT_Z]==1 && count%6==0){
		for(int i=0;i<PSHOT_MAX;i++){
			if(shot[i].flag==false){
				shot[i].flag=true;
				shot[i].angle=-PI/2;
				shot[i].speed=10;
				shot[i].x=x;
				shot[i].y=y;
				break;
			}
		}
	}

	//フラグの立っている弾の移動
	for(int i=0;i<PSHOT_MAX;i++){
		double h_x=shot[i].speed+17/2;//スピード+自機画像/2
		double h_y=shot[i].speed+21/2;
		
		if(shot[i].flag==true){
			shot[i].y+=sin(shot[i].angle)*shot[i].speed;
			shot[i].x+=cos(shot[i].angle)*shot[i].speed;
		}
		//画面外の弾のフラグをおろす
		if(shot[i].x < -h_x || shot[i].x > FIELD_MAX_X+h_x || shot[i].y < -h_y || shot[i].y > FIELD_MAX_Y+h_y){
			shot[i].flag=false;
		}
	}	
}

void PLAYER::Draw(){
	//プレイヤーの描画
	if(life){
		DrawRotaGraph(x,y,1.0,0.0,gh,TRUE);
	}

	//弾の描画
	for(int i=0;i<PSHOT_MAX;i++){
		if(shot[i].flag==true){
			DrawRotaGraph(shot[i].x-12,shot[i].y,1.0,shot[i].angle+(-PI/2),shot[i].gh,TRUE);
			DrawRotaGraph(shot[i].x+12,shot[i].y,1.0,shot[i].angle+(-PI/2),shot[i].gh,TRUE);
		}
	}
	//DrawFormatString(50,20,GetColor(255,255,255),"player座標(%f,%f)",this->x,this->y);
	
}

void PLAYER::All(){
	Move();
	Shot();
	Draw();
	count++;
}
最後に編集したユーザー kar on 2014年3月23日(日) 19:22 [ 編集 1 回目 ]

kar
記事: 15
登録日時: 10年前

Re: 自機の座標の取得について

#2

投稿記事 by kar » 10年前

追記です。私はこの構成http://bituse.info/game/shot/2を参考にして作っています。
質問の件なのですが、
DrawFormatStringで今現在の座標を表示するなどしてみたところGetPosition以外の関数(MoveやShot,Draw)の中ではちゃんと座標が表示されるのですが、やはりGetPositionの中だけで初期座標が表示されてしまいます。
なにか初歩的な勘違いをしてしまっているのでしょうか?。

アバター
nullptr
記事: 239
登録日時: 12年前

Re: 自機の座標の取得について

#3

投稿記事 by nullptr » 10年前

不正な値を検出する、GetPositionを呼び出すコードを見せて下さい。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

kar
記事: 15
登録日時: 10年前

Re: 自機の座標の取得について

#4

投稿記事 by kar » 10年前

呼び出しているコードはこれです。control.cppという場所にあります。controlクラスでplayerなどのインスタンスを生成する仕組みにしています。

コード:

double CONTROL::GetAtan(double &x,double &y){
	double px,py;
	double rad;
	player->GetPosition(&px,&py);
	rad=atan2(py-y,px-x);

	return rad;
}
このGetAtanを呼び出しているコードはこれです。switch内のcase1,case2で呼び出しています。controlクラスはシングルトンにしています。

コード:

void ENEMY::Shot(){
	//CONTROLクラスの参照
	CONTROL &control = CONTROL::GetInstance();
	

	if(game_count == in_count+shot_count){
		shotflag=true;
	}

	if(shotflag == true){
		switch(spattern){
		case 0:{//前方に5発ショット
			if(scount%10==0 && scount<=40){
				for(int i=0;i<ESHOT_MAX;i++){
					if(shot[i].flag == false){
						shot[i].flag =true;
						shot[i].x=x;
						shot[i].y=y;
						break;
					}
				}
			}
			break;
		}
		case 1:{//自機狙い(角度記憶)
			static double rad=0;
			if(scount==0)//最初だけ角度取得
				rad=control.GetAtan(x,y);
			
			if(scount%10==0 && scount<=40){
				for(int i=0;i<ESHOT_MAX;i++){
					if(shot[i].flag == false){
						shot[i].flag =true;
						shot[i].x=x;
						shot[i].y=y;
						shot[i].angle=rad;
						break;
					}
				}
			}
			break;
		}
		case 2:{//常に自機狙い
			if(scount%10==0 && scount<=40){
				for(int i=0;i<ESHOT_MAX;i++){
					if(shot[i].flag == false){
						shot[i].flag =true;
						shot[i].x=x;
						shot[i].y=y;
						shot[i].angle=control.GetAtan(x,y);
						break;
					}
				}
			}
			break;
		}
		default:
			printfDx("enemy内spattern分岐エラー\n");
			break;
		}
	
		int s=0;//フラグの立っている弾の数

		for(int i=0;i<ESHOT_MAX;i++){
			if(shot[i].flag == true){
				shot[i].x+=cos(shot[i].angle)*shot[i].speed;
				shot[i].y+=sin(shot[i].angle)*shot[i].speed;
			
				if(shot[i].x <  FIELD_START_X-10 || shot[i].x >  FIELD_MAX_X+10 || shot[i].y <  FIELD_START_Y-10 || shot[i].y >  FIELD_MAX_Y+10){
					shot[i].flag = false;
					continue;
				}
				s++;
			}
		}

		if(s == 0 && flag == false){
			endflag = true;
		}
		scount++;
	}
}

アバター
nullptr
記事: 239
登録日時: 12年前

Re: 自機の座標の取得について

#5

投稿記事 by nullptr » 10年前

なるほど。

controlがプレイヤーも保持しているのですね。
初期座標が得られてしまうというのは、まずplayerが生成されたのちに座標が変更されていない可能性を疑います。しかしどうやら座標の変数は正しそうです。となると、GetPositionされた時点でまだ自機が動いていない可能性があります。生成されたPlayerにちゃんとアクセスできているか、本当に正しく移動しているかを確認したいところです。
ですので、更にplayerの生成部分を見せて下さい。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

kar
記事: 15
登録日時: 10年前

Re: 自機の座標の取得について

#6

投稿記事 by kar » 10年前

コード:

CONTROL::CONTROL(){
player = new PLAYER;
	back = new BACK;
	board = new BOARD;



	//敵クラスの生成
	for(i=0;i<ENEMY_MAX;i++){
		enemy[i] = new ENEMY(date[i].type,date[i].stype,date[i].m_pattern,date[i].s_pattern,date[i].in_count,date[i].wait_time,date[i].shot_count,date[i].x,date[i].y,date[i].speed,date[i].hp,date[i].item);
	}
}

kar
記事: 15
登録日時: 10年前

Re: 自機の座標の取得について

#7

投稿記事 by kar » 10年前

すいません間違えて投稿してしまいました

kar
記事: 15
登録日時: 10年前

Re: 自機の座標の取得について

#8

投稿記事 by kar » 10年前

うえで投稿したコードはcsvファイルの読み込みも行っていてそれを元にenemyを生成していますが、長すぎたので省略しました。
関係があるのか分かりませんが下のコードはplayerの実行部です。

コード:

void CONTROL::All(){
	
	
	board->All();//ボードの表示、計算
	
	SetDrawArea(FIELD_START_X,FIELD_START_Y,FIELD_MAX_X+1,FIELD_MAX_Y+1);
	
	back->All();//背景の表示、計算
	
	//存在している敵クラスがあったら
	for(int i=0;i<ENEMY_MAX;i++){
		if(enemy[i]!=NULL){//敵の表示、計算
			if(enemy[i]->All() == true){
				delete enemy[i];
				enemy[i]=NULL;
			}
		}
	}
	
	player->All();//自機の表示、計算

	SetDrawArea(0,0,640+1,480+1);
	
	DrawFormatString(10,10,GetColor(255,255,255),"%d",game_count);//ゲームカウントの表示
	
	game_count++;
}

アバター
nullptr
記事: 239
登録日時: 12年前

Re: 自機の座標の取得について

#9

投稿記事 by nullptr » 10年前

自機を移動させてみて、確かに移動しているのに取得する座標が初期位置のままという状態ですか?
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

kar
記事: 15
登録日時: 10年前

Re: 自機の座標の取得について

#10

投稿記事 by kar » 10年前

はい、その状態になっています。
DrawFormatStringでも確認しましたが、初期位置のままでした。

アバター
nullptr
記事: 239
登録日時: 12年前

Re: 自機の座標の取得について

#11

投稿記事 by nullptr » 10年前

うーん やはり自分で試してみないと原因がわからないですね。ソースコード一式もらうことは出来ませんか?zipなどにしてどこかに上げてもらえればこちらでデバッグしてみますが。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

kar
記事: 15
登録日時: 10年前

Re: 自機の座標の取得について

#12

投稿記事 by kar » 10年前

すいません。ソースコードを上げた事が無いのですがどのようにすればよいのでしょうか?
生成されているcppファイルとヘッダファイルをコピーしたファイルをzipにして上げればいいのでしょうか?

アバター
nullptr
記事: 239
登録日時: 12年前

Re: 自機の座標の取得について

#13

投稿記事 by nullptr » 10年前

VisualStudioですよね?.slnと.vcprojと.vcproj.filterとソースコード一式をコピーして、それをzipにまとめれば大丈夫です
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

kar
記事: 15
登録日時: 10年前

Re: 自機の座標の取得について

#14

投稿記事 by kar » 10年前

すいません遅くなりました。
http://filescase.biz/src/COMP100MB1394.zip.html
ここにあります。パスワードはkarです。

アバター
nullptr
記事: 239
登録日時: 12年前

Re: 自機の座標の取得について

#15

投稿記事 by nullptr » 10年前

player = 0x0e060158 {x=69.088310883252007 y=237.08831088325269 gh=67436547 ...} // control.cpp 127
this = 0x0a92a930 {x=180.00000000000000 y=420.00000000000000 gh=71303225 ...} // player.cpp 35

別物を指していますね。原因はPlayerが別物だということ。
そしてPlayerを生成しているのはControlだけなので、COんtろlが複数存在しているという事。

main.cpp 22行目
CONTROL* control = new CONTROL;

もうシングルトンじゃないですね。
CONTROL* control = &CONTROL::GetInstance();
にしたところ正常に動きました。

この方法でシングルトンにするならコンストラクタはprivateするなりする必要があります。今回のように新しく作ってしまうかもしれないからです。プログラム中で唯一であることを保証できなければいけません。

control.h

コード:

#ifndef DEF_CONTROL
#define DEF_CONTROL
#include"player.h"
#include"enemy.h"
#include"back.h"
#include"board.h"

class CONTROL{
private:
	PLAYER* player;
	ENEMY* enemy[ENEMY_MAX];
	BACK* back;
	BOARD* board;

private:
	CONTROL();
public:
	~CONTROL();
	void All();
	void GetPlayerPosition(double *x,double *y);
	void GetEnemyPosition(int index,double *x,double *y);
	double GetAtan(double &x,double &y);
	static CONTROL& GetInstance(){
		static CONTROL control;
		return control;
	}
};

#endif
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

kar
記事: 15
登録日時: 10年前

Re: 自機の座標の取得について

#16

投稿記事 by kar » 10年前

動きました!!ありがとうございます。
なるほどコンストラクタはprivateにしなければいけないんですね。シングルトンがどのようなものなのかあまり知らずに使ってしまっていました。
大変ご迷惑をおかけしました。もっと勉強していきたいと思います。
長い間お付き合いいただきありがとうございました。ずっと困っていたもので、本当に助かりました。

閉鎖

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