動く足場について

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

動く足場について

#1

投稿記事 by ありた » 1年前

こんにちは。

現在サイドビューの2Dアクションを作ろうとしています。
色々なサイトを参考にして、プレイヤーとブロックの当たり判定、押し返し処理はできたのですが、
プレイヤーと動くブロックの当たり判定で、行き詰ってしまいました。

状況としては
「左に動いているプレイヤー」と「右に動いているブロック」
「右に動いているプレイヤー」と「左に動いているブロック」
の判定を行うと、プレイヤーが上に押し出されてしまうというものです。
(移動している向きが同じ場合は押し出されませんでした。)

プレイヤーとブロックの当たり判定では
「1フレーム前からX座標だけ動かしたプレイヤー」と「ブロック」
「1フレーム前からY座標だけ動かしたプレイヤー」と「ブロック」
の2つの判定を行い、もし斜めからプレイヤーがブロックに侵入している場合は、
「Y軸」の押し返しを優先する
というものです。

動く足場の処理を色々調べてみましたが、詳しい記事は見つからず、こちらの質問掲示板でもキーワードが無効であるとしてヒットしませんでした。

アルゴリズムの考え方、もしくは2Dアクションの作り方に関する詳しい記事がありましたらご教授いただければ幸いです。

よろしくお願いします。


コード:


void Game::player_vs_block() {

  //プレイヤーの着地判定を外す
	player.set_ground(false);

       //プレイヤーの1フレーム前の座標と現在の座標、X,Y軸における移動量を取得
	RectF old_rect = player.get_old_rect();
	RectF rect = player.get_rect();
	double move_x = rect.x - old_rect.x;
	double move_y = rect.y - old_rect.y;

	//x座標だけ動かしたもの・y座標だけ動かしたもの
	RectF rect_x = old_rect.movedBy(move_x, 0);
	RectF rect_y = old_rect.movedBy(0, move_y);

	//動くブロック用
	bool on_move_block = false;
	double on_move_block_x = 0;
	double on_move_block_y = 0;



	//動くブロックの判定

	for (auto& b : block) {

		if (b.get_name() == U"move_block") {

                        //プレイヤーとブロックが触れた場合
			if (player.get_rect().intersects(b.get_old_rect())) {

				bool bottom = 0;

				//下(乗っている)
				if (move_y > 0) {

					//プレイヤーの下の辺をブロックの上に合わせる
					if (rect_y.intersects(b.get_rect())) {
						on_move_block = true;
						on_move_block_x = b.get_moved_x();
						on_move_block_y = b.get_moved_y();
					}
				}
			}
		}
	}

	//動くブロックに乗っているプレイヤーを動かす
	if (on_move_block == true) {
		player.move_x(on_move_block_x);
		player.move_y(on_move_block_y);
	}

       //プレイヤーとブロックの判定
	for (auto& b : block) {

		if (player.get_rect().intersects(b.get_rect())) {

			bool right = false;
			bool left = false;
			bool top = false;
			bool bottom = false;

			//右
			if (move_x > 0) {

				//プレイヤーとブロックが触れた場合
				if (rect_x.intersects(b.get_rect())) {
					right = true;
				}
			}
			//左
			else if (move_x < 0) {

				//プレイヤーとブロックが触れた場合
				if (rect_x.intersects(b.get_rect())) {
					left = true;
				}
			}

			//下
			if (move_y > 0) {

				//プレイヤーとブロックが触れた場合
				if (rect_y.intersects(b.get_rect())) {
					bottom = true;
				}
			}//上
			else if (move_y < 0) {

				//プレイヤーとブロックが触れた場合
				if (rect_y.intersects(b.get_rect())) {
					top = 1;
				}
			}


			//斜め判定

			if (left == true or right == true) {
				if (top == true or bottom == true) {

					left = false;
					right = false;
				}
			}

			

			if (right == true) {
				player.set_pos_x(b.get_rect().x - player.get_size());
				
				//慣性を0にする
				player.zero_inertia();
				
			}
			else if (left == true) {
				player.set_pos_x(b.get_rect().x + b.get_rect().w);
				
				//慣性を0にする
				player.zero_inertia();
				
			}
			

			if (bottom == true) {

				player.set_pos_y(b.get_rect().y - player.get_size());

				//地上にいる判定にする
				player.set_ground(true);

				//重力加速度を0にする
				player.zero_speed_y();

				//コヨーテタイム
				player.set_coyote_time(0.2);

				
			}
			else if (top == true) {
				player.set_pos_y(b.get_rect().y + b.get_rect().h);

				//重力加速度を0にする
				player.zero_speed_y();
			}
		}
	}
}



