idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

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

idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#1

投稿記事 by Ouxiy » 4年前

  • 環境
    Windows10
    visual studio 2019
    DXライブラリ

コード:

#include "DxLib.h"



int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}


	
	char key[256];
	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};

	int playerX,playerY = (2,2); // 最初のキャラのX座playerXとY座標playerYである。配列の真ん中の0を最初の座標としたため(2,2)となる

	int dx;//移動するキャラのx座標
	int dy;//移動するキャラのy座標
	
	int nx;//x移動後の新しいマスの座標
	int ny;//y移動後の新しいマスの座標




	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);
	//DrawGraph(playerX, playerY, gh[5], FALSE);// プレイヤーの画像を描画

	SetDrawScreen(DX_SCREEN_BACK);

	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {

		int playerphoto;
		// カーソルキーの右が押されている

		if (Key[KEY_INPUT_RIGHT] == 1);
		{
			nx = dx + 1;
			①if (idou[ny + 1][nx + 1]) {nx==0,}//紙を読む nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能と
			//①のidou[ny + 1][nx + 1]を利用してif文で書きたいのですが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使うにはどうすればいいですか?

			playerphoto = gh[9];
		}
		if (Key[KEY_INPUT_LEFT] == 1);
		{
			nx = dx - 1;
			playerphoto = gh[2];
		}

		if (Key[KEY_INPUT_UP] == 1);
		{
			ny = dy + 1;
			playerphoto = gh[4];
		}
		if (Key[KEY_INPUT_DOWN] == 1);
		{
			ny = dy - 1;
			playerphoto = gh[3];
		}

		if (dx== 0 && dy == 0)
		{

			playerphoto = gh[7];
		}

		ScreenFlip();
		// 画面をクリア
		ClearDrawScreen();

		DrawGraph(playerX, playerY, playerphoto, FALSE);



	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}
以上は全体のコードです。
その中に存在する。

コード:

if (Key[KEY_INPUT_RIGHT] == 1);
		{
			nx = dx + 1;
			①if (idou[ny + 1][nx + 1]) {nx==0,}//紙を読む nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能と
			//①のidou[ny + 1][nx + 1]を利用してif文で書きたいのですが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使うにはどうすればいいですか?

			playerphoto = gh[9];
に関して、コメントにもあるのですが、①のidou[ny + 1][nx + 1]を利用してif文で書きたいのですが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使うにはどうすればいいですか?

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#2

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

そのまんまidou[ny + 1]と書けばいいと思います。

まず、idouは「int型の要素5個の配列」型の要素5個の配列です。
idou[ny + 1]はidouの要素である「int型の要素5個の配列」であり、
式中では一部の例外を除いてその配列の先頭要素(int型)へのポインタに変換されます。
したがって、idou[ny + 1]は例えばint*型の変数に代入できます。

あとは、どう使うかですね。
オフトピック
提示されたコードには、
  • 文法エラーがある
  • 未初期化の自動変数の値(不定)が計算に使われている
  • if文のカッコの後に余計なセミコロンがあり、条件分岐が効かない
  • int playerX,playerY = (2,2);ではplayerXは初期化されない ("(2,2)"のコンマはコンマ演算子であり、計算結果は2)
などの問題があります。
ただ、描画先を裏ページにはするようになったようでよかったです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#3

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

Ouxiy さんが書きました:
4年前
nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能
は、

コード:

if (nx == 0 && idou[nx + 1]==idou[1]) {
    // 移動可能にして、その座標に移動する
} else if (nx == 1 && idou[nx + 1] == idou[2]) {
    // 移動不可能
} else {
    // 不明
}
と書けます。
ただし、(nxがint型のとき)nx==0のとき常にnx+1は1、nx==1のとき常にnx+1は2なので、
各条件文の後半は常に成り立ち、実質nxの値だけで移動可能かを判定していることになります。
ちなみに、idou[nx + 1]==idou[1]やidou[nx + 1] == idou[2]は、
配列の中身ではなく先頭要素へのポインタ同士の比較です。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#4

投稿記事 by Ouxiy » 4年前

ありがとうございます!
そのまんまidou[ny + 1]と書けばいいと思います。
まず、idouは「int型の要素5個の配列」型の要素5個の配列です。
idou[ny + 1]はidouの要素である「int型の要素5個の配列」であり、
式中では一部の例外を除いてその配列の先頭要素(int型)へのポインタに変換されます。
したがって、idou[ny + 1]は例えばint*型の変数に代入できます。
idou[ny + 1]は例えばint*型の変数に代入できます。において、私の理解が正しいか不安ですが、
ポインタを使ってidou[ny + 1]の出力をint型(整数)と出来るということでしょうか?
例えば、

コード:

if (nx == 0 && idou[nx + 1]==idou[1]) {
    // 移動可能にして、その座標に移動する
} else if (nx == 1 && idou[nx + 1] == idou[2]) {
    // 移動不可能
} else {
    // 不明
}
と書けます。
ただし、(nxがint型のとき)nx==0のとき常にnx+1は1、nx==1のとき常にnx+1は2なので、
各条件文の後半は常に成り立ち、実質nxの値だけで移動可能かを判定していることになります。
ちなみに、idou[nx + 1]==idou[1]やidou[nx + 1] == idou[2]は、
配列の中身ではなく先頭要素へのポインタ同士の比較です。
ちなみに、idou[nx + 1]==idou[1]やidou[nx + 1] == idou[2]は、
配列の中身ではなく先頭要素へのポインタ同士の比較です。に関して、出力がidou[1]だった場合は進めると判断され、 idou[2]の場合は進めないと判断されるということでしょうか?
違っていたらすいません、「配列の中身ではなく先頭要素へのポインタ同士の比較です。」に関してうまく理解できていないかもしれません。

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#5

投稿記事 by Ouxiy » 4年前

全体コードが書けましたが、少しエラーが出てしまい、どのように解決すればいいか困っています。
とりあえず、右のキーを押した場合の条件だけは書きました。

コード:

#include "DxLib.h"



int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);
	
	int nx = 0;//最初のキャラのx座標
	int ny = 0;//最初のキャラのy座標
	int playerphoto;
	int dx, dy = (2, 2); // 最初のキャラのX座をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}



	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};

	
	DrawGraph(dx, dy, playerphoto, FALSE);





	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);
	//DrawGraph(playerX, playerY, gh[5], FALSE);// プレイヤーの画像を描画

	SetDrawScreen(DX_SCREEN_BACK);

	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {

	
		// カーソルキーの右が押されている

		if (Key[KEY_INPUT_RIGHT] == 1)
		{
			nx = dx + 1;
			//①if (idou[ny + 1][nx + 1]) {nx==0,}//紙を読む nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能と
			//①のidou[ny + 1][nx + 1]を利用してif文で書きたいが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使えるか?

			if (nx == 0 && idou[nx + 1] == idou[1]) {
				// 移動可能にして、その座標に移動する
			}
			else if (nx == 1 && idou[nx + 1] == idou[2]) {
				// 移動不可能
				playerphoto = gh[9];
			}
			if (Key[KEY_INPUT_LEFT] == 1)
			{
				nx = dx - 1;
				playerphoto = gh[2];
			}

			if (Key[KEY_INPUT_UP] == 1)
			{
				ny = dy + 1;
				playerphoto = gh[4];
			}
			if (Key[KEY_INPUT_DOWN] == 1)
			{
				ny = dy - 1;
				playerphoto = gh[3];
			}

			if (dx == 0 && dy == 0)
			{

				playerphoto = gh[7];
			}

			ScreenFlip();
			// 画面をクリア
			ClearDrawScreen();

			DrawGraph(nx, ny, playerphoto, FALSE);

		}
	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}
