プログラムが進まない

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

プログラムが進まない

#1

投稿記事 by kaku » 10年前

visualstudio2015とdxライブラリでゲームを作っているものです
現在コードは以下のようになっています

コード:

#include "DxLib.h"

const char gStageData[] = "\
########\n\
#  ..  #\n\
#  o o #\n\
#  p   #\n\
########";

const int gStageWidth = 8;
const int gStageHeight = 5;

int handle[gStageWidth*gStageHeight];

enum Object {
	OBJ_SPACE,
	OBJ_WALL,
	OBJ_GOAL,
	OBJ_BLOCK,
	OBJ_BLOCK_ON_GOAL,
	OBJ_MAN,
	OBJ_MAN_ON_GOAL,
	OBJ_UNKNOWN
};

int Key[256];

void initialize(Object* state, int width, int height, const char* stageData);
void draw(const Object* state, int width, int height);
void update(Object* s, int w, int h);
bool checkClear(const Object* s, int width, int height);
int gpUpdateKey();

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {

	ChangeWindowMode(true);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);


	Object* state = new Object[gStageWidth*gStageHeight];

	initialize(state, gStageWidth, gStageHeight, gStageData);

	while (true) {

		draw(state, gStageWidth, gStageHeight);

		if (checkClear(state, gStageWidth, gStageHeight))
			break;

		update(state, gStageWidth, gStageHeight);

	}

	delete[] state;
	state = 0;

	DxLib_End();
	return 0;


}

void initialize(Object* state, int width, int height, const char* stageData) {

	const char* d = stageData;
	int x = 0;
	int y = 0;

	while (*d != '\0') {

		Object t;

		switch (*d) {

		case '#':t = OBJ_WALL; break;
		case ' ':t = OBJ_SPACE; break;
		case 'o':t = OBJ_BLOCK; break;
		case 'O':t = OBJ_BLOCK_ON_GOAL; break;
		case '.':t = OBJ_GOAL; break;
		case 'p':t = OBJ_MAN; break;
		case 'P':t = OBJ_MAN_ON_GOAL; break;
		case '\n':
			x = 0;
			y++;
			t = OBJ_UNKNOWN;
			break;
		default:t = OBJ_UNKNOWN;
		}

		d++;

		if (t != OBJ_UNKNOWN) {
			state[y*width + x] = t;
			x++;
		}
	}
}

void draw(const Object* state, int width, int height) {

	int x = 0;
	int y = 0;
	const Object* s = state;

	ClearDrawScreen();

	for (int i = 0; i < gStageHeight; i++) {

		for (int j = 0; j < gStageWidth; j++) {

			switch (*s) {
			case OBJ_SPACE:handle[i*gStageHeight + j] = LoadGraph("objspace.png"); break;
			case OBJ_WALL:handle[i*gStageHeight + j] = LoadGraph("objwall.png"); break;
			case OBJ_GOAL:handle[i*gStageHeight + j] = LoadGraph("objgoal.png"); break;
			case OBJ_BLOCK:handle[i*gStageHeight + j] = LoadGraph("objblock.png"); break;
			case OBJ_BLOCK_ON_GOAL:handle[i*gStageHeight + j] = LoadGraph("objblockongoal.png"); break;
			case OBJ_MAN:handle[i*gStageHeight + j] = LoadGraph("objman.png"); break;
			case OBJ_MAN_ON_GOAL:handle[i*gStageHeight + j] = LoadGraph("objmanongoal.png"); break;
			}

			DrawGraph(x, y, handle[i*gStageHeight + j], true);

			x = x + 50;
			s++;
		}
		x = 0;
		y = y + 50;

	}

	ScreenFlip();

}

