[DxLib]2DACTでの重力と地形判定

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

[DxLib]2DACTでの重力と地形判定

#1

投稿記事 by 刀流 » 2週間前

C++とDxLibにて2DACTを制作しているものです。

先日、この掲示板で2DACTでの重力の実装について質問させていただき、そのトピックにて基本的なところは理解・実装できたのですが、細かいところでどうしてもわからないところがあります。

現在困っているバグは、
「『移動先の座標に進んでいいか否か』を判定する工程に問題があるらしく」
「座標の更新時に1フレームのラグが出来てしまい、1フレームだけキャラクターがめり込んで表示されてしまったり、その1フレームのラグの間にキャラクター座標が大きく移動すると、めり込んだまま戻ってこなくなってしまったりする」
というものです。

コードはこちらになります。


Gravity.cpp

コード:

int y;
double speed = 0;

              //   足の衝突  頭の衝突
double Gravity(int hantei, bool hedhit) {
	y += speed; //重力加速度を足しこむ
	if (hantei == 0) { // 地面に足がついていないなら
		speed += 0.4f; // 加速
		if (hedhit == true) { // 頭が地形に当たったなら
			y = y / 32 * 32 + 33; // 位置を修正
			speed = 2.0f; // 加速度を遅めに固定する
		}
	}
	if (hantei == 1) { // 地面に足がついているなら
		if (jump == 1) { // ジャンプボタンがおされたなら
			speed = -9.8f; // ジャンプ
		}
			y = y / 32 * 32 + 4 ; // 位置調整
		}
	if (speed > 10.2f) // 重力が最大値を超えていたら
		speed = 10.2f; // 調整
	return y; // y座標を返す
}
Player.h

コード:

typedef struct {
	int player_x;
	double player_y;
        //その他、ゲーム進行に使う変数(地形判定とは無関係)
} Player_t;

extern int camera_x;
extern bool player_isabletogoright, player_isabletogoleft;
extern bool player_hedhit;
Player.cpp

コード:

int Player_maphit_x_1, Player_maphit_x_2, Player_maphit_x_3, Player_maphit_x_4, Player_maphit_y_1, Player_maphit_y_2, Player_maphit_y_3, Player_maphit_y_4;
int camera_x;
int player_hantei;
bool player_isabletogoright;
bool player_isabletogoleft;
bool player_hedhit;

void Player_Update(Player_t *Player){

	Player_maphit_x_1 = Player->player_x / 32.0000 + camera_x / 32.0000 - 16 / 32.0000 + 1 / 32.0000; // 最左のx座標
	Player_maphit_x_2 = Player->player_x / 32.0000 + camera_x / 32.0000 - 8 / 32.0000; // 真ん中少し左のx座標
	Player_maphit_x_3 = Player->player_x / 32.0000 + camera_x / 32.0000 + 8 / 32.0000; // 真ん中少し右のx座標
	Player_maphit_x_4 = Player->player_x / 32.0000 + camera_x / 32.0000 + 16 / 32.0000 - 1 / 32.0000; // 最右のx座標
	Player_maphit_y_1 = Player->player_y / 32.0000 - 32 / 32.0000 + 1 / 32.0000; // 最高のy座標
	Player_maphit_y_2 = Player->player_y / 32.0000 - 16 / 32.0000;// 真ん中少し上のy座標
	Player_maphit_y_3 = Player->player_y / 32.0000 + 16 / 32.0000;// 真ん中少し下のy座標
	Player_maphit_y_4 = Player->player_y / 32.0000 + 32 / 32.0000 - 1 / 32.0000; // 最低のy座標

	if (Keyboard_Get(KEY_INPUT_LEFT) >= 1) {//左キーが押されていたら
		if (player_isabletogoleft == true) {
			if (Player->player_x <= 200 && camera_x >= 1)
				camera_x -= 2;
			else
				Player->player_x -= 2;
		}
	}
	if (Keyboard_Get(KEY_INPUT_RIGHT) >= 1) {//右キーが押されていたら
		if (player_isabletogoright == true) {
			if (Player->player_x < 320)
				Player->player_x += 2;
			else
				camera_x += 2;
		}
	}

	Player->player_y = Gravity(player_hantei, player_hedhit);
        //その他、ゲーム進行に必要な処理(地形判定とは無関係)
}
Stage1.h

コード:

