【DxLib】マップの壁について

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

【DxLib】マップの壁について

#1

投稿記事 by recomm » 4年前

昨日連射に関するトピックを建てて、今日もまた別件でトピックを建てるのはあまり好まないのですがどうしてもわからないので教えていただきたいです

キャラクターを操作する際、壁に入らせたくないのですがその時の計算がわかりません

コード:

//0は行動可能領域、1は壁
int map[15][20] = {
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 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, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 },
};

//px、pyはプレイヤーの現在の座標位置です
int kx = px, ky = py;
		if (Key[KEY_INPUT_LEFT]) {
			kx -= 10;
		}
		if (Key[KEY_INPUT_RIGHT]) {
			kx += 10;
		}
		if (Key[KEY_INPUT_UP]) {
			ky -= 10;
		}
		if (Key[KEY_INPUT_DOWN]) {
			ky += 10;
		}
    //ここからが壁判定になります
    //1でないときは移動する、というコードです
		if (map[ky / 32][kx / 32] != 1) {
			px = kx;
			py = ky;
		} 
このように余り切り捨ての除算で行動後の座標からmap[][]の添字とマップデータを取得しているのですが、うまく反映されません
壁にめり込んでしまいます
めり込みつつも変に壁判定が生きたりしておかしなことになってます
私は普通のゲームのようにそもそも壁に入らせたくないのですがどうすればよいのでしょうか

画像

アバター
usao
記事: 1584
登録日時: 7年前

Re: 【DxLib】マップの壁について

#2

投稿記事 by usao » 4年前

そもそも 「入る」とか「めり込む」とかいう事柄の定義 が不明なので答えようがないと思います.

(キャラクターの「大きさ」だとか「形」だとかいう要素をあれこれ考慮する必要が生じるのではないかと想像しますが,
 そういった要素がコード内に見当たらないように見受けます)

recomm
記事: 12
登録日時: 4年前

Re: 【DxLib】マップの壁について

#3

投稿記事 by recomm » 4年前

いろんな表現を乱用しすぎたようで申し訳ございません
したいことだけを簡潔にいうと、
「mapの0でのみ行動できる」ようにしたいです

この手の処理は座標だけでは成し得ないものなのでしょうか

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【DxLib】マップの壁について

#4

投稿記事 by Rittai_3D » 4年前

recomm さんが書きました:

コード:

//px、pyはプレイヤーの現在の座標位置です
int kx = px, ky = py;
		if (Key[KEY_INPUT_LEFT]) {
			kx -= 10;
		}
		if (Key[KEY_INPUT_RIGHT]) {
			kx += 10;
		}
		if (Key[KEY_INPUT_UP]) {
			ky -= 10;
		}
		if (Key[KEY_INPUT_DOWN]) {
			ky += 10;
		}
    //ここからが壁判定になります
    //1でないときは移動する、というコードです
		if (map[ky / 32][kx / 32] != 1) {
			px = kx;
			py = ky;
		} 
先に壁かどうか判定する処理を書けばよいと思います。
初心者です

アバター
usao
記事: 1584
登録日時: 7年前

Re: 【DxLib】マップの壁について

#5

投稿記事 by usao » 4年前

>いろんな表現を乱用しすぎたようで申し訳ございません

そういうことを言っているのではないです.
防止したい状態(めり込み)の明確な定義が説明される必要があるのではありませんか?ということです.


>この手の処理は座標だけでは成し得ないものなのでしょうか

あなたが考えている当たり判定というのが,キャラクターの絵の形状に厳密なもの
(=人物の絵のどの一部分であっても移動不能エリアに入りこんではならない)なのか
それとも別の形状(円とか矩形とか)なのかわかりませんが,
とにかく何かしらその当たり判定の形状を考慮した判定計算が必要になりそうに思うのですが,違うのでしょうか.
(「(px,py)ってその形状のどこなの?中央?」とかいう話も必要でしょうし)

そうではなくて,
座標(px,py)さえ移動不能エリアに入らなければ(絵の一部が移動不能エリアに入りこんでも)問題ないのだ
という話なのであれば,キャラクターの当たり判定の形状とかいうものを考えなくて済むかもしれません.

[追記]
提示された画像において,(px,py)とはどこになりますか?
その座標を明示的に確認できるような描画(点を打つとか?)を行う形にして動作を見ると良いのかもしれません.
現在の判定処理でも(px,py)だけは壁の中に入らないように動くのかもしれません.
オフトピック
個人的には,マップの升目のサイズ32 に対して移動量が10 で「判定した座標が壁なら全く移動できない」という話も気がかりだけど.
例えばキャラクターと壁との間に10未満の空間があっても移動できないわけで,
しかもこの幅というのがマップ上のどこらへんにいるかによって変わるわけで,スムーズにプレイするのは困難そうに思える.

recomm
記事: 12
登録日時: 4年前

Re: 【DxLib】マップの壁について

#6

投稿記事 by recomm » 4年前

Rittai_3D さんが書きました:先に壁かどうか判定する処理を書けばよいと思います。
先に書くとキーボード操作自体が無効になりました
ご回答ありがとうございます
usao さんが書きました:提示された画像において,(px,py)とはどこになりますか?
その座標を明示的に確認できるような描画(点を打つとか?)を行う形にして動作を見ると良いのかもしれません.
現在の判定処理でも(px,py)だけは壁の中に入らないように動くのかもしれません.
この部分でピンときました、ありがとうございます
前の(px, py)はキャラクター画像の左上の角でしたので右側が壁に入り込んでいたようです
壁との当たり判定を円(中心からの距離)で取得するようにしました

コード:

//キャラクター画像が32*32なので中心は16*16
//そしてマップチップ一つ分をまたぐので(32+16,32+16) = (48,48)
//DrawRotaGraphは中心を基準に描画するため使いまわせる
int px = 48, py = 48;

//0は行動可能領域、1は壁
int map[15][20] = {
    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 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, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 },
};

//(中略)

int kx = px, ky = py;
int kx2 = px, ky2 = py;
if (Key[KEY_INPUT_LEFT]) {
	kx -= 8;
	kx2 -= 16;
}
if (Key[KEY_INPUT_RIGHT]) {
	kx += 8;
	kx2 += 16;
}
if (Key[KEY_INPUT_UP]) {
	ky -= 8;
	ky2 -= 16;
}
if (Key[KEY_INPUT_DOWN]) {
	ky += 8;
	ky2 += 16;
}

if (map[ky2 / 32][kx2 / 32] != 1)
{
	px = kx;
	py = ky;
}

//(中略)

//このプログラムではキャラクターの回転を扱うためDrawRotaGraphを使うが、
//このトピックとは関係なし
//【補足】PIは円周率として定義済み、関係ないので省略
DrawRotaGraph(px, py, 1.0, PI / 0.5, reimu, TRUE);
皆さんご協力ありがとうございました
最後に編集したユーザー recomm on 2015年8月18日(火) 15:49 [ 編集 1 回目 ]

アバター
usao
記事: 1584
登録日時: 7年前

Re: 【DxLib】マップの壁について

#7

投稿記事 by usao » 4年前

進行方向の先の1点だけを判定すると下図のような挙動になりそうですが,大丈夫ですか?

A地点から右方向に移動することは可能 → 結果としてB地点に行ける
しかしC地点から下方向に移動することは不可能 → この方向からはB地点に行けない

>壁との当たり判定を円(中心からの距離)…

ということであれば,前者側の挙動はまずいように思います.
Move.png
Move.png (7.33 KiB) 閲覧数: 2161 回

recomm
記事: 12
登録日時: 4年前

Re: 【DxLib】マップの壁について

#8

投稿記事 by recomm » 4年前

usao さんが書きました:進行方向の先の1点だけを判定すると下図のような挙動になりそうですが,大丈夫ですか?

A地点から右方向に移動することは可能 → 結果としてB地点に行ける
しかしC地点から下方向に移動することは不可能 → この方向からはB地点に行けない

>壁との当たり判定を円(中心からの距離)…

ということであれば,前者側の挙動はまずいように思います.
あ…そうですね
デバッグしてみたら画像のようにおかしなことになりました

kx[4]とky[4]を宣言して上下左右4点の座標で壁判定を行えばいいのでしょうか
頭がパンクしてきました…

recomm
記事: 12
登録日時: 4年前

Re: 【DxLib】マップの壁について

#9

