マップとの当たり判定

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

マップとの当たり判定

#1

投稿記事 by 県民 » 14年前

すごい初歩的な質問で申し訳ないです
この前、プログラミングの館を読み終えたのですが分からない所があるので教えてください

縦横斜め動けるマップで実装したい当たり判定は / こんな感じの斜めです
その場所にキャラが下から突っ込みます
当たり判定に沿ってキャラが自動的に右上に移動していきます

説明が分かりやすくなくて悪いのですがよくRPGなどで使われている手法です
ご回答よろしくお願いします

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#2

投稿記事 by softya(ソフト屋) » 14年前

自動的な障害物回避のことでしょうか?
そういう場合は、真正面に進めない場合は自動的に45度づつ角度を変えて移動してみて進める方向に進むってことをすれば実現できますよ。
[追記]移動速度次第では22.5度単位じゃないと違和感が出るかも知れません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#3

投稿記事 by 県民 » 14年前

多分、当たり判定を順番に確かめていくということだと思うのですが
(この場合だと四方向の当たり判定だけじゃなくて八方向の当たり判定)
よく分かりません(主に実装の仕方と実装の仕方と実装の仕方と・・・)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#4

投稿記事 by softya(ソフト屋) » 14年前

ベースとなるソースコードを貼ってもらえば、どう直せばよいか説明しますよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#5

投稿記事 by 県民 » 14年前

お恥ずかしながら角度の求め方が分かりません
公式か何かを教えてください お願いします

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#6

投稿記事 by softya(ソフト屋) » 14年前

角度と移動距離の関係がわからない場合は、

「C言語~ゲームプログラミングの館~ s13a. sin,cosって何?(STGでの使用方法)」
http://dixq.net/g/s.13.a.html
「C言語~ゲームプログラミングの館~ s13. sin,cosって何? シューティングの基本概念」
http://dixq.net/g/s.13.b.html

をもう一度読みなおしてみてください。
プログラムを打ち込んで色々いじってみると分かってくると思います。

[追記]
とりあえず4方向にドット単位で動くものを作ってみてください。
たしか、ゲームプログラミングの館には区間単位での移動をするものしか無かったはずですのの、そこからオリジナルになります。
それが出来たら、それを8方向に移動させるように改造していきましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#7

投稿記事 by 県民 » 14年前

>>とりあえず4方向にドット単位で動くものを作ってみてください
このドット単位なるものがよく分からないのですが(ゲームはあまり詳しくないのですみません)
普通にint型の変数を増加させるだけでしょうか? 
それともドットっていうのは小数ということになるのでしょうか?

それと今更なんですが当たり判定の付け方で質問です
私のやり方は実際に目で見える障害物よりも少し大きめな位で当たり判定をつくっておき、
それとキャラが重なったときにフラグ変数に1を代入して移動判定を行うという手順なのですが
このやり方ならわざわざ角度を求めなくてもフラグ変数に2を代入させて
45度の方向に移動させるというやり方が出来ると思います
・・・と考えたのですが当たり判定の設定の仕方から間違っているのでしょうか?

少々、長くなってしまいましたがご回答願います

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#8

投稿記事 by softya(ソフト屋) » 14年前

ゲームに詳しくないとしても、ゲームを作る以上は用語は調べるようにしてください。
ドットは画面の画素単位です。DXライブラリは、整数の単位でドットの座標を扱えます。
他にピクセルという単位もあるのですが、拡大や縮小など変わったことしなければピクセル=ドットで同じ単位と思ってもらって構いません。
>普通にint型の変数を増加させるだけでしょうか?
座標のドット単位の移動ということならyesです。
県民 さんが書きました:それと今更なんですが当たり判定の付け方で質問です
私のやり方は実際に目で見える障害物よりも少し大きめな位で当たり判定をつくっておき、
それとキャラが重なったときにフラグ変数に1を代入して移動判定を行うという手順なのですが
このやり方ならわざわざ角度を求めなくてもフラグ変数に2を代入させて
45度の方向に移動させるというやり方が出来ると思います
・・・と考えたのですが当たり判定の設定の仕方から間違っているのでしょうか?
「フラグ変数に2が来たときに45度の方向に移動させる」と言う部分がどうやるか具体的に分かりませんのでyesともnoとも答えかねます。
もうすこし具体的に説明して頂けますか?
そうですね。フラグ変数が0,1,2になる条件とそれぞれの場合にやることを書いて頂けると私に伝わると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#9

