当たり判定

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

当たり判定

#1

投稿記事 by シー » 17年前

突然なんですが、今『シューティングの館」の「シューティング」を作っているのですが、当たり判定のことで質問です。
今、自分への当たり判定を作っているのですが、複雑すぎて自分でもわからなくなってしまいました。
皆さんなら、どういう風に当たり判定を作りますか??もしよろしければ、ソースを見せてほしいのですが??

管理人

Re:当たり判定

#2

投稿記事 by 管理人 » 17年前

特に複雑なことはないですよ。
表示している弾と自機との距離を全て計算すればいいだけです。
どのように情報を用意されているかわかりませんが、
ベクターとか使わずに、普通に固定の配列で用意しているなら、
以下のようにしてはいかがでしょうか。
#define 弾MAX 1000
#define ショットMAX 100

typedev struct{
    int flag,あたり範囲;
    double x,y;
}弾情報_t;

typedef struct{
    int flag;
    弾情報_t 弾情報[弾MAX];
}ショット情報_t;

ショット情報_t ショット情報[ショットMAX];

このように、1000種類の弾情報を保持できるショット情報が100個あったとしましょう。

for(i=0;i<ショットMAX;i++){
	if(弾情報.flag!=0){
		for(n=0;n<弾MAX;n++){
			if(ショット情報.弾情報[n].flag==1){
				x=ショット情報.弾情報[n].x-キャラの座標.x;
				y=ショット情報.弾情報[n].y-キャラの座標.y;
				range=sqrt(x*x+y*y);
				if(range<自機範囲+ショット情報.あたり範囲){
					//ココ
				}
			}
		}
	}
}


//ココに入ればあたりです。

シー

Re:当たり判定

#3

投稿記事 by シー » 17年前

管理人さま、解答ありがとうございます。
このソースを参考に自分のソースを直してみたいと思います。

そそ

Re:当たり判定

#4

投稿記事 by そそ » 17年前

どうも、まだプログラミング始めたばかりで、このサイトにはいつもお世話になってます。今、自分も自機の当り判定作ってるんですけど、エラーが出てしまいます。どこが間違ってるのかどうしても分からないので、是非教えてもらいたいです。ソースは

--------------------------------GlobalVariable.h------------------------------------
/* 定義 */
#define PLAYER_MAX_SHOT1 11
#define PLAYER_MAX_SHOT2 15

#define PLAYER_X_SIZE 128.0
#define PLAYER_Y_SIZE 48.0


#define ENEMY_TOTAL_NUM 100
#define ENEMY_TOTAL_SHOT_NUM 400
#define ENEMY_SHOT_XSIZE 16
#define ENEMY_SHOT_YSIZE 8


#define MONSTER1_X_SIZE 140.0
#define MONSTER1_Y_SIZE 128.0
-----------------------------------------------------------------------------------

------------------------player.cpp-------------------------------------------------
void PlayerHantei(){
//int p_x=PLAYER_X_SIZE;
//int p_y=PLAYER_Y_SIZE;

for(int i=0;i<ENEMY_TOTAL_SHOT_NUM;i++){//ショットの全列分
//for(int j=0;j<EnemyShot[j];j++){//1列全弾分

if(EnemyShot.flag==1)
{
if( EnemyShot.x+ENEMY_SHOT_XSIZE >Player.x &&
EnemyShot.x > Player.x+PLAYER_X_SIZE &&
EnemyShot.y+ENEMY_SHOT_YSIZE >Player.y &&
EnemyShot.y >Player.y+PLAYER_Y_SIZE)
{
Player.flag=0;
EnemyShot.flag=0;
}

}
}
}
-----------------------------------------------------------------------------------------

こんな感じです。お願いします

yamahara

Re:当たり判定

#5

投稿記事 by yamahara » 17年前

>そそさん
円×円なら、管理人さんの
>range=sqrt(x*x+y*y);
>if(range<自機範囲+ショット情報.あたり範囲){
>	//ココ
>}


この計算方法でいいはずです。

SIZEになっているので、もしかしたら、矩形でしょうか?
矩形×矩形の場合、

>if( EnemyShot.x+ENEMY_SHOT_XSIZE >Player.x &&
>EnemyShot.x > Player.x+PLAYER_X_SIZE &&
>EnemyShot.y+ENEMY_SHOT_YSIZE >Player.y &&
>EnemyShot.y >Player.y+PLAYER_Y_SIZE)

