Rectangle Runde Hitbox

RegenSonne

Aktives Mitglied
Hallo, ich habe ein kleines Spiel gemacht.. nur die Hitbox ist ein Quadrat.. obwohl mein Bild n kreis ist... Vermutlich wird auch der Alpha Kanal als bild gewertet? wie kann ich das umgehen.. dass eben nur der kreis als hitbox dient.

Ausschnitt:

Java:
  r1 = new Rectangle(Draw.ballx, Draw.bally, Draw.rectbs, Draw.rectbs);
  for (int i = 0; i < 25; i++) {
   r2 = new Rectangle(CreateGegner.gx[i], CreateGegner.gy[i], 10, 10);
   if (r1.intersects(r2)) {
    col[i] = true;
   } else {
    col[i] = false;
   }
  }

Die Gegner passen so perfekt..


Lg und danke für eure Hilfe! :)
 

RegenSonne

Aktives Mitglied
Ich habe pngs als kreis aber ich meinte wie ich die hitbox als kreis mache..

Ich schau mir den beitrag von graphics aber mal an ^^

Lg
 

Harry Kane

Top Contributor
Ich habe pngs als kreis
Hier liegt offenbar ein grundsätzliches Missverständnis vor.
Ein Kreis, der in einem PNG gezeichnet wird, ist etwas vollkommen anderes als ein "kreisförmiges PNG". Letzteres gibt es nicht. Ein PNG (oder allgemein, ein Image) ist etwas rechteckiges. Wenn von dem Rechteck nur bestimmte Pixel zählen sollen, musst du wohl die dafür notwendige Kollionsabfrage unter Berücksichtigung der Pixeleigenschaften selber programmieren.
 

Blender3D

Top Contributor
Wenn du berechnen willst ob zwei Kreise sich berühren. Berechne einfach den Abstand der Mittelpunkte.
distance = distancePoints( M1, M2 );
sumRadius = R1+R2;
distance > sumRadius -> keine Kollision
distance = sumRadius -> Berührung
distance < sumRadius -> Kollision
Code:
// Calculates distance between 2 points.
double distancePoints( Point p1, Point p2 ){
    return Math.sqrt(Math.pow( p2.x - p1.x ) + Math.pow(p2.y - p1.y ));
}
;)
 

Thallius

Top Contributor
Naja einfacher ist es das Bild als Maske zu benutzen und die Hitbox durch eine Pixelfarbe zu definieren. Damit kann man mit ganz wenig Aufwand beliebig komplexe Hitboxen erstellen indem man sie einfach malt.

Gruß

Claus
 

JuKu

Top Contributor
@Thallius Das was du meinst ist leider recht ineffizient, da du kaum erkennen kannst, dass es sich auf dem Bild um einen Kreis handelt (es sei denn, dein Programm ist echt so intelligent), stattdessen müsstest du dann mit vielen kleinen Polygnen arbeiten. Und das wiederum benötigt sehr viel Performance.
 

Thallius

Top Contributor
@Thallius Das was du meinst ist leider recht ineffizient, da du kaum erkennen kannst, dass es sich auf dem Bild um einen Kreis handelt (es sei denn, dein Programm ist echt so intelligent), stattdessen müsstest du dann mit vielen kleinen Polygnen arbeiten. Und das wiederum benötigt sehr viel Performance.

Wie kommst du denn auf das schmale Brett. Mal einen schwarzen Kreis auf weißen Grund und dann mach daraus ein Image. Nun kann ich für jede Koordinate mit einer Abfrage feststellen ob diese im Kreis liegt oder nicht. Schneller geht es überhaupt nicht.
 

mrBrown

Super-Moderator
Mitarbeiter
Wie kommst du denn auf das schmale Brett. Mal einen schwarzen Kreis auf weißen Grund und dann mach daraus ein Image. Nun kann ich für jede Koordinate mit einer Abfrage feststellen ob diese im Kreis liegt oder nicht. Schneller geht es überhaupt nicht.
Du musst dann Pixelweise prüfen, fällt dir etwa noch was ineffizienteres ein? ;)
 

JuKu

Top Contributor
Du musst dann Pixelweise prüfen, fällt dir etwa noch was ineffizienteres ein? ;)

Dem ist ja eig. schon nichts mehr hinzuzufügen.

@Thallius Diese Behauptung ist leider Quatsch, da du zwar eine Hülle um das komplexe Polygon ziehen kannst (und somit nicht jedes mal alles berechnen musst), aber sobald das Objekt die Hülle durchschreitet, musst du, wie @mrBrown es bereits gesagt hat, Pixelweise prüfen.

@RegenSonne
Die effizienteste Lösung wäre es, einen Kreis zu nehmen und diesen gar nicht erst aus dem Bild zu generieren, sondern lediglich den Radius in irgendeine Datei zu schreiben und dann den Kreis mittig auf das Bild zu zentrieren.
 

Thallius

Top Contributor
Sorry erklärt mir einer eure Denkweise? Wenn ich das Bild als bifferdImage habe, dann mache ich eine einzige Abfrage auf den Pixelwert der Koordinate von der ich wissen will ob sie im Kreis liegt oder nicht. Das ein einziger Speicherzugriff auf einen Speicherblock im Heap. Das Schaft jeder Prozessor in einem Taktzyklus. Wie willst du das mit irgendwelchen polygonberechnungen schneller hinbekommen?
 

mrBrown

Super-Moderator
Mitarbeiter
In den meisten Fälle reicht dir nicht zu wissen, ob irgendein Pixel mit der Hitbox kollidiert, sondern ob zwei Hitboxen miteinander kollidieren.
 