投稿記事 by 県民 » 14年前

実際に試したわけではないので分からないのですが

もし自分の上に何もない場合はフラグに0を代入します
━←こんなような当たり判定が自分の上に合った場合はフラグに1を代入します
/←こんなような当たり判定が自分の上に合った場合はフラグに2を代入します
上キーが押された時にフラグが0の場合、y-1を実行します
上キーが押された時にフラグが1の場合、何も実行しません
上キーが押された時にフラグが2の場合、y-1,x+1を実行します

これで自動移動というのは実装できると考えたのですがやっぱり没です
左上も実装しなくちゃいけないし、なにより45度限定ってのがおかしいですね
自分的には10度から90度まで計って進める角度があればその方向に進むということがしたいのですが
sinを使えば出来ますでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#10

投稿記事 by softya(ソフト屋) » 14年前

実際にゲームを作ってみると分かりますが、1ドット単位の移動は遅すぎるので数ドット/毎フレームで移動する必要があります。

>sinを使えば出来ますでしょうか?
sin,cosを使えば角度から移動ドット数1の場合のx,y方向の各移動量を求めることが出来ますので、それに実際の移動ドット数を乗算してください
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#11

投稿記事 by 県民 » 14年前

分かりました  
角度をつけた移動の求め方は分かりました(理論とかアレですが)

さっきも言っちゃったのですが10度くらいから90度くらいまでを全て確かめて
進めるならその方向に前進ということをしたいのです
もしこのやり方を実装するには当たり判定の考え方から見直す必要があるとかでしたら
ヒントか何か教えてください  わがまま言ってスマンです

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#12

投稿記事 by softya(ソフト屋) » 14年前

地形との当たり判定のバリエーション次第でかなり難しくなります。
三角形と四角形を当たり判定しようとすると次のようなことを考えないといけません。
「当たり判定 - ゲームプログラミングWiki」
http://www.c3.club.kyutech.ac.jp/gamewi ... 8%BD%C4%EA

難しいと感じたら別にこんな事をしなくても、壁への当たり方を工夫してシンプルにすることは出来ます。
そのためには、壁の形状を限定的するなどの工夫が必要です。
そうすれば少ないパターンで四角形同士の当たり判定で処理ができます。
「2Dゲームの当たり判定」
http://www5f.biglobe.ne.jp/~kenmo/progr ... 2d/2d.html
斜めの壁は四角形を積み重ねたものと考えることが出来ますからね。
atari.png
atari.png (1008 バイト) 閲覧数: 10952 回
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#13

投稿記事 by 県民 » 14年前

まだ詳しくないので分からないのですが

if(上キーが押されたら){
  for(int i = 90 : i<1 : i--){
if(もし進めるなら){
      x += i * speed ; //x座標計算
   y += i * speed ; //y座標計算
}
}
}

こんな感じの文を書けばいいのかなあと思ったのですが(これで合っているかは分かりません)
合っているとしたらif(もし進めるなら)という部分がどうなるのかが分かりません

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#14

投稿記事 by softya(ソフト屋) » 14年前

擬似的なコードを見て思いましたが、やはり先に4方向の移動を作ってください。
そこから始めましょう。
すごく基本的なところで問題がありますが、今説明しても分からないと思いますので実際に作ってみるのが一番です。

あと、一つ前に書いた当たり判定も一旦忘れてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#15

投稿記事 by 県民 » 14年前

一応、4方向移動ならやるんですけどね(言っても簡単な移動だけですが)
この質問もインベーダーが完成したので4方向に歩くものがつくりたいなぁ~と思ったものですので・・・

できれば先ほどの文のおかしいというところを教えてください
言っても分からないと仰いましたが理解するよう勤めますので教えてください

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#16

投稿記事 by softya(ソフト屋) » 14年前

県民 さんが書きました:できれば先ほどの文のおかしいというところを教えてください
言っても分からないと仰いましたが理解するよう勤めますので教えてください
for文を使っているのが問題ですね。
県民 さんが書きました:一応、4方向移動ならやるんですけどね(言っても簡単な移動だけですが)
この質問もインベーダーが完成したので4方向に歩くものがつくりたいなぁ~と思ったものですので・・・
それでは8方向でお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#17

