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

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

ただいまの
回答率

90.51%

  • Processing

    274questions

    Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

弾幕ゲームの作成に関して

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 164

plarex

score 4

 使用している画像

pStart
pGameclear
pGameover
pGameback

 実現したいこと

レーザーとボス、自機と弾幕の当たり判定がうまくいきません

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

動くことは動くが当たり判定が出ない

 該当のソースコード

PImage    pStart;
PImage    pGameback;
PImage    pGameover;
PImage    pGameclear;

Bullet bullet;
Ship ship;
Boss boss;
GameStage gamestage;

private ArrayList<Bullet> danmaku = new ArrayList<Bullet>();     
enum GameScene {
START, PLAY, CLEAR, OVER;
}
private GameScene scene = GameScene.START; 

void setup() {
size(320, 480);

frameRate(30);

noCursor();  // clear mouse cursor

pStart = loadImage("start.png");
pGameback = loadImage("back.png");
pGameover = loadImage("gameover.png");
pGameclear = loadImage("gameclear.png");

bullet = new Bullet(width/2, height/2, 20, 0, 0 );//クラスからインスタンスを生成
ship = new Ship(mouseX,mouseY);
gamestage = new GameStage() ;
boss = new Boss(160, 150);
}

//GameStage class
class GameStage {

void update() {
boss.doShinking();

//画面切り替え
if (ship.hp == 0) {
scene = GameScene.OVER;
}
if (boss.hp == 0) {
scene = GameScene.CLEAR;
}
}
}

// ship(自機) class 
class Ship {
private int sx, sy;
private int hp = 1;
boolean is_Alive() {
//return is_alive;
return hp != 0;
}
Ship(int x, int y) {
sx = x;
sy = y;
}
void update(int x, int y) {
sx = x;
sy = y;
stroke(255, 255, 255);
noFill();

}

//hit check
void damage() {
if (abs(ship.sx -boss.tx) < (boss.bw/2)) {
boss.hp--;
}
}
}

// Boss class
class Boss {
private int tx, ty;
private int dx, dy;
private int bw = 20;
private int bh = 10; 
private long routine = 0;
private int hp = 10;
boolean isAlive() {
//return is_alive;
return hp != 0;
}

Boss(int x, int y) {
tx = x;
ty = y;
dx = 10;
dy = -8;
}
void move() {
tx += dx;
ty += dy;
if (tx < 0 || tx > width) {
dx*= -1;
}
if (ty < 0 || ty > height/3) {
dy*= -1;
}
stroke(255, 204, 0);

}
void doShinking() {
routine++;
if (routine % 10 == 0) {
move();
}
if (routine % 30 == 0) {
danmaku.addAll(this.shot());                           
println("#shot!!" +routine + ":" + tx + "," + ty);
}
}
//hit check 
void damage() {
if (dist(tx, ty, ship.sx, ship.sy) < bullet.tr/2) {
ship.hp--;
}
}

ArrayList<Bullet> shot() {
ArrayList<Bullet> danmaku = new ArrayList();
for (int i = 0; i < 360; i+= 10) {                            //インスタンス(弾幕)の作成
double rad = radians(i);
danmaku.add(new Bullet(this.tx, this.ty, 10, Math.cos(rad), Math.sin(rad)));           
}
return danmaku;              

}

// Bullet(弾幕) class

class Bullet {
private double tx, ty;
private final double tr;
private double dx, dy;
private boolean is_alive = true;
Bullet(double x, double y, double r, double temp_dx, double temp_dy ) {
tx = x;
ty = y;
tr = r;
dx = temp_dx;
dy = temp_dy;
}
boolean isAlive() {
return is_alive;
}
void update() { 
tx += dx;
ty += dy;
//area check
if (Math.min(tx, ty) < 0) {
is_alive = false;
//println("#" + tx + "," + ty);
return ;
}
if (tx > width || ty > height) {
is_alive = false;
return ;
}

stroke(255, 0, 0);

ellipse((float)tx, (float)ty, (float)tr, (float)tr);
}
}
void draw() {
rect(boss.tx - boss.bw/2, boss.ty + boss.bh/2, boss.bw, boss.bh);
fill(255,0,0);
text("boss.hp",100,100);
fill(255,255,255);

background(0); // clear

triangle(mouseX, mouseY -7, mouseX - 10, mouseY + 7, mouseX + 10, mouseY + 7);

boss.damage();
ship.damage(); 

//レーザーの描写
if (mousePressed) {
line(mouseX, mouseY - 7, mouseX, 0);
}

for (int i = danmaku.size() -1; i  >= 0; i--) {        
Bullet b = (Bullet)danmaku.get(i);
if (!b.isAlive()) {
danmaku.remove(i);
continue;
}
b.update();
}

if (scene == GameScene.START) {
image(pStart, 0, 0);
}
if (mousePressed) {
if (mouseButton == LEFT) {
scene = GameScene.PLAY;
}
}
if (scene == GameScene.PLAY) {
gamestage.update();
//image(pGameback,0,0);
}
if (scene == GameScene.OVER) {
image(pGameover, 0, 0);

}
if (scene == GameScene.CLEAR) {
image(pGameclear, 0, 0);
}

}

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • umyu

