ページ 11

当たり判定がうまく出ません

Posted: 2010年9月02日(木) 03:27
by Wize
初めて質問させて頂きます。画面の左右からキャラを発射して、接触時に文字を表示させようとしています。
現段階では文字は表示されません。
どこがまずいのか、どなたか教えて頂けないでしょうか?

[1] 質問文
 [1.1] 自分が今行いたい事は何か
   動かしている二つのキャラが接触したかを判定させたい。二つのキャラはY軸においては同じです。

 [1.2] どのように取り組んだか(プログラムコードがある場合記載)
   プログラムコードは以下の通りです。大本はこのサイトのゲーム基本編26のコードを改編したものです。
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
//対戦型風の表現
#include "DxLib.h"

struct shot{
int x1,y1,t_x1,t_y1;
int flag1,t_flag1;
};

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode( TRUE ) ; // ウインドウモードに変更
if( DxLib_Init() == -1 ) return -1; //DXライブラリ初期化 エラーが起きたら終了

int image[16],i1,t1,counter=0; //counter=発射してからのカウントをする変数。
char Key[256];

struct shot tama[20]; //tamaを20個作る。
struct shot teki[20]; //tekiを20体作る。

for(i1=0;i1<20;i1++){ //初期化処理
tama[i1].x1=600; tama[i1].y1=480/4; //座標代入
tama[i1].flag1=0; //飛んでいない事を示すフラグ=0
}
for(t1=0;t1<20;t1++){ //初期化処理
teki[t1].t_x1=10; teki[t1].t_y1=480/4; //座標代入
teki[t1].t_flag1=0; //飛んでいない事を示すフラグ=0
}

SetDrawScreen( DX_SCREEN_BACK ) ;//描画先を裏画面に設定
LoadDivGraph( "char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存
int beak = LoadGraph("haikei.png");
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
while(1){
ClearDrawScreen(); //裏画面のデータを全て削除
DrawGraph(0,0,beak,TRUE);
GetHitKeyStateAll( Key ) ; // すべてのキーの状態を得る
if( ProcessMessage() == -1 ) break ; //異常がおきたら終了
if(counter<5) //前にエンターを押してから5カウント未満なら
counter++; //カウントアップ
else if( Key[ KEY_INPUT_P ] == 1 ){//5カウント以上たっていたら
counter=0; //カウンターを戻す
for(i1=0;i1<20;i1++){
if(tama[i1].flag1==0){ //発射していない玉を探し、
tama[i1].flag1=1; //発射フラグを立てる
break;
} } }
else if( Key[ KEY_INPUT_Q ] == 1 ){//5カウント以上たっていたら
counter=0; //カウンターを戻す
for(t1=0;t1<20;t1++){
if(teki[t1].t_flag1==0){ //発射していない玉を探し、
teki[t1].t_flag1=1; //発射フラグを立てる
break;
} } }
for(i1=0;i1<10;i1++){
if(tama[i1].flag1==1){ //発射している玉なら
tama[i1].x1-=1; //座標を1減らす
DrawGraph( tama[i1].x1 , tama[i1].y1 , image[4] , TRUE );//玉を描画
if(tama[i1].x1 < -32){ //もし画面外まで来たら
tama[i1].x1=640; //初期値に戻し、
tama[i1].flag1=0; //発射フラグを戻す
} } }
for(t1=0;t1<10;t1++){
if(teki[t1].t_flag1==1){ //発射している玉なら
teki[t1].t_x1+=1; //座標を1増やす
DrawGraph( teki[t1].t_x1 , teki[t1].t_y1 , image[12] , TRUE );//敵を描画
if(teki[t1].t_x1 > 671){ //もし画面外まで来たら
teki[t1].t_x1=0; //初期値に戻し、
teki[t1].t_flag1=0; //発射フラグを戻す
} } }
/*  こっちの括りが、私が書いた当たり判定文です。うまくいかず第二案へ */
// if( tama[i1].flag1 ==1 && teki[t1].flag1 ==1 )
// if( teki[t1].t_flag1 == 1 )
// if( tama[i1].flag1 == 1)
// if( teki[t1].t_x1 == tama[i1].x1 )
// printfDx("骨");
/* 他のサイトを参考に書いた第2案です */
if( ( tama[i1].x1 < teki[t1].t_x1 + 32 ) &&
( tama[i1].x1 + 32 > teki[t1].t_x1 ) ){
printfDx("魚");
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 [1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
   キャラがぶつかっても当たり判定メッセージが出ない。
 [1.4] 今何がわからないのか、知りたいのか
   当たり判定をどう記述したらいいかわからない。
[2] 環境  
 [2.1] OS : XPです。
 [2.2] コンパイラ名 :    Microsoft Visual Studio 2008
[3] その他
 ・どの程度C言語を理解しているか
   初心者です。このサイトで勉強してる程度。
 ・ライブラリを使っている場合は何を使っているか
   DXライブラリを使用しています。 画像

Re:当たり判定がうまく出ません

Posted: 2010年9月02日(木) 21:54
by めるぽん
tama や teki は 20個ずつあるので、tama[i1] と teki[t1] だけの当たり判定をしてもダメですね。
tama[0] と teki[0]
tama[0] と teki[1]
...
tama[0] と teki[19]
tama[1] と teki[0]
tama[1] と teki[1]
...
tama[1] と teki[19]
tama[2] と teki[0]
...
...
tama[19] と teki[19]
と、それぞれが当たっていないかをチェックします。当然まだ使われていないデータもあるので、flag1 や t_flag1 もチェックする必要がありそうです。
for (i1 = 0; i1 < 20; i1++)
{
    if (tama[i1].flag1 == 0) continue;
    for (t1 = 0; t1 < 20; t1++)
    {
        if (teki[t1].t_flag1 == 0) continue;
        if( ( tama[i1].x1 < teki[t1].t_x1 + 32 ) &&
            ( tama[i1].x1 + 32 > teki[t1].t_x1 ) ){
        printfDx("魚");
    }
}
という感じではないでしょうか。
あと、これ以降は全部当たり判定とは関係無いことなんですが、
for(i1=0;i1<10;i1++){
                        ...
                for(t1=0;t1<10;t1++){
ここら辺、10 ではなくて 20 じゃないでしょうか。こういうのは定数でやっておいた方が分かりやすくなりますし、間違いも少なくなります。
const int TAMA_NUM = 20;
const int TEKI_NUM = 20;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
    ...
    struct shot tama[TAMA_NUM];
    struct shot teki[TEKI_NUM];

    for (i1 = 0; i1 < TAMA_NUM; i1++) {
        ...
    }
}
あと、コードを見る限り、tama は x1,y1,flag1 しか使っていなくて、teki は t_x1,t_y1,t_flag1 しか使っていないみたいなので、
struct shot{
    int x1,y1;
    int flag1;
};
としておいた方が、tama が間違って t_x1 や t_flag1 を使ってしまったり、teki が y1 や flag1 を使うことが無くなるので、そうした方が良いと思います。

Re:当たり判定がうまく出ません

Posted: 2010年9月15日(水) 01:33
by Wize
返答がずいぶん遅くなってしまい、申し訳ないです。
おかげさまで問題は解決しました。

定数の助言もありがとうございます。
プログラミングが進んだ後で数を変更する際にも便利で助かってます。
ただ、最後の助言の個別にまとめるのがうまくいかずに棚上げになっていますが…まだ自分で試行錯誤してみます。