void update(Object* s, int w, int h) {

	int dx = 0;
	int dy = 0;


	while (gpUpdateKey()==0) {

		
		if (Key[KEY_INPUT_UP] >= 1) {
			dy = -1;
			break;
		}

		if (Key[KEY_INPUT_DOWN] >= 1) {
			dy = 1;
			break;
		}

		if (Key[KEY_INPUT_LEFT] >= 1) {
			dx = -1;
			break;
		}

		if (Key[KEY_INPUT_RIGHT] >= 1) {
			dx = 1;
			break;
		}

	}


	int i = -1;


	for (i = 0; i < w*h; i++)
		if (s[i] == OBJ_MAN || s[i] == OBJ_MAN_ON_GOAL)
			break;

	int x = i%w;
	int y = i / w;

	int tx = x + dx;
	int ty = y + dy;

	if (tx < 0 || ty < 0 || tx >= w || ty >= h)
		return;

	int p = y*w + x;
	int tp = ty*w + tx;

	if (s[tp] == OBJ_SPACE || s[tp] == OBJ_GOAL) {

		s[tp] == (s[tp] == OBJ_GOAL) ? OBJ_MAN_ON_GOAL : OBJ_MAN;
		s[p] == (s[p] == OBJ_MAN_ON_GOAL) ? OBJ_GOAL : OBJ_SPACE;

	}
	else if (s[tp] == OBJ_BLOCK || s[tp] == OBJ_BLOCK_ON_GOAL) {

		int tx2 = tx + dx;
		int ty2 = ty + dy;

		if (tx2 < 0 || ty2 < 0 || tx2 >= w || ty2 >= h)
			return;

		int tp2 = (ty + dy)*w + (tx + dx);

		if (s[tp2] == OBJ_SPACE || s[tp2] == OBJ_GOAL) {

			s[tp2] = (s[tp2] == OBJ_GOAL) ? OBJ_BLOCK_ON_GOAL : OBJ_BLOCK;
			s[tp] = (s[tp] == OBJ_BLOCK_ON_GOAL) ? OBJ_MAN_ON_GOAL : OBJ_MAN;
			s[p] = (s[p] == OBJ_MAN_ON_GOAL) ? OBJ_GOAL : OBJ_SPACE;
		}

	}

}

bool checkClear(const Object* s, int width, int height) {

	for (int i = 0; i < width*height; i++)
		if (s[i] == OBJ_BLOCK)
			return false;

	return true;

}

int gpUpdateKey() {

	char tmpKey[256];
	GetHitKeyStateAll(tmpKey);
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) {
			Key[i]++;
		}
		else
		{

			Key[i] = 0;
		}

	}
	return 0;
}
メインループの構造は「配列を参考に画像を表示(draw関数)」→「クリアチェック(checkClear関数)」→「キー入力を参考に配列の値を変える(update関数)」(以下繰り返し)
となっているのですがキー入力のところでなぜか↑キーを押したときしか処理が行われず、しかもそのあとはどのキーをおしても処理が行われなくなります。どうすればうまく処理が行われるでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: プログラムが進まない

#2

投稿記事 by みけCAT » 10年前

kaku さんが書きました:メインループの構造は「配列を参考に画像を表示(draw関数)」→「クリアチェック(checkClear関数)」→「キー入力を参考に配列の値を変える(update関数)」(以下繰り返し)
となっているのですが
  • 57行目で、stateには0(整数)ではなくNULL(ポインタ)を代入するべきである気がします。
  • draw関数において、各マスごとにLoadGraphを使うのは、実行速度の低下とリソースの枯渇を招く非常に良くない処理です。
    プログラムの最初(メインループの前)にまとめて読み込んで変数(配列を含む)にハンドルを保存し、draw関数ではそのハンドルを利用するようにしてください。
  • キーが入力されるまでupdate関数を抜けないのはあまり良くない設計だと思います。毎フレームWinMain関数のループに戻るようにするほうがいい気がします。
  • ProcessMessage関数を全く呼び出してないのは、あまり良くないと思います。
kaku さんが書きました:キー入力のところでなぜか↑キーを押したときしか処理が行われず、しかもそのあとはどのキーをおしても処理が行われなくなります。
本当にここに書かれた現象が発生していますか?
例えば、マップを

コード:

const char gStageData[] = "\
########\n\
#  ..  #\n\
#  oo  #\n\
#  po. #\n\
########";
とするとどうなりますか?
190行目と191行目の、副作用の無い無意味な文が気になりますね。
kaku さんが書きました:どうすればうまく処理が行われるでしょうか?
移動しようとした方向にブロックが無い場合も、マップを更新するようにするといいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