JuKu

Top Contributor
Wenn ich das Bild als bifferdImage habe, dann mache ich eine einzige Abfrage auf den Pixelwert der Koordinate von der ich wissen will ob sie im Kreis liegt oder nicht.

Angenommen die Texture sieht so aus (gelb):

hn.PNG

Du kannst aber eben nicht (es sei denn, dein Programm ist super intelligent, wovon ich nicht ausgehe!) erkennen, dass es sich bei dieser Grafik (gelb) um einen Kreis handelt! Für den Computer kannst du das nur durch einzelne Linien / Polygone (rote Linien) approximieren. Und dann prüfst du ja auch nicht nur einen Pixel deines Charakters, sondern du willst ja wissen, ob irgendein Pixel deines Charakters im Kreis liegt!
D.h. du müsstest nach deiner Methode alle Pixel des Charakters mit der Hitbox des Kreises abgleichen. Und das ist eben ineffizient.

Fakt ist: Du hast diesen Kreis nicht, von dem du die ganze Zeit ausgehst!
Wenn du nicht gerade ein neuronales Netz hast, welches diesen erkennt, dann ist es dir nahezu unmöglich (es sei denn, er ist irgendwie zentriert, aber das ist ein anderes Thema), zu erkennen, dass es sich um einen Kreis in der Grafik handelt! Und das ist nicht mal gegeben, der Thread Ersteller hat "Runde Hitbox" und nicht Kreis geschrieben, d.h. es kann sich auch um ein Ei handeln o.ä.
Er hat lediglich eine Grafik und will daraus eine Hitbox generieren. Und da kommst du höchstens auf Polygone.
 

Blender3D

Top Contributor
Er hat lediglich eine Grafik und will daraus eine Hitbox generieren. Und da kommst du höchstens auf Polygone.
Das ist eine Variante die sehr gut funktioniert.
Bau Dir eine Klasse z.B. Sprite. die beinhaltete ein Image, Koordinaten usw. und ein Polygon als Hitbox.
Default = Rechteck. für genauere Kollisionsabfrage gib ein Polygon an. ( Mittels Grafikprogramm kannst Du die Koordinaten des Polygons ermitteln.) --> sehr genaue Kollision.
Ich habe das bereits für einige Spiele verwendet. funktioniert sehr effizient.
;)
Wenn Du nur Kreise hast dann verwende meinen Vorschlag wie oben beschrieben.
 

Thallius

Top Contributor
Ich bin jetzt hier raus. Ihr konstruiert gerade irgendwas um eure Meinung zu rechtfertigen ohne auch nur ansatzweise auf die Aufgabenstellung des TO einzugehen...
 

InfectedBytes

Top Contributor
Aus dem Anfangspost geht hervor das er einen "ball" mit "gegnern" kollidieren lassen möchte. Der Ball wird garantiert ein Kreis sein und die Gegner höchstwahrscheinlich Rechtecke und/oder Kreise. Falls sie doch komplizierte Figuren darstellen, ist es vermutlich mehr als ausreichend diese per Rechteck zu approximieren, falls sie dennoch genauer kollidieren sollen -> Polygone.

Falls die Gegner Kreise sind:
Distanz der Kreiszentren vergleichen, falls diese kleiner als die Summe der Radien ist -> Kollision

Falls die Gegner Rechtecke sind:
Am besten zwei schrittig vorgehen. Erstmal so tun als wäre der Kreis ein Rechteck, falls sich diese Rechtecke nicht berühren, ist man fertig (fail-fast). Falls sich diese jedoch berühren, musst du etwas aufwendiger die Kreis-Rechteck Kollision prüfen: Am "einfachsten" indem du jeweils auf Kollision mit den einzelnen Kanten des Rechtecks prüfst.

Eine Pixelgenaue Überprüfung sollte definitiv vermieden werden, da dass ewig langsam ist, denn dann müsste man die "Kollisionsbilder" (schwarz=nichts, weiß=Objekt) entsprechend ihrer positiv quasi übereinander legen und per &-Operation "zeichnen", in dem resultierenden Bild würde jeder weiße Pixel eine überlappung darstellen. => Pixel für Pixel durchgehen und prüfen ist nunmal etwas das sehr lange dauert, insbesondere bei großen Bilder. Um es zumindest etwas schneller zu machen, sollte man definitiv vorher auf Rechteck Kollision prüfen (fail-fast) und nur das überlappende Rechteck Pixelgenau prüfen.
 

Blender3D

Top Contributor
Falls die Gegner Rechtecke sind:
Am besten zwei schrittig vorgehen. Erstmal so tun als wäre der Kreis ein Rechteck, falls sich diese Rechtecke nicht berühren, ist man fertig (fail-fast). Falls sich diese jedoch berühren, musst du etwas aufwendiger die Kreis-Rechteck Kollision prüfen: Am "einfachsten" indem du jeweils auf Kollision mit den einzelnen Kanten des Rechtecks prüfst.
Ich verwende Rechtecke ob zu testen, ob eine Kollision infrage kommt. Falls ja genauerer Check, wenn gewünscht.
;)
 

RegenSonne

Aktives Mitglied
Ja es sind alles Kreise. Ich probiereal das was @InfectedBytes gesagt hat...

Wo ich gerade im Chat bin, kennt jemand ein gutes Tutorial für OpenGL? Wollte das Mal ausprobieren ^^ LG und danke an alle Antworter ^^
 

Ähnliche Java Themen


Oben