R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

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

R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#1

投稿記事 by Ouxiy » 2週間前

R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃するようなプログラムを書きました。ですが、精度が悪く同時押しで何度もれ出して押さないと機能しません。
どうにかしてRキーを押した後、Aキーを押して精度よく一度押しただけで攻撃でるように出来ないでしょうか。
後、相手の陣地に踏み込んだ後、相手の陣地に踏み込む前の座標に自分が戻るようにしたいのですが、その場合は変数をもう一つ作り作ったほうがいいのでしょうか。
以下はR(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃するプログラムです。

コード:

if (Key[KEY_INPUT_R] == 1 && playerY==enemyY) {
			enemyImage = enemyGHandle[8];
			int prokey = Key[KEY_INPUT_R] == 1;
			prokey = 1;
			prokey++;//変数prokeyを1ずつ増やしていく
			if (prokey > 0) {
			
			//Key[KEY_INPUT_R] == 1がRを押した後もデータが残るように変数として置き、一定時間キーRが押された後も残るようにする。
				if (prokey < 100000 && Key[KEY_INPUT_A] == 1) {  // アタック
					int player2;//移動後の座標
					player2 = enemyX - 1;//敵の一つ前のX座標がplayer2に入り、
					player2 = playerX ;
					playerMove = 1; playerImage = playerGHandle[4];
					enemyMove = 1; enemyImage = enemyGHandle[10];
					prokey = 1;
				}
			

			}
以下は全体のコードです。
行が多くここには載せられなかったためこちらに書きました。

Rittai_3D
記事: 522
登録日時: 6年前

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#2

投稿記事 by Rittai_3D » 2週間前

どうにかしてRキーを押した後、Aキーを押して精度よく一度押しただけで攻撃でるように出来ないでしょうか。
Rキーを押したあと、一定の時間内にAが押されたら攻撃、という風にすればいいと思います。
一定の時間はご自分の好きな時間を設定してください。
後、相手の陣地に踏み込んだ後、相手の陣地に踏み込む前の座標に自分が戻るようにしたいのですが、その場合は変数をもう一つ作り作ったほうがいいのでしょうか。
方向キーが押されたタイミングで、次進む予定の座標が敵の陣地かどうかを確認し、そこが敵の陣地であれば、いったんそこにプレイヤーを移動させた後好きなタイミングで元の座標に戻す、という処理でいいと思います。
変数を作るかどうかはご自分で判断してください。

関係ないですが、リンク先の88行目、prokey は 0 or 1 で、89行目で1、90行目で2になると思うのですが、どういう意図でこのコードを書いたのでしょうか?
オフトピック
なぜ関数を新規に作らないのですか?
適切な名前をつけた関数をmainで呼び出す方が可読性も上がり、デバッグをする際や、他人に意見を求める際にも有効だと思います。

また、マジックナンバーが多いので列挙型などを使ってそのあたりの解消をするのも、可読性が上がるのでした方がいいです。
コメントに 0-2:後ろ向き、3-5:右向き、6-8:前向き、9-11:左向き のように書くのはわかりにくいです。

最近の質問を読ませていただきました。
質問をするのは悪いことではないのですが、Ouxiyさんはまずやりたいことを細分化して、処理の流れを頭の中なり紙なり、一旦まとめる必要があると思います。
初心者です

かずま

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#3

投稿記事 by かずま » 2週間前

Rittai_3D さんが書きました:
2週間前
関係ないですが、リンク先の88行目、prokey は 0 or 1 で、89行目で1、90行目で2になると思うのですが、どういう意図でこのコードを書いたのでしょうか?
意図。

コード:

if (Key[KEY_INPUT_R] == 1 && playerY==enemyY) {
	// Rキーが押されていて、プレイヤーと敵の Y座標が等しいからロックオンだ。

	enemyImage = enemyGHandle[8];  // 敵画像を変更しておこう。

	int prokey = Key[KEY_INPUT_R] == 1;
	// 次に Aキーが押されたかどうかチェックしたいけど、すぐに見てもダメだと
	// 言われたので、Rキーが押されたことを変数 prokey に憶えておこう。

	prokey = 1;
	prokey++;
	// Aキーが押されるのをいつまでも待つわけにいかないので、カウンタを用意
	// して、100000 になるまでに Aキーが押されることを期待しよう。
	// Aキーが押されるまでは prokey の値がここでどんどん増えていくぞ。

	if (prokey > 0) {  // まだロックオン状態だな。
		// 適当に時間もたったし、そろそろ Aキーが押されているだろう。	

		if (prokey < 100000 && Key[KEY_INPUT_A] == 1) {
			// 時間内に Aキーが押されたぞ。

			int player2;  // 移動後の座標
			player2 = enemyX - 1; // 敵の左隣りに移動。

			player2 = playerX ;  // アタックの後は、元の位置に戻るぞ。

			playerMove = 1; playerImage = playerGHandle[4];
			enemyMove = 1; enemyImage = enemyGHandle[10];
			// プレイヤーと敵の画像をもとに戻そう。

			prokey = 1;  // ???
		}
	}
}
DXライブラリの processMessage() の while ループの意味を理解していませんね。
というより、コードの各行がどのように動いて次の行に行くのかを理解していません。
自分の思った通りに動くと信じているようです。

Ouxiy
記事: 148
登録日時: 1ヶ月前

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#4

投稿記事 by Ouxiy » 2週間前

DXライブラリの processMessage() の while ループの意味を理解していませんね。
というより、コードの各行がどのように動いて次の行に行くのかを理解していません。
DXライブラリのループは理解が至ってない部分もありますが、コードの各行くらいどのように動いているかわかります。

Ouxiy
記事: 148
登録日時: 1ヶ月前

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#5

投稿記事 by Ouxiy » 2週間前

自分の思った通りに動くと信じているようです。
数日前までは本気で動くと思っていました。
ですが、最大60フレームしかないため、prokey < 1000000としても無意味とわかりました。
私を馬鹿にするのはいいですが、馬鹿にするならばヒントが欲しいですね。

かずま

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#6

投稿記事 by かずま » 2週間前

Ouxiy さんが書きました:
2週間前
コードの各行くらいどのように動いているかわかります。

コード:

if (Key[KEY_INPUT_R] == 1 && playerY==enemyY) {
	enemyImage = enemyGHandle[8];
	int prokey = Key[KEY_INPUT_R] == 1;  // (1)
	prokey = 1;                          // (2)
	prokey++;                            // (3)
	if (prokey > 0) {                    // (4)
		if (prokey < 100000 && Key[KEY_INPUT_A] == 1) {  // (5)
			int player2;
			player2 = enemyX - 1;        // (6)
			player2 = playerX ;          // (7)
			playerMove = 1; playerImage = playerGHandle[4];
			enemyMove = 1; enemyImage = enemyGHandle[10];
			prokey = 1;
		}
	}  // (8)
}   // (9)
質問1. (1) で prokey の値はいくつになりますか?
質問2. (2) で prokey の値はいくつになりますか?
質問3. (3) で prokey の値はいくつになりますか?
質問4. (4) で prokey の値が 0以下になることがありますか?
質問5. (5) で prokey の値が 100000以上になることがありますか?
質問6. (5) で Key[KEY_INPUT_A] の値が 1になることがありますか?
質問7. (6) (7) を続けて実行すると、(6) の意味がないと思いませんか?
質問8. (8) では、変数player2 が消えてなくなるのを知っていますか?
質問9. (9) では、変数prokey が消えてなくなるのを知っていますか?

すべての質問に答えていただくと、ヒントを差し上げます。

Ouxiy
記事: 148
登録日時: 1ヶ月前

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#7

投稿記事 by Ouxiy » 2週間前

質問1. (1) で prokey の値はいくつになりますか? A,1
質問2. (2) で prokey の値はいくつになりますか? A,1
質問3. (3) で prokey の値はいくつになりますか? A,2
質問4. (4) で prokey の値が 0以下になることがありますか? A,ないです。
質問5. (5) で prokey の値が 100000以上になることがありますか? A,ないです。
質問6. (5) で Key[KEY_INPUT_A] の値が 1になることがありますか? A,条件式として1になるので、あります。
質問7. (6) (7) を続けて実行すると、(6) の意味がないと思いませんか? A,思います。
質問8. (8) では、変数player2 が消えてなくなるのを知っていますか? A,知りませんでした。なぜ無くなるのでしょうか。
質問9. (9) では、変数prokey が消えてなくなるのを知っていますか? A,知りませんでした。なぜ無くなるのでしょうか。
ヒントを頂けると嬉しいです。出来れば、勉強になるヒントをください。
今後もカズマさんにご負担のないように頼れるよう、
どうかよろしくお願いいたします。

以下のプログラムは編集前のまともなプログラムです。意味はないですが、代入を理解していることを伝えたくて載せました。これでも必死に学習しています。

コード:

if (prokey > 0) {
				prokey++;//変数prokeyを1ずつ増やしていく
				//Key[KEY_INPUT_R] == 1がRを押した後もデータが残るように変数として置き、一定時間キーRが押された後も残るようにする。
			}
			else if
			 (prokey <= 60 && Key[KEY_INPUT_A] == 1) {  // アタック
					int player2;//移動後の座標
					playerX = enemyX - 1;//敵の一つ前のX座標がplayer2に入り、
					playerX = playerX;
					playerMove = 1; playerImage = playerGHandle[4];
					enemyMove = 1; enemyImage = enemyGHandle[10];
					prokey = 1;
				}


			}

かずま

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#8

投稿記事 by かずま » 2週間前

インデントがおかしなプログラムをまともなプログラムとは言えません。

if (prokey > 0) があると、else 以降は prokey が 0 以下の場合の処理と
なりますが、prokey が 0以下にはならないので、まともなプログラムとは
言えません。

playerX = playerX; を見ると、代入を理解しているとはとても思えません。

ヒントを出そうと思いましたが、私には、Ouxiy さんが理解できるような
説明をする能力はありません。お詫びに、ロック、アタックを適当に
実装したソースを示します。

コード:

#include "DxLib.h"

int Key[256];

int gpUpdateKey()
{
	char tmpKey[256];
	GetHitKeyStateAll(tmpKey);
	for (int i = 0; i < 256; i++)
		(tmpKey[i] == 0) ? (Key[i] = 0) : Key[i]++;
	return 0;
}

int stage[4][7][2];  // 盤上のマスの格子点の座標
int pos[3][6][2];    // キャラ描画座標

void init_stage()  // stage と pos を初期化する
{
	for (int j = 0; j < 7; j++) {
		int w = (j - 3) * 100, h = 600;
		for (int i = 4; --i >= 0; ) {
			stage[i][j][0] = w + 400, stage[i][j][1] = h - 200;
			w = w * 9 / 10, h = h * 9 / 10;
		}
	}
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 6; j++) {
			pos[i][j][0] = (stage[i][j][0] + stage[i + 1][j + 1][0]) / 2 - 25;
			pos[i][j][1] = (stage[i][j][1] + stage[i + 1][j + 1][1]) / 2 - 55;
		}
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
	SetGraphMode(780, 680, 32);         // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);             // 全画面ではなくウインドウを使用
	if (DxLib_Init() == -1) return -1;  // DXライブラリ初期化処理
	SetDrawScreen(DX_SCREEN_BACK);      // 裏画面を使用する設定

	init_stage(); // ステージとキャラ描画座標の初期化

	int enemyX = 4, enemyY = 1;   // 敵の位置
	int playerX = 1, playerY = 1;  // 俺の位置
	int playerX2 = 1, playerY2 = 1;  // ロック解除の戻り位置

	int enemyMove = 0;   // 敵の移動状態
	int playerMove = 1;  // 俺の移動状態

	int lock = 0;    // ロック状態
	int attack = 0;  // アタック状態

	int enemyGHandle[12];   // 敵のグラフィックハンドル格納用配列
	int playerGHandle[12];  // 俺のグラフィックハンドル格納用配列
		// 0:後向き右足前,  1:後向き,  2:後向き左足前
		// 3:右向き左足前,  4:右向き,  5:右向き右足前
		// 6:前向き右足前,  7:前向き,  8:前向き左足前
		// 9:左向き右足前, 10:左向き, 11:左向き左足前
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, enemyGHandle);
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, playerGHandle);

	int enemyImage = enemyGHandle[11];    // 敵 左向き
	int playerImage = playerGHandle[4];   // 俺 右向き

	

	const int MOVE_INTERVAL = 1000; // 何ミリ秒ごとに移動処理をするか
	int nextMoveTime = GetNowCount() + MOVE_INTERVAL; // 次回移動処理をする時刻
	int stopCount = 0; // 動かないのがあと何回か

	while (ProcessMessage() == 0) {
		
		gpUpdateKey();  // キーの入力状態を取得

		// 俺の移動
		if (Key[KEY_INPUT_RIGHT] == 1 && playerX < 2) {
			playerMove = 1; playerX++; playerImage = playerGHandle[4];
		}
		if (Key[KEY_INPUT_LEFT] == 1 && playerX > 0) {
			playerMove = 1; playerX--; playerImage = playerGHandle[9];
		}
		if (Key[KEY_INPUT_UP] == 1 && playerY > 0) {
			playerMove = 1; playerY--; playerImage = playerGHandle[2];
		}
		if (Key[KEY_INPUT_DOWN] == 1 && playerY < 2) {
			playerMove = 1; playerY++; playerImage = playerGHandle[8];
		}

		if (Key[KEY_INPUT_R] == 1 && playerY == enemyY) {  // ロック
			enemyImage = enemyGHandle[8];  // 敵の画像変更
			playerX2 = playerX; playerY2 = playerY;  // 元の位置保存
			lock = 1;  // ロックオン
		}
		if (lock > 0 && ++lock > 3*60) { // 3秒経った
			playerX = playerX2, playerY = playerY2;  // 元の位置に戻る
			playerMove = 1; playerImage = playerGHandle[4];
			lock = 0;  // ロック解除
		}
		if (lock && Key[KEY_INPUT_A] == 1) {  // アタック
			playerX = enemyX - 1;  // 敵の左に移動
			playerMove = 1; playerImage = playerGHandle[4];
			lock = 0; attack = 1;  // ロック状態からアタック状態に移行
		}
		if (attack > 0 && ++attack > 60) { // 1秒経った
			playerX = playerX2, playerY = playerY2;  // 元の位置に戻る
			playerMove = 1; playerImage = playerGHandle[4];
			attack = 0;  // アタック状態解除
		}

		// 敵の移動
		int t = GetNowCount();
		if (t >= nextMoveTime) { // 指定の時間が経ったら(1sごとに)
			nextMoveTime = t + MOVE_INTERVAL; // 次回移動処理をする時刻
			if (stopCount > 0) { // 停止中のとき
				stopCount--; // 止まっている残り時間(回数)を減らす
			}
			else { // 普通の状態のとき
				if (GetRand(99) < 10) { // たまに(10%の確率で)
					stopCount = GetRand(4); // 数秒間(1~5秒間)その場に止まる
				}
				else { // 9マス上のいずれかのパネルに移動させる
					int cy = enemyY, cx = enemyX;
					do {
						enemyY = GetRand(2);
						enemyX = GetRand(2) + 3;
					} while (enemyX == cx && enemyY == cy ||
						enemyX == playerX && enemyY == playerY);
					enemyImage = enemyGHandle[10];
					enemyMove = 1;
				}
			}
		}

		if (playerMove > 0) {
			playerMove++;
			if (playerMove == 10) {
				playerImage = playerGHandle[4];
			}
			else if (playerMove == 30) {
				playerImage = playerGHandle[5];
			}
			else if (playerMove == 40) {
				playerImage = playerGHandle[4];
			}
			else if (playerMove == 50) {
				playerImage = playerGHandle[3];
				playerMove = 1;
			}
		}

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

		// ステージの描画
		int stageColor = GetColor(160, 64, 64);
		for (int i = 0; i < 4; i++)
			DrawLine(stage[i][0][0], stage[i][0][1],
				stage[i][6][0], stage[i][6][1], stageColor, 5);
		for (int j = 0; j < 7; j++)
			DrawLine(stage[0][j][0], stage[0][j][1],
				stage[3][j][0], stage[3][j][1], stageColor, 5);

		DrawGraph(pos[enemyY][enemyX][0], pos[enemyY][enemyX][1],
			enemyImage, true);   // 敵キャラの描画
		DrawGraph(pos[playerY][playerX][0], pos[playerY][playerX][1],
			playerImage, true);  // 俺キャラの描画

		if (lock) DrawFormatString(100, 200, GetColor(255, 255, 255), "LOCK");
		ScreenFlip();  // 裏画面を表画面に反映
	}

	DxLib_End();  // DXライブラリ使用の終了処理
	return 0;  // ソフトの終了 
}