kaku

返信ありがとうございます

#3

投稿記事 by kaku » 10年前

コード:

#include "DxLib.h"

const char gStageData[] = "\
########\n\
#  ..  #\n\
#  oo  #\n\
#  po. #\n\
########";

const int gStageWidth = 8;
const int gStageHeight = 5;

int Handle[gStageWidth*gStageHeight];

int gHandle[7];

enum Object {
	OBJ_SPACE,
	OBJ_WALL,
	OBJ_GOAL,
	OBJ_BLOCK,
	OBJ_BLOCK_ON_GOAL,
	OBJ_MAN,
	OBJ_MAN_ON_GOAL,
	OBJ_UNKNOWN
};

int Key[256];



void initialize(Object* state, int width, int height, const char* stageData);
void draw(const Object* state, int width, int height);
void update(Object* s, int w, int h);
bool checkClear(const Object* s, int width, int height);
int gpUpdateKey();

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {

	ChangeWindowMode(true);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);


	Object* state = new Object[gStageWidth*gStageHeight];

	initialize(state, gStageWidth, gStageHeight, gStageData);

	gHandle[0] = LoadGraph("objspace.png");
	gHandle[1] = LoadGraph("objwall.png");
	gHandle[2] = LoadGraph("objgoal.png");
	gHandle[3] = LoadGraph("objblock.png");
	gHandle[4] = LoadGraph("objblockongoal.png");
	gHandle[5] = LoadGraph("objman.png");
	gHandle[6] = LoadGraph("objmanongoal.png");

	while (true) {

		ProcessMessage();

		draw(state, gStageWidth, gStageHeight);

		if (checkClear(state, gStageWidth, gStageHeight))
			break;

		update(state, gStageWidth, gStageHeight);

		Sleep(1000);

	}

	delete[] state;
	state = '\0';

	DxLib_End();
	return 0;


}

void initialize(Object* state, int width, int height, const char* stageData) {

	const char* d = stageData;
	int x = 0;
	int y = 0;

	while (*d != '\0') {

		Object t;

		switch (*d) {

		case '#':t = OBJ_WALL; break;
		case ' ':t = OBJ_SPACE; break;
		case 'o':t = OBJ_BLOCK; break;
		case 'O':t = OBJ_BLOCK_ON_GOAL; break;
		case '.':t = OBJ_GOAL; break;
		case 'p':t = OBJ_MAN; break;
		case 'P':t = OBJ_MAN_ON_GOAL; break;
		case '\n':
			x = 0;
			y++;
			t = OBJ_UNKNOWN;
			break;
		default:t = OBJ_UNKNOWN;
		}

		d++;

		if (t != OBJ_UNKNOWN) {
			state[y*width + x] = t;
			x++;
		}
	}
}

void draw(const Object* state, int width, int height) {

	int x = 0;
	int y = 0;
	const Object* s = state;

	ClearDrawScreen();

	for (int i = 0; i < gStageHeight; i++) {

		for (int j = 0; j < gStageWidth; j++) {

			switch (*s) {
			case OBJ_SPACE:Handle[i*gStageHeight + j] = gHandle[0]; break;
			case OBJ_WALL:Handle[i*gStageHeight + j] = gHandle[1]; break;
			case OBJ_GOAL:Handle[i*gStageHeight + j] = gHandle[2]; break;
			case OBJ_BLOCK:Handle[i*gStageHeight + j] = gHandle[3]; break;
			case OBJ_BLOCK_ON_GOAL:Handle[i*gStageHeight + j] = gHandle[4]; break;
			case OBJ_MAN:Handle[i*gStageHeight + j] = gHandle[5]; break;
			case OBJ_MAN_ON_GOAL:Handle[i*gStageHeight + j] = gHandle[6]; break;
			}

			DrawGraph(x, y, Handle[i*gStageHeight + j], true);

			x = x + 50;
			s++;
		}
		x = 0;
		y = y + 50;

	}

	ScreenFlip();

}