この条件よりも、もうちょっと複雑で、
各点が、お互いの四角の中に入っているという判定が必要です。

ttp://www.c3.club.kyutech.ac.jp/gamewiki/index.php?%C5%F6%A4%BF%A4%EA%C8%BD%C4%EA

ここに、求め方が書いてありますが、一応、サンプル書いてみたので添付します。

はね

Re:当たり判定

#6

投稿記事 by はね » 17年前

横から突然すいません。

1つだけ、提案があります。
今はsqrt関数で距離を取っていますが、sqrtだと呼び出すのに結構時間がかかるので
ゲームではsqrtは使わない方が良いです。
と言ってもそんなに変わらないのですが^^;

ちなみに、
自機のx座標をx0
敵のx座標をx1

自機のy座標をy0
敵のy座標をy1

自機の半径をr0
敵の半径をr1
とした場合、

if( (x0-x1)*(x0-x1)+(y0-y1)*(y0-y1) <= (r0+r1)*(r0+r1) )
で同じことができます。

管理人

Re:当たり判定

#7

投稿記事 by 管理人 » 17年前

おぉ、かなり違いますね。
時々sqrtが遅い話は聞きますが、どれ位違うのか知らなかったので、
気になってどれ位早さが違うか実験してみました。

・sqrtを用いて1億回計算
・ 2乗を用いて1億回計算

それぞれ5回ずつ測定した結果です。

実行結果

sqrtで計算中・・・
3.972秒
3.988秒
3.972秒
3.972秒
3.987秒
2乗で計算中・・・
0.622秒
0.606秒
0.622秒
0.622秒
0.622秒
 
1億回でこれだけ時間がかかるなら、10万回計算すると、もう処理落ちの原因になりますね。
スペックが低いPCだともっとかもしれません。

一応計測に使ったプログラムはこちらです。(zは最適化による省略を防ぐ為に入れました)

#include <stdio.h>
#include <math.h>
#include <time.h>

int main(){
	int i,n;
	double x=1.2,y=2.3,z;
	clock_t t;
	z=0;
	printf("sqrtで計算中・・・\n");
	for(n=0;n<5;n++){
		t=clock();
		for(i=0;i<100000000;i++){
			if(1.9<sqrt(x*x+y*y)){
				z+=1;
			}
		}
		printf("%.3f秒   z=%f\n",(clock()-t)/(double)CLOCKS_PER_SEC,z);
	}
	z=0;
	printf("2乗で計算中・・・\n");
	for(n=0;n<5;n++){
		t=clock();
		for(i=0;i<100000000;i++){
			if(1.9*1.9<x*x+y*y){
				z+=1;
			}
		}
		printf("%.3f秒   z=%f\n",(clock()-t)/(double)CLOCKS_PER_SEC,z);
	}

	return 0;
}
 

にゃっき

Re:当たり判定

#8

投稿記事 by にゃっき » 17年前

こちらのサイトにあるシューティングゲームについて。
シューティングで自機の当たり判定で苦戦しています。
管理人さんが作る予定の自機当たり判定のソースを見せてもらうことは可能ですか?

やそ

Re:当たり判定

#9

投稿記事 by やそ » 17年前

にゃっきさんへ
管理人さんがよほどのMでもないかぎり不可能です。
まず管理人さん自身、課題提出が終わったとはいえ、シューティングの作成で忙しいでしょうし、
就職活動だってあるでしょう。
友達とだって遊んでもらいたいでしょうし(笑)
このHPのリニューアルだって考えておられるようですし。
というかすでに当たり判定については既出の話題がありますし、
シューティングの館で詳しく解説されてます。
それを理解できないうちはあまりアレンジしないほうがいいでしょう。

「当たり判定に苦戦しているから、管理人さんの作ったヤツ頂戴よ」???
・・・それはイチバン嫌われる行為だと言うことをまず自覚してください。

