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

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

新規登録して質問してみよう
ただいま回答率
85.49%
JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

解決済

1回答

4467閲覧

JavaFXでImageViewとShape,ImageViewとImageViewが触れたというのを取得するメソッドなどないでしょうか

nuiri1343

総合スコア54

JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

0グッド

1クリップ

投稿2016/06/25 04:47

###前提・実現したいこと・試したこと
javaFXで、Timelineを使い
ImageViewをsetLayoutX()とsetLayoutY()を使い少しずつ動かしている時、

他の、たとえばShapeのRectangleやCircle、他のImageViewなどとぶつかった時に
操作をしたいのです。
ImageViewを消したり、移動を反転させたりという操作を。

自分の考えられる手段としては、
全てのShapeの存在する座標を把握して、ImageViewの座標がそこにいたったら操作をする
というものですが、

ImageViewの座標といってもgetLayoutX()とgetLayoutY()で得られるのは左上の一点の座標で、
ShapeのgetLayoutX()とgetLayoutY()もRectangleなら左上の一点、Circleなら中心の一点しか得られません。

それを考慮して、ImageViewで表示している画像とShapeで表示している図形が少しでも触れた瞬間に操作をさせる
というのはかなり難しいです。
if文使って、&&や||でかなり分岐させればできますが、

Shapeをたくさんランダムに生起させ、かつ動かしている状態で
ImageViewもgetTransforms().add(new Rotate());などで向きも回転させたりしているともう何がなんだか・・・
Shapeの方もRotateさせていたり、他のImageViewも回転していたらもうわけ分からなくなってしまいます。

###質問
もしも、上で書いたようにやりたいとしたら
やはり自分のいったように全座標を管理するしか方法が無いのでしょうか?
それともこう、都合のいいメソッドなどが存在しているのでしょうか?
何かアドバイスなどあればヨロシクお願いします。

###該当のソースコード
一応、自分の作ったプログラムを書いておきます。
ですが、まだ途中ですし、今回の質問とは直接は関係のない部分も多いので見にくいかもしれません
もうしわけありません。

もし、何か補足してほしい情報など、聞きたい事などあれば聞いてくだされば補足いたします。

java