投稿記事 by 県民 » 14年前

何度も考えを覆すようなことを書いてごめんなさい、、、思いつきました

今までのように目で見える障害物よりも少し大きめに当たり判定を設定しておきます
そして、その次に今までは歩けるかどうかのフラグを関数に渡していましたが
今回はどれくらいの角度で歩けば通れるかの変数を関数に渡します
そして渡された変数はsinとして使い、移動スピードとかけて移動位置を導き出します

・・・と初心者なりに妄想してみたのですがどうでしょうか?


>>8方向でお願いします
4方向に動けるようにした場合、勝手に斜め方向にも移動できるようになっていたと思います

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#18

投稿記事 by softya(ソフト屋) » 14年前

県民 さんが書きました:何度も考えを覆すようなことを書いてごめんなさい、、、思いつきました

今までのように目で見える障害物よりも少し大きめに当たり判定を設定しておきます
そして、その次に今までは歩けるかどうかのフラグを関数に渡していましたが
今回はどれくらいの角度で歩けば通れるかの変数を関数に渡します
そして渡された変数はsinとして使い、移動スピードとかけて移動位置を導き出します

・・・と初心者なりに妄想してみたのですがどうでしょうか?
その説明だと具体的なコードが私には見えません。
ぜひ、実証コードを作って、ここに貼りつけてみてください。
県民 さんが書きました: >>8方向でお願いします
4方向に動けるようにした場合、勝手に斜め方向にも移動できるようになっていたと思います
本当になんども書いて申し訳ないのですが、その8方向に動けるコードを貼りつけてください。
県民さんにとって貼り付けることは何の問題もないはずです。貼付けを避ける理由があったら教えてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#19

投稿記事 by 県民 » 14年前

すいません旅行にいっていて返信おそくなりました
コードを書こうと思ったのですが初歩的なところでつまずきました

コード:

#include "DxLib.h"

int x,y,a,b;
int aleft = x+2;
int bright = a+333;
int aright =x+23;
int bleft = a+32;
int atop = y+4;
int bbottom = b+218;
int abottom =y+19;
int btop = b+214;
int flag;


// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode( TRUE ) ;


	
	int GraphHandle,handle ;

	// DXライブラリ初期化処理
	if( DxLib_Init() == -1 ) return -1;

	// グラフィック『test1.bmp』をメモリにロード
	GraphHandle = LoadGraph( "戦闘機.bmp" ) ;
	handle = LoadGraph( "壁.bmp" ) ;
	
	while(1){
	
	 ClearDrawScreen() ;

	
	// 0,0 座標にメモリに読みこんだグラフィックを描画
	DrawGraph( x , y , GraphHandle , TRUE ) ;
        DrawGraph( a , b , handle, TRUE);
	
	if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ) x -= 4 ;
	if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 ) x += 4 ;
	if( CheckHitKey( KEY_INPUT_UP ) == 1 && flag==0) y -= 4 ;
	if( CheckHitKey( KEY_INPUT_DOWN ) == 1 ) y += 4 ;

          if((aleft < bright)&&(aright > bleft)&&(atop < bbottom)&&(abottom > btop)) flag==1;
	   
	
	WaitTimer( 20 ) ;

	if( ProcessMessage() == -1 ) break ;

	// ESCキーが押されたらループから抜ける
	if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ) break ;
        }

	// DXライブラリ使用の終了処理
	DxLib_End() ;

	// ソフトの終了
	return 0 ;
}

歩けない所に言った場合、フラグ変数に1を代入しています
2週間前にこれと同じようなコードを書いた時は正常に動作したのですが・・・
どこかちがいますかね?質問してしまい申し訳ないです
(ソフト屋さんのあげてくれたサイトを参考にしています)

それと厳密には斜め方向に移動していませんでしたね・・・
斜め移動の時はまっすぐ移動と増える座標を変えなければいけないと思いますが。。。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#20

投稿記事 by softya(ソフト屋) » 14年前

明日またコードを確認して返事をさせていただきます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#21

投稿記事 by softya(ソフト屋) » 14年前

戦闘機bmp・・・あれ?前に違う名前で質問されませんでした?もしそうでしたら、名前を統一してもらうと前の回答を踏まえての回答がしやすくなりますので統一をお願いします。
※ フォーラムルールでは統一をお願いしております。