typedef struct {
        //マップデータ
	int stage1_hantei[17][131] = {
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,0,0,2,2,0,0,2,2,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
		{0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
		{0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
		{2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,0,0,2,2,0,0,1,1,0,0,1,1,1,1,1,1,1,2,2,0,2,2,2,0,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
		{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
		{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
		{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
	};
        //その他、ゲーム進行に使う変数(地形判定とは無関係)
} Stage1_t;
Stage1.cpp

コード:

void Stage1_Update(Stage1_t *stage1) {
	   //底部の衝突判定
	if (stage1->stage1_hantei[Player_maphit_y_4][Player_maphit_x_2] != 0 || stage1->stage1_hantei[Player_maphit_y_4][Player_maphit_x_3] != 0) {
		player_hantei = 1;
	}
	else if (stage1->stage1_hantei[Player_maphit_y_4][Player_maphit_x_2] == 0 && stage1->stage1_hantei[Player_maphit_y_4][Player_maphit_x_3] == 0) {
		player_hantei = 0;
	}
	   //頭の衝突判定
	if (stage1->stage1_hantei[Player_maphit_y_1][Player_maphit_x_2] != 0 || stage1->stage1_hantei[Player_maphit_y_1][Player_maphit_x_3] != 0) {
		player_hedhit = true;
	}
	else if (stage1->stage1_hantei[Player_maphit_y_1][Player_maphit_x_2] == 0 && stage1->stage1_hantei[Player_maphit_y_1][Player_maphit_x_3] == 0) {
		player_hedhit = false;
	}
	   //右に進めるか判定
	if (stage1->stage1_hantei[Player_maphit_y_2][Player_maphit_x_4] != 0 || stage1->stage1_hantei[Player_maphit_y_3][Player_maphit_x_4] != 0) {
		player_isabletogoright = false;
	}
	else if (stage1->stage1_hantei[Player_maphit_y_2][Player_maphit_x_4] == 0 && stage1->stage1_hantei[Player_maphit_y_3][Player_maphit_x_4] == 0) {
		player_isabletogoright = true;
	}
	//左に進めるか判定
	if (stage1->stage1_hantei[Player_maphit_y_2][Player_maphit_x_1] != 0 || stage1->stage1_hantei[Player_maphit_y_3][Player_maphit_x_1] != 0) {
		player_isabletogoleft = false;
	}
	else if (stage1->stage1_hantei[Player_maphit_y_2][Player_maphit_x_1] == 0 && stage1->stage1_hantei[Player_maphit_y_3][Player_maphit_x_1] == 0) {
		player_isabletogoleft = true;
	}
	Player_Update(&Player);
}//更新
なお、コードは衝突判定に関係あるところのみの記載になっております。
また、キャラクターはLoadDivGraphにて読み込んで描画しているので、Player->player_xとPlayer->player_yはそれぞれ真ん中の座標になっています。
実行に関してはStage1_Updateを呼び出して行っています。

ご解答よろしくお願いします。

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

Re: [DxLib]2DACTでの重力と地形判定

#2

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

詳しく見てはいないですが、Player_maphit_*系の変数の値を設定した後、
それらの値を使った判定を行う前にプレイヤーの座標を更新してしまっているので、
これが「1フレームのラグ」になりそうですね。

そのため、Player_maphit_*系の変数の値の設定を
プレイヤーの座標の更新(Gravity関数の呼び出しまで)の後に持ってくると改善するかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

刀流
記事: 9
登録日時: 3ヶ月前

Re: [DxLib]2DACTでの重力と地形判定

#3

投稿記事 by 刀流 » 2週間前

みけCAT さんが書きました:
2週間前
詳しく見てはいないですが、Player_maphit_*系の変数の値を設定した後、
それらの値を使った判定を行う前にプレイヤーの座標を更新してしまっているので、
これが「1フレームのラグ」になりそうですね。

そのため、Player_maphit_*系の変数の値の設定を
プレイヤーの座標の更新(Gravity関数の呼び出しまで)の後に持ってくると改善するかもしれません。
返信ありがとうございます!
お教えいただいた改善策を使ってみることで地面に当たった時の底面のめり込みは改善されたのですが、
どうやらキャラクターの頭が地形にぶつかった時には元から2,3フレームのラグがあったらしく、めり込みが完全には解決されませんでした。

刀流
記事: 9
登録日時: 3ヶ月前

Re: [DxLib]2DACTでの重力と地形判定

#4

投稿記事 by 刀流 » 2週間前

連投での補足失礼します。
書き忘れてしまっていたのですが、キャラクターの画像は横32×縦64ピクセルのものを使用しています。
新たに変数aを作り、player_hedhit == 1のとき++aすることでaの値からキャラクターがめり込んでいるフレーム数を出そうと試みたところ、
①「キャラクターのy座標の減りが小さい時はaの増加量は1」
②「キャラクターのy座標の減りが小さい時(具体的にはキャラクターが半分めり込んでいる=衝突判定するまでのy座標の減少量が32を超えマップチップ一つ分のサイズより大きくなってしまい、すりぬけが発生してしまう時)はaの増加量は2」という2つの結果が発生しました。
しかし①でもめり込みがかすかに認められるため、恐らくは①の時1フレームのラグ、②の時2フレームのラグが発生してしまっているようです。

刀流
記事: 9
登録日時: 3ヶ月前

Re: [DxLib]2DACTでの重力と地形判定

#5

投稿記事 by 刀流 » 2週間前

x、y座標が真ん中に設定されているのは「LoadDivGraphでの読み込み」ではなく「DrawRotaGraphでの描画」が原因でした、すみません…

返信

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