लगता है आप अपने checkBounds में मामूली तर्क त्रुटि है दिनचर्या - आप सही तरीके से टकराव (सीमा के आधार पर) का पता लगाने कर रहे हैं, लेकिन अपने ब्लॉक का भरण अधिलेखित कर रहे हैं जब आप प्रदर्शन उसी टकराव में बाद में टकराव की जांच।
कुछ इस तरह का प्रयास करें - ताकि नियमित नहीं "भूल" है कि एक टक्कर का पता चला था कि यह एक ध्वज जोड़ता है:
private void checkBounds(Shape block) {
boolean collisionDetected = false;
for (Shape static_bloc : nodes) {
if (static_bloc != block) {
static_bloc.setFill(Color.GREEN);
if (block.getBoundsInParent().intersects(static_bloc.getBoundsInParent())) {
collisionDetected = true;
}
}
}
if (collisionDetected) {
block.setFill(Color.BLUE);
} else {
block.setFill(Color.GREEN);
}
}
ध्यान दें कि चेक आप कर रहे हैं (मूल में सीमा के आधार पर) होगा एक ही पैरेंट समूह के भीतर नोड्स की दृश्य सीमाओं को संलग्न आयत के चौराहे की रिपोर्ट करें।
वैकल्पिक कार्यान्वयन
मामले आपको इसकी आवश्यकता में, मैं अपने मूल नमूना अद्यतन इतना है कि यह दृश्य के बजाय दृश्य आकार का सीमांकन बॉक्स नोड के आकार के आधार पर जांच करने के लिए सक्षम है। यह आपको मंडलियों जैसे गैर-आयताकार आकारों के लिए टकराव का सटीक रूप से पता लगाने देता है। इसके लिए कुंजी Shape.intersects(shape1, shape2) विधि है।
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.util.ArrayList;
import javafx.scene.shape.*;
public class CircleCollisionTester extends Application {
private ArrayList<Shape> nodes;
public static void main(String[] args) { launch(args); }
@Override public void start(Stage primaryStage) {
primaryStage.setTitle("Drag circles around to see collisions");
Group root = new Group();
Scene scene = new Scene(root, 400, 400);
nodes = new ArrayList<>();
nodes.add(new Circle(15, 15, 30));
nodes.add(new Circle(90, 60, 30));
nodes.add(new Circle(40, 200, 30));
for (Shape block : nodes) {
setDragListeners(block);
}
root.getChildren().addAll(nodes);
checkShapeIntersection(nodes.get(nodes.size() - 1));
primaryStage.setScene(scene);
primaryStage.show();
}
public void setDragListeners(final Shape block) {
final Delta dragDelta = new Delta();
block.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
// record a delta distance for the drag and drop operation.
dragDelta.x = block.getLayoutX() - mouseEvent.getSceneX();
dragDelta.y = block.getLayoutY() - mouseEvent.getSceneY();
block.setCursor(Cursor.NONE);
}
});
block.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
block.setCursor(Cursor.HAND);
}
});
block.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
block.setLayoutX(mouseEvent.getSceneX() + dragDelta.x);
block.setLayoutY(mouseEvent.getSceneY() + dragDelta.y);
checkShapeIntersection(block);
}
});
}
private void checkShapeIntersection(Shape block) {
boolean collisionDetected = false;
for (Shape static_bloc : nodes) {
if (static_bloc != block) {
static_bloc.setFill(Color.GREEN);
Shape intersect = Shape.intersect(block, static_bloc);
if (intersect.getBoundsInLocal().getWidth() != -1) {
collisionDetected = true;
}
}
}
if (collisionDetected) {
block.setFill(Color.BLUE);
} else {
block.setFill(Color.GREEN);
}
}
class Delta { double x, y; }
}
नमूना प्रोग्राम आउटपुट। नमूने में सर्किलों को चारों ओर खींच लिया गया है और उपयोगकर्ता वर्तमान में एक सर्कल खींच रहा है जिसे किसी अन्य सर्कल (इसे नीले रंग से चित्रित करके) के साथ टकराने के रूप में चिह्नित किया गया है - प्रदर्शन उद्देश्यों के लिए केवल वर्तमान में खींचा जाने वाला सर्कल यह टकराव रंग है।
टिप्पणियां अतिरिक्त प्रश्न
लिंक मैं एक पूर्व टिप्पणी में एक intersection demo application पर पोस्ट किए गए के आधार पर नहीं बल्कि टक्कर पता लगाने नमूना की एक विशिष्ट प्रकार के रूप में की तुलना में विभिन्न सीमा प्रकार के उपयोग के उदाहरण देकर स्पष्ट करने के लिए था । आपके उपयोग के मामले में, आपको परिवर्तन श्रोता की अतिरिक्त जटिलता और विभिन्न प्रकार के सीमा प्रकारों की जांच करने की आवश्यकता नहीं है - बस एक प्रकार पर बसने के लिए पर्याप्त होगा। अधिकांश टकराव का पता लगाने के लिए केवल अन्य जावाएफएक्स सीमा प्रकारों जैसे कि लेआउट सीमा या नोड की स्थानीय सीमाओं के बजाय दृश्य सीमाओं के छेड़छाड़ में दिलचस्पी होगी। तो अगर आप कर सकते हैं: getBoundsInParent
के चौराहे (यदि आप अपने मूल प्रश्न में किया था के रूप में) जो छोटी से छोटी आयताकार बॉक्स जो नोड के दृश्य हाथ पैरों या
उपयोग Shape.intersect(shape1, shape2)
दिनचर्या अगर शामिल होगा पर काम करता है के लिए
- चेक आपको दृश्य आकार के बाध्यकारी बॉक्स की बजाय नोड के दृश्य आकार के आधार पर जांचना होगा।
मैं आयत
layoutX और layoutY गुण स्थिति या नोड्स बिछाने के लिए हैं के लिए setLayoutX या translateX प्रयोग करना चाहिए। translateX और अनुवाद वाई गुण नोड के दृश्य स्थान पर अस्थायी परिवर्तनों के लिए हैं (उदाहरण के लिए जब नोड एनीमेशन से गुजर रहा है)। आपके उदाहरण के लिए, यद्यपि कोई भी संपत्ति काम करेगी, फिर भी अनुवादकों की तुलना में लेआउट गुणों का उपयोग करने के लिए शायद यह बेहतर रूप है, इस तरह यदि आप नोड्स पर TranslateTransition जैसे कुछ चलाने के लिए चाहते हैं, तो यह और अधिक स्पष्ट होगा कि शुरुआत और अंतिम अनुवाद मान होना चाहिए क्योंकि वे मान मूल समूह की स्थिति के बजाय नोड की वर्तमान लेआउट स्थिति के सापेक्ष होंगे।
एक और तरीका है कि आप इन लेआउट का उपयोग कर सकते हैं और अपने नमूने में टंडेम में समन्वय का अनुवाद कर सकते हैं यदि आपके पास ड्रैग ऑपरेशन के दौरान रद्द करने के लिए ईएससी की तरह कुछ था। आप लेआउटएक्स, वाई को अपने नोड के शुरुआती स्थान पर सेट कर सकते हैं, एक ड्रैग ऑपरेशन शुरू करें जो अनुवादेटएक्स, वाई मान सेट करता है और यदि उपयोगकर्ता ईएससी दबाता है, तो अनुवादेटएक्स सेट करें, वाई को 0 पर ड्रैग ऑपरेशन रद्द करने के लिए या यदि उपयोगकर्ता माउस को रिलीज़ करता है लेआउटएक्स सेट करें, वाई लेआउटएक्स, वाई + ट्रांसलेटएक्स, वाई और अनुवाद अनुवादएक्स, वाई को वापस 0 पर सेट करें। विचार यह है कि अनुवाद का मान नोड के दृश्य समन्वय के अस्थायी संशोधन के लिए मूल लेआउट स्थिति से अस्थायी संशोधन के लिए किया जाता है।
सर्किल एनिमेटेड होने के बावजूद काम छेड़छाड़ करेगा? मेरा मतलब माउस द्वारा सर्कल खींचने के बिना, अगर मैं उन्हें यादृच्छिक रूप से घूमने के लिए बनाया तो क्या होगा। क्या इस मामले में रंग भी बदल जाएगा?
ऐसा करने के लिए, टकराव का पता लगाने के कार्य को कहां बुलाया जाता है और टक्कर हैंडलर को बुलाया जाता है। माउस ड्रैग इवेंट (ऊपर दिए गए उदाहरण की तरह) के आधार पर छेड़छाड़ की जांच करने के बजाय, प्रत्येक नोड के boundsInParentProperty()
पर एक परिवर्तन श्रोता के भीतर टकराव की जांच करें।
block.boundsInParentProperty().addListener((observable, oldValue, newValue) ->
checkShapeIntersection(block)
);
नोट: यदि आप आकार के पास बहुत एनिमेटेड किया जा रहा है, तो एक game loop भीतर एक बार फ्रेम प्रति टकराव के लिए जाँच एक टक्कर की जांच चलाने की तुलना में अधिक कुशल हो जाएगा जब भी कोई नोड चाल (के रूप में boundsInParentProperty परिवर्तन श्रोता में किया जाता है ऊपर)।
इस [चौराहे डेमो एप्लिकेशन] (https://gist.github.com/jewelsea/1441960) के साथ खेलने का प्रयास करें जिसे मैंने JavaFX में विभिन्न सीमा प्रकारों के छेड़छाड़ संबंधों को प्रदर्शित करने के लिए लिखा था। – jewelsea
ठीक है ऐसा लगता है कि मुझे अभी भी जो कुछ भी दिलचस्पी है उस फ़ाइल में पहली कक्षा में है। एक महत्वपूर्ण बात जो मैं उठाता हूं वह टकराव पर जांच के लिए बदल जाता है। चेक (??) पर लेआउटबाउंड का भी उपयोग करें। क्या मुझे आयत के लिए setLayoutX या translateX का उपयोग करना चाहिए? मुझे लगता है कि आप सेटएक्स का उपयोग कर रहे हैं, लेकिन यह निजी है जो मुझे लगता है और डॉक्टर पर यह स्पष्ट नहीं है कि सार्वजनिक विधि कौन सा विशेषता बदल रही है। – Giannis
अतिरिक्त प्रश्नों के समाधान के लिए अद्यतन उत्तर। – jewelsea