ここは質問掲示板です。
たとえ悪意が無くても、「自分じゃ分からないから誰か作ってそれを見せてくださいよ」
っていうのは
「作るの面倒くさいから誰かに作ってもらってコピペすれば楽ジャン」
といっていることとほぼ同義に受け取られてしまいます。
なによりそれでは自分で作ったプログラムではなくなります。
自分で組んだプログラムのどこが分からなくて、どこでバグって、どんなエラーが出たのか。
本来はどういうことをしたかったのか。
まず質問者の側から情報提供をしなければ、答えてくれる人はほとんどいないと思います。
(管理人さんは優しいからな~。手とり○とり答えちゃうのかなぁ?)

taku.net

Re:当たり判定

#10

投稿記事 by taku.net » 17年前

にゃっきさん以前のレスを参考にすればよいと思うのですが・・・
どうしても管理人さんのコードが見たいなら管理人さんが既に公開されている
四聖龍神録のコードを解読すればいいと思います。
それが理解できなければここで見せてもらっても実装は不可能だと思いますので・・・

管理人

Re:当たり判定

#11

投稿記事 by 管理人 » 17年前

すみません、今時間がないので、あまり詳しくかけないのですが、
当たり判定は四角で考えると難しいので、最初は全部円にしてみてはどうでしょうか?
というのも、23度回転したりしたときなど、四角形も回転させなければならず、判定がなかなか難しいと思うので。

円での当たり判定のプログラムはゲームプログラミングの館で紹介していますので、参考にしてください。
http://dixq.net/g/#s11

私のプログラムをお見せしてもいいのですが、ほかの処理がたくさん書いてあるので、よけいにみにくいと思います。
というのも、ボスがせりふを言っている時には玉が当たらないとか、カウンタがスコア表示中なら当たらないとか、
あたったときが「食らいボム中か」の判定も呼んだり、
あたったかどうかだけの判定じゃなく、ほかにも処理がたくさん書いてあるので余計わかりにくいと思います。

>やそさん

ここは初心者さんをターゲットにした掲示板ですし、気軽に何でも話をしてほしいので、まぁそこまでお怒りにならず^^;
確かに熟練者からみると、初心者の投稿には直してほしいところがたくさんあると思うのですが、
私自身、昔散々言われて嫌になった記憶があるので、なるべくここではそういう事が少なくなればな・・・と思っています。
ただしそれを許していると何でもありな投稿が増えてしまう事になり、ある程度のラインを引く必要はあると思いますが、なるべくいろんな初心者が救われるような掲示板を目指していますm(_ _)m

そそ

Re:当たり判定

#12

投稿記事 by そそ » 17年前

はねさん、やまはらさん返答ありがとうございます。上に書いておいたプログラムを実行すると、コンパイルの途中で
              if( EnemyShot.x+ENEMY_SHOT_XSIZE >Player.x &&
                EnemyShot.x > Player.x+PLAYER_X_SIZE &&
→               EnemyShot.y+ENEMY_SHOT_YSIZE >Player.y &&
                EnemyShot.y >Player.y+PLAYER_Y_SIZE)

見たいな感じになって中断されてしまうんですが、これも、「各点が、お互いの四角の中に入っているという判定」がないせいですか?何度も質問すいません。

KIJ

Re:当たり判定

#13

投稿記事 by KIJ » 17年前

はじめまして。自分も今当り判定のプログラム作ってます。一応組んでみたんですが、敵の判定が左上画面に自機が移動したら敵の弾が消えるようになってます。ここから色々変えてみたんですけど、どうしても自機の範囲に入って玉が消えるようになりません。是非アドバイスいただきたいと思い、投稿しました。宜しくお願いします。ソースは
-------------------------------GlobalVariable.h-------------------------------------------
#define PLAYER_MAX_SHOT1 11
#define PLAYER_MAX_SHOT2 15

#define PLAYER_X_SIZE 128.0
#define PLAYER_Y_SIZE 48.0


#define ENEMY_TOTAL_NUM 100
#define ENEMY_TOTAL_SHOT_NUM 400
#define ENEMY_SHOT_XSIZE 16
#define ENEMY_SHOT_YSIZE 8
#define ENEMY_MAX_SHOT1 1000
#define ENEMY_MAX_SHOT2 100


typedef struct{
double x,y;
int status,counter,range,flag,size;
} BODY_player_t;

BODY_player_t Player;


//敵
typedef struct{
double x,y,range;
int flag,counter,hp,pattern;
} BODY_enemy_t;