以下はエラーです。

コード:

1>------ ビルド開始: プロジェクト: VisualStudio_2019用, 構成: Release x64 ------
1>Source.cpp
1>コード生成しています。
1>Previous IPDB and IOBJ mismatch, fall back to full compilation.
1>C:\Users\Daito\Desktop\DxLib_VC\サンプルプログラム実行用フォルダ\Source.cpp(50): error C4700: 初期化されていないローカル変数 'playerphoto' が使用されます
1>C:\Users\Daito\Desktop\DxLib_VC\サンプルプログラム実行用フォルダ\Source.cpp(50): error C4700: 初期化されていないローカル変数 'dx' が使用されます
1>All 2 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
1>LINK : fatal error LNK1257: コードの生成に失敗しました。
1>プロジェクト "VisualStudio_2019用.vcxproj" のビルドが終了しました -- 失敗。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#6

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

Ouxiy さんが書きました:
4年前
ポインタを使ってidou[ny + 1]の出力をint型(整数)と出来るということでしょうか?
「idou[ny + 1]の出力」の意味がよくわかりませんが、
idou[ny + 1]はint*型(ポインタ)になります。 (sizeof演算子に渡す場合などの例外は除く)
間接演算子*を用いてデリファレンスすることで、idou[ny + 1]からint型(整数)の値を得ることができます。
Ouxiy さんが書きました:
4年前
出力がidou[1]だった場合は進めると判断され、 idou[2]の場合は進めないと判断されるということでしょうか?
「出力」がidou[ny + 1]の値のことだと仮定すると、
&&演算子の左辺の条件により、結果的にそうなりますね。
Ouxiy さんが書きました:
4年前
全体コードが書けましたが、少しエラーが出てしまい、どのように解決すればいいか困っています。
エラーはplayerphotoとdxが初期化されないまま使われているということなので、
初期化してから使うようにすればいいでしょう。
  1. #2でも書いたとおり、ここでの(2, 2)は実質2です。dx = 2, dy = 2のように1個ずつ初期化しましょう。
  2. まだグラフィックを読み込んでいない段階でのDrawGraph(dx, dy, playerphoto, FALSE);は消しましょう。
  3. グラフィックを読み込んだあと、
    DrawGraphを呼ぶ前のどこか(DrawGraphを呼ぶならば確実に通る場所、例えばwhileのブロックの開始直後)で、
    playerphotoにghの中のどれか適当な要素を代入しましょう。
オフトピック
右キーが押されていないと他のキーの判定をしない仕様にしたのですね。
インデントも整っているので、}の位置を打ち間違えたとは考えにくいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#7

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

オフトピック
ちなみに、Pythonなら

コード:

dx, dy = (2, 2)
でdxにもdyにも2を代入できます。
どうしてもこのような書き方をしたいのであれば、Pythonを使うのもいいかもしれません。
DXライブラリも使えるようです。
例:PythonでDXライブラリを利用してみた - 気まぐれ雑記(仮)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#8

投稿記事 by Ouxiy » 4年前

ありがとうございます!!
早速試してみます!いつもいつもありがとうございます!

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#9

投稿記事 by Ouxiy » 4年前

質問1
#2でも書いたとおり、ここでの(2, 2)は実質2です。dx = 2, dy = 2のように1個ずつ初期化しましょう。
適切なアドバイスのおかげで、初期化することができたためエラーは消えました。
あの、int dx, dy = (2, 2);という書き方ではなぜdx = 2, dy = 2のように1個ずつ初期化されずに実質2になってしまうのですか?また実質2とは何の2でしょうか?座標ではないと思いますが、、、。

質問2
好奇心でいじった部分があるのですが、

コード:

//グラフィックハンドル格納用配列
	int gh[12];
	playerphoto = gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, playerphoto);//画像読み込み
とgh[12]はint型であるため、int型の変数playerphotoに変えて、関数LoadDivGraphに代入してみたのですが、赤い下線部となり、エラーとなります。確か同じ型の置き換えは出来たと思うのですが、関数LoadDivGraphもint型を引数にとっているため大丈夫かと思ったらダメでした。なぜでしょうか。
以下はエラーメッセージです。

コード:

1>------ ビルド開始: プロジェクト: VisualStudio_2019用, 構成: Release x64 ------
1>Source.cpp
1>C:\Users\Daito\Desktop\DxLib_VC\サンプルプログラム実行用フォルダ\Source.cpp(60,59): error C2664:  'int DxLib::LoadDivGraph(const TCHAR *,int,int,int,int,int,int *,int)': 引数 7 を 'int' から 'int *' へ変換できません。
1>C:\Users\Daito\Desktop\DxLib_VC\サンプルプログラム実行用フォルダ\Source.cpp(60,48): message :  整数型からポインター型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。
1>プロジェクト "VisualStudio_2019用.vcxproj" のビルドが終了しました -- 失敗。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========
質問3
コード全体に関してはエラーは消えましたが、思った通りの動きにはなっていません。
DrawGraph(dx, dy, gh[5], FALSE)の入れている部分は間違っていないと思うのですが、
キャラの最初の位置座標

コード:

int dx=2, dy =2 ; // 最初のキャラのX座をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる

コード:

int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};
に反映されているか心配です。というのも移動後の座標の数字1か0で移動可能かの変数

コード:

int nx = 0;//移動後のキャラのx座標の0か1の数字
	int ny = 0;//移動後のキャラのy座標の数字
を作りましたが、形的に

コード:

int nx = 0;
	int ny = 0;

コード:

int dx=2, dy =2 ;
が似ていたり、int idou[5][5]の座標との関係がしっかりかけていないような気がしてきたためです。ただ、idou[5][5]での真ん中の0の座標を表すのはint dx=2, dy =2 ;で良いと思うので、何とも言えないのですが。
あと何をどのように修正すればいいでしょうか。

以下は少し修正したプログラムです。

コード:

#include "DxLib.h"



int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);
	
	int playerphoto;
	int dx=2, dy =2 ; // 最初のキャラのX座をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる

	int nx = 0;//移動後のキャラのx座標の0か1の数字
	int ny = 0;//移動後のキャラのy座標の数字

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}



	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};

	
	//DrawGraph(dx, dy, playerphoto, FALSE);





	//グラフィックハンドル格納用配列
	int gh[12];
	playerphoto = gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, playerphoto);//画像読み込み
	

	SetDrawScreen(DX_SCREEN_BACK);
	DrawGraph(dx, dy, gh[5], FALSE);// プレイヤーの画像を描画
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {

	
		// カーソルキーの右が押されている

		if (Key[KEY_INPUT_RIGHT] == 1)
		{
			nx = dx + 1;
			//①if (idou[ny + 1][nx + 1]) {nx==0,}//紙を読む nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能と
			//①のidou[ny + 1][nx + 1]を利用してif文で書きたいが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使えるか?

			if (nx == 0 && idou[nx + 1] == idou[1]) {
				// 移動可能にして、その座標に移動する
			}
			else if (nx == 1 && idou[nx + 1] == idou[2]) {
				// 移動不可能
				playerphoto = gh[9];
			}
			if (Key[KEY_INPUT_LEFT] == 1)
			{
				nx = dx - 1;
				playerphoto = gh[2];
			}

			if (Key[KEY_INPUT_UP] == 1)
			{
				ny = dy + 1;
				playerphoto = gh[4];
			}
			if (Key[KEY_INPUT_DOWN] == 1)
			{
				ny = dy - 1;
				playerphoto = gh[3];
			}

			if (dx == 0 && dy == 0)
			{

				playerphoto = gh[7];
			}

			ScreenFlip();
			// 画面をクリア
			ClearDrawScreen();

			DrawGraph(nx, ny, playerphoto, FALSE);

		}
	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#10

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

Ouxiy さんが書きました:
4年前
あの、int dx, dy = (2, 2);という書き方ではなぜdx = 2, dy = 2のように1個ずつ初期化されずに実質2になってしまうのですか?また実質2とは何の2でしょうか?座標ではないと思いますが、、、。
C++の規格書(のドラフト)であるN3337から引用します。
まず、8 Declaratorsの1より、変数宣言のうち型(と修飾子)を除いたdx, dy = (2, 2)にあたる部分の文法は
init-declarator-list:
  init-declarator
  init-declarator-list , init-declarator
init-declarator:
  declarator initializeropt
となっています。ここで、declaratorはdxやdyのような識別子などのことです。
そして、initializerの定義は、8.5 Initializersの1より
initializer:
  brace-or-equal-initializer
  ( expression-list )
brace-or-equal-initializer:
  = initializer-clause
  braced-init-list
initializer-clause:
  assignment-expression
  braced-init-list
initializer-list:
  initializer-clause ... opt
  initializer-list , initializer-clause ... opt
braced-init-list:
  { initializer-list , opt }
  { }
となっています。
dx, dy = (2, 2)のように書くことで複数の変数を初期化する、というような文法はありません。
「dx」および「dy = (2, 2)」がそれぞれinit-declaratorとして解釈されます。

dx, dy = (2, 2)の= (2, 2)の部分は、=で始まるため、= initializer-clauseに該当します。
そのため、(2, 2)がinitializer-clauseに該当します。
initializer-clauseはassignment-expressionまたはbraced-init-listですが、
(2, 2)は{}で囲まれていないので、braced-init-listではありません。
したがって、(2, 2)はassignment-expressionとなります。
5.17 Assignment and compound assignment operatorsによると、assignment-expressionは
assignment-expression:
  conditional-expression
  logical-or-expression assignment-operator initializer-clause
  throw-expression
となっていますが、今回は代入演算子でもthrowでもないのでconditional-expressionです。
同様に他の演算子でもないのでどんどん辿っていくと、primary-expressionとなり、
5.1 Primary expressionsにあるprimary-expressionの定義の中に
( expression )
があります。(2, 2)はこれに当てはまるので、カッコの中の2, 2がexpressionとして解釈されます。
5.18 Comma operatorより、expressionの定義は
expression:
  assignment-expression
  expression , assignment-expression
となっており、2, 2はexpression , assignment-expressionに当てはまります。
(2はprimary-expressionの定義の1つであるliteralとなります)
そして、このコンマ演算子の効果は、同じく5.18より
A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded-
value expression (Clause 5). 83 Every value computation and side effect associated with the left expression
is sequenced before every value computation and side effect associated with the right expression. The type
and value of the result are the type and value of the right operand; the result is of the same value category
as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field.
となっています。
すなわち、「まず、コンマの左辺が評価される。
コンマの左辺の評価が完了したあと、コンマの右辺が評価される。
コンマ演算子の評価結果は、右辺の評価結果になる。」ということです。
今回の2, 2の右辺は2なので、評価結果は2になります。

「実質2」とは、このコンマ演算子の右辺の2です。
また、dx, dy = (2, 2)においては、dxの方にはinitializerがついていないため、初期化されません。
8.5より、正確にはdefault-initializeされますが、
int型の自動変数のdefault-initializeは「初期化しない(no initialization is performed)」(8.5の6)なので、
値は不定になります。(8.5の11)
Ouxiy さんが書きました:
4年前
gh[12]はint型であるため
式中のgh[12]はint型(ただし範囲外へのアクセスとなり、危険!)ですが、
変数宣言中のgh[12]をint型というのはおかしいでしょう。
このgh[12]は、N3337の8 Declaratorsにあるnoptr-declaratorの定義のうち、
noptr-declarator [ constant-expression opt ] attribute-specifier-seqoptに該当します。
これは宣言の一部であり、これの型を考えるのはおかしいと考えられます。
Ouxiy さんが書きました:
4年前
int型の変数playerphotoに変えて、関数LoadDivGraphに代入してみたのですが
関数の引数としているだけで、関数に代入はしていないですね。
Ouxiy さんが書きました:
4年前
赤い下線部となり、エラーとなります。確か同じ型の置き換えは出来たと思うのですが、関数LoadDivGraphもint型を引数にとっているため大丈夫かと思ったらダメでした。なぜでしょうか。
DXライブラリの関数LoadDivGraphはint型の引数も取りますが、リファレンスを見ると、
int LoadDivGraph( char *FileName , int AllNum ,
          int XNum , int YNum ,
          int XSize , int YSize , int *HandleBuf ) ;
となっており、playerphotoを渡している第7引数はint型ではなくint*型です。
そのため、第7引数にint型の値を渡してはいけません。

コード:

	int playerphoto;
	LoadDivGraph("charall.png", 1, 1, 1, 49, 66, &playerphoto);//画像読み込み
のように、ポインタ演算子&によってint型の変数のポインタを取り、
画像のハンドルをそこに1個だけ入れることはできるでしょう。
ただし、

コード:

	int playerphoto;
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, &playerphoto);//危険!
のように複数のハンドルを入れようとしてしまうと、
int型の変数にはint型1個分の領域しか無いのに、
複数のデータを入れようとしてしまい、はみ出してしまって危険です。
Ouxiy さんが書きました:
4年前
DrawGraph(dx, dy, gh[5], FALSE)の入れている部分は間違っていないと思うのですが、
私は間違っていると思います。
ループ前に入れるということは、ループ前の1回しか実行されないということであり、
そこにキー入力が反映されることは無いでしょう。
ついでにDrawGraph(nx, ny, playerphoto, FALSE);も怪しいです。
キャラクターが1ドットずつしか動かない仕様でいいのでしょうか?
Ouxiy さんが書きました:
4年前
キャラの最初の位置座標

コード:

int dx=2, dy =2 ; // 最初のキャラのX座をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる

コード:

int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};
に反映されているか心配です。というのも移動後の座標の数字1か0で移動可能かの変数

コード:

int nx = 0;//移動後のキャラのx座標の0か1の数字
	int ny = 0;//移動後のキャラのy座標の数字
を作りましたが、形的に

コード:

int nx = 0;
	int ny = 0;

コード:

int dx=2, dy =2 ;
が似ていたり、int idou[5][5]の座標との関係がしっかりかけていないような気がしてきたためです。ただ、idou[5][5]での真ん中の0の座標を表すのはint dx=2, dy =2 ;で良いと思うので、何とも言えないのですが。
あと何をどのように修正すればいいでしょうか。
「反映されている」の意味がよくわからないです。
「0か1」というのはよくわからないですが、同じ「座標」を扱う変数が似た形になるのは自然でしょう。
(ただし、使うときに取り違えないように注意が必要かもしれません)
idou[5][5]での真ん中の座標を表すのはint dx=2, dy =2 ;でいいでしょう。
Ouxiyさんのコードを、希望の動作をするように修正すればいいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#11

投稿記事 by Ouxiy » 4年前

詳しい解説ありがとうございます。
キャラの持続的な描画はwhileループにより可能になりました。
ですが、右のキーを押しても移動は出来ずにいます。
プログラミを見直し、右のキーでの移動できるようにif文で作ったつもりなのですが、、、。

↓編集したプログラムです。

コード:

#include "DxLib.h"



int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);
	
	int playerphoto;
	int dx=2, dy =2 ; // 最初のキャラのX座をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる

	int nx = 0;//移動後のキャラのx座標の0か1の数字
	int ny = 0;//移動後のキャラのy座標の数字

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}



	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};

	
	//DrawGraph(dx, dy, playerphoto, FALSE);





	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);//画像読み込み
	

	SetDrawScreen(DX_SCREEN_BACK);
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {
		DrawGraph(dx, dy, gh[5], FALSE);// プレイヤーの画像を描画
	
		// カーソルキーの右が押されている

		if (Key[KEY_INPUT_RIGHT] == 1)
		{
			
			//①if (idou[ny + 1][nx + 1]) {nx==0,}//紙を読む nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能と
			//①のidou[ny + 1][nx + 1]を利用してif文で書きたいが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使えるか?

			if (nx == 0 && idou[nx + 1] == idou[1]) {// 移動可能にして、その座標に移動する
				nx = dx + 1;
				playerphoto = gh[7];
			}
			else if (nx == 1 && idou[nx + 1] == idou[2]) {
				// 移動不可能
				playerphoto = gh[9];
			}


			if (Key[KEY_INPUT_LEFT] == 1)
			{
				nx = dx - 1;
				playerphoto = gh[2];
			}

			if (Key[KEY_INPUT_UP] == 1)
			{
				ny = dy + 1;
				playerphoto = gh[4];
			}
			if (Key[KEY_INPUT_DOWN] == 1)
			{
				ny = dy - 1;
				playerphoto = gh[3];
			}

			if (dx == 0 && dy == 0)
			{

				playerphoto = gh[7];
			}

			ScreenFlip();
			// 画面をクリア
			ClearDrawScreen();

			DrawGraph(nx, ny, playerphoto, FALSE);

		}
	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#12

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

どのような動作を「移動」と呼んでいるのかわかりませんが、
#11のコードで右キーにキャラが反応することを確認できました。

まず、charall.pngとして以下の画像を用意しました。
charall.png
描画用画像
charall.png (1.23 KiB) 閲覧数: 16837 回
これを読み込める状態で#11のコードを実行すると、以下の画像のようになりました。
(4倍に拡大し、左上を切り抜いています)
sukusyo1-trim-large.png
右キーを押す前の状態
sukusyo1-trim-large.png (10.33 KiB) 閲覧数: 16837 回
DrawGraph(dx, dy, gh[5], FALSE);により、(dx, dy)すなわち(2, 2)の位置に
gh[5]の画像が描画されていることが確認できます。

この状態で右キーを押すと、以下の画像のようになりました。
(4倍に拡大し、左上を切り抜いています)
sukusyo2-trim-large.png
右キーを押した後の状態
sukusyo2-trim-large.png (10.05 KiB) 閲覧数: 16838 回
nxは0だったので、その後の処理により、gh[5]の画像が描画される前に、
DrawGraph(nx, ny, playerphoto, FALSE);により、(nx, ny)すなわち(3, 0)の位置に
gh[7]の画像が描画されていることが確認できます。

ただし、ScreenFlip関数実行後の裏ページの状態は環境によって変わるようなので、
Ouxiyさんの環境では異なる結果になるかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#13

投稿記事 by Ouxiy » 4年前

どのような動作を「移動」と呼んでいるのかわかりませんが、
できればこのように動かしたいという実行ファイルの動画をお渡ししたいのですが、
元ネタのこちらを送らせて頂きます。
今のコードからこの動画のように移動させたいです。キャラクターにこのような動きをさせたいです。

みけCATさんの確認プログラムで動いていることはわかりました。ですが、動画のように動くのかわかりません。
どのように修正すれば、動画のように一マス一マスを

コード:

if (Key[KEY_INPUT_RIGHT] == 1)
		{
			
			
			if (nx == 0 && idou[nx + 1] == idou[1]) {// 移動可能にして、その座標に移動する
				nx = dx + 1;
				playerphoto = gh[7];
			}
			else if (nx == 1 && idou[nx + 1] == idou[2]) {
				// 移動不可能
				playerphoto = gh[9];
			}
を利用してキャラが動かせるでしょうか。

以下は全体のコードです。

コード:

#include "DxLib.h"



int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);
	
	int playerphoto;
	int dx=2, dy =2 ; // 最初のキャラのX座をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる

	int nx = 0;//移動後のキャラのx座標の0か1の数字
	int ny = 0;//移動後のキャラのy座標の数字

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}



	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};

	
	//DrawGraph(dx, dy, playerphoto, FALSE);





	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);//画像読み込み
	

	SetDrawScreen(DX_SCREEN_BACK);
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {
		DrawGraph(dx, dy, gh[5], FALSE);// プレイヤーの画像を描画
	
		// カーソルキーの右が押されている

		if (Key[KEY_INPUT_RIGHT] == 1)
		{
			
			//①if (idou[ny + 1][nx + 1]) {nx==0,}//紙を読む nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能と
			//①のidou[ny + 1][nx + 1]を利用してif文で書きたいが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使えるか?

			if (nx == 0 && idou[nx + 1] == idou[1]) {// 移動可能にして、その座標に移動する
				nx = dx + 1;
				playerphoto = gh[7];
			}
			else if (nx == 1 && idou[nx + 1] == idou[2]) {
				// 移動不可能
				playerphoto = gh[9];
			}


			if (Key[KEY_INPUT_LEFT] == 1)
			{
				nx = dx - 1;
				playerphoto = gh[2];
			}

			if (Key[KEY_INPUT_UP] == 1)
			{
				ny = dy + 1;
				playerphoto = gh[4];
			}
			if (Key[KEY_INPUT_DOWN] == 1)
			{
				ny = dy - 1;
				playerphoto = gh[3];
			}

			if (dx == 0 && dy == 0)
			{

				playerphoto = gh[7];
			}

			ScreenFlip();
			// 画面をクリア
			ClearDrawScreen();

			DrawGraph(nx, ny, playerphoto, FALSE);

		}
	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#14

投稿記事 by Ouxiy » 4年前

こんなこと言うのは大変申し訳ないのですが、どうか今の自分のコードに何が足りなくて何がダメだったのか知るため、動画のような動きをさせるためにどうすればいいのか勉強するために、
私のコードを修正した物を頂けないでしょうか。
ここ数週間入門書やサイトを見て回っているのですが、全く進まず行き詰まっています。
どうかよろしくお願いいたします。

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#15

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

Ouxiy さんが書きました:
4年前
どうか今の自分のコードに何が足りなくて何がダメだったのか知るため、動画のような動きをさせるためにどうすればいいのか勉強するために、
私のコードを修正した物を頂けないでしょうか。
まず第一に、「キャラがマップのどのマスにいるか」から「キャラを画面のどの位置に描画するか」に
変換するための処理が無いのがダメですね。

こんな感じでどうでしょうか?

コード:

#include "DxLib.h"



int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);
	
	int playerphoto;
	int dx=2, dy =2 ; // 最初のキャラのX座標をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる

	int nx = 0;//キャラが移動できるかを表す0か1の数字
	int ny = 0;//キャラが移動しようとしているかを表す0か1の数字

	int mx = 0, my = 0; // キャラの移動先の座標
	int moveTimer = 0; // 移動時間の管理に使うカウンタ

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}

	// 描画用パラメータ
	const int BOX_LEFT = 70; // 有効範囲の左上(1, 1)のマスの左のX座標
	const int BOX_TOP = 50; // 有効範囲の左上(1, 1)のマスの上のY座標
	const int BOX_WIDTH = 70; // マスの横幅(ピクセル)
	const int BOX_HEIGHT = 50; // マスの縦幅(ピクセル)
	const int BOX_CHARA_X = 10; // マスの左上から横に何ピクセルの位置にキャラを描画するか
	const int BOX_CHARA_Y = -26; // マスの左上から縦に何ピクセルの位置にキャラを描画するか

	// 移動制御用パラメータ
	const int MOVE_TIME = 20; // 移動の演出にかける時間(フレーム数)
	const int MOVE_NG_TIME = 10; // 移動できない時の演出にかける時間(フレーム数)

	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};

	
	//DrawGraph(dx, dy, playerphoto, FALSE);





	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);//画像読み込み
	playerphoto = gh[5];

	SetDrawScreen(DX_SCREEN_BACK);
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {

		// ----------- 状態の更新 -----------

		if (moveTimer == 0) {
			// カーソルキーの入力を受け付ける
			ny = 0; // 「移動しようとしていない」をセット
			mx = dx; my = dy; // 移動先のキャラの位置を今の位置にセット

			if (Key[KEY_INPUT_RIGHT] == 1)
			{
				ny = 1;
				mx = dx + 1;
				playerphoto = gh[7];
			}
			if (Key[KEY_INPUT_LEFT] == 1)
			{
				ny = 1;
				mx = dx - 1;
				playerphoto = gh[2];
			}

			if (Key[KEY_INPUT_UP] == 1)
			{
				ny = 1;
				my = dy - 1;
				playerphoto = gh[4];
			}
			if (Key[KEY_INPUT_DOWN] == 1)
			{
				ny = 1;
				my = dy + 1;
				playerphoto = gh[3];
			}

			if (ny != 0) { // キャラが移動しようとしている場合
				// 移動先に障害物が無いかをチェックする
				if (idou[my][mx] != 0) {
					// 障害物があるので、移動不可能
					nx = 1;
				} else {
					// 障害物が無いので、移動可能
					nx = 0;
				}

				//①if (idou[ny + 1][nx + 1]) {nx==0,}//紙を読む nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能と
				//①のidou[ny + 1][nx + 1]を利用してif文で書きたいが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使えるか?

				if (nx == 0 && idou[nx + 1] == idou[1]) {// 移動可能にして、その座標に移動する
					moveTimer = MOVE_TIME;
				}
				else if (nx == 1 && idou[nx + 1] == idou[2]) {
					// 移動不可能
					moveTimer = MOVE_NG_TIME;
					mx = dx; my = dy;
					playerphoto = gh[9];
				}
			}
		} else {
			// 移動中
			moveTimer--;
			if (moveTimer == MOVE_TIME / 2) {
				// キャラの座標を移動先のものに更新
				dx = mx; dy = my;
			}
			if (moveTimer == 0) {
				// キャラの画像を戻す
				playerphoto = gh[5];
			}
		}

		// ----------- 状態の描画 -----------

		// 画面をクリア
		ClearDrawScreen();

		// プレイヤーの画像を描画
		int px = BOX_LEFT + BOX_WIDTH * (dx - 1) + BOX_CHARA_X;
		int py = BOX_TOP + BOX_HEIGHT * (dy - 1) + BOX_CHARA_Y;
		DrawGraph(px, py, playerphoto, FALSE);

	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}
charall.pngも、各画像の役割をわかりやすくしてみました。
charall.png
描画用画像
charall.png (3.11 KiB) 閲覧数: 16731 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#16

投稿記事 by Ouxiy » 4年前

ちなみに、

コード:

if (ny != 0) { // キャラが移動しようとしている場合
				// 移動先に障害物が無いかをチェックする
				if (idou[my][mx] != 0) {
					// 障害物があるので、移動不可能
					nx = 1;
				} else {
					// 障害物が無いので、移動可能
					nx = 0;
				}

				
はキャラのyに関しての移動できるかどうかの判断するプログラムの部分ですが、以下のようにny == 0 && idou[ny + 1] などのようにif文でも表せるのでしょうか。表せるとしたら以下のnx == 0 && idou[nx + 1] の部分をny == 0 && idou[ny + 1] と変化させればよいと考えています。間違っていたらご指摘お願いいたします。

コード:

		if (nx == 0 && idou[nx + 1] == idou[1]) {// 移動可能にして、その座標に移動する
					moveTimer = MOVE_TIME;
				}
				else if (nx == 1 && idou[nx + 1] == idou[2]) {
					// 移動不可能
					moveTimer = MOVE_NG_TIME;
					mx = dx; my = dy;
					playerphoto = gh[9];
				}
			}
		}
				

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#17

投稿記事 by Ouxiy » 4年前

できればキャラのyに関しての移動できるかどうかの判断するプログラムの部分もxでの移動できるかどうか判断するようなプログラムのように、if (nx == 0 && idou[nx + 1] == idou[1])を真似て(ny == 0 && idou[ny + 1]==idou[1])のように表したいです。

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#18

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

Ouxiy さんが書きました:
4年前
ちなみに、

コード:

if (ny != 0) { // キャラが移動しようとしている場合
				// 移動先に障害物が無いかをチェックする
				if (idou[my][mx] != 0) {
					// 障害物があるので、移動不可能
					nx = 1;
				} else {
					// 障害物が無いので、移動可能
					nx = 0;
				}

				
はキャラのyに関しての移動できるかどうかの判断するプログラムの部分ですが、
x,y両方に関しての判断を行っています。
nyという変数名は、元のコードとの差分を少なくするために使っているだけで、y座標という意味ではありません。。
Ouxiy さんが書きました:
4年前
以下のようにny == 0 && idou[ny + 1] などのようにif文でも表せるのでしょうか。
このプログラムでは既にif文を用いていますが、「if文でも表せる」とはどういう意味でしょうか?
Ouxiy さんが書きました:
4年前
表せるとしたら以下のnx == 0 && idou[nx + 1] の部分をny == 0 && idou[ny + 1] と変化させればよいと考えています。間違っていたらご指摘お願いいたします。

コード:

		if (nx == 0 && idou[nx + 1] == idou[1]) {// 移動可能にして、その座標に移動する
					moveTimer = MOVE_TIME;
				}
				else if (nx == 1 && idou[nx + 1] == idou[2]) {
					// 移動不可能
					moveTimer = MOVE_NG_TIME;
					mx = dx; my = dy;
					playerphoto = gh[9];
				}
			}
		}
				
