ページ 11

ステージの初期化についてなのですが・・・

Posted: 2012年7月25日(水) 10:41
by C.C
http://dixq.net/forum/viewtopic.php?f=3&t=10986    ←こちらの続きです。ソースのzipファイルもあります。

何度も質問してしまい申し訳ありません。
今回はステージの初期化についてなのですが、ステージの初期化関数を作り、プレイヤー座標を初期化したのですが、指定した座標に表示されず、うまくいきません。教えていただけないでしょうか。

コード:

float playerX, playerY;  //プレイヤー座標x, y。txtファイルから読み込んでいるので、値は入れてあります。

void GameInit();          //ステージの初期化関数のプロトタイプ宣言

void GameInit(){
     memset( &playerX, (int)playerX, sizeof(float) );
     memset( &playerY, (int)playerY, siseof(float) );
}
そして、ほかにも床の座標なども初期化したほうがよいのでしょうか?
よろしくお願いします。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月25日(水) 10:55
by h2so5
ビルドの通るコードを貼りましょう。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月25日(水) 11:11
by C.C
h2so5 さんが書きました:ビルドの通るコードを貼りましょう。
すみません。
画像は無いですが、よろしくお願いします

すみません。ファイルは消させていただきました

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月25日(水) 11:13
by C.C
すみません。GameInit関数はGoGameMain()関数の中で呼び出してください

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月25日(水) 15:17
by softya(ソフト屋)
不用意にファイルがデカくなるのでRENSYU.sdfやipchフォルダとDebugフォルダは圧縮ファイルには不要ですので取り除いてから圧縮して下さい。

GameInit関数の問題点を指摘しますと

1.memsetは必要ありません。
普通に代入できるのにmemsetを使う意味はまったくなくバグの危険性が増えるだけです。

2.値が不定のものを代入しても初期化にはなりませんので、デバッガで確認して下さいね。
コレは何度も説明したはずですが、動作がおかしかったらまずデバッガで確認が基本です。
どういう問題があったか報告をしてください。

3.初期化の仕方がすごく間違っています。
プログラムの流れを意識してと言うのも何度も書いたはずですので、stage.Wallがどんな流れで初期化されるか説明してみて下さい。

※ すごく大事な基本の基本が分かっていないとしか思えない組み方をしています。
C言語の入門書を読みなおしたほうが良いかも知れません。

表示出来る出来ない以前の確認をまずお願いします。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月25日(水) 17:51
by ISLe
デバッグ情報は容量がデカいだけじゃなく、個人情報が漏れる可能性もありますよ。
学校のPC使ってるっぽいので学校の関係者くらいにしか役に立たない情報かもしれませんが。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 09:46
by C.C
ISLe さんが書きました:デバッグ情報は容量がデカいだけじゃなく、個人情報が漏れる可能性もありますよ。
学校のPC使ってるっぽいので学校の関係者くらいにしか役に立たない情報かもしれませんが。
返信ありがとうございます。
ファイルは消しました。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 10:00
by C.C
softya(ソフト屋) さんが書きました:不用意にファイルがデカくなるのでRENSYU.sdfやipchフォルダとDebugフォルダは圧縮ファイルには不要ですので取り除いてから圧縮して下さい。

GameInit関数の問題点を指摘しますと

1.memsetは必要ありません。
普通に代入できるのにmemsetを使う意味はまったくなくバグの危険性が増えるだけです。

2.値が不定のものを代入しても初期化にはなりませんので、デバッガで確認して下さいね。
コレは何度も説明したはずですが、動作がおかしかったらまずデバッガで確認が基本です。
どういう問題があったか報告をしてください。

3.初期化の仕方がすごく間違っています。
プログラムの流れを意識してと言うのも何度も書いたはずですので、stage.Wallがどんな流れで初期化されるか説明してみて下さい。

※ すごく大事な基本の基本が分かっていないとしか思えない組み方をしています。
C言語の入門書を読みなおしたほうが良いかも知れません。

表示出来る出来ない以前の確認をまずお願いします。
返信、そして何度も答えていただきありがとうございます。
1.ほかの方法を探します。

2.txtファイルでのプレイヤーの座標はx 576, y 360なのですが、GameInitではx 3.003925, y 4.3900599e+024に設定されています。

3.txtファイルのx座標, y座標, 幅, 高さをStageInfo構造体に入れています

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 11:12
by softya(ソフト屋)
C.C さんが書きました:返信、そして何度も答えていただきありがとうございます。
1.ほかの方法を探します。

2.txtファイルでのプレイヤーの座標はx 576, y 360なのですが、GameInitではx 3.003925, y 4.3900599e+024に設定されています。