ありた

Re: 動く足場について

#2

投稿記事 by ありた » 1年前

1フレーム前のプレイヤーが現在の移動したブロックに当たっているかを判定することで、
上から乗ることにするか、横から押されたかどうかを判定することができました。

ありがとうございました。

コード:

 
 
 //移動するブロック

	String blow = U"";

	
	double on_move_block_x = 0;
	double on_move_block_y = 0;


	for (auto& b : block) {

		if (b.get_type() == U"move") {

			//前フレームのプレイヤーが移動後のブロックに当たっている場合
			if (player.get_old_rect().intersects(b.get_rect())) {

				//左
				if (b.get_moved_x() < 0) {

					blow = U"left";
				}
				//右
				else if (b.get_moved_x() > 0) {

					blow = U"right";
				}
			}
		}
	}



	for (auto& b : block) {

		if (b.get_type() == U"move") {

			if (player.get_rect().intersects(b.get_rect())) {

				bool right = 0;
				bool left = 0;
				bool top = 0;
				bool bottom = 0;

				//右
				if (move_x > 0) {

					//プレイヤーの右の辺をブロックの左に合わせる
					if (rect_x.intersects(b.get_rect())) {
						right = true;
					}
				}
				//左
				else if (move_x < 0) {

					//プレイヤーの右の辺をブロックの左に合わせる
					if (rect_x.intersects(b.get_rect())) {
						left = true;
					}
				}

				//下
				if (move_y > 0) {

					//プレイヤーの下の辺をブロックの上に合わせる
					if (rect_y.intersects(b.get_rect())) {
						bottom = true;
					}
				}//上
				else if (move_y < 0) {

					//プレイヤーの上の辺をブロックの下に合わせる
					if (rect_y.intersects(b.get_rect())) {
						top = 1;
					}
				}


				//斜め判定

				if (left == true or right == true) {
					if (top == true or bottom == true) {

						left = false;
						right = false;


					}
				}

				//左向きブロック
				if (blow == U"left") {
					top = false;
					bottom = false;
					right = true;
				}
				//右向きブロック
				else if (blow == U"right") {
					top = false;
					bottom = false;
					left = true;
				}



				if (right == true) {
					player.set_pos_x(b.get_rect().x - player.get_size());
					player.zero_inertia();

				}
				else if (left == true) {
					player.set_pos_x(b.get_rect().x + b.get_rect().w);
					player.zero_inertia();

				}


				if (bottom == true) {

					player.set_pos_y(b.get_rect().y - player.get_size());

					//地上にいる判定にする
					player.set_ground(true);

					//重力加速度を0にする
					player.zero_speed_y();

					//コヨーテタイム
					player.set_coyote_time(0.2);

					on_move_block_x = b.get_moved_x();
					on_move_block_y = b.get_moved_y();
				}
				else if (top == true) {
					player.set_pos_y(b.get_rect().y + b.get_rect().h);

					//重力加速度を0にする
					player.zero_speed_y();
				}
			}
		}
	}

	//動く
	
	player.move_x(on_move_block_x);
	player.move_y(on_move_block_y);
 
 

返信

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