Rittai_3D
記事: 522
登録日時: 6年前

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#9

投稿記事 by Rittai_3D » 2週間前

Ouxiy さんが書きました:
2週間前
DXライブラリの processMessage() の while ループの意味を理解していませんね。
というより、コードの各行がどのように動いて次の行に行くのかを理解していません。
DXライブラリのループは理解が至ってない部分もありますが、コードの各行くらいどのように動いているかわかります。
わかっているなら
Rittai_3D さんが書きました:
2週間前
関係ないですが、リンク先の88行目、prokey は 0 or 1 で、89行目で1、90行目で2になると思うのですが、どういう意図でこのコードを書いたのでしょうか?
Ouxiyさんの言葉でこの説明をしてください。

まずはコーディング以前に
Rittai_3D さんが書きました:
2週間前
Ouxiyさんはまずやりたいことを細分化して、処理の流れを頭の中なり紙なり、一旦まとめる必要があると思います。
これをする必要があると思います。

ヒントをください、とありますが、ヒントはコード以外にもありますよ。
コードを書くだけがプログラミングではないです。
どちらかといえば、自分でロジックを考えるのがプログラミングのメインですよ。そこを勘違いしないでください。
オフトピック
サンプルコードでも書こうと思いましたが、手元にDxLibどころかWindows環境もないので書けませんでしたっていう…。
初心者です

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

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#10

