質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.55%

弾の当たり判定をどこにどのように書けばいいかわかりません。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 4,617

alastashim

score 10

前提・実現したいこと

現在processingで簡単なシューティングゲームを作っているのですが、弾(BULLET)と敵(ENEMY1)との当たり判定をうまくつけることができません。
自分で一度,
{(弾のX座標)+(弾のwidth/2)<(敵のX座標)}
かつ{(弾のY座標)<(敵のY座標)+(敵のheight/2)}
かつ{(弾のY座標)>(敵のY座標)-(敵のheight/2)}
として当たり判定をつけて見たのですが、、敵のX座標とは異なる場所で当たり判定がでました。そして、よくわからず ArrayList を用いて弾を作ってしまったのでどこに当たり判定の行を書けば良いかわかりません。なので、どこの行にどのように当たり判定のプログラムを書くとうまくいくのでしょうか。拙い説明ですが、お許しください。

発生している問題・エラーメッセージ

当たり判定がうまくいかない

該当のソースコード

float mx=mouseX;
float my=mouseY;
int msp=3;
float e1x = 1250;
float e1y = random(0, height);
float ree1x = 1250;
float ree1y = random(0, height);
float ebx=1200, eby=350;
int jotai=0;
ME me;
ENEMY1 en1;
ArrayList<BULLET> bulletList = new ArrayList<BULLET>();
float bx;//弾のx
float by;//弾のy
float bwi;//弾のサイズ
float bhe;
float bsp;
int score = 0;

void setup() {
  size(1250, 700);
  frameRate(30);
  noCursor();
  me = new ME();
  en1 = new ENEMY1(e1x, e1y);
}

void draw() {

  if (jotai==0) {
    background(0);
    textSize(32);
    fill(255);
    text("'Right Click' is clicked to start", 400, 350) ;
  }


  if (jotai==1) {
    background(0);
    for (int i=bulletList.size()-1; i>=0; i--) {
      BULLET b = bulletList.get(i);
      if (b.isAlive()) {
        b.move();
        b.display();
      } else {
        //画面外の弾は削除
        bulletList.remove(i);
      }
    }  
    en1.move();
    en1.display();
    me.move(mouseY);
    me.display();
    text("SCORE:"+str(score), width/7, height -50) ;
  }

  if (jotai==2) {
    fill(0);
    rect(0, 0, width, height);
    textSize(32);
    fill(255);
    text("GAME OVER", 600, 350) ;
    text("RESTART is 'Right Click'", 600, 500);
  }
}


void mousePressed() {

  if (jotai==0) {

    if (mouseButton==RIGHT) {
      jotai=1;
    }
  }
  if (jotai==1) {
    if (mouseButton==LEFT) {
      bulletList.add(new BULLET(me.mx, me.my));
    }
  }
  if (jotai==2) {
    if (mouseButton==RIGHT) {
      jotai=0;
    }
  }
}

class ME {//自機の情報
  float mx=50, my;//自機のx,y座標

  void move(float _y) {
    my = _y;
  }
  void display() {
    noStroke();
    fill(40, 190, 255);
    ellipse(mx, my, 30, 30);
  }
}

class BULLET {
  float bx;//弾のx
  float by;//弾のy
  float bwi;//弾のサイズ
  float bhe;
  float bsp;

  BULLET(float _x, float _y) {
    bx = _x;//弾の初期位置
    by = _y;//弾の初期位置
    bwi = 30;//弾のサイズ
    bhe = 5;
    bsp = 15;
  }

  void move() {
    bx += bsp;

    if (e1x<50||e1x<mouseX) {
      bx = width;
      by = height;
    }
  }
  void display() {
    stroke(50, 225, 100);
    fill(255);
    ellipse(bx, by, bwi, bhe);
  }
  //画面内かどうか
  boolean isAlive() {
    if (bx+bwi/2<0 || width<bx-bwi/2 || by+bhe/2<0 || height<by-bhe/2) {
      return false;
    }
    return true;
  }
}

class ENEMY1 {
  float e1x, e1y;
  float e1_xsp = 4;
  ENEMY1(float ene1X, float ene1Y) {
    e1x = ene1X;
    e1y = ene1Y;
  }

  void move() {

    e1x-=e1_xsp;

    if (e1x<50) {
      jotai=2;
    }
    if (e1x<50) {
      e1x = ree1x;
      e1y = ree1y;
    }
  }
  void display() {
    stroke(255, 0, 0);
    line(e1x, 0, e1x, height);
    noStroke();
    fill(255);
    ellipse(e1x, e1y, 10, 25);
  }
}

試したこと

ArrayList を用いて弾を作りました。

補足情報(言語/FW/ツール等のバージョンなど)

Processing

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

{(弾のX座標)+(弾のwidth/2)<(敵のX座標)}
かつ{(弾のY座標)<(敵のY座標)+(敵のheight/2)}
かつ{(弾のY座標)>(敵のY座標)-(敵のheight/2)}

四角形同士の範囲の当たり判定をやりたかったのでしたら、上下左右の4つで判定しなければいけませんね。
これだと敵のX座標が大きい側では全て当たり判定が発生します。
自機より右が全部当たり判定になる、グラディウスのレーザーみたいな判定のイメージですね。

判定場所自体は

if (b.isAlive()) {


の中あたりが妥当に思えます。

ただ、四角形で正確に判定できるようになったとしても、弾が早すぎるとすり抜けてしまう問題が発生するのにも注意が必要です。
あるフレームとその次のフレーム間に弾が存在していたはずの全ての領域で判定しないといけないのですが、ややこしいです。がんばってください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/15 12:40

    回答ありがとうございます。当たり判定の範囲を変えたことと敵の大きさをいじってみたら、きちんとできました。アドバイスありがとうございました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.55%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる