四角形の衝突判定がうまくできません(重なります)。
解決済
回答 3
投稿
- 評価
- クリップ 0
- VIEW 2,335
前提・実現したいこと
X,Y座標をテキストフィールドに入力しボタンを押すと、縦横50の塗りつぶされた正方形を描くものです。
ただし正方形の始点の座標は、2次元配列を用いることと、既に存在する正方形と衝突する場合は、「衝突します」と表示させたいです。
```
import java.applet.Applet;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Prog2Lec10Subject02 extends Applet implements ActionListener{
TextField tf1,tf2;
Button additionButton;
int i,j;
int x,y;
int[][] zahyo;
String str = "";
public void init(){
i=j=0;
zahyo = new int[10][2];
add(new Label("x座標"));
tf1 = new TextField("",5);
tf1.addActionListener(this);
add(tf1);
add(new Label("y座標"));
tf2 = new TextField("",5);
tf2.addActionListener(this);
add(tf2);
additionButton = new Button("追加");
additionButton.addActionListener(this);
add(additionButton);
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == additionButton) {
x = Integer.parseInt(tf1.getText());
y = Integer.parseInt(tf2.getText());
zahyo[i][0] =x;
zahyo[i][1] =y;
}
repaint();
}
public void update(Graphics g){
paint(g);
g.drawString(str, 100, 50);
if(isCollision() == false){
g.setColor(Color.RED);
g.fillRect(x,y, 50, 50);
str = "";
i++;
}
else if(isCollision() == true){
str = "追加しようとする正方形は、他の正方形と衝突します";
}
}
public boolean isCollision(){
for(int j=0; i>j; j++);{
if(zahyo[0][j]+50 > zahyo[i][0]&&
zahyo[1][j]+50 > zahyo[i][1]&&
zahyo[i][0]+50 > zahyo[0][j]&&
zahyo[i][1]+50 > zahyo[1][j])
return true;
}
return false;
}
}
試したこと
最初にx=50,y=50を入れ、次にx=75,y=75を入力すると、重なるため衝突しますと出ました。
しかしx=200,y=100を入れ、次にx=230,y=100を入力すると、重なってしまいます。
恐らく最初のzahyo[i][0],[i][1]にx・yは代入されているので、「i++」の位置か、boolean isCollisionの中身がおかしいような気がするのですが、うまく動かないので、ご教示願います。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+3
四角形の交差の判定は、
(以下、青の正方形がある状態で赤の正方形を加えようとする状況とみてください)
このいずれかに当てはまれば交差せず、いずれにも当てはまらなかったとき交差すると判定できます。
こう考えると、正方形でない長方形にも応用が利きます。
public boolean isCollision(){
int[] source = zahyo[i]; //衝突判定を行う四角形の左上のXY座標
int sourceX = source[0];
int sourceY = source[1];
for(int j = 0; i > j; j++){
int[] target = zahyo[j]; //比較対象の四角形の左上のXY座標
int targetX = target[0];
int targetY = target[1];
if (!(sourceX + 50 < targetX || targetX + 50 < sourceX
|| sourceY + 50 < targetY || targetY + 50 < sourceY)) {
return true;
}
}
return false;
}
二次元配列について
Javaの二次元配列は、実は「配列の配列」、つまり「配列を要素に持つ配列」なのです。
int[]
がint
を要素に持つ配列であるように、int[][]
はint[]
を要素に持つ配列なのです。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
とりあえずヒントだけ。
zahyo[A][B]
のAとBが何を意味しているか考えましょう。
isCollision()
を見ると使い方が定まっていません。
見るところはisCollision()
の関数の中のzahyo[][]
の箇所です。
i
の取りうる範囲は0 ≦ i < 9
ですね。
j
の取りうる範囲は0 ≦ j < i
ですね。
isCollision()
内で使われているzahyo[][]
は以下の種類です。
zahyo[0][j]
zahyo[i][0]
zahyo[1][j]
zahyo[i][1]
zahyo[i][0]
zahyo[0][j]
zahyo[i][1]
zahyo[1][j]
zahyo[A][B]
で、A
とB
の範囲はぞれぞれどうなっているでしょうか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
おそらく、isCollision()を以下のようにすれば、正しく判定できると思います。
public boolean isCollision(){
for(int j = 0; i > j; j++){
//[1]
int[] source = zahyo[i]; //衝突判定を行う四角形の左上のXY座標
int sourceX = source[0];
int sourceY = source[1];
int[] target = zahyo[j]; //比較対象の四角形の左上のXY座標
int targetX = target[0];
int targetY = target[1];
//[2]
//左上の点が四角形内部にあるか確認する
if(targetX <= sourceX && sourceX <= targetX + 50
&& targetY <= sourceY && sourceY <= targetY + 50){
return true;
}
//右上の点が四角形内部にあるか確認する
if(targetX <= sourceX + 50 && sourceX + 50 <= targetX + 50
&& targetY <= sourceY && sourceY <= targetY + 50){
return true;
}
//左下の点が四角形内部にあるか確認する
if(targetX <= sourceX && sourceX <= targetX + 50
&& targetY <= sourceY + 50 && sourceY + 50 <= targetY + 50){
return true;
}
//右下の点が四角形内部にあるか確認する
if(targetX <= sourceX + 50 && sourceX + 50 <= targetX + 50
&& targetY <= sourceY + 50 && sourceY + 50 <= targetY + 50){
return true;
}
}
return false;
}
コードを読む限り、zahyo[x][y]のzahyo[x]は、入力した四角形のXY座標が代入されています。
System.out.print(zahyo[0][0]) //1回目に入力した四角形のX座標
System.out.print(zahyo[1][0]) //2回目に入力した四角形のX座標
System.out.print(zahyo[2][0]) //3回目に入力した四角形のX座標
System.out.print(zahyo[2][1]) //3回目に入力した四角形のY座標
ですので、isCollision()内で、zahyo[i]とすると、衝突判定を行う四角形のXY座標を、長さ2のint配列で取得できます。(上記コードの[1])
次に衝突判定についてですが、今回、四角形は回転しないので、衝突判定を行う四角形の4つの頂点が、いずれも他の四角形内に存在しないことを確かめれば、正しく衝突判定が行えます。(上記コードの[2])
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.20%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2018/10/19 12:39
コードを入れるとうまくできました。
私の理解不足ですが、単純に[]が一次元、[][]が二次元配列と言うわけではないのでしょうか?
最初に青の四角形(source)のxは[0][0]で、yが[0][1]で、比較対象の赤の四角形(target)のxは[1][0]、yが[1][1]で、[][]同士を比較するのではないのでしょうか?
やっているうちに「iとj」、「xとy」の関係が分からなくなってしまいました。
あと衝突した場合のコメントが、次に衝突しない場合でも残ってしまうことと、「追加」を押して衝突する場合、「追加」をもう一度押さないと、コメントがでません。
お手数ですが、御教授願います。
2018/10/19 12:50
2018/10/19 16:35
何とか課題はできたのですが、二次元配列についてほとんど理解できていなかったと思うので、再度、勉強しなおします。
ありがとうございました。