    2018/05/06 06:34

    1,start.pngなどの画像がないので、デバックできません。質問文に追記してくださいな。2,一般的な衝突検知と衝突応答の基礎知識については大丈夫でしょうか?

    キャンセル

回答 1

checkベストアンサー

+1

ship(mouseX, mouseY);

shipクラスのインスタンスをsetup()メソッドで生成していないような。


質問内容が全面的に変わっている(汗)ので追記。

弾幕の判定に関して矩形の衝突とはなにか。
物体Aと物体Bの座標が重なっている部分があること。
イメージ説明
逆にいうと座標が重なっていなければの判定ができれば、背理法で衝突検知はできます。

自機から発射するレーザーも消える条件が特殊な弾の一種と考えるとよいですよ。
自機から発射した弾なのか。
ボスが発射した弾なのか。
Bulletクラスを生成時に渡して、それで判断すれば良いです。

この2つの条件が両方ともtrueならば衝突しているという事です。

if((A.Left < B.Right) && (A.Right > B.Left)) {
   return true;
}
return false;
if((A.Top < B.Bottom) && (A.Bottom > B.Top)) {
  return true;
}
return false;

判定を纏めると以下になります。

if((A.Top < B.Bottom) && (A.Bottom > B.Top)) {
  if((A.Left < B.Right) && (A.Right > B.Left)) {
     return true;
  }
}
return false;


衝突検知はパフォーマンスの問題が出てくると思うので、
弾幕データのY軸で事前にソートして衝突検知は二分探索で判定する事をお勧めします。

最後に回答に対するフィードバックが一切無い方みたいなので、私はここでギブアップさせて頂きます。
あとは頑張ってくださいな。
◇参考情報
4-2. どのように解決したのかを伝えましょう

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/06 22:13

    画像載せ忘れてました。すみません。
    レーザーとボスの衝突判定はこれでいけましたが【 if (abs(mouseX -boss.tx) < 10) {
    boss.hp--;
    } 】

    弾と自機は【if (Math.abs(bullet.tx - ship.sx) < 5 && Math.abs(bullet.ty - ship.sy) < 5) {
    ship.hp--;
    }】でいけるかなと思ったのですがまだうまくいってませんが、頑張って動くようにしたいと思います。
    二分分割もまだ勉強不足なので勉強します。。。
    それと、回答に対するフィードバックをしてなくてすみません気を付けます。。。今まで質問に回答していただきありがとうございました。

    キャンセル

  • 2018/05/06 22:13

    画像載せ忘れてました。すみません。
    レーザーとボスの衝突判定はこれでいけましたが【 if (abs(mouseX -boss.tx) < 10) {
    boss.hp--;
    } 】

    弾と自機は【if (Math.abs(bullet.tx - ship.sx) < 5 && Math.abs(bullet.ty - ship.sy) < 5) {
    ship.hp--;
    }】でいけるかなと思ったのですがまだうまくいってませんが、頑張って動くようにしたいと思います。
    二分分割もまだ勉強不足なので勉強します。。。
    それと、回答に対するフィードバックをしてなくてすみません気を付けます。。。今まで質問に回答していただきありがとうございました。

    キャンセル

  • 2018/05/06 22:48 編集

    >plarexさんへ
    フィードバック情報ありがとうございました。
    えっとですね、私としてはお礼の言葉はあまり気にしてなくて、
    plarexさんと同じ課題(問題)を持った人が将来このページを見た時にplarexさんがどう解決したのかが知りたいと思うのです。それだけですー。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る

  • Processing

    274questions

    Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。