投稿記事 by みけCAT » 2週間前

Ouxiy さんが書きました:
2週間前
質問8. (8) では、変数player2 が消えてなくなるのを知っていますか? A,知りませんでした。なぜ無くなるのでしょうか。
質問9. (9) では、変数prokey が消えてなくなるのを知っていますか? A,知りませんでした。なぜ無くなるのでしょうか。
{ ~ } (ブロック)の中でstaticなどの指定をせずに宣言された変数の有効期限は、
そのブロックの終わりまでです。
ブロックを抜けるときにこれらの変数はなくなり、
次にまたブロックの変数宣言のところに来るとまた新しく変数が作られます。
したがって、(8)ではplayer2が宣言されたブロックを抜けているのでplayer2はなくなっており、
(9)ではprokeyが宣言されたブロックを抜けるのでprokeyがなくなります。
(player2が消えるのは(8)の1行上ですね。(9)と統一されていないのはミスでしょうか?)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 148
登録日時: 1ヶ月前

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#11

投稿記事 by Ouxiy » 2週間前

みけCATさんありがとうございます。
以下は自分なりに編集して書いてみた全体のコードです。
このコードを書くにあたってヒントやコードを載せてくださった皆様、どうもありがとうございました!

コード:

#include "DxLib.h"

int Key[256];

