Hi,
bisher habe ich für die Kollisionserkennung für jeden Eckpunkt jeder Fläche des Spielerobjektes überprüft, ob er sich in der Bounding Box des anderen Objektes befindet. Zusätzlich gab es für jeden Punkt auch noch 2 "Referenzpunkte" die auf der Kante der Fläche ein wenig verschoben waren, da an einen Punkt 3 Flächen grenzten. Es hat teilweise funktioniert, war aber total langsam und verbuggt.
Jetzt versuche ich es "einfach" über die x,y,z - Koordinaten und über die Breite, Höhe und Tiefe zu regeln. Meine grobe Kollisionserkennung, die überprüft, ob es überhaupt zu einer Kollision kommt, sieht z.B. so aus:
Mein Problem ist es allerdings nun herauszufinden, welche Seite mit dem anderen Objekt kollidiert. Der Code für die genauere Kollisionserkennung sieht zurzeit folgendermaßen aus:
An den Booleans in den If-Abfragen könnt ihr ja erkennen, für welche seite die Kollisionserkennung durchgeführt wird.
Ein paar kleine Anmerkungen zum Code:
- die Fläche der oberen und unteren "Kollisionsfläche" habe ich eingeschränkt, da ma ansonsten evtl. in einer Wand hängen bleibt (-> hängt mit meinem Problem zusammen)
- die Kollisionserkennung für die Seiten habe ich auch auf eine bestimmte Mindesthöhe begrenzt, da anonsten seitliche Kollisionen auftreten (hängt letztendlich auch mit dem Problem zusammen)
Das Problem ist, dass sich vor allem an den Seiten die "Kollisionsvolumen" überschneiden. D.h. wenn sich ein Block bewegt, gibt es bei jedem Durchlauf von der einen Position zur nächsten eine gewisse Lücke. Wenn z.B. ein Eckpunkt plötzlich rechts vorne innerhalb eines anderen Blocks ist, befindet er sich von den Koordinaten her an einer Stelle, durch die sowohl right, als auch front auf false gesetzt werden, obwohl sich der Block eigentlich rechts vom Spieler befindet. Dadurch kommt es zu sehr unschönen Hängern und ruckligen Bewegungen, wenn man an einer Wand entlanglaufen will.
Da es sich bei den Boundig Boxes um AABBs (Axis Aligned Boundig Boxes) handelt, darf aber bei einer einfachen Kollision des Spieler(-blocks) mit einem Block nur eine Bewegungsachse betroffen sein, bei meinem Beispiel sind aber fast immer 2 Achsen betroffen. (!= Sliding-Effekt an Wänden)
Wie könnte ich jetzt erkennen, an welcher Seite die Kollisionserkennung wirklich stattfindet?
(ja, ich weiß, dass es parrallel noch einen anderen Kollisionserkennungs-Threat gibt, mein Problem ist allerdings ein wenig spezifischer)
EDIT:
Das mit der Achsen-Bewegung habe ich beim Spieler übrigens ganz einfach so gelöst:
Nur damit das hoffentlich auch verständlich ist.
bisher habe ich für die Kollisionserkennung für jeden Eckpunkt jeder Fläche des Spielerobjektes überprüft, ob er sich in der Bounding Box des anderen Objektes befindet. Zusätzlich gab es für jeden Punkt auch noch 2 "Referenzpunkte" die auf der Kante der Fläche ein wenig verschoben waren, da an einen Punkt 3 Flächen grenzten. Es hat teilweise funktioniert, war aber total langsam und verbuggt.
Jetzt versuche ich es "einfach" über die x,y,z - Koordinaten und über die Breite, Höhe und Tiefe zu regeln. Meine grobe Kollisionserkennung, die überprüft, ob es überhaupt zu einer Kollision kommt, sieht z.B. so aus:
Java:
public boolean collisionTest(GameObject a, GameObject b)
{
if(b.getX() <= a.getX() + a.getWidth() && b.getX()+b.getWidth() >= a.getX())
{
if(b.getZ() <= a.getZ() + a.getDeep() && b.getZ()+b.getDeep() >= a.getZ())
{
if(b.getY() <= a.getY() + a.getHeight() && b.getY()+b.getHeight() >= a.getY())
{
return true;
}
}
}
return false;
}
Mein Problem ist es allerdings nun herauszufinden, welche Seite mit dem anderen Objekt kollidiert. Der Code für die genauere Kollisionserkennung sieht zurzeit folgendermaßen aus:
Java:
boolean top = true;
boolean bottom = true;
boolean front = true;
boolean back = true;
boolean right = true;
boolean left = true;
for(GameObject obj:objects)
{
if(collisiondetector.collisionTest(obj, mainplayer))
{
if(obj != mainplayer)
{
if(obj.isSolid())
{
if(obj.getY() <= mainplayer.getY()+mainplayer.getHeight() && obj.getY() > mainplayer.getY() + mainplayer.getHeight()/3*2)
{
if(obj.getX() <= mainplayer.getX() + mainplayer.getWidth() -0.2f && obj.getX()+obj.getWidth() >= mainplayer.getX() +0.2f)
{
if(obj.getZ() <= mainplayer.getZ() + mainplayer.getDeep() -0.2f && obj.getZ()+obj.getDeep() >= mainplayer.getZ() +0.2f)
{
top = false;
}
}
}
if(obj.getY()+obj.getHeight() >= mainplayer.getY() && obj.getY() < mainplayer.getY() + mainplayer.getHeight()/3)
{
if(obj.getX() <= mainplayer.getX() + mainplayer.getWidth() -0.2f && obj.getX()+obj.getWidth() >= mainplayer.getX() +0.2f)
{
if(obj.getZ() <= mainplayer.getZ() + mainplayer.getDeep() -0.2f && obj.getZ()+obj.getDeep() >= mainplayer.getZ() +0.2f)
{
//cam.forceSetY(mainplayer.getHeight()+obj.getY()+obj.getHeight());
bottom = false;
}
}
}
if( (obj.getY() >= mainplayer.getY() && obj.getY() <= mainplayer.getY() + mainplayer.getHeight()) ||
(obj.getY() + obj.getHeight() >= mainplayer.getY()+0.15f && obj.getY() + obj.getHeight() <= mainplayer.getY() + mainplayer.getHeight()) ||
(obj.getY() <= mainplayer.getY() && obj.getY() + obj.getHeight() >= mainplayer.getY() + mainplayer.getHeight()))
{
if(obj.getX() < mainplayer.getX() + mainplayer.getWidth()/2)
{
right = false;
}
if(obj.getX() > mainplayer.getX() + mainplayer.getWidth()/2)
{
left = false;
}
if(obj.getZ() < mainplayer.getZ() + mainplayer.getDeep()/2)
{
back = false;
}
if(obj.getZ() > mainplayer.getZ() + mainplayer.getDeep()/2)
{
front = false;
}
}
}
obj.collisionEvent();
}
}
}
An den Booleans in den If-Abfragen könnt ihr ja erkennen, für welche seite die Kollisionserkennung durchgeführt wird.
Ein paar kleine Anmerkungen zum Code:
- die Fläche der oberen und unteren "Kollisionsfläche" habe ich eingeschränkt, da ma ansonsten evtl. in einer Wand hängen bleibt (-> hängt mit meinem Problem zusammen)
- die Kollisionserkennung für die Seiten habe ich auch auf eine bestimmte Mindesthöhe begrenzt, da anonsten seitliche Kollisionen auftreten (hängt letztendlich auch mit dem Problem zusammen)
Das Problem ist, dass sich vor allem an den Seiten die "Kollisionsvolumen" überschneiden. D.h. wenn sich ein Block bewegt, gibt es bei jedem Durchlauf von der einen Position zur nächsten eine gewisse Lücke. Wenn z.B. ein Eckpunkt plötzlich rechts vorne innerhalb eines anderen Blocks ist, befindet er sich von den Koordinaten her an einer Stelle, durch die sowohl right, als auch front auf false gesetzt werden, obwohl sich der Block eigentlich rechts vom Spieler befindet. Dadurch kommt es zu sehr unschönen Hängern und ruckligen Bewegungen, wenn man an einer Wand entlanglaufen will.
Da es sich bei den Boundig Boxes um AABBs (Axis Aligned Boundig Boxes) handelt, darf aber bei einer einfachen Kollision des Spieler(-blocks) mit einem Block nur eine Bewegungsachse betroffen sein, bei meinem Beispiel sind aber fast immer 2 Achsen betroffen. (!= Sliding-Effekt an Wänden)
Wie könnte ich jetzt erkennen, an welcher Seite die Kollisionserkennung wirklich stattfindet?
(ja, ich weiß, dass es parrallel noch einen anderen Kollisionserkennungs-Threat gibt, mein Problem ist allerdings ein wenig spezifischer)
EDIT:
Das mit der Achsen-Bewegung habe ich beim Spieler übrigens ganz einfach so gelöst:
Java:
public void setX(float x)
{
if(x > campos.x)
{
if(left)
{
campos.x = x;
}
}
else
{
if(right)
{
campos.x = x;
}
}
}
public void setY(float y)
{
if(y > campos.y)
{
if(top)
{
campos.y = y;
}
}
else
{
if(bottom)
{
campos.y = y;
}
}
}
public void setZ(float z)
{
if(z > campos.z)
{
if(front)
{
campos.z = z;
}
}
else
{
if(back)
{
campos.z = z;
}
}
}
Zuletzt bearbeitet: