当たり判定

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

当たり判定

#1

投稿記事 by きつね » 14年前

質問ですが、よろしくお願いします。
ゲームプログラミングの館の当たり判定でたくさんの当たり判定をやろうと思い
描画する円の数を増やして、当たり判定の式を入れようとしたら詰まってしまいました。

円が2つだけだったらこの式でいいというのは理解できるのですが
range=enemy[0].range+enemy[1].range;

もっと数が増えた場合はどのような式になるのでしょうか?(自分とそれ以外の円のrangeの計算方法)

下記に指定した数の円を描画するプログラムを作ったので記載しておきます。
構造体とかポインタはあまり理解していないので間違っていたらそちらも指摘をお願いします・・・


************************************************************************
#include "DxLib.h"
#define NUM 5

typedef struct{
int x,y,range;
}enemy_t;

char Key[256];

void enemy_circle(enemy_t*e , int x,int y,int range){
e->x=x;
e->y=y;
e->range=range;
}

void Circle(enemy_t e){
DrawCircle(e.x,e.y,e.range,GetColor(255,0,0),FALSE);
}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){

enemy_t En[NUM];

if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //描画先を裏画面に設定
SetDrawBlendMode( DX_BLENDMODE_ADD , 256 ) ;

for(int i=0;i<NUM;i++){
enemy_circle(&En,GetRand(640),GetRand(480),GetRand(200));
}

while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了

for(int i=0;i<NUM;i++){
Circle(En);
}
ScreenFlip();
}

DxLib_End();
return 0;
}

************************************************************************

Ultimate

Re:当たり判定

#2

投稿記事 by Ultimate » 14年前

円と円の当たり判定でしたらこの前作りました。

自作のまとめヘッダファイルを添付しておきます。

結局は中心を結んだ距離が半径の和以下であればいいというだけです。

ちなみに関数の使い方を「DXライブラリ 関数リファレンスページ」風に書くと、

int CircleHitCircle(double x1, double y1, double z1, double x2, double y2, double z2 , int flag);

double x1 1つ目円のx座標
double y1 1つ目円のy座標
double z1 1つ目円のz座標
double x2 2つ目円のx座標
double y2 2つ目円のy座標
double z2 2つ目円のz座標
int flag  当たったかどうかを表示するフラグ(これは適当な変数でOK)

これでもしあたっていれば 1 当たっていなければ 0
が返るようになっています。


使用例


//上のほうとかは略
if(CircleHitCircle(double x1, double y1, double z1, double x2, double y2, double z2 , int flag)==1)HP--; //もし当たればHPを1減らす
//下のほうも略


こんな感じでできるのでよかったらどうぞ!!! 画像

asm

Re:当たり判定

#3

投稿記事 by asm » 14年前

あまり詳しくは無いので
概念的なことだけ書いてみます



const int NUMBER = 100;//キャラの最大数

struct SChar
{
int hitrang;//攻撃判定の大きさ
int grang;//防御判定の大きさ
int flag;//死亡フラグ
};

struct SChar obj[NUMBE[/url];//NUMBERぶんキャラデータを作成



int i1 , i2;
for(i1=0;i1<NUMBER;i1++)//キャラ同士を全てチェック
{
if (obj[i1].flag==0)continue;//自分が死んでいたらとばす

for(i2=0;i2<NUMBER;i2++)//自分(i1) と相手(i2)のチェック
{
if (obj[i2].flag==0)continue;//相手が死んでいたら飛ばす

if (obj[i1].grang<obj[i1].hitrang + obj[i2].hitrang)//敵と自分の判定
{
obj[i1].flag=0;//自分死亡
obj[i2].flag=0;//相手死亡
break;//ループから抜けてi1を増やす
}

}
}


上に上げたループでは(最大で)NUMBERの二乗回ループしています
キャラ数はデフォルトでは100なので、10000回ループします
キャラ数が1000体になれば1000*1000で100万回ループします
(巨大な構造体を値渡ししてでもしない限りは100万回ループでも動作速度に問題はなさそうです)

この方式だと、キャラが増える分だけ、ループ数もどんどん肥大化していきます

こんな感じでやるのかな?と私は思ってます。
少なくとも一つのループでは無理だと思います。

自機が 、敵、敵弾、背景と当たり判定のチェックをする・・・
と、攻撃判定をするキャラが増えていくたびにどんどんループのネストは深まっていきます

こういうのを対処するには、リスト構造でのキャラの管理やタスクシステムを使ったりします
(詳しくは「STL リスト」 や 「タスクシステム」 で)

うしお

Re:当たり判定

#4

投稿記事 by うしお » 14年前

>もっと数が増えた場合

衝突判定をループすれば良いかと思います

Ultimateさん

もし必要でも関数内のローカルで用意すればよいので、
最後の引数flagは必要ないのではないでしょうか?
(ただ無駄に引数が増えるだけ)

一般にbool値は0がfalse 0以外がtrueなので、
if(!CircleHitCircle(...))
{
}
がより汎用的かと思います

zは3Dにおけるz座標のような印象も出てしまうかと

好みの問題かもしれませんが
bool CircleHitCircle(double x0,double y0,double radius0,double x1,double y1,double radius1);
もしVector2クラスなどがあれば、
bool CircleHitCircle(const Vector2& p0,double radius0,const Vector2& p1,double radius1);
といった形も良いのではないでしょうか

好みの問題もありますが、ご一考ください

Ultimate

Re:当たり判定

#5

投稿記事 by Ultimate » 14年前

>もし必要でも関数内のローカルで用意すればよいので、 最後の引数flagは必要ないのではないでしょうか?

ご指摘ありがとうございますm(_ _)m
その通りでした。
そんなことになぜ気付かなかったのか自分でも不思議ですw
修正しておきます!

きつね

Re:当たり判定

#6

投稿記事 by きつね » 14年前

みなさんありがとうございます。

考え方の例として添付した図のように(わかりにくいかも知れません・・・)
攻撃範囲R1は自機範囲B1,B2,B3と当たっているか計算し
攻撃範囲R2は自機範囲B1,B2,B3と当たっているか計算・・・

というのをキャラの数だけループさせればいい、という事ですよね?

そのループの仕組みを作るのが頭がちょっと混乱しててわかりません。
そう少し考えてみたいと思います。

Ultimate

Re:当たり判定

#7

投稿記事 by Ultimate » 14年前

総当たりの考え方で

敵1は自機1,自機2,自機3
敵2は自機1,自機2,自機3
   ・
   ・
   ・
といった感じにやればいいと思います。。。


もっと良い方法はあるかもしれませんが。。。

Ultimate

Re:当たり判定

#8

投稿記事 by Ultimate » 14年前

ということできつねさんのやり方は正しいはずです。

ループ内に大量に当たり判定プログラムを入れるだけです。

きつね

Re:当たり判定

#9

投稿記事 by きつね » 14年前

返信遅れて申し訳ありません。いろいろ試してみたいとおもいます!
ありがとうございました。

閉鎖

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