1import javafx.application.Application; 2import javafx.application.Platform; 3import javafx.stage.Stage; 4import javafx.scene.Scene; 5import javafx.scene.shape.*; 6import javafx.event.*; 7import javafx.scene.layout.*; 8import javafx.scene.paint.*; 9import javafx.animation.*; 10import javafx.util.*; 11import javafx.scene.input.*; 12import javafx.scene.transform.Rotate; 13import javafx.scene.image.Image; 14import javafx.scene.image.ImageView; 15import java.io.File; 16 17public class Sample extends Application{ 18 19 Boolean w = false; //wが押されているかどうか 20 Boolean a = false; //aが押されているかどうか 21 Boolean s = false; //sが押されているかどうか 22 Boolean d = false; //dが押されているかどうか 23 24 int num = 0; //現在生起しているミサイルの数 25 double[] dx = new double[5]; //ミサイルの1サイクルあたりのxの移動量 26 double[] dy = new double[5]; //ミサイルの1サイクルあたりのyの移動量 27 Boolean[] check = new Boolean[5]; //ミサイルが生起しているかどうか 28 29 Image img = new Image(new File("point.png").toURI().toString()); //マウスで動く照準 30 ImageView imgView = new ImageView(img); 31 Image fire = new Image(new File("fire.png").toURI().toString()); //ミサイル 32 ImageView[] imgFire = new ImageView[5]; 33 final int COOLTIME = 10; 34 int time=0; 35 36 Image img2 = new Image(new File("syatai.png").toURI().toString()); //戦車の車体 37 Image img3 = new Image(new File("houdai.png").toURI().toString()); //戦車の砲塔部分 38 39 ImageView imgSyatai = new ImageView(img2); 40 ImageView imgHoudai = new ImageView(img3); 41 42 43 public void start(Stage stage){ 44 stage.setTitle("Sample"); 45 stage.setWidth(600); 46 stage.setHeight(600); 47 stage.setResizable(false); 48 49 50 for(int i=0;i<5;i++) 51 check[i] = false; 52 imgSyatai.setLayoutX(imgSyatai.getLayoutX()+17); 53 imgHoudai.setLayoutY(imgHoudai.getLayoutY()+6); 54 55 imgSyatai.setLayoutX(imgSyatai.getLayoutX()+253); 56 imgSyatai.setLayoutY(imgSyatai.getLayoutY()+288); 57 imgHoudai.setLayoutX(imgHoudai.getLayoutX()+253); 58 imgHoudai.setLayoutY(imgHoudai.getLayoutY()+288); 59 60 imgView.setLayoutX(288); 61 imgView.setLayoutY(288); 62 63 //背景色 64 Rectangle back = new Rectangle(0,0,600,600); 65 back.setFill(Color.rgb(174,255,175)); 66 67 for(int i=0;i<5;i++) 68 imgFire[i] = new ImageView(fire); 69 70 BorderPane root = new BorderPane(); 71 AnchorPane center = new AnchorPane(); 72 center.getChildren().addAll(back); 73 root.setCenter(center); 74 center.setFocusTraversable(true); 75 76 //クリックで、そこに向かってミサイルが飛ぶ 77 root.setOnMouseClicked(event ->{ 78 if(num!=5&&time==0){ 79 int i; 80 time++; 81 for(i=0;i<5;i++){ 82 if(check[i]) continue; 83 break; 84 } 85 check[i] = true; 86 87 imgFire[i].setLayoutX(imgSyatai.getLayoutX()+14.5); 88 imgFire[i].setLayoutY(imgSyatai.getLayoutY()-63); 89 90 center.getChildren().add(imgFire[i]); 91 92 double x = imgView.getLayoutX()+12.5 - (imgSyatai.getLayoutX()+22); 93 double y = imgView.getLayoutY()+12.5 - (imgSyatai.getLayoutY()+14); 94 int mx = 0; 95 int my = 0; 96 if(x<0){ 97 x=-x; 98 mx = -1; 99 } 100 if(y<0){ 101 y=-y; 102 my=-1; 103 } 104 105 dx[i] = (x*5)/(x+y); 106 dy[i] = (y*5)/(x+y); 107 if(mx==-1) 108 dx[i]=-dx[i]; 109 if(my==-1) 110 dy[i]=-dy[i]; 111 112 imgFire[i].getTransforms().clear(); 113 if(mx<0) imgFire[i].getTransforms().add(new Rotate(180,7.5,77.5)); 114 imgFire[i].getTransforms().add(new Rotate(90+Math.toDegrees(Math.atan(dy[i]/dx[i])),7.5,77.5)); 115 imgHoudai.getTransforms().clear(); 116 imgHoudai.getTransforms().add(new Rotate(Math.toDegrees(Math.atan(dy[i]/dx[i])),41,8)); 117 if(mx==0) 118 imgHoudai.getTransforms().add(new Rotate(180,41,8)); 119 num++; 120 } 121 }); 122 123 124 //マウスが動くと照準も動く ついでに戦車の砲塔も動く 125 root.setOnMouseMoved(event -> { 126 imgView.setLayoutX(event.getX()-12.5); 127 imgView.setLayoutY(event.getY()-12.5); 128 double x = imgView.getLayoutX()+12.5 - (imgSyatai.getLayoutX()+22); 129 double y = imgView.getLayoutY()+12.5 - (imgSyatai.getLayoutY()+14); 130 int mx = 0; 131 int my = 0; 132 if(x<0){ 133 x=-x; 134 mx = -1; 135 } 136 if(y<0){ 137 y=-y; 138 my=-1; 139 } 140 141 double tx = (x*2)/(x+y); 142 double ty = (y*2)/(x+y); 143 if(mx==-1) 144 tx=-tx; 145 if(my==-1) 146 ty=-ty; 147 imgHoudai.getTransforms().clear(); 148 imgHoudai.getTransforms().add(new Rotate(Math.toDegrees(Math.atan(ty/tx)),41,8)); 149 if(mx==0) 150 imgHoudai.getTransforms().add(new Rotate(180,41,8)); 151 }); 152 //ドラッグしてしまっても動く 153 center.setOnMouseDragged(event->{ 154 imgView.setLayoutX(event.getX()-12.5); 155 imgView.setLayoutY(event.getY()-12.5); 156 double x = imgView.getLayoutX()+12.5 - (imgSyatai.getLayoutX()+22); 157 double y = imgView.getLayoutY()+12.5 - (imgSyatai.getLayoutY()+14); 158 int mx = 0; 159 int my = 0; 160 if(x<0){ 161 x=-x; 162 mx = -1; 163 } 164 if(y<0){ 165 y=-y; 166 my=-1; 167 } 168 169 double tx = (x*4)/(x+y); 170 double ty = (y*4)/(x+y); 171 if(mx==-1) 172 tx=-tx; 173 if(my==-1) 174 ty=-ty; 175 imgHoudai.getTransforms().clear(); 176 imgHoudai.getTransforms().add(new Rotate(Math.toDegrees(Math.atan(ty/tx)),41,8)); 177 if(mx==0) 178 imgHoudai.getTransforms().add(new Rotate(180,41,8)); 179 }); 180 181 182 //戦車移動 setRotateは車体の向きを変化させる。 183 center.setOnKeyPressed(event ->{ 184 if(event.getCode() == KeyCode.W){ 185 w = true; 186 imgSyatai.setRotate(90); 187 } 188 if(event.getCode() == KeyCode.A){ 189 a = true; 190 imgSyatai.setRotate(0); 191 } 192 if(event.getCode() == KeyCode.S){ 193 s = true; 194 imgSyatai.setRotate(270); 195 } 196 if(event.getCode() == KeyCode.D){ 197 d = true; 198 imgSyatai.setRotate(180); 199 } 200 if(w&&a) 201 imgSyatai.setRotate(45); 202 if(w&&d) 203 imgSyatai.setRotate(135); 204 if(a&&s) 205 imgSyatai.setRotate(315); 206 if(s&&d) 207 imgSyatai.setRotate(225); 208 }); 209 center.setOnKeyReleased(event ->{ 210 if(event.getCode() == KeyCode.W) 211 w = false; 212 if(event.getCode() == KeyCode.A) 213 a = false; 214 if(event.getCode() == KeyCode.S) 215 s = false; 216 if(event.getCode() == KeyCode.D) 217 d = false; 218 if(w) 219 imgSyatai.setRotate(90); 220 if(a) 221 imgSyatai.setRotate(0); 222 if(s) 223 imgSyatai.setRotate(270); 224 if(d) 225 imgSyatai.setRotate(180); 226 }); 227 228 229 Timeline timeline = new Timeline( 230 new KeyFrame(Duration.millis(10), 231 new EventHandler<ActionEvent>(){ 232 public void handle(ActionEvent event){ 233 if(time!=0){ 234 time++; 235 if(time==COOLTIME) time=0; 236 } 237 if(w&&imgSyatai.getLayoutY()>0){ 238 imgSyatai.setLayoutY(imgSyatai.getLayoutY()-2); 239 imgHoudai.setLayoutY(imgHoudai.getLayoutY()-2); 240 } 241 if(s&&imgSyatai.getLayoutY()<552){ 242 imgSyatai.setLayoutY(imgSyatai.getLayoutY()+2); 243 imgHoudai.setLayoutY(imgHoudai.getLayoutY()+2); 244 } 245 if(a&&imgSyatai.getLayoutX()>-22){ 246 imgSyatai.setLayoutX(imgSyatai.getLayoutX()-2); 247 imgHoudai.setLayoutX(imgHoudai.getLayoutX()-2); 248 } 249 if(d&&imgSyatai.getLayoutX()<574){ 250 imgSyatai.setLayoutX(imgSyatai.getLayoutX()+2); 251 imgHoudai.setLayoutX(imgHoudai.getLayoutX()+2); 252 } 253 254 for(int i=0;i<5;i++){ 255 if(!check[i]) continue; 256 imgFire[i].setLayoutX(imgFire[i].getLayoutX()+dx[i]); 257 imgFire[i].setLayoutY(imgFire[i].getLayoutY()+dy[i]); 258 if(imgFire[i].getLayoutX()<=-75||imgFire[i].getLayoutX()>=590||imgFire[i].getLayoutY()<=-75||imgFire[i].getLayoutY()>=590){ 259 center.getChildren().remove(imgFire[i]); 260 check[i] = false; 261 num--; 262 } 263 } 264 } 265 })); 266 timeline.setCycleCount(timeline.INDEFINITE); 267 timeline.play(); 268 stage.setScene(new Scene(root)); 269 stage.show(); 270 271 //ここでマップの生成処理をしたい。 Shapeで壁を作り、ImageViewで敵戦車を作りたい。 272 273 274 275 center.getChildren().addAll(imgView,imgSyatai,imgHoudai); 276 } 277} 278

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

やはり自分のいったように全座標を管理するしか方法が無いのでしょうか?
それともこう、都合のいいメソッドなどが存在しているのでしょうか?

同じPane内であれば、Node#getBoundsInParentでそれぞれの「Pane内でのBounds」が得られるので、そのBounds同士をintercectsにかけると非常に手軽に当たり判定が取れます。ここにgetBoundsInParentとgetBoundsInLocalの違いがわかりやすく絵に書かれているので見てみるとよいでしょう。
https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/Node.html

あまり画像と当たり範囲が乖離していると感じるのであれば、少しgetBoundsで得た矩形を小さく補正してちょっといい感じに調整してみるといいでしょう。

###追記

Java

1// imgView1とimgView2は同一のPane内であること 2Bounds b1 = imgView1.getBoundsInParent(); 3Bounds b2 = imgView2.getBoundsInParent(); 4if(b1.intersects(b2)) { 5 //衝突 6}

投稿2016/06/25 09:29

編集2016/06/26 06:31
masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nuiri1343

2016/06/26 05:51

すみません。 できれば例文というか、ソースコードをためしに作ってみていただけ無いでしょうか 簡単な例でいいので・・・>< お願いします
masaya_ohashi

2016/06/26 06:32

追記しました。あなたの現状のコードでは「何と何」をぶつけたいのか不明だったので、imgView1、imgView2という仮のImageView同士の当たり判定の例です。
nuiri1343

2016/06/26 12:21

え! たったこれだけで、imageView1とimageView2があたったかどうかって事ができるんですか! Bounds b1 = imgView1.getBoundsInParent(); Circle c = new Circle(0,0,8,Color.BLACK); Bounds b2 = c.getBoundsInParent(); if(b1.intersects(b2)){ } これでShapeの丸とImageViewの接触判定が出来るということでしょうか?
masaya_ohashi

2016/06/26 14:04

getBounds系はあくまで「そのノードを取り囲む形の四角形」なので、Shapeが丸であっても四角く判定されます。それでもよければたったこれだけで判定できます。
nuiri1343

2016/06/27 04:46

そのノードを取り囲む四角形ということは、ImageViewで表示している画像がpngで背景色の一部が透明化されていて形が複雑な画像になっていても、透明化されている部分で判定されることがあるということでしょうか? もし、Shapeの丸や、複雑な形で判定させようとしたらどうしたらいいのでしょうか?
masaya_ohashi

2016/06/27 04:55

残念ながらその通りで、「透明だから」というのはgetBoundsに全く影響を与えないため、単純に画像のピクセルの大きさで判定されます。複雑な形で判定させるというのは、JavaFX標準機能で済むものではありません。お手軽なメソッドでは済まなくなります。 「当たり判定」とは、それだけで分厚い本で何冊も書籍が出るほどのゲームプログラミングにおけるテーマです。おそらくいまのあなたの技術力では、頭がパンクするでしょう。どうしても知りたいのであれば、「どんな形」と「どんな形」の当たり判定が知りたいのかを決めてください。「複雑な形」では教えようがありません。
nuiri1343

2016/06/27 05:50

>「当たり判定」とは、それだけで分厚い本で何冊も書籍が出るほどのゲームプログラミ>ングにおけるテーマです。おそらくいまのあなたの技術力では、頭がパンクするでしょ>う。 本当にこれだと思います。 考えているのは、細長い長方形をRotateさせた斜めの長方形同士のあたり判定が知りたいです。 細長い長方形が斜めだと、getBoundsだとかなり余計な部分まであたり判定を取得してしまうっぽいので・・・
masaya_ohashi

2016/06/27 06:32

まずそのためには各長方形の四点の頂点座標を求める必要があります。いまのところオブジェクトの座標や回転は全てNode任せになっていますよね。そこから四点の頂点座標を得るにはNode#localToSceneTransformPropertyで得られるTransformを使い、元の頂点座標をTransform#transformで変換する必要があります。 ここまでの話は理解できますか?頂点座標とはなにか、Transformが何をしているか、を理解しないとここから先の話は余計に理解できないと思いますので確認のためここでストップです。
nuiri1343

2016/06/27 11:12

すみません。あまり理解できないです。 Transformが、Node.getTransforms().add(new Rotate());で使ったものだというのは分かるのですが・・・。
masaya_ohashi

2016/06/28 00:48

正直でいいですね。ここで「よくわからないけど次を聞くために嘘をつく」のが一番嫌いです。 頂点座標は図形の角の部分を指します。四角形なら頂点座標は4つ、三角形なら3つあります。 Transformは変換行列と呼ばれるもののクラスで、xyの座標を「移動、回転、拡大縮小」できます。add(new Rotate())は、このTransformに回転のTransformを掛け合わせて新しいTransformを計算させています。このTransformを使い、頂点座標を変換、もともとの四角形の左上の位置がいまどこにあり、左下、右上、右下それぞれ同じように位置を求めます。その後、それぞれの頂点位置を使い、当たり判定の公式に当てはめてチェックしていく作業となります。 公式の参考ページ http://www.c3.club.kyutech.ac.jp/gamewiki/index.php?%C5%F6%A4%BF%A4%EA%C8%BD%C4%EA
nuiri1343

2016/06/28 10:01

参考ページを一通り読んだのですが、 結局どうすればいいのかがわかりませんでした。 Transformの何かのメソッドを使い、頂点座標を得て、、、 そしてそれを使ってどうすればいいのでしょうか?
masaya_ohashi

2016/06/28 11:17

そこは私が説明したら授業料を取ってもいいほどの内容と長さになるので、ご自身で調査してください。どれだけ「回転した矩形同士の衝突判定」が難しいかは、参考ページの分からなさ具合から理解できたかと思います。 いまの技術力では難しいと最初に言ったように、「きっちり当たり判定を取ること」よりも、簡易な当たり判定で済むようにゲームの設計を見直すようにしたほうがいいと思います。弾の形を円にして、戦車や敵機の当たり判定も円にしてしまえば、円と円の当たり判定だけで済みます。円同士の当たり判定は非常に簡単なので、そちらも調べてみるとよいでしょう。
nuiri1343

2016/06/28 11:40

なるほど、その通りだと思いました。 色々頑張ってみます。
nuiri1343

2016/06/28 11:51

また何かあった時は、どうかよろしくお願いいたいます。 色々ありがとうございました
nuiri1343

2016/07/01 06:37

すみません。しらべたのですがよくわからなかったため質問いたします 右下の頂点座標を得るというのはなんというメソッドを使えばいいのでしょうか?
masaya_ohashi

2016/07/01 06:49

なんの図形の右下ですか?
nuiri1343

2016/07/01 10:25

ImageViewで表示させている画像のです
masaya_ohashi

2016/07/01 10:36

画像の透過等を考慮しないのであれば、Node#getBoundsInParent()で取れるBoundsのgetMaxXが右端、getMaxYが下端になります。
nuiri1343

2016/07/02 04:54

なるほどー 助かります。ありがとうございます!
nuiri1343

2016/07/05 12:34

長方形画像を回転させた時の、それぞれの頂点座標、 移動先の頂点座標は、自分で角度を使って計算しないと出せないのでしょうか? それとも、これを得られるメソッドがあるのでしょうか?
masaya_ohashi

2016/07/05 13:20

Node#localToSceneTransformPropertyでえられるTransformを使い、左上の座標(普通0,0)、右下の座標(画像の幅、高さ)をそれぞれTransform#transformで変換した座標、が移動+回転後の左上、右下になると思います。ちょっと試したことがないのでわからないですが…ちなみにもともとが画像の右下の座標であったとして、時計回りに90度回転していたらそれは今表示されている画像の左下に来ている、ということを考慮してくださいね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問