でプログラムの問題ですが、
●その1
if((aleft < bright)&&(aright > bleft)&&(atop < bbottom)&&(abottom > btop)) flag==1;
が固定値同士を比較しているので無意味です。
int aleft = x+2;は代入時に値が確定してるのでこの宣言位置ではifでの比較時には固定値となりますので、このintの宣言をif文の直前に移動させる必要があります。
それと、flag==1が代入文ではなく条件式です。

●その2
if((aleft < bright)&&(aright > bleft)&&(atop < bbottom)&&(abottom > btop)) flag==1;
この条件が何を制限したいのか分かりません。画面外への移動の制限ならもっとシンプルに済みまし現状正常に機能しません。
デバッガなどを使って動きをトレースしてみてください。
「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&b=982&c=2

●その3
x,y,a,b,flagの初期値がありません。0クリアを当てにせず初期化しましょう。

●その4
KEY_INPUT_UP時しかflagをチェックしていません。

●その5
今まで部分を直してしまうと一度flagが1になると移動できなくなると思います。

●その6
斜め移動はsin/cosを使わないと約1.4倍速で斜め移動します。

●その7
インデントの整理をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#22

投稿記事 by 県民 » 14年前

ごめんなさい 名前を統一します
あの複数の条件のif文は壁と戦闘機の当たり判定を示しています
戦闘機は壁に当たると移動をストップします 
このような処理なのですがなぜかぶつかってもストップしません
※全方向の処理は面倒臭いとおもったのでコードには書いていません

なぜストップしないのでしょうか分かりますか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#23

投稿記事 by softya(ソフト屋) » 14年前

県民 さんが書きました:ごめんなさい 名前を統一します
あの複数の条件のif文は壁と戦闘機の当たり判定を示しています
戦闘機は壁に当たると移動をストップします 
このような処理なのですがなぜかぶつかってもストップしません
※全方向の処理は面倒臭いとおもったのでコードには書いていません

なぜストップしないのでしょうか分かりますか?
こちらには絵がないので壁の位置がわかりません。
ためしに

コード:

    if( (aleft < bright) ) {
		flag = 1;
		if( (aright > bleft) ) {
			flag=2;
			if( (atop < bbottom) ) {
				flag=3;
				if( (abottom > btop)) {
					flag=4;
				}
			}
		}
	}
    DrawFormatString(0,0,GetColor(255,255,255),"flag=%d",flag);
こうしてみたら壁の位置がようやく分かりました。
一応四角いブロックどうしの判定は、値が想定通りならちゃんと行われていますよ。flag==1を直せば機能するはずです。
ただ、flag=0に戻しているところがないので一度壁に衝突すると上には動けなくなります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#24

投稿記事 by 県民 » 14年前

何回やっても当たり判定がうまくいかないのであきらめました
このやり方でできるようなのでとりあえず当たり判定は保留で・・・

コード:

#include "DxLib.h"
 
int x,y,a,b;
int aleft = x+2;
int bright = a+333;
int aright =x+23;
int bleft = a+32;
int atop = y+4;
int bbottom = b+218;
int abottom =y+19;
int btop = b+214;
int flag;
 
 
// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine, int nCmdShow )
{
    ChangeWindowMode( TRUE ) ;
 
 
    
    int GraphHandle,handle ;
 
    // DXライブラリ初期化処理
    if( DxLib_Init() == -1 ) return -1;
 
    // グラフィック『test1.bmp』をメモリにロード
    GraphHandle = LoadGraph( "戦闘機.bmp" ) ;
    handle = LoadGraph( "壁.bmp" ) ;
    
    while(1){
    
     ClearDrawScreen() ;
 
    
    // 0,0 座標にメモリに読みこんだグラフィックを描画
    DrawGraph( x , y , GraphHandle , TRUE ) ;
        DrawGraph( a , b , handle, TRUE);
    
    if( CheckHitKey( KEY_INPUT_UP ) == 1 ){
                  x += 4 * flag ;
                  y += 4 * flag ;         
    }  
          if((aleft < bright)&&(aright > bleft)&&(atop < bbottom)&&(abottom > btop)) flag=45;
       
    
    WaitTimer( 20 ) ;
 
    if( ProcessMessage() == -1 ) break ;
 
    // ESCキーが押されたらループから抜ける
    if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ) break ;
        }
 
    // DXライブラリ使用の終了処理
    DxLib_End() ;
 
    // ソフトの終了
    return 0 ;
}

