[QUOTE=Marco13]Also, dann mal mangels JavaFX munter aus dem Bauch raus geraten - alles unter dem starken (!) vorbehalt, dass ich nicht sicher bin, wie die Tatsache, dass dort alles „Nodes“ eines Szenegraphen sind, diesen Test beeinflusst: Die Objekte haben jeweils „Bounds“ - also ein Rechteck, das ihre Position und Größe beschreibt. Vermutlich muss man sich die „local bounds“ beider Objekte abholen und sie mit Node#localToScene in ein gemeinsames Koordinatensystem transformieren. Dort kann man testen, ob sie sich überschneiden mit boundsA.intersects(boundsB). FALLS sie sich überschneiden, muss man den Überschneidungsbereich bestimmten. Auf die Schnelle hab’ ich da keine Methode dafür gesehen, gibt’s aber vermutlich (wenn nicht, ist es auch nicht so schwer, die selbst zu schreiben). Dieser Überschneidungsbereich (wieder ein Bounds) muss dann vermutlich mit Node#sceneToLocal wieder zurück ins lokale Koordinatensystem geholt werden - jeweils für jeden der beiden Knoten. Dann sollte dieser (ins lokale Koordinatensystem der Knoten transformierte) Überschneidungsbereich jeweils genau dem Bereich des „Images“ entsprechen, das im jeweiligen Knoten das Image des jeweils anderen Knotens schneidet. Und die Pixel, die in diesem Bildbereich liegen, kann man dann überprüfen, so wie es bei Quaxli auch gemacht wird.
Alles ohne Gewähr. Aber vielleicht teste ich es bei Gelegenheit mal. Wollte schon ewig mal "irgend"was mit JavaFX machen. Aber man kommt ja zu nix…[/QUOTE]
Klingt ziemlich rechenintensiv… Wenn ich sonst keine bessere Lösung finde werde ich das mal ausprobieren! Danke
[QUOTE=Melfis;86693]Das folgende Beispiel ist zwar weit weg vom Optimum verdeutlicht aber die Vorgehensweise:
- Intersection-Test zwischen den beiden Raumschiffen
- Wenn erfolgreich: überlappender Bereich berechnen
- jeweils Snapshots der Nodes im überlappender Bereich erstellen
- Pixel für Pixel auf Transperenz testen
Ich hab im Beispiel mit den BoundsInParent gearbeitet um relativ simple den Scale-Effekt einzubauen.
Pfeiltasten zum bewegen, NUM+/- zum vergrößern des Raumschiffs
Der Code läuft mit Java 8.
import javafx.geometry.Bounds;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.layout.TilePane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
/**
*
* @author Melfis
*/
public class Collosion extends Application {
@Override
public void start(Stage primaryStage) {
Image img_spaceship = new Image("http://staff.unak.is/andy/gameprogramming0910/bitMapGame/spaceship.png");
ImageView imgView_1 = new ImageView(img_spaceship);
ImageView imgView_2 = new ImageView(img_spaceship);
imgView_2.setX(50);
imgView_2.setY(100);
ImageView imgV_intersect_1 = new ImageView();
ImageView imgV_intersect_2 = new ImageView();
Circle int_point = new Circle(3, Color.TRANSPARENT);
int_point.setStroke(Color.RED);
int_point.setVisible(false);
BorderPane root = new BorderPane();
Pane pane = new Pane();
pane.setBorder(new Border(new BorderStroke(Color.GREEN, BorderStrokeStyle.SOLID, new CornerRadii(1), new BorderWidths(2))));
pane.setPrefSize(200, 200);
pane.setOnMouseClicked((MouseEvent me) -> {
pane.requestFocus();
});
Rectangle clip=new Rectangle();
clip.heightProperty().bind(pane.heightProperty());
clip.widthProperty().bind(pane.widthProperty());
pane.setClip(clip);
pane.getChildren().addAll(imgView_1, imgView_2, int_point);
pane.focusTraversableProperty().set(true);
VBox vb = new VBox();
Label lb_irec = new Label("Intersect Rec:");
Label lb_irec_result = new Label("-");
Label lb_ipx = new Label("Intersect Pixel:");
Label lb_ipx_result = new Label("-");
TilePane tp=new TilePane();
tp.setPrefTileHeight(40);
tp.setPrefTileWidth(40);
tp.getChildren().addAll(imgV_intersect_1, imgV_intersect_2);
vb.getChildren().addAll(lb_irec, lb_irec_result, lb_ipx, lb_ipx_result, tp);
pane.addEventHandler(KeyEvent.KEY_PRESSED, (KeyEvent ke) -> {
double speed = 5.0;
double scalerate = 1.1;
double scale = imgView_1.getScaleX();
double x = imgView_1.getX();
double y = imgView_1.getY();
if (ke.getCode() == KeyCode.UP) y -= speed;
if (ke.getCode() == KeyCode.DOWN) y += speed;
if (ke.getCode() == KeyCode.LEFT) x -= speed;
if (ke.getCode() == KeyCode.RIGHT) x += speed;
if (ke.getCode() == KeyCode.ADD) scale *= scalerate;
if (ke.getCode() == KeyCode.SUBTRACT) scale /= scalerate;
imgView_1.setX(x);
imgView_1.setY(y);
imgView_1.setScaleX(scale);
imgView_1.setScaleY(scale);
imgView_1.setScaleZ(scale);
Bounds b1 = imgView_1.getBoundsInParent();
Bounds b2 = imgView_2.getBoundsInParent();
boolean px_intersection = false;
boolean rec_intersection = b1.intersects(b2);
WritableImage intersect_img1 = null;
WritableImage intersect_img2 = null;
if (rec_intersection) {
//Überlappender Bereich
double min_x = b1.getMinX() > b2.getMinX() ? b1.getMinX() : b2.getMinX();
double max_x = b1.getMaxX() < b2.getMaxX() ? b1.getMaxX() : b2.getMaxX();
double min_y = b1.getMinY() > b2.getMinY() ? b1.getMinY() : b2.getMinY();
double max_y = b1.getMaxY() < b2.getMaxY() ? b1.getMaxY() : b2.getMaxY();
//Snapshot der beiden Nodes
SnapshotParameters ssp = new SnapshotParameters();
ssp.setFill(Color.TRANSPARENT);
Rectangle2D rec_clip=new Rectangle2D(min_x, min_y, max_x - min_x, max_y - min_y);
ssp.setViewport(rec_clip);
intersect_img1 = imgView_1.snapshot(ssp, null);
intersect_img2 = imgView_2.snapshot(ssp, null);
//Test der Transperenz
for (int j = 0; j < intersect_img1.getHeight(); j++) {
for (int i = 0; i < intersect_img1.getWidth(); i++) {
Color col_1 = intersect_img1.getPixelReader().getColor(i, j);
Color col_2 = intersect_img2.getPixelReader().getColor(i, j);
if (col_1.getOpacity() > 0.1 && col_2.getOpacity() > 0.1) {
px_intersection = true;
int_point.setCenterX(min_x + i);
int_point.setCenterY(min_y + j);
break;
}
}
if(px_intersection)break;
}
}
int_point.setVisible(px_intersection);
lb_irec_result.setText("" + rec_intersection);
lb_ipx_result.setText("" + px_intersection);
imgV_intersect_1.setImage(intersect_img1);
imgV_intersect_2.setImage(intersect_img2);
});
root.setBottom(vb);
root.setCenter(pane);
Scene scene = new Scene(root, 300, 300);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
```[/QUOTE]
Sieht sehr hilfreich aus :) Vielen vielen Dank!
Habe nach deinem Vorbild eine Kollisionscheck Methode erstellt, aber noch nicht getestet. Nochmals: Vielen Dank :D
Im Moment bin ich wirklich am Zweifeln... bringt es JavaFX wirklich?
Eine Menge der wichtigen Methoden von AWT/SWING fehlen einfach... Das meiste konnte ich zwar - wenn auch mit viel Arbeit - ersetzen aber ich frage mich ernsthaft ob sich das Ganze überhaupt lohnt...
Was mir zum Beispiel gerade Schwierigkeiten bereitet: Die Erstellung von "Subimages" aus einem Bild. Dafür gibt es (Zumindest habe ich noch keine entdeckt) einfach keine einfachen direkten Methoden!
Ich glaube ich höre wieder mit JavaFX auf... dafür aber noch eine Frage: Lassen sich JavaFX Elemente in ein Projekt mit AWT/Swing einbauen ohne große Performance Probleme zu bereiten?
Ich hatte hauptsächlich aufgrund der modernen Audio API mit JavaFX angefangen, und die würde ich gerne weiterhin irgendwie benutzen.