その座標上で足踏みするようにしたい。

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

その座標上で足踏みするようにしたい。

#1

投稿記事 by Ouxiy » 2ヶ月前

以下のプログラムに関して、

コード:

#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;   // 敵の移動状態
	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];   // 俺 右向き

	

	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[6];
			if (Key[KEY_INPUT_A] == 1) {  // アタック
				playerX = enemyX - 1;
				playerX = playerX;
				playerMove = 1; playerImage = playerGHandle[4];
				enemyMove = 1; enemyImage = enemyGHandle[10];
			}

			
		}
		else {
			// 敵の移動
			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 (enemyMove > 0 && ++enemyMove > 20) {
			enemyMove = 0; enemyImage = enemyGHandle[11];
		}
		if (playerMove > 0 && ++playerMove > 20) {//右を向くためのプログラム
			playerImage = playerGHandle[4];//playerMoveが20より大きい21になったら[4]を描画し、次に—1して20になったら[5]を描画し、再び+1して[4]を描画してif (playerMove > 0 && ++playerMove > 20によってループを繰り返す。
			--playerMove ; playerImage = playerGHandle[5];//playerMoveは20となる
			if (playerMove == 20) {
				++playerMove; playerImage = playerGHandle[4];//playerMoveは21となる
			}
		}

		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;  // ソフトの終了 
}
使用した画像のサイトの画像を使って以下のように移動していないときでも、その座標上で足踏みするようにしたいです。
以下のようにプログラムを書きましたが思うように動きません。あと何が足りないのでしょうか。
出来る限りこのプログラムの原型のままで問題を解決したいです。
どうかよろしくお願いいたします。

コード:

if (playerMove > 0 && ++playerMove > 20) {//右を向くためのプログラム
playerImage = playerGHandle[4];//playerMoveが20より大きい21になったら[4]を描画し、次に—1して20になったら[5]を描画し、再び+1して[3]を描画してif (playerMove > 0 && ++playerMove > 20によってループを繰り返す。
--playerMove ; playerImage = playerGHandle[5];//playerMoveは20となる
if (playerMove == 20) {
++playerMove; playerImage = playerGHandle[3];//playerMoveは21となる
}
}

Ouxiy
記事: 165
登録日時: 3ヶ月前

Re: その座標上で足踏みするようにしたい。

#2

投稿記事 by Ouxiy » 2ヶ月前

その座標上でゆっくり足踏みするようにしたいのですが、未だに機能しません。
改良したプログラムです。

コード:

if (playerMove > 0 && ++playerMove > 20) {//右を向くためのプログラム
			playerImage = playerGHandle[4];//playerMoveが20より大きい21になったら[4]を描画し、次に—1して20になったら[5]を描画し、再び+1して[4]を描画してif (playerMove > 0 && ++playerMove > 20によってループを繰り返す。
			--playerMove ; playerImage = playerGHandle[5];//playerMoveは20となる
			if (playerMove == 20) {
				for (int i = 19; i <= 1; --i) {//i = 19として、iが1になるまで—1を繰り返し、1になるまでの間はplayerGHandle[3]が描画される。
					playerMove = playerMove - i;//playerMoveを1にして
					playerImage = playerGHandle[3];//playerMoveは1となり、上のif (playerMove > 0 && ++playerMove > 20)より再びループする。
				}
			}
		}
できれば、このプログラムの原形のままでどんなふうにしたらその場でゆっくり足踏みするようになるのか教えてほしいです。

Ouxiy
記事: 165
登録日時: 3ヶ月前

Re: その座標上で足踏みするようにしたい。

#3

投稿記事 by Ouxiy » 2ヶ月前

コメントを書き直しました。

コード:

#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];   // 俺 右向き

	

	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[6];
			if (Key[KEY_INPUT_A] == 1) {  // アタック
				playerX = enemyX - 1;
				playerX = playerX;
				playerMove = 1; playerImage = playerGHandle[4];
				enemyMove = 1; enemyImage = enemyGHandle[10];
			}

			
		}
		else {
			// 敵の移動
			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 (enemyMove > 0 && ++enemyMove > 20) {
			enemyMove = 0; enemyImage = enemyGHandle[11];
		}
		if (playerMove > 0 && ++playerMove > 20) {//右を向くためのプログラム
			playerImage = playerGHandle[4];//右向きの画像。playerMoveが20より大きい21になったら[4]を描画し、次に—1して20になったら[5]を描画し、再び+1して[4]を描画してif (playerMove > 0 && ++playerMove > 20によってループを繰り返す。
			--playerMove ; playerImage = playerGHandle[5];//右足を出した右向き画像。playerMoveは20となる
			if (playerMove == 20) {
				for (int i = 19; i <= 1; --i) {//i = 19として、iが1になるまで—1を繰り返し、1になるまでの間はplayerGHandle[3]が描画される。
					playerMove = playerMove - i;//playerMoveを1にして
					playerImage = playerGHandle[3];//左足をだした右向きの画像playerMoveは1となり、上のif (playerMove > 0 && ++playerMove > 20)より再びループする。
				}
			}
		}

		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;  // ソフトの終了 
}

かずま

Re: その座標上で足踏みするようにしたい。

#4

投稿記事 by かずま » 2ヶ月前

DXライブラリの基本を全く理解していませんね。

playerImage を playerGHandl[3~5] で何度変更しても
DrawGraph(... playerImage, true); は 1フレームに 1回しか実行
しないので、最後の playerImage しか表示されませんよ。

同じ画像を何フレームか表示したら次の画像に切り替えるようにしないと。

コード:

		if (playerMove > 0) {
			playerMove++;
			if (playerMove == 20)
				playerImage = playerGHandle[4];
			else if (playerMove == 25)
				playerImage = playerGHandle[5];
			else if (playerMove == 44)
				playerImage = playerGHandle[4];
			else if (playerMove == 49) {
				playerImage = playerGHandle[3];
				playerMove = 1;
			}
		}
20, 25 などのフレーム数は、3枚の画像の表示時間に応じて調整してください。

Ouxiy
記事: 165
登録日時: 3ヶ月前

Re: その座標上で足踏みするようにしたい。

#5

投稿記事 by Ouxiy » 2ヶ月前

回答ありがとうございます。
えと、連続のif文をelse ifにする事と、フレーム数の関係がイマイチわからないのですが、
なぜ連続のif文ではいけなかったのでしょうか。
例えば1から+1されていき、
if playerMove==20になったら画像A
if playerMove==30になったら画像B
if playerMove==40になったら画像C
と出来ない理由がわかりません。
飲み込みが悪くてすいません。
どうか違いをわかりやすく教えてください。

Ouxiy
記事: 165
登録日時: 3ヶ月前

Re: その座標上で足踏みするようにしたい。

#6

投稿記事 by Ouxiy » 2ヶ月前

フレームが一度の画像しか表さないため、
連続のif文ではなく、else ifにより、playerMoveが更新されるように工夫したのかもと考えています。

返信

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