質問ですが、よろしくお願いします。
ゲームプログラミングの館の当たり判定でたくさんの当たり判定をやろうと思い
描画する円の数を増やして、当たり判定の式を入れようとしたら詰まってしまいました。
円が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;
}
************************************************************************
当たり判定
Re:当たり判定
円と円の当たり判定でしたらこの前作りました。
自作のまとめヘッダファイルを添付しておきます。
結局は中心を結んだ距離が半径の和以下であればいいというだけです。
ちなみに関数の使い方を「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減らす
//下のほうも略
こんな感じでできるのでよかったらどうぞ!!!
自作のまとめヘッダファイルを添付しておきます。
結局は中心を結んだ距離が半径の和以下であればいいというだけです。
ちなみに関数の使い方を「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減らす
//下のほうも略
こんな感じでできるのでよかったらどうぞ!!!

Re:当たり判定
あまり詳しくは無いので
概念的なことだけ書いてみます
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 リスト」 や 「タスクシステム」 で)
概念的なことだけ書いてみます
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:当たり判定
>もっと数が増えた場合
衝突判定をループすれば良いかと思います
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さん
もし必要でも関数内のローカルで用意すればよいので、
最後の引数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);
といった形も良いのではないでしょうか
好みの問題もありますが、ご一考ください