前に私が言った何度で移動すればいいかという変数を渡すというやり方が上のやり方です
書き直しただけなのでおかしいところがあると思いますが

まず、上のコードは四角形の当たり判定ですが右肩上がり45度の斜めの壁だと思ってください
まず戦闘機が壁の付近に来たらflagに何度だったら移動できるかのフラグを渡して
それを移動量とかけて移動位置を導き出しています
(公式は移動量×角度と解釈していますが良いですよね?)

ですが新たな問題がうまれました 右上に移動すればいいでしょう?
右上に移動するにはyからは座標を引いてxには足さないといけないですよね?
どうやって値を変動させればいいか・・・

長くなりましたが聞きたいことは三つ
・このやり方は実践できるか   ・もっと効率よいやり方があるか ・新たな問題
教えてくだせぇ お願います

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#25

投稿記事 by softya(ソフト屋) » 14年前

県民 さんが書きました:長くなりましたが聞きたいことは三つ
・このやり方は実践できるか   ・もっと効率よいやり方があるか ・新たな問題
教えてくだせぇ お願います
この件ですが前に指摘した
●その1
●その3
●その6
に対応していないので、まともには動きません。
直すところが分からないなら各々何処が分からないか聞いてくださいね。
県民 さんが書きました:まず、上のコードは四角形の当たり判定ですが右肩上がり45度の斜めの壁だと思ってください
まず戦闘機が壁の付近に来たらflagに何度だったら移動できるかのフラグを渡して
それを移動量とかけて移動位置を導き出しています
(公式は移動量×角度と解釈していますが良いですよね?)
その6で指摘していますが、sin/cosが必要です。
公式はベクトルx = 移動量 x sin(ラジアン角)とベクトルy = 移動量 x -cos(ラジアン角)です。
下記の2つは必ず読んで理解してください。
「s13a. sin,cosって何?(STGでの使用方法)」
http://dixq.net/g/s.13.a.html
「s13. sin,cosって何? シューティングの基本概念」
http://dixq.net/g/s.13.b.html
弧度法(ラジアン)なので要注意。

それとソースが見づらいのでインデントの整理をぜひお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#26

投稿記事 by 県民 » 14年前

何度もすまないです
とりあえずプログラミングの館を習って書いてみました

コード:

#include "DxLib.h"
 
int x,y,a,b;
int flag;
 
 
// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine, int nCmdShow )
{
    ChangeWindowMode( TRUE ) ;
 
 
    
    int GraphHandle,handle ;
 
    // DXライブラリ初期化処理
    if( DxLib_Init() == -1 ) return -1;
 
    // グラフィック『test1.bmp』をメモリにロード
    GraphHandle = LoadGraph( "戦闘機.bmp" ) ;
    handle = LoadGraph( "壁.bmp" ) ;
    
    while(1){
    
     ClearDrawScreen() ;
 
    
    // 0,0 座標にメモリに読みこんだグラフィックを描画
    DrawGraph( x , y , GraphHandle , TRUE ) ;
        DrawGraph( a , b , handle, TRUE);
    
    if( CheckHitKey( KEY_INPUT_UP ) == 1 ){
                  x += sin( flag ) * 4;
                  y += cos( flag ) * 4;         
  }  

int aleft = x+2;
int bright = a+333;
int aright =x+23;
int bleft = a+32;
int atop = y+4;
int bbottom = b+218;
int abottom =y+19;
int btop = b+214;
    

if((aleft < bright)&&(aright > bleft)&&(atop < bbottom)&&(abottom > btop)) flag=45;
       
    
    WaitTimer( 20 ) ;
 
    if( ProcessMessage() == -1 ) break ;
 
    // ESCキーが押されたらループから抜ける
    if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ) break ;
        }
 
    // DXライブラリ使用の終了処理
    DxLib_End() ;
 
    // ソフトの終了
    return 0 ;
}

どうでしょうか?

sin ( flag ) の部分の意味が分かりません  この括弧はどういう意味をしているのでしょうか?
それともっと効率のよいやり方ってありますかね?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#27

投稿記事 by softya(ソフト屋) » 14年前