int gpUpdateKey()
{
	char tmpKey[256];
	GetHitKeyStateAll(tmpKey);
	for (int i = 0; i < 256; i++)
		(tmpKey[i] == 0) ? (Key[i] = 0) : Key[i]++;
	return 0;
}

int stage[4][7][2];  // 盤上のマスの格子点の座標
int pos[3][6][2];    // キャラ描画座標

void init_stage()  // stage と pos を初期化する
{
	for (int j = 0; j < 7; j++) {
		int w = (j - 3) * 100, h = 600;
		for (int i = 4; --i >= 0; ) {
			stage[i][j][0] = w + 400, stage[i][j][1] = h - 200;
			w = w * 9 / 10, h = h * 9 / 10;
		}
	}
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 6; j++) {
			pos[i][j][0] = (stage[i][j][0] + stage[i + 1][j + 1][0]) / 2 - 25;
			pos[i][j][1] = (stage[i][j][1] + stage[i + 1][j + 1][1]) / 2 - 55;
		}
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
	SetGraphMode(780, 680, 32);         // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);             // 全画面ではなくウインドウを使用
	if (DxLib_Init() == -1) return -1;  // DXライブラリ初期化処理
	SetDrawScreen(DX_SCREEN_BACK);      // 裏画面を使用する設定

	init_stage(); // stage, pos の初期化

	int enemyX = 4, enemyY = 1;   // 敵の位置
	int playerX = 1, playerY = 1;  // 俺の位置

	int enemyMove = 0;   // 敵の移動状態
	  // 俺の移動状態//1~21で右に振り向きのプログラム①が終わり、22になったら足踏みする②を実行するようにする。
	int playerMove = 1;



	int lock = 0;  // ロック状態

	int enemyGHandle[12];   // 敵のグラフィックハンドル格納用配列
	int playerGHandle[12];  // 俺のグラフィックハンドル格納用配列
			// 0-2:後ろ向き、3-5:右向き、6-8:前向き、9-11:左向き
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, enemyGHandle);
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, playerGHandle);

	int enemyImage = enemyGHandle[11];    // 敵 左向き
	int playerImage = playerGHandle[4];   // 俺 右向き
	int preplayerX;
	int after = 0;
	

	const int MOVE_INTERVAL = 1000; // 何ミリ秒ごとに移動処理をするか
	int nextMoveTime = GetNowCount() + MOVE_INTERVAL; // 次回移動処理をする時刻
	int stopCount = 0; // 動かないのがあと何回か

	while (ProcessMessage() == 0) {
		
		gpUpdateKey();  // キーの入力状態を取得

		// 俺の移動
		if (Key[KEY_INPUT_RIGHT] == 1 && playerX < 2) {
			playerMove = 1; playerX++; playerImage = playerGHandle[4];
		}
		if (Key[KEY_INPUT_LEFT] == 1 && playerX > 0) {
			playerMove = 1; playerX--; playerImage = playerGHandle[9];
		}
		if (Key[KEY_INPUT_UP] == 1 && playerY > 0) {
			playerMove = 1; playerY--; playerImage = playerGHandle[2];
		}
		if (Key[KEY_INPUT_DOWN] == 1 && playerY < 2) {
			playerMove = 1; playerY++; playerImage = playerGHandle[8];
		}

		if (Key[KEY_INPUT_R] == 1 && playerY == enemyY ) {
			lock = 1;//Key[KEY_INPUT_R] == 1 && playerY == enemyYの時、lockを1にする。lockを「何フレーム目の時」でも値を1として置いたため、条件式lockの入力キーAに呼び出せる。
			enemyImage = enemyGHandle[2];

		}
		if(playerY != enemyY) { lock = 0; }//playerY != enemyYよりY座標が異なる場合を表す、Y座標が異なる場合はlockの値は0になる。要はロックが解除されてしまう。
		if (lock) {

			if (Key[KEY_INPUT_A] == 1) {  // アタック
				lock = 0;//lock = 1の時の「lock!!」の描画を消すためにlockの値を0に変更。

				preplayerX = playerX; // 元の位置を保持
				playerX = enemyX - 1; // 俺は敵の眼前へ
				after = 1;//アタック状態 ここまでをアタックとしてafter = 1と置いた。
			}
		}
			if (after > 0 && ++after > 20) {//afterが1より大きい時++afterが働き20より大きくなったら、
				//ifの中にifを書いてしまうとその前のifを否定してしまうためデータが引き継げない。なので別のif文として書いた。
				playerX = preplayerX;//preplayerXの座標をplayerXに代入する。
				playerImage = playerGHandle[4];
				after = 0;//アタック解除
			
			}
		

			
		
		
			// 敵の移動
			int t = GetNowCount();
			if (t >= nextMoveTime) { // 指定の時間が経ったら(1sごとに)
				nextMoveTime = t + MOVE_INTERVAL; // 次回移動処理をする時刻
				if (stopCount > 0) { // 停止中のとき
					stopCount--; // 止まっている残り時間(回数)を減らす
				}
				else { // 普通の状態のとき
					if (GetRand(99) < 10) { // たまに(10%の確率で)
						stopCount = GetRand(4); // 数秒間(1~5秒間)その場に止まる
					}
					else { // 9マス上のいずれかのパネルに移動させる
						int cy = enemyY, cx = enemyX;
						do {
							enemyY = GetRand(2);
							enemyX = GetRand(2) + 3;
						} while (enemyX == cx && enemyY == cy ||
							enemyX == playerX && enemyY == playerY);
						enemyImage = enemyGHandle[10];
						enemyMove = 1;
					}
				}
			}

			
			
		
		

		if (playerMove > 0) {//1フレームで処理を終わらせるためifの後はelse ifを使った。//フレームがあってもplayerMove++を書かないと1ずつ上がらない。playerMove++をフレームの60回ループするするところに書くことで以下のように書いて足踏みしている画像が描けた。
			playerMove++;//60フレームの中で、このifで条件(playerMove > 0)が真であるためplayerMove++を「フレーム」と「条件式」により繰り返しplayerMove++して、
			if (playerMove == 20)//以前の文を否定しないelse ifが次にあるためplayerMoveの情報を引き継ぎplayerMove == 30となるまで繰り返しplayerMove++をした。次にもelse ifがあるので同様、、、
			{
				playerImage = playerGHandle[4];
			}
			else if (playerMove == 30)//条件式として書くため=は==と書いた。//else ifによりplayerMoveが20を超えて(20の場合を否定し)30の場合を表す。
			{
				playerImage = playerGHandle[5];
			}
			else if (playerMove == 40)//30まで上がったものが40に上がった時、playerGHandle[4]になる。if文の連続では文法のルールで前の文を否定するため連続的に画像が流れず足踏みできない、なのでelse ifにしたのだ。
			{
				playerImage = playerGHandle[4];
			}
			else if (playerMove == 60*4) {//下に書いているように60フレームないに納めないといけないため、50まで上がったところで終わっている。
				playerImage = playerGHandle[3];//上に書いてることには誤りがある、60フレームで1sなだけ、超えてもいい。
				playerMove = 1;//
			}

		}


		//ループ内に書いたenemyMoveについてenemyMoveが0より大きくて40を超えたら{}の中身を実行。
		if (enemyMove > 0 && ++enemyMove > 40) {//pcが60フレームで一周するためenemyMoveが61以上だとenemyGHandle[8]が反映されず元のままで移動が終わる。なのでenemyMoveは60以下でなくてはならない
			enemyMove = 0; enemyImage = enemyGHandle[11];//60になる前に画像11を描画するようにしなければならないため、60より小さい40フレームにした。
		}

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

		// ステージの描画
		int stageColor = GetColor(160, 64, 64);
		for (int i = 0; i < 4; i++)
			DrawLine(stage[i][0][0], stage[i][0][1],
				stage[i][6][0], stage[i][6][1], stageColor, 5);
		for (int j = 0; j < 7; j++)
			DrawLine(stage[0][j][0], stage[0][j][1],
				stage[3][j][0], stage[3][j][1], stageColor, 5);

		DrawGraph(pos[enemyY][enemyX][0], pos[enemyY][enemyX][1],
			enemyImage, true);   // 敵キャラの描画
		DrawGraph(pos[playerY][playerX][0], pos[playerY][playerX][1],
			playerImage, true);  // 俺キャラの描画
		
		if (lock) DrawFormatString(100, 200, GetColor(255, 255, 255), "LOCK");//ループ内に書くと条件式lockのによりlockの値を0にしてもずっと表示されるため、必要な時に表示するようにここに書いた
		ScreenFlip();  // 裏画面を表画面に反映
	}

	DxLib_End();  // DXライブラリ使用の終了処理
	return 0;  // ソフトの終了 
}