nx == 0 && idou[nx + 1] の部分をny == 0 && idou[ny + 1] と変化させる場合、
その上の移動可能かの判定の部分でnxだけでなくnyにも移動可能かの情報を入れなければいけません。
Ouxiy さんが書きました:
4年前
できればキャラのyに関しての移動できるかどうかの判断するプログラムの部分もxでの移動できるかどうか判断するようなプログラムのように、if (nx == 0 && idou[nx + 1] == idou[1])を真似て(ny == 0 && idou[ny + 1]==idou[1])のように表したいです。
nyの判定もこの冗長なものにしたいというのであれば、こんな感じでどうでしょうか?
nyの0と1の意味を入れ替え、条件式を差し替えました。

コード:

#include "DxLib.h"



int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);
	
	int playerphoto;
	int dx=2, dy =2 ; // 最初のキャラのX座標をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる

	int nx = 0;//キャラが移動できるかを表す0か1の数字
	int ny = 0;//キャラが移動しようとしているかを表す0か1の数字

	int mx = 0, my = 0; // キャラの移動先の座標
	int moveTimer = 0; // 移動時間の管理に使うカウンタ

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}

	// 描画用パラメータ
	const int BOX_LEFT = 70; // 有効範囲の左上(1, 1)のマスの左のX座標
	const int BOX_TOP = 50; // 有効範囲の左上(1, 1)のマスの上のY座標
	const int BOX_WIDTH = 70; // マスの横幅(ピクセル)
	const int BOX_HEIGHT = 50; // マスの縦幅(ピクセル)
	const int BOX_CHARA_X = 10; // マスの左上から横に何ピクセルの位置にキャラを描画するか
	const int BOX_CHARA_Y = -26; // マスの左上から縦に何ピクセルの位置にキャラを描画するか

	// 移動制御用パラメータ
	const int MOVE_TIME = 20; // 移動の演出にかける時間(フレーム数)
	const int MOVE_NG_TIME = 10; // 移動できない時の演出にかける時間(フレーム数)

	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};

	
	//DrawGraph(dx, dy, playerphoto, FALSE);





	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);//画像読み込み
	playerphoto = gh[5];

	SetDrawScreen(DX_SCREEN_BACK);
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {

		// ----------- 状態の更新 -----------

		if (moveTimer == 0) {
			// カーソルキーの入力を受け付ける
			ny = 1; // 「移動しようとしていない」をセット
			mx = dx; my = dy; // 移動先のキャラの位置を今の位置にセット

			if (Key[KEY_INPUT_RIGHT] == 1)
			{
				ny = 0;
				mx = dx + 1;
				playerphoto = gh[7];
			}
			if (Key[KEY_INPUT_LEFT] == 1)
			{
				ny = 0;
				mx = dx - 1;
				playerphoto = gh[2];
			}

			if (Key[KEY_INPUT_UP] == 1)
			{
				ny = 0;
				my = dy - 1;
				playerphoto = gh[4];
			}
			if (Key[KEY_INPUT_DOWN] == 1)
			{
				ny = 0;
				my = dy + 1;
				playerphoto = gh[3];
			}

			if (ny == 0 && idou[ny + 1]==idou[1]) { // キャラが移動しようとしている場合
				// 移動先に障害物が無いかをチェックする
				if (idou[my][mx] != 0) {
					// 障害物があるので、移動不可能
					nx = 1;
				} else {
					// 障害物が無いので、移動可能
					nx = 0;
				}

				//①if (idou[ny + 1][nx + 1]) {nx==0,}//紙を読む nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能と
				//①のidou[ny + 1][nx + 1]を利用してif文で書きたいが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使えるか?

				if (nx == 0 && idou[nx + 1] == idou[1]) {// 移動可能にして、その座標に移動する
					moveTimer = MOVE_TIME;
				}
				else if (nx == 1 && idou[nx + 1] == idou[2]) {
					// 移動不可能
					moveTimer = MOVE_NG_TIME;
					mx = dx; my = dy;
					playerphoto = gh[9];
				}
			}
		} else {
			// 移動中
			moveTimer--;
			if (moveTimer == MOVE_TIME / 2) {
				// キャラの座標を移動先のものに更新
				dx = mx; dy = my;
			}
			if (moveTimer == 0) {
				// キャラの画像を戻す
				playerphoto = gh[5];
			}
		}

		// ----------- 状態の描画 -----------

		// 画面をクリア
		ClearDrawScreen();

		// プレイヤーの画像を描画
		int px = BOX_LEFT + BOX_WIDTH * (dx - 1) + BOX_CHARA_X;
		int py = BOX_TOP + BOX_HEIGHT * (dy - 1) + BOX_CHARA_Y;
		DrawGraph(px, py, playerphoto, FALSE);

	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#19

投稿記事 by Ouxiy » 4年前

返信遅くなりすいません。コード、ありがとうございます。
自分の方でも少し書いてみたのですが、なぜうまくいかないのかわからなくて困っていました。

キャラクターはnx=2,ny=2の座標からから右に動き、x方向には+1進むがy方向には0しか進まないのでidou[nx + 1][ny + 0] となりidou[2 + 1][2 + 0] =idou[3][2] となるように書いてみたのですが、実行フィルのキャラは右に動かず静止したままでした。なぜでしょうか。
以下は全体のコードです。

コード:

#include "DxLib.h"



int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);
	
	int playerphoto;
	int nx=2, ny =2 ; // 最初のキャラのX座をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}



	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{1,1,1,1,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,0,0,0,1 },
					{1,1,1,1,1 },
	};

	
	//DrawGraph(dx, dy, playerphoto, FALSE);





	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);//画像読み込み
	

	SetDrawScreen(DX_SCREEN_BACK);
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {
		DrawGraph(nx, ny, gh[5], FALSE);// プレイヤーの画像を描画
	
		// カーソルキーの右が押されている

		if (Key[KEY_INPUT_RIGHT] == 1)
		{
			
			//①if (idou[ny + 1][nx + 1]) {nx==0,}//紙を読む nx==0でidou[nx + 1]がidou[1]の時移動可能にして、その座標に移動する、nx==1でidou[nx + 1]がidou[2]の時移動不可能と
			//①のidou[ny + 1][nx + 1]を利用してif文で書きたいが、idou[ny + 1][nx + 1]を単体でidou[ny + 1]として使えるか?
			if ( nx == 3 && idou[nx + 1][ny + 0] == idou[3][2]) {// 移動可能にして、その座標に移動する
				//nx == 3は移動するxの座標として書きました。
				idou[nx + 1][ny + 0] == idou[3][2];

				playerphoto = gh[7];
			}
			else if (nx == 1 && idou[nx + 1] == idou[2]) {
				// 移動不可能
				playerphoto = gh[9];
			}


			if (Key[KEY_INPUT_LEFT] == 1)
			{
				nx = nx - 1;
				playerphoto = gh[2];
			}

			if (Key[KEY_INPUT_UP] == 1)
			{
				ny = ny + 1;
				playerphoto = gh[4];
			}
			if (Key[KEY_INPUT_DOWN] == 1)
			{
				ny = ny - 1;
				playerphoto = gh[3];
			}

			if (nx == 0 && ny == 0)
			{

				playerphoto = gh[7];
			}

			ScreenFlip();
			// 画面をクリア
			ClearDrawScreen();

			DrawGraph(nx, ny, playerphoto, FALSE);

		}
	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#20

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

Ouxiy さんが書きました:
4年前
idou[nx + 1][ny + 0] となりidou[2 + 1][2 + 0] =idou[3][2] となるように書いてみたのですが、

コード:

idou[nx + 1][ny + 0] == idou[3][2];
は「idou[nx + 1][ny + 0]の値とidou[3][2]の値が等しいかを比較し、その結果にかかわらず何もしない」
というコードです。
Ouxiyさんは、このコードによって何をしてもらうことを期待したのでしょうか?
Ouxiy さんが書きました:
4年前
実行フィルのキャラは右に動かず静止したままでした。なぜでしょうか。
キャラを右に動かす(キャラのX座標を大きくする)コードが無いからですね。

また、ディスプレイや視点の回転によりX座標の正の方向以外が「右」になっていることも考えられますが、
手元での実験においては、矢印キーをぴったり同時
(Key[KEY_INPUT_RIGHT] == 1かつKey[KEY_INPUT_LEFT] == 1など)に入力することはできず、
頑張っても5フレーム程度ずれてしまいました。
(キーボードの仕様などの環境によって異なるかもしれません)
右キーを押したタイミングでなくても他のキーの入力を有効にする仕様に戻すか、
同時押しの判定方法を見直すべきでしょう。

そして、どうせこの部分に移動するためのコードは無いとはいえ、
if (Key[KEY_INPUT_RIGHT] == 1)の後他のキーの判定をする前のif文において、
初期状態であるnx == 2の判定が無いのも気になりますね。

ちなみに、このコードにおいてidou[3][2]は0なので、
右(X座標の正の方向)に行けるかの判定として
idou[nx + 1][ny + 0] == idou[3][2] (nx == 3 && は付けない) は悪くないでしょう。
素直にidou[nx + 1][ny + 0] == 0 としたほうがいいとは思いますが、変な書き方にこだわるなら勝手にどうぞ。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#21

投稿記事 by Ouxiy » 4年前

解答ありがとうございます。
>>Ouxiyさんは、このコードによって何をしてもらうことを期待したのでしょうか?
右にだけ1マス移動すると期待していました。

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#22

投稿記事 by Ouxiy » 4年前

ちなみに、このコードにおいてidou[3][2]は0なので、
右(X座標の正の方向)に行けるかの判定として
idou[nx + 1][ny + 0] == idou[3][2] (nx == 3 && は付けない) は悪くないでしょう。
素直にidou[nx + 1][ny + 0] == 0 としたほうがいいとは思いますが、変な書き方にこだわるなら勝手にどうぞ。
ありがとうございます。あの、ちなみに、私の載せたプログラムは後なにを付け足せば、右に一マス動くでしょうか。
以下のコードが元のコードです。

コード:

	if ( nx == 3 && idou[nx + 1][ny + 0] == idou[3][2]) {// 移動可能にして、その座標に移動する
				//nx == 3は移動するxの座標として書きました。
				idou[nx + 1][ny + 0] == idou[3][2];

				playerphoto = gh[7];
			}
			else if (nx == 1 && idou[nx + 1] == idou[2]) {
				// 移動不可能
				playerphoto = gh[9];
			}

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#23

投稿記事 by Ouxiy » 4年前

載せさせて頂いたプログラムに関して、出来る限り原型を残して何を削り、何を付け足せばよかったのかわかれば勉強になるのでどうかお願いいたします。

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

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#24

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

Ouxiy さんが書きました:
4年前
ありがとうございます。あの、ちなみに、私の載せたプログラムは後なにを付け足せば、右に一マス動くでしょうか。
以下のコードが元のコードです。

コード:

	if ( nx == 3 && idou[nx + 1][ny + 0] == idou[3][2]) {// 移動可能にして、その座標に移動する
				//nx == 3は移動するxの座標として書きました。
				idou[nx + 1][ny + 0] == idou[3][2];

				playerphoto = gh[7];
			}
			else if (nx == 1 && idou[nx + 1] == idou[2]) {
				// 移動不可能
				playerphoto = gh[9];
			}
描画するX座標を増やすコードを付け足せば、右に動けるようになるでしょう。

コード:

	if ( nx == 3 && idou[nx + 1][ny + 0] == idou[3][2]) {// 移動可能にして、その座標に移動する
				//nx == 3は移動するxの座標として書きました。
				idou[nx + 1][ny + 0] == idou[3][2];

				playerphoto = gh[7];
			}
			else if (nx == 1 && idou[nx + 1] == idou[2]) {
				// 移動不可能
				playerphoto = gh[9];
			}
			nx = nx + 1; // 追加
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 173
登録日時: 4年前

Re: idou[ny + 1][nx + 1]を利用してif文でキャラを縦、横に動かしたいです。

#25

投稿記事 by Ouxiy » 4年前

いつもいつもどうもありがとうございます。

返信

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