当たり判定
Re:当たり判定
特に複雑なことはないですよ。
表示している弾と自機との距離を全て計算すればいいだけです。
どのように情報を用意されているかわかりませんが、
ベクターとか使わずに、普通に固定の配列で用意しているなら、
以下のようにしてはいかがでしょうか。
//ココに入ればあたりです。
表示している弾と自機との距離を全て計算すればいいだけです。
どのように情報を用意されているかわかりませんが、
ベクターとか使わずに、普通に固定の配列で用意しているなら、
以下のようにしてはいかがでしょうか。
#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:当たり判定
どうも、まだプログラミング始めたばかりで、このサイトにはいつもお世話になってます。今、自分も自機の当り判定作ってるんですけど、エラーが出てしまいます。どこが間違ってるのかどうしても分からないので、是非教えてもらいたいです。ソースは
--------------------------------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;
}
}
}
}
-----------------------------------------------------------------------------------------
こんな感じです。お願いします
--------------------------------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;
}
}
}
}
-----------------------------------------------------------------------------------------
こんな感じです。お願いします
Re:当たり判定
>そそさん
円×円なら、管理人さんの
この計算方法でいいはずです。
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
ここに、求め方が書いてありますが、一応、サンプル書いてみたので添付します。
円×円なら、管理人さんの
>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:当たり判定
おぉ、かなり違いますね。
時々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:当たり判定
にゃっきさんへ
管理人さんがよほどのMでもないかぎり不可能です。
まず管理人さん自身、課題提出が終わったとはいえ、シューティングの作成で忙しいでしょうし、
就職活動だってあるでしょう。
友達とだって遊んでもらいたいでしょうし(笑)
このHPのリニューアルだって考えておられるようですし。
というかすでに当たり判定については既出の話題がありますし、
シューティングの館で詳しく解説されてます。
それを理解できないうちはあまりアレンジしないほうがいいでしょう。
「当たり判定に苦戦しているから、管理人さんの作ったヤツ頂戴よ」???
・・・それはイチバン嫌われる行為だと言うことをまず自覚してください。
ここは質問掲示板です。
たとえ悪意が無くても、「自分じゃ分からないから誰か作ってそれを見せてくださいよ」
っていうのは
「作るの面倒くさいから誰かに作ってもらってコピペすれば楽ジャン」
といっていることとほぼ同義に受け取られてしまいます。
なによりそれでは自分で作ったプログラムではなくなります。
自分で組んだプログラムのどこが分からなくて、どこでバグって、どんなエラーが出たのか。
本来はどういうことをしたかったのか。
まず質問者の側から情報提供をしなければ、答えてくれる人はほとんどいないと思います。
(管理人さんは優しいからな~。手とり○とり答えちゃうのかなぁ?)
管理人さんがよほどのMでもないかぎり不可能です。
まず管理人さん自身、課題提出が終わったとはいえ、シューティングの作成で忙しいでしょうし、
就職活動だってあるでしょう。
友達とだって遊んでもらいたいでしょうし(笑)
このHPのリニューアルだって考えておられるようですし。
というかすでに当たり判定については既出の話題がありますし、
シューティングの館で詳しく解説されてます。
それを理解できないうちはあまりアレンジしないほうがいいでしょう。
「当たり判定に苦戦しているから、管理人さんの作ったヤツ頂戴よ」???
・・・それはイチバン嫌われる行為だと言うことをまず自覚してください。
ここは質問掲示板です。
たとえ悪意が無くても、「自分じゃ分からないから誰か作ってそれを見せてくださいよ」
っていうのは
「作るの面倒くさいから誰かに作ってもらってコピペすれば楽ジャン」
といっていることとほぼ同義に受け取られてしまいます。
なによりそれでは自分で作ったプログラムではなくなります。
自分で組んだプログラムのどこが分からなくて、どこでバグって、どんなエラーが出たのか。
本来はどういうことをしたかったのか。
まず質問者の側から情報提供をしなければ、答えてくれる人はほとんどいないと思います。
(管理人さんは優しいからな~。手とり○とり答えちゃうのかなぁ?)
Re:当たり判定
すみません、今時間がないので、あまり詳しくかけないのですが、
当たり判定は四角で考えると難しいので、最初は全部円にしてみてはどうでしょうか?
というのも、23度回転したりしたときなど、四角形も回転させなければならず、判定がなかなか難しいと思うので。
円での当たり判定のプログラムはゲームプログラミングの館で紹介していますので、参考にしてください。
http://dixq.net/g/#s11
私のプログラムをお見せしてもいいのですが、ほかの処理がたくさん書いてあるので、よけいにみにくいと思います。
というのも、ボスがせりふを言っている時には玉が当たらないとか、カウンタがスコア表示中なら当たらないとか、
あたったときが「食らいボム中か」の判定も呼んだり、
あたったかどうかだけの判定じゃなく、ほかにも処理がたくさん書いてあるので余計わかりにくいと思います。
>やそさん
ここは初心者さんをターゲットにした掲示板ですし、気軽に何でも話をしてほしいので、まぁそこまでお怒りにならず^^;
確かに熟練者からみると、初心者の投稿には直してほしいところがたくさんあると思うのですが、
私自身、昔散々言われて嫌になった記憶があるので、なるべくここではそういう事が少なくなればな・・・と思っています。
ただしそれを許していると何でもありな投稿が増えてしまう事になり、ある程度のラインを引く必要はあると思いますが、なるべくいろんな初心者が救われるような掲示板を目指していますm(_ _)m
当たり判定は四角で考えると難しいので、最初は全部円にしてみてはどうでしょうか?
というのも、23度回転したりしたときなど、四角形も回転させなければならず、判定がなかなか難しいと思うので。
円での当たり判定のプログラムはゲームプログラミングの館で紹介していますので、参考にしてください。
http://dixq.net/g/#s11
私のプログラムをお見せしてもいいのですが、ほかの処理がたくさん書いてあるので、よけいにみにくいと思います。
というのも、ボスがせりふを言っている時には玉が当たらないとか、カウンタがスコア表示中なら当たらないとか、
あたったときが「食らいボム中か」の判定も呼んだり、
あたったかどうかだけの判定じゃなく、ほかにも処理がたくさん書いてあるので余計わかりにくいと思います。
>やそさん
ここは初心者さんをターゲットにした掲示板ですし、気軽に何でも話をしてほしいので、まぁそこまでお怒りにならず^^;
確かに熟練者からみると、初心者の投稿には直してほしいところがたくさんあると思うのですが、
私自身、昔散々言われて嫌になった記憶があるので、なるべくここではそういう事が少なくなればな・・・と思っています。
ただしそれを許していると何でもありな投稿が増えてしまう事になり、ある程度のラインを引く必要はあると思いますが、なるべくいろんな初心者が救われるような掲示板を目指していますm(_ _)m
Re:当たり判定
はねさん、やまはらさん返答ありがとうございます。上に書いておいたプログラムを実行すると、コンパイルの途中で
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)
見たいな感じになって中断されてしまうんですが、これも、「各点が、お互いの四角の中に入っているという判定」がないせいですか?何度も質問すいません。
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)
見たいな感じになって中断されてしまうんですが、これも、「各点が、お互いの四角の中に入っているという判定」がないせいですか?何度も質問すいません。
Re:当たり判定
はじめまして。自分も今当り判定のプログラム作ってます。一応組んでみたんですが、敵の判定が左上画面に自機が移動したら敵の弾が消えるようになってます。ここから色々変えてみたんですけど、どうしても自機の範囲に入って玉が消えるようになりません。是非アドバイスいただきたいと思い、投稿しました。宜しくお願いします。ソースは
-------------------------------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;
}
}
}
}
}
}
-------------------------------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:当たり判定
管理人様及び掲示板利用の皆様へ
ここ数日風邪で寝込んでいた為返答が出来ずもうしわけありませんでした。
にゃっき様へ
私の投稿にご気分を害されたようで誠に申し訳ありません。
にゃっきさんに対して怒っているなんてことは全く無いです。m(_ _)m
管理人様もいわれているとおりここは初心者を対象にした質問掲示板なので、逆に私のほうが言いすぎな部分が多々あると思います。
これからも気軽に掲示板を覗いて、興味のある話題に参加、投稿していただければありがたく思います。
初心者さんらの傾向として、
1.問題が分からない(問題文の
2.問題を解くための手法(使うべき命令とその用法)が分からない
3.処理の流れを組み立てられない
4.質問の仕方が分からず自分の意図がうまく伝えられない
5.そもそも規約を読まずに投稿する人が多い
といったことが多く見受けられます。
特に最近多いのが、課題の丸投げです。
もう、1の問題が分からないのレベルを越え、考えることを辞めてしまっているようです(・・;)
そうなると、閲覧している側も苦笑するしか有りません。
その中で興味が持てる話題であれば、暇があるときに考えたりすることもあることはありますが。
このサイトでは丸投げも許容しておられますが、質問者の書き方で得られる回答は大きく違います。
規約に則り、自分の環境(OS、コンパイラなど)や自分のレベル(最近習った命令文やポインタの理解度など)を明らかにしてじっと待つ^^
回答者はなんら義務を負うものでは有りませんが、優しい方が多いので、問い方次第では結構回答が得られでしょう。
>管理人様
お騒がせしてしまってすみません。
そうですね。ちょっと書き方も悪いし、権限も逸脱した書き込みだったと反省しています。
そろそろ、初心者に多い質問を集めたFAQなんかが有ってもいいかもしれませんね。
(って勝手に提案を管理人さんに丸投げ~(^o^))
ここ数日風邪で寝込んでいた為返答が出来ずもうしわけありませんでした。
にゃっき様へ
私の投稿にご気分を害されたようで誠に申し訳ありません。
にゃっきさんに対して怒っているなんてことは全く無いです。m(_ _)m
管理人様もいわれているとおりここは初心者を対象にした質問掲示板なので、逆に私のほうが言いすぎな部分が多々あると思います。
これからも気軽に掲示板を覗いて、興味のある話題に参加、投稿していただければありがたく思います。
初心者さんらの傾向として、
1.問題が分からない(問題文の
2.問題を解くための手法(使うべき命令とその用法)が分からない
3.処理の流れを組み立てられない
4.質問の仕方が分からず自分の意図がうまく伝えられない
5.そもそも規約を読まずに投稿する人が多い
といったことが多く見受けられます。
特に最近多いのが、課題の丸投げです。
もう、1の問題が分からないのレベルを越え、考えることを辞めてしまっているようです(・・;)
そうなると、閲覧している側も苦笑するしか有りません。
その中で興味が持てる話題であれば、暇があるときに考えたりすることもあることはありますが。
このサイトでは丸投げも許容しておられますが、質問者の書き方で得られる回答は大きく違います。
規約に則り、自分の環境(OS、コンパイラなど)や自分のレベル(最近習った命令文やポインタの理解度など)を明らかにしてじっと待つ^^
回答者はなんら義務を負うものでは有りませんが、優しい方が多いので、問い方次第では結構回答が得られでしょう。
>管理人様
お騒がせしてしまってすみません。
そうですね。ちょっと書き方も悪いし、権限も逸脱した書き込みだったと反省しています。
そろそろ、初心者に多い質問を集めたFAQなんかが有ってもいいかもしれませんね。
(って勝手に提案を管理人さんに丸投げ~(^o^))