県民 さんが書きました:sin ( flag ) の部分の意味が分かりません  この括弧はどういう意味をしているのでしょうか?
(0)これはC言語の基本的な文法と標準ライブラリの知識が不足の問題です。
関数の勉強をされましたか?
「C言語 関数」
http://www9.plala.or.jp/sgwr-t/c/sec11.html
sinやcosはC言語が標準で用意している三角関数の標準ライブラリ関数です。
DXライブラリでゲームを作る以上は、C言語の文法が分からないと進みませんので本かサイトで分からないことは調べるようにしてください。
「苦しんで覚えるC言語」など。
http://9cguide.appspot.com/

それと馴染みのある度数法(0度とか90度とか)から弧度法(ラジアン)の変換が必要です。
360度=2πラジアンと言う法則があるので、180度=πラジアンとなり、度=π/180ラジアンです。
つまり、45度なら 45 x π / 180でラジアン角に変換されます。
県民 さんが書きました:それともっと効率のよいやり方ってありますかね?
効率以前に問題があるので、見逃していたポイントも含めて指摘します。
(1)WaitTimer( 20 ) ;ではなくScreenFlip()を使ってください。下記を参考に。
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ] 1.9章 ゲームプログラムの骨格の完成」
http://dixq.net/g/01_09.html
(2)前にも書きましたがx,y,a,b,flagを初期化してください。もし、どうして良いか分からなければ聞いてください。
(3)これも前に書きましたが、"ソースが見づらいのでインデントの整理をぜひお願いします。"。これも分からなければ聞いてください。
(4)flagと言う名前で角度を管理するのは止めましょう。angleなどの名称を使ってください。
(5)flag=45とするとずっとその値が継続するプログラミになっています。理由は考えてみてください。
(6)壁の回避が1フレーム遅れて発生します。それとキーを離すタイミングや当たり方次第では回避もせず壁に刺さります。
これは移動処理部分のアルゴリズムの問題で、次のようにしないといけません。

移動→衝突→移動前の位置に戻す(移動キャンセル)→回避移動

が1フレーム内に起こらないといけないのと移動出来ない場合

移動→衝突→移動前の位置に戻す(移動キャンセル)→回避移動→衝突→移動前の位置に戻す(移動キャンセル)

とする必要があります。

(7)今のプログラムは0度の時に下にしか移動しないプログララムなので壁には衝突しません。
下にしか移動しないのはsin/cosの使い方の問題でもありますが、当たり判定の範囲が変なのも原因です。
本当に当たり判定の範囲は狙い通りなのか確認してみてください。DrawBox で当たり判定の範囲を確認してみましょう。
DrawBox( aleft, atop, aright, abottom, GetColor(0,0,255), FALSE );//自機
DrawBox( bleft, btop, bright, bbottom, GetColor(255,0,0), FALSE );//壁

(8)sin/cosを使うためにincludeを行ってください。
#include <math.h>
これを使わないとそもそもエラーになるはずなのですが、コンパイルされていますか?

(9)今のプログラは0度が下向きの移動となっています。0度が上向きに移動したいなら符号を逆転する必要があります。


番号を振りましたので(0)~(9)までどう対処したか、次回には書いてくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#28

投稿記事 by 県民 » 14年前

勉強のせいで書き込みが遅れました

(0)標準関数だったのですか、、、こういう文法があると思っていました・・・
(1) while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 )纏めました
   ところでウェイトタイマーとスクリーンフィリップは違う役目だと思うのですが 間違ってたらごめんなさい
(2)初期値を代入します
(3)いつもはtabキーを使っているのですが掲示板では機能しません
(4)わかりました
(6)あたり判定を実際のオブジェクトよりも大きく設定すれば移動キャンセルの処理もいらなくなると思います
  まぁ後で支障をきたすとかそういうことが起こるかは分からないのですが
(7)四角形の当たり判定がうまくいっていないためあたり判定の処理は
  脳内で斜めの壁があるとして考えています(正しいあたり判定コードはかけていないということです
(8)コンパイラーのせいでコンパイルしていません
(9)数学座標とごちゃになっていました ごめんなさい

(5)がどうすればいいか分からないのですが今、思いついたのだと
elseのときは‐90を代入すればいいと思いました

箇条書きで申し訳ないです

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#29

投稿記事 by softya(ソフト屋) » 14年前

学生さんだと思いますので勉強を優先してくださいね。

(1) while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 )纏めました
   ところでウェイトタイマーとスクリーンフィリップは違う役目だと思うのですが 間違ってたらごめんなさい