void update(Object* s, int w, int h) {

	int dx = 0;
	int dy = 0;


	while (gpUpdateKey()==0) {

		ProcessMessage();

		
		if (Key[KEY_INPUT_UP] >= 1) {
			dy = -1;
			break;
		}

		if (Key[KEY_INPUT_DOWN] >= 1) {
			dy = 1;
			break;
		}

		if (Key[KEY_INPUT_LEFT] >= 1) {
			dx = -1;
			break;
		}

		if (Key[KEY_INPUT_RIGHT] >= 1) {
			dx = 1;
			break;
		}

	}


	int i = -1;


	for (i = 0; i < w*h; i++)
		if (s[i] == OBJ_MAN || s[i] == OBJ_MAN_ON_GOAL)
			break;

	int x = i%w;
	int y = i / w;

	int tx = x + dx;
	int ty = y + dy;

	if (tx < 0 || ty < 0 || tx >= w || ty >= h)
		return;

	int p = y*w + x;
	int tp = ty*w + tx;

	if (s[tp] == OBJ_SPACE || s[tp] == OBJ_GOAL) {

		s[tp] == (s[tp] == OBJ_GOAL) ? OBJ_MAN_ON_GOAL : OBJ_MAN;
		s[p] == (s[p] == OBJ_MAN_ON_GOAL) ? OBJ_GOAL : OBJ_SPACE;

	}
	else if (s[tp] == OBJ_BLOCK || s[tp] == OBJ_BLOCK_ON_GOAL) {

		int tx2 = tx + dx;
		int ty2 = ty + dy;

		if (tx2 < 0 || ty2 < 0 || tx2 >= w || ty2 >= h)
			return;

		int tp2 = (ty + dy)*w + (tx + dx);

		if (s[tp2] == OBJ_SPACE || s[tp2] == OBJ_GOAL) {

			s[tp2] = (s[tp2] == OBJ_GOAL) ? OBJ_BLOCK_ON_GOAL : OBJ_BLOCK;
			s[tp] = (s[tp] == OBJ_BLOCK_ON_GOAL) ? OBJ_MAN_ON_GOAL : OBJ_MAN;
			s[p] = (s[p] == OBJ_MAN_ON_GOAL) ? OBJ_GOAL : OBJ_SPACE;
		}

	}

}

bool checkClear(const Object* s, int width, int height) {

	for (int i = 0; i < width*height; i++)
		if (s[i] == OBJ_BLOCK)
			return false;

	return true;

}

int gpUpdateKey() {

	char tmpKey[256];
	GetHitKeyStateAll(tmpKey);
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) {
			Key[i]++;
		}
		else
		{

			Key[i] = 0;
		}

	}
	return 0;
}
返信ありがとうございます。なおせるところは自分なりになおしてみました。
マップをみけCATさんのものになおして実行したところブロックがある方向にしか処理が行われないことに気が付きました。
この部分はもう少し考えてみようと思います。あと分からない点が一つあるのですが毎フレームwinmain関数に戻るにはどうすればいいのですか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 返信ありがとうございます

#4

投稿記事 by みけCAT » 10年前

kaku さんが書きました:あと分からない点が一つあるのですが毎フレームwinmain関数に戻るにはどうすればいいのですか?
毎フレームwinmain関数に戻るプログラムに修正すればいいです。
例えば、update関数の前半を

コード:

void update(Object* s, int w, int h) {

	int dx = 0;
	int dy = 0;


	if (gpUpdateKey()==0) {

		if (Key[KEY_INPUT_UP] >= 1) {
			dy = -1;
		}

		if (Key[KEY_INPUT_DOWN] >= 1) {
			dy = 1;
		}

		if (Key[KEY_INPUT_LEFT] >= 1) {
			dx = -1;
		}

		if (Key[KEY_INPUT_RIGHT] >= 1) {
			dx = 1;
		}

	}
	if (dx == 0 && dy == 0) return;


	int i = -1;
とするとか。(テストしていません)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

kaku

無事解決しました

#5

投稿記事 by kaku » 10年前

190行目と191行目をなおすことで思い通りにいきました。
ありがとうございました。(^^)

閉鎖

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