投稿記事 by recomm » 4年前

4点は4点でおかしくなりました

画像

円で判定できれば楽なのですが…
画像

アバター
usao
記事: 1584
登録日時: 7年前

Re: 【DxLib】マップの壁について

#10

投稿記事 by usao » 4年前

>上下左右4点の座標で壁判定を行えばいいのでしょうか

現行の方法(=座標を32で除してmap[][]のindexとして使って判定)でやるのであれば
1点だけ とか 4点だけ とか極端に判定する場所の個数をケチらなくとも,例えば

・円を(幅1pixelで)描画した際に,描画が行われる画素位置の集合を使う
とか
・円周上を1度刻みで360点サンプリングした座標を使う
とかもう少し贅沢にサンプル点を取れば,よりマシに(程度問題)なるのではないでしょうか.


[追記]
面倒なら円じゃなくて矩形にしちゃうとか…
これなら四隅(のうちの進行方向側にある点)で済みそうな気がする.
Move2.png
Move2.png (3.86 KiB) 閲覧数: 2031 回
最後に編集したユーザー usao on 2015年8月18日(火) 19:16 [ 編集 2 回目 ]

アバター
usao
記事: 1584
登録日時: 7年前

Re: 【DxLib】マップの壁について

#11

投稿記事 by usao » 4年前

別の(?)方法として……

移動先での当たり判定円に衝突する可能性のあるマス( map[][] のindex )というのは
円の中心座標と円の径とマスの大きさ(32) から絞り込める
(例えば, 円の直径 ≦ マスの大きさ(32) であるなら,map[][]のうち4カ所以下……かな)
でしょうから,
その中で壁な箇所の32x32サイズ矩形と円との交差判定等を行えば良いように思います.

recomm
記事: 12
登録日時: 4年前

Re: 【DxLib】マップの壁について

#12

投稿記事 by recomm » 4年前

usao さんが書きました:現行の方法(=座標を32で除してmap[][]のindexとして使って判定)でやるのであれば
1点だけ とか 4点だけ とか極端に判定する場所の個数をケチらなくとも,例えば

・円を(幅1pixelで)描画した際に,描画が行われる画素位置の集合を使う
とか
・円周上を1度刻みで360点サンプリングした座標を使う
とかもう少し贅沢にサンプル点を取れば,よりマシに(程度問題)なるのではないでしょうか.
円の描画も考えてみましたが処理速度が極端に遅くなりそうなのでやめました
(円の描画からの点の座標取得、移動するたび全ての座標データを書き換える)

なので、
usao さんが書きました:[追記]
面倒なら円じゃなくて矩形にしちゃうとか…
これなら四隅(のうちの進行方向側にある点)で済みそうな気がする.
こちらを利用させてもらうことにしました
これなら簡単でいいですね、ちゃんと動いてくれました
画像も用意してわかりやすく教えていただいてありがとうございました
オフトピック
usaoさんが載せていただいた画像を作成しているソフト、とても便利そうです
できれば教えていただけないでしょうか

アバター
usao
記事: 1584
登録日時: 7年前

Re: 【DxLib】マップの壁について

#13

投稿記事 by usao » 4年前

>円の描画も考えてみましたが処理速度が極端に遅くなりそうなのでやめました
>(円の描画からの点の座標取得、移動するたび全ての座標データを書き換える)

こういうのは毎回計算せずに,あらかじめ座標データを用意してしまえば良いかと思います.

オフトピック
>usaoさんが載せていただいた画像を作成しているソフト

officeです…
(PowerPointで適当に描いたのをコピー → ペイントとかにペーストして画像ファイルとして保存)

recomm
記事: 12
登録日時: 4年前

Re: 【DxLib】マップの壁について

#14

投稿記事 by recomm » 4年前

usao さんが書きました:こういうのは毎回計算せずに,あらかじめ座標データを用意してしまえば良いかと思います.
なるほど、初めにすべて取得しておくということでしょうか
参考にさせてもらいます
オフトピック
usao さんが書きました:officeです…
(PowerPointで適当に描いたのをコピー → ペイントとかにペーストして画像ファイルとして保存)
officeなんですか!
まさかとは思ってましたがそのまさかとは…
教えていただきありがとうございます

閉鎖

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