Ouxiy
記事: 148
登録日時: 1ヶ月前

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#12

投稿記事 by Ouxiy » 2週間前

あの、カズマさんに質問があります。
質問5. (5) で prokey の値が 100000以上になることがありますか?
に関して、 prokey の値が 100000以上になることは無いと答えましたが、理由はわかりませんでした。
なぜ prokey の値が 100000以上にならないのか教えてください!!

かずま

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#13

投稿記事 by かずま » 2週間前

Ouxiy さんが書きました:
2週間前
あの、カズマさんに質問があります。
質問5. (5) で prokey の値が 100000以上になることがありますか?
に関して、 prokey の値が 100000以上になることは無いと答えましたが、理由はわかりませんでした。
なぜ prokey の値が 100000以上にならないのか教えてください!!
prokey が 2 だからです。

逆にお尋ねします。
いつどこで 3 になるんですか?
いつどこで 4 になるんですか?
いつどこで 100000 になるんですか?

Ouxiy
記事: 148
登録日時: 1ヶ月前

Re: R(ロックオン)キーを押した後、A(攻撃)キーを押して攻撃する

#14

投稿記事 by Ouxiy » 2週間前

コード:

if (Key[KEY_INPUT_R] == 1 && playerY==enemyY) {
	enemyImage = enemyGHandle[8];
	int prokey = Key[KEY_INPUT_R] == 1;  // (1)
	prokey = 1;                          // (2)
	prokey++;                            // (3)
	if (prokey > 0) {                    // (4)
		if (prokey < 100000 && Key[KEY_INPUT_A] == 1) {  // (5)
			int player2;
			player2 = enemyX - 1;        // (6)
			player2 = playerX ;          // (7)
			playerMove = 1; playerImage = playerGHandle[4];
			enemyMove = 1; enemyImage = enemyGHandle[10];
			prokey = 1;
		}
	}  // (8)
}   // (9)
フレームは60回で1sを利用して、prokey++; と書けば毎秒60ずつ増えていくと勘違いしていました。if文もprokey++; の後に書いてあるためフレームを利用できないし。以下のようにprokey++をif文の中に書いていればフレームを利用できました。
ですが、
if (playerMove > 0) {
playerMove++;if (playerMove == 20)//0より大きい場合は1を足すをplayerMoveが20になるまで(フレームを)繰り返す。

コード:

if (enemyMove > 0 && ++enemyMove > 40)//enemyMoveが0より大きい場合、40より大きくなるまで+1を繰り返す。 
のように書けていないため、2になったままで終わったのだと理解しました。

返信

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