3.txtファイルのx座標, y座標, 幅, 高さをStageInfo構造体に入れています
主に3の問題なのですが関数の実行順番や何処の関数でどういう値なのかの情報が抜け落ちています。
こう言う風に書いてもらえますか? StageInfoとPlayer関係の初期化だけ抜け出せば良いです。
かならず書き換えている所を全部書きだしてください。

(例) 例なので適当な関数名でっちあげです。
main
 ↓
PlayerInit → PlayerXとPlayerYを定数(10,20)で初期化。
 ↓
MapInit → マップ座標をファイルの情報で初期化。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 15:06
by C.C
GameMapLoad関数 → txtファイルから
マップサイズx, マップサイズy, プレイヤー座標x, プレイヤー座標y,
壁座標x, 壁座標y, 壁の幅, 壁の高さをそれぞれ初期化します。

GoGameMain関数 → ゲームの本編の前にInitGame関数を呼び出します。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 15:07
by softya(ソフト屋)
InitGameで行なっていることが書かれていませんよ。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 15:18
by C.C
すみません。InitGameでは画面の状態をリセットし、その後GameMapLoadで初期化した位置に表示したいと考えています。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 15:26
by softya(ソフト屋)
C.C さんが書きました:すみません。InitGameでは画面の状態をリセットし、その後GameMapLoadで初期化した位置に表示したいと考えています。
そこが分からないということでしょうか。
GameMapLoad()の時の情報を何処かに保存しておいて、InitGameで毎回保存しておいた値から復元するのが一般的です。
現状のコードは、GameMapLoad()で保存していない & InitGameでどこからともなく不定な値を持ってきている という状態です。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 22:10
by C.C
softya(ソフト屋) さんが書きました:
C.C さんが書きました:すみません。InitGameでは画面の状態をリセットし、その後GameMapLoadで初期化した位置に表示したいと考えています。
そこが分からないということでしょうか。
GameMapLoad()の時の情報を何処かに保存しておいて、InitGameで毎回保存しておいた値から復元するのが一般的です。
現状のコードは、GameMapLoad()で保存していない & InitGameでどこからともなく不定な値を持ってきている という状態です。
遅くなって申し訳ありません。保存用の変数を用意すればよいのでしょうか?

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 22:14
by softya(ソフト屋)
上書きたり書き換えれたら元の状態に戻せませんので、まるまる複製した元の状態をとっておくしかありません。
必要なのは、元の型に合わせたそっくり同じ型の別の名前の変数です。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 23:09
by C.C
softya(ソフト屋) さんが書きました:上書きたり書き換えれたら元の状態に戻せませんので、まるまる複製した元の状態をとっておくしかありません。
必要なのは、元の型に合わせたそっくり同じ型の別の名前の変数です。
すみませんが、GameMapLoad関数を見ていただけませんか?
sscanf_sで変数に値を読み込み、これを構造体変数に代入しているのですが、(プレイヤーも同じようにやるつもりです)sscanf_sで使っている変数をそのまま保存用の変数としてはつかえないのですか?

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 23:34
by softya(ソフト屋)
C.C さんが書きました:
softya(ソフト屋) さんが書きました:上書きたり書き換えれたら元の状態に戻せませんので、まるまる複製した元の状態をとっておくしかありません。
必要なのは、元の型に合わせたそっくり同じ型の別の名前の変数です。
すみませんが、GameMapLoad関数を見ていただけませんか?
sscanf_sで変数に値を読み込み、これを構造体変数に代入しているのですが、(プレイヤーも同じようにやるつもりです)sscanf_sで使っている変数をそのまま保存用の変数としてはつかえないのですか?
wallXなど単なるスカラ変数は複数の要素を記憶することはできません。
たぶん、何度も同じ指摘をしていると思いますが一つの変数には一つの値しか入れることはできません。これはC言語を始めプログラミング言語の基本原則です。
その為に配列がありますし、stage.Wallはその役目のために配列になっています。
wallXなどに次の値が入った時前の値は何処にも残っていませんので消滅します。

変数というのは単なる入れ物です。この入れ物は一つの値しか入れることができません。時間を巻き戻して前の値に戻すことも出来ません。
それを理解されていないので、そういう質問に成るんだと思いますがよく考えてみて下さい。

このプログラムでiが1の時のwの値がforループの外で取り出せますか(再計算してはいけません)?
それと同じ事です。

コード:

#include <stdio.h>