違いますがゲームならウェイトタイマーはまず使いません。

(3)いつもはtabキーを使っているのですが掲示板では機能しません

インデントはソースコード作成時に整形してくださいね。

(6)あたり判定を実際のオブジェクトよりも大きく設定すれば移動キャンセルの処理もいらなくなると思います
  まぁ後で支障をきたすとかそういうことが起こるかは分からないのですが

そんなことはありません。
言われても実感できないと思いますので試してみてください。
少なくとも今のコードは問題山積みです。

(7)四角形の当たり判定がうまくいっていないためあたり判定の処理は
  脳内で斜めの壁があるとして考えています(正しいあたり判定コードはかけていないということです

正しい当たり判定の以前にあの大きさと位置は想定通りなのですか?

(8)コンパイラーのせいでコンパイルしていません

イマイチ意味が分かりませんが、コンパイルして確認していないと言うことでしょうか?

(5)がどうすればいいか分からないのですが今、思いついたのだと
elseのときは‐90を代入すればいいと思いました

上が-90度なのか0度なのか明確にしてくださいね。
それと正常が-90度で回避が45度ではバラバラですよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

県民

Re: マップとの当たり判定

#30

投稿記事 by 県民 » 14年前

やはりあたり判定がうまくいっていない状態でやるのは無理があると考えたので
とりあえず当たり判定のだけはやっておきたいとおもって、
前にソフト屋さんが提示してくださったDrawBoxを使って当たり判定を調べる方法をやってみたところ
思った位置に四角が描画されていました
しかし、
・当たっていない時にも関わらず戦闘機が常に上に移動できない
・青の四角が移動しない
という問題がありました
どこが悪いのか診断してください onegaisimasu

コード:


#include "DxLib.h"

int x,y,a,b;
int aleft = x+2;
int bright = a+333;
int aright =x+23;
int bleft = a+32;
int atop = y+4;
int bbottom = b+218;
int abottom =y+19;
int btop = b+214;
int flag;
	

// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode( TRUE ) ;
        SetWindowSizeChangeEnableFlag( TRUE ) ;

	
	int GraphHandle,handle ;

	// DXライブラリ初期化処理
	if( DxLib_Init() == -1 ) return -1;

	// グラフィック『test1.bmp』をメモリにロード
	GraphHandle = LoadGraph( "戦闘機.bmp" ) ;
	handle = LoadGraph( "壁.bmp" ) ;
	
	while(1){
	
	 ClearDrawScreen() ;

	
	// 0,0 座標にメモリに読みこんだグラフィックを描画
	        DrawGraph( x , y , GraphHandle , TRUE ) ;
             DrawGraph( a , b , handle, TRUE);
	
             DrawBox( aleft, atop, aright, abottom, GetColor(0,0,255), FALSE );//自機
             DrawBox( bleft, btop, bright, bbottom, GetColor(255,0,0), FALSE );//壁




	
	if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ) x -= 4 ;
	if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 ) x += 4 ;
	if( CheckHitKey( KEY_INPUT_UP ) == 1&&flag==0 ) y -= 4 ;
	if( CheckHitKey( KEY_INPUT_DOWN ) == 1 ) y += 4 ;

          if((aleft < bright)&&(aright > bleft)&&(atop < bbottom)&&(abottom > btop)) flag=1;
	   
	
	WaitTimer( 20 ) ;

	if( ProcessMessage() == -1 ) break ;

	// ESCキーが押されたらループから抜ける
	if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ) break ;
        }

	// DXライブラリ使用の終了処理
	DxLib_End() ;

	// ソフトの終了
	return 0 ;
}


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: マップとの当たり判定

#31

投稿記事 by softya(ソフト屋) » 14年前

とりあえず最初から今までの私の回答を読みなおしてみてください。
ソースコードの当たり判定が昔の状態に戻っているので当たり判定が移動しなくなっています。
※ 今まで私が書いたことを確認の上、ソースコードに反映させてください。そうしてもらわないと私のアドバイスがまったく意味を持ちません。

ちなみに私の環境では上に移動します。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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