BODY_enemy_t enemy[ENEMY_TOTAL_NUM];//[100]


//ショット
typedef struct{
double x,y;
int flag,range;
} SHOT_t;

SHOT_t PlayerShot[PLAYER_MAX_SHOT1][PLAYER_MAX_SHOT2];//[11][15]




typedef struct{
int flag;
double x,y,angle,disp_angle,speed;
} ENEMY_SHOTS_t;

//敵ショット
typedef struct{
int flag,pattern,counter,img,range;
double x,y,mem_ex,mem_ey,mem_px,mem_py,Enx[60],Eny[60];//[200];
ENEMY_SHOTS_t EnemyShots[ENEMY_TOTAL_SHOT_NUM];//[200];
} ENEMY_SHOT_t;

ENEMY_SHOT_t EnemyShot[ENEMY_TOTAL_NUM];//[100];

-----------------------------------player.cpp-------------------------------------

for(int i=0;i<ENEMY_MAX_SHOT2;i++){
if(EnemyShot.flag!=0){
for(int n=0;n<ENEMY_MAX_SHOT1;n++){
if(EnemyShot.flag==1){
double x,y;
int range;
Player.range=(PLAYER_X_SIZE-60)/2.0f*Player.size;
x=EnemyShot.EnemyShots[n].x-Player.x;
y=EnemyShot.EnemyShots[n].y-Player.y;
range=sqrt(x*x+y*y);
int P_x=PLAYER_X_SIZE;
int P_y=PLAYER_Y_SIZE;
if(range<P_x+P_y+EnemyShot.y){
//ココ
EnemyShot.flag=0;
}
}
}
}
}
}

にゃっき

Re:当たり判定

#14

投稿記事 by にゃっき » 17年前

やそさん、管理人さん、悪気は無かったんですが、お気を悪くされたみたいですいませんでした。反省してます。
ご迷惑をおかけしてしまった償いに、もう質問するのをやめます。本当にすみませんでした。

管理人

Re:当たり判定

#15

投稿記事 by 管理人 » 17年前

>にゃっきさん
いえいえ、人のコードを見たいというのはいいことだと思いますよ。
いつも我流では自分の知識の範囲内でしか進歩しませんが、人のコードを読んで刺激を受けることは大事だと思います。
いつでも気軽にまたご質問下さい・・。

やそ

Re:当たり判定

#16

投稿記事 by やそ » 17年前

管理人様及び掲示板利用の皆様へ

ここ数日風邪で寝込んでいた為返答が出来ずもうしわけありませんでした。

にゃっき様へ
私の投稿にご気分を害されたようで誠に申し訳ありません。
にゃっきさんに対して怒っているなんてことは全く無いです。m(_ _)m
管理人様もいわれているとおりここは初心者を対象にした質問掲示板なので、逆に私のほうが言いすぎな部分が多々あると思います。
これからも気軽に掲示板を覗いて、興味のある話題に参加、投稿していただければありがたく思います。
初心者さんらの傾向として、

 1.問題が分からない(問題文の
 2.問題を解くための手法(使うべき命令とその用法)が分からない
 3.処理の流れを組み立てられない
 4.質問の仕方が分からず自分の意図がうまく伝えられない
 5.そもそも規約を読まずに投稿する人が多い

といったことが多く見受けられます。
特に最近多いのが、課題の丸投げです。
もう、1の問題が分からないのレベルを越え、考えることを辞めてしまっているようです(・・;)
そうなると、閲覧している側も苦笑するしか有りません。
その中で興味が持てる話題であれば、暇があるときに考えたりすることもあることはありますが。
このサイトでは丸投げも許容しておられますが、質問者の書き方で得られる回答は大きく違います。
規約に則り、自分の環境(OS、コンパイラなど)や自分のレベル(最近習った命令文やポインタの理解度など)を明らかにしてじっと待つ^^
回答者はなんら義務を負うものでは有りませんが、優しい方が多いので、問い方次第では結構回答が得られでしょう。

>管理人様
お騒がせしてしまってすみません。
そうですね。ちょっと書き方も悪いし、権限も逸脱した書き込みだったと反省しています。
そろそろ、初心者に多い質問を集めたFAQなんかが有ってもいいかもしれませんね。
(って勝手に提案を管理人さんに丸投げ~(^o^))

閉鎖

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