int main(void)
{
	int i,w;
	for( i=0; i<3; i++ ) {
		w = i*3;
		printf( "%d-%d\n",i,w );
	}
	
	printf( "final:%d\n",w );
}

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 23:41
by C.C
[quote」wallXなど単なるスカラ変数は複数の要素を記憶することはできません。
たぶん、何度も同じ指摘をしていると思いますが一つの変数には一つの値しか入れることはできません。これはC言語を始めプログラミング言語の基本原則です。
その為に配列がありますし、stage.Wallはその役目のために配列になっています。
wallXなどに次の値が入った時前の値は何処にも残っていませんので消滅します。

変数というのは単なる入れ物です。この入れ物は一つの値しか入れることができません。時間を巻き戻して前の値に戻すことも出来ません。
それを理解されていないので、そういう質問に成るんだと思いますがよく考えてみて下さい。

このプログラムでiが1の時のwの値がforループの外で取り出せますか(再計算してはいけません)?
それと同じ事です。

コード:

#include <stdio.h>

int main(void)
{
	int i,w;
	for( i=0; i<3; i++ ) {
		w = i*3;
		printf( "%d-%d\n",i,w );
	}
	
	printf( "final:%d\n",w );
}
[/quote]

すみません。説明不足でしたね。もちろん壁のほうは配列を用意するつもりです。
これでもう一度お聞きします。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月26日(木) 23:45
by softya(ソフト屋)
配列を用意するなら、同じ構造のものを用意したほうが混乱がなく素直に処理できます。
なので、stageと同じ型を用意したほうがシンプルで分かりやすくなります。
playerも構造体にまとめたほうが良いでしょう。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月27日(金) 10:39
by C.C
softya(ソフト屋) さんが書きました:配列を用意するなら、同じ構造のものを用意したほうが混乱がなく素直に処理できます。
なので、stageと同じ型を用意したほうがシンプルで分かりやすくなります。
playerも構造体にまとめたほうが良いでしょう。
おはようございます。
早速試してみましたが、壁が表示されなくなってしまいました。

コード:

struct StageInfo{
	int timerstart;				//待機タイマーの開始時刻
	int gamestarttime;			//ゲームの開始時間
	int gametime;				//ゲーム開始からの経過ミリ秒
	float playerX;
	float playerY;
	float mapsize_w, mapsize_h;	//マップサイズ

	Character Wall[MAXMAPCHARA];
	Ball Ball[MAXBALLCHARA];

	int num_mapchara;
	bool isheroleft;	//主人公の向き
	bool isontheground;
};
//保存用の構造体
struct Retain{
	int timerstart;				//待機タイマーの開始時刻
	int gamestarttime;			//ゲームの開始時間
	int gametime;				//ゲーム開始からの経過ミリ秒
	float playerX;
	float playerY;
	float mapsize_w, mapsize_h;	//マップサイズ

	Character Wall[MAXMAPCHARA];
	Ball Ball[MAXBALLCHARA];

	int num_mapchara;
	bool isheroleft;			//主人公の向き
	bool isontheground;
};

コード:

//マップの読み込み
int GameMapLoad(char *filepath){
	
	int f;			//ファイルハンドル
	char buf[1024];	//テキスト読み込みバッファ

	f = FileRead_open(filepath);
	if (f == 0) return -1;		//読み込みエラー

	//マップサイズと主人公初期位置読み込み
	if(FileRead_gets( buf, 1023, f ) == -1) return -1;
	sscanf_s(buf, "%f, %f, %f, %f", &retain.mapsize_w, &retain.mapsize_h, &retain.playerX, &retain.playerY);
	stage.playerX = retain.playerX;
	stage.playerY = retain.playerY;
	stage.mapsize_w = retain.mapsize_w;
	stage.mapsize_h = retain.mapsize_h;

	//地形オブジェクト読み込み
	if(FileRead_gets( buf, 1023, f ) == -1)	return -1;
	int imax;
	sscanf_s(buf, "%d" , &imax);	//行数取得

	float wallX, wallY, wallW, wallH, angle;
	int id;
	for(int i = 0; i < imax; i++){
		if(FileRead_gets( buf, 1023, f ) == -1) return -1;
		sscanf_s( buf, "%f, %f, %f, %f, %f, %d", &wallX, &wallY, &wallW, &wallH, &angle, &id);

		if((int)wallW == 48){
			ch.ID = WALL_48;
			ch.ID_X = (int)wallX;
			ch.ID_Y = (int)wallY;
			ch.ID_W = (int)wallW;
			ch.ID_H = (int)wallH;
			ch.ID_Angle = angle;
		}
		if((int)wallW == 192){
			ch.ID = WALL_192;
			ch.ID_X = (int)wallX;
			ch.ID_Y = (int)wallY;
			ch.ID_W = (int)wallW;
			ch.ID_H = (int)wallH;
			ch.ID_Angle = angle;
		}
		if((int)wallW == 284){
			ch.ID = WALL_284;
			ch.ID_X = (int)wallX;
			ch.ID_Y = (int)wallY;
			ch.ID_W = (int)wallW;
			ch.ID_H = (int)wallH;
			ch.ID_Angle = angle;
		}
		if((int)wallW == 568){
			ch.ID = WALL_568;
			ch.ID_X = (int)wallX;
			ch.ID_Y = (int)wallY;
			ch.ID_W = (int)wallW;
			ch.ID_H = (int)wallH;
			ch.ID_Angle = angle;
		}
		if(id == 1){
			ch.ID = GOAL_FLAG;
			ch.ID_X = (int)wallX;
			ch.ID_Y = (int)wallY;
			ch.ID_W = (int)wallW;
			ch.ID_H = (int)wallH;
			ch.ID_Angle = angle;
		}

		ch.used = true;
		stage.Wall[stage.num_mapchara] = ch;
		retain.Wall[stage.num_mapchara] = stage.Wall[stage.num_mapchara];
		stage.num_mapchara++;
		retain.num_mapchara = stage.num_mapchara;
	}

	FileRead_close(f);
	return 0;
}
すみません。2つに分けます。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月27日(金) 10:41
by softya(ソフト屋)
同じ構造の構造体は2つ用意しなくて良いのですが?
struct Retainは無駄です。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月27日(金) 10:43
by C.C

コード:

//初期化関数
void GameInit(){
	ZeroMemory(&stage, sizeof(stage));         //StageInfo構造体の変数をすべて0にする

	stage.playerX = retain.playerX;
	stage.playerY = retain.playerY;
	stage.mapsize_w = retain.mapsize_w;
	stage.mapsize_h = retain.mapsize_h;

	for(int i = 0; i <= retain.num_mapchara; i++){
		stage.Wall[i] = retain.Wall[i];
	}
	
	stage.gamestarttime = g_lasttime;
}
ブレークポイントで値を見るとちゃんと代入されているようなんですが、なぜ表示されないのでしょうか

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月27日(金) 10:48
by softya(ソフト屋)
ZeroMemory(&stage, sizeof(stage)); //StageInfo構造体の変数をすべて0にする
で全部0にしているのからでは?
ステージ最初の状態に戻すなら他にも設定すべきものがあるのではないでしょうか。

上にも書きましたがstruct StageInfoだけで十分でstruct Retainは不要です。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月27日(金) 11:09
by C.C
softya(ソフト屋) さんが書きました:ZeroMemory(&stage, sizeof(stage)); //StageInfo構造体の変数をすべて0にする
で全部0にしているのからでは?
ステージ最初の状態に戻すなら他にも設定すべきものがあるのではないでしょうか。

上にも書きましたがstruct StageInfoだけで十分でstruct Retainは不要です。
自己解決しました。
GameInitの中でLoadGameMapを呼び出すとうまく表示されました。
ありがとうございました。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月27日(金) 11:13
by softya(ソフト屋)
C.C さんが書きました:
softya(ソフト屋) さんが書きました:ZeroMemory(&stage, sizeof(stage)); //StageInfo構造体の変数をすべて0にする
で全部0にしているのからでは?
ステージ最初の状態に戻すなら他にも設定すべきものがあるのではないでしょうか。

上にも書きましたがstruct StageInfoだけで十分でstruct Retainは不要です。
自己解決しました。
GameInitの中でLoadGameMapを呼び出すとうまく表示されました。
ありがとうございました。
まぁ、その手はあることはあるんですが他にも初期化するものがあるような・・・。
ここのルールですので、最終コードの貼り付けをお願いします。

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月27日(金) 11:51
by C.C
まぁ、その手はあることはあるんですが他にも初期化するものがあるような・・・。
ここのルールですので、最終コードの貼り付けをお願いします。
初期化が必要なものがでてきたら、自分で考えてみます。
とりあえず表示はされましたので解決にさせていただきます。
ありがとうございました
載せるのはGameInitだけでいいんですか?

コード:

//初期化関数
void GameInit(){
	ZeroMemory( &stage, sizeof(stage) );

	stage.playerX = retain.playerX;
	stage.playerY = retain.playerY;
	stage.mapsize_w = retain.mapsize_w;
	stage.mapsize_h = retain.mapsize_h;

	for(int i = 0; i <= retain.num_mapchara; i++){
		stage.Wall[i] = retain.Wall[i];
	}

	GameMapLoad("media\\stage01.txt");
		
	stage.gamestarttime = g_lasttime;
}

Re: ステージの初期化についてなのですが・・・

Posted: 2012年7月27日(金) 11:55
by softya(ソフト屋)
すくなくとも5行目から12行めまでは意味がありません。
あと、どんどんプログラムがダーティ(汚いコード・無駄な処理・不可解な処理)になってますので整理をおすすめします。