Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Jul 17, 2025 15:39

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Collision mal wieder
BeitragVerfasst: Fr Jan 27, 2006 14:41 
Offline
DGL Member

Registriert: Mo Jan 16, 2006 16:52
Beiträge: 20
Hallo, ich versuche zur Zeit mir eine eigene Collisionsfunktion zu schreiben, da ich bisher noch durch die Wände meiner Räume laufen kann. Die Funktion sieht zur Zeit so aus:

Code:
  1.  
  2. FUNCTION TForm1.Collision(posX,posZ:Single):Boolean;
  3. VAR
  4.   WallCount: Integer;
  5.   CollisionCount: Integer;
  6.   d: Single;
  7.   c: Single;
  8.   n: TVector;
  9.   M: TVector;
  10.  
  11.   FUNCTION Abstand(i:Integer):Single;
  12.     BEGIN
  13.       n.X := -WallVectors[i].Z;
  14.       n.Y := 0;
  15.       n.Z := WallVectors[i].X;
  16.       c := WallVectors[i].Start.X*n.X+WallVectors[i].Start.Z*n.Z;
  17.       Result := abs((1/sqrt(n.x*n.x+n.z*n.z))*(n.X*(posX/100)+n.Z*(posZ/100)+c));
  18.     END;
  19.  
  20.   FUNCTION CenterPoint:TVector;
  21.   VAR
  22.     t: Single;
  23.   BEGIN
  24.     t := (c-n.X*posX-n.Z*posZ)/(n.X*n.X+n.Z*n.Z);
  25.     Result.X := posX+t*n.X;
  26.     Result.Y := 0;
  27.     Result.Z := posZ+t*n.Z;
  28.   END;
  29.  
  30. BEGIN
  31.   CollisionCount := 0;
  32.   FOR WallCount := 0 TO High(WallVectors) DO BEGIN
  33.     d := Abstand(WallCount);
  34.     IF d < Radius THEN BEGIN
  35.       M := CenterPoint;
  36.       IF (M.X >= WallVectors[WallCount].Start.X) AND (M.X <= WallVectors[WallCount].Ende.X) AND
  37.           (M.Z >= WallVectors[WallCount].Start.Z) AND (M.Z <= WallVectors[WallCount].Ende.X) THEN
  38.         inc(CollisionCount);
  39.       END;
  40.     END;
  41.     IF CollisionCount > 0 THEN
  42.       Result := TRUE
  43.     ELSE
  44.       Result := FALSE;
  45. END;
  46.  


Zur Erklärung:
Mein Ansatz ist, dass ich auf Schnitt zwischen Kugel und Ebene prüfe. Die Ebene ist meine Wand und die Kugel (Radius = 1) bin ich selber. Nun gehe ich jede Wand durch und teste ob der Abstand von meiner Position zur Wand kleiner ist als mein Radius (Function Abstand). Ist dies der Fall, berechne ich mir den Mittelpunkt des entstandenen Schnittkreises (Function CenterPoint) und teste ob der Mittelpunkt auf der Wand liegt oder nur in der Ebene liegt. Das ganze ist im 3D Bereich. Wer sich jetzt wundert, wo die Y-Komponenten geblieben sind, Y ist immer 0 und das wird sich auch nie ändern.

Mein Problem ist nun, dass ich trotzdem noch durch meine Wände laufen kann. Kann mir einer sagen wo mein Fehler liegt?

mfg, Lt.Cmd.Data


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Jan 27, 2006 18:35 
Offline
DGL Member

Registriert: Mo Jan 16, 2006 16:52
Beiträge: 20
Hat denn keiner ne Idee? Oder ist mein Code unverständlich? Wenn ja, dann sagt es bitte. Versuche ihn dann nochmal genauer zu erklären.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Jan 27, 2006 20:33 
Offline
DGL Member
Benutzeravatar

Registriert: Di Nov 26, 2002 22:12
Beiträge: 259
Wohnort: Dresden
Was genau machst du denn, wenn du feststellst, dass eine Kollision stattgefunden hat?

Außerdem solltest du vielleicht darüber nachdenken Informationen zur kollidierenden Ebene zurückzuliefern um beispielsweise Sliding zu realisieren

_________________
Nichts auf der Welt ist so gerecht verteilt wie der Verstand. Denn jederman ist überzeugt, dass er genug davon habe.
Rene Descartes, frz. Mathematiker u. Philosoph, 1596-1650


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Jan 28, 2006 13:29 
Offline
DGL Member

Registriert: Mo Jan 16, 2006 16:52
Beiträge: 20
Aufrufen tu ich das ganze so:

Code:
  1.  
  2. procedure TForm1.CheckKeys;
  3. begin
  4.     if Keys[Ord('W')] then begin
  5.       IF Collision(abs((movX + Sin(-Rotate * (PI / 180)) * (1 * (100/Frames)))/100),
  6.                    abs((movZ + Cos(-Rotate * (PI / 180)) * (1 * (100/Frames)))/100)) = FALSE THEN BEGIN
  7.         movX:=movX + Sin(-Rotate * (PI / 180)) * (1 * (100/Frames));
  8.         movZ:=movZ + Cos(-Rotate * (PI / 180)) * (1 * (100/Frames));
  9.         Position.X := movX;
  10.         Position.Z := movZ;
  11.       END;
  12.     end;
  13.     if Keys[Ord('S')] then begin
  14.       IF Collision(abs((movX - Sin(-Rotate * (PI / 180)) * (1 * (100/Frames)))/100),
  15.                    abs((movZ - Cos(-Rotate * (PI / 180)) * (1 * (100/Frames)))/100)) = FALSE THEN BEGIN
  16.         movX:=movX - Sin(-Rotate * (PI / 180)) * (1 * (100/Frames));
  17.         movZ:=movZ - Cos(-Rotate * (PI / 180)) * (1 * (100/Frames));
  18.         Position.X := movX;
  19.         Position.Z := movZ;
  20.       END;
  21.     end;
  22.     if Keys[Ord('A')] then begin
  23.       IF Collision(abs((movX + sin((Rotate + 90) * pi / 180) * (1 * (100/Frames)))/100),
  24.                    abs((movZ - cos((Rotate + 90) * pi / 180) * (1 * (100/Frames)))/100)) = FALSE THEN BEGIN
  25.         movX := movX + sin((Rotate + 90) * pi / 180) * (1 * (100/Frames));
  26.         movZ := movZ - cos((Rotate + 90) * pi / 180) * (1 * (100/Frames));
  27.         Position.X := movX;
  28.         Position.Z := movZ;
  29.       END;
  30.     end;
  31.     if Keys[Ord('D')] then begin
  32.       IF Collision(abs((movX - sin((Rotate + 90) * pi / 180) * (1 * (100/Frames)))/100),
  33.                    abs((movZ + cos((Rotate + 90) * pi / 180) * (1 * (100/Frames)))/100)) = FALSE THEN BEGIN
  34.         movX := movX - sin((Rotate + 90) * pi / 180) * (1 * (100/Frames));
  35.         movZ := movZ + cos((Rotate + 90) * pi / 180) * (1 * (100/Frames));
  36.         Position.X := movX;
  37.         Position.Z := movZ;
  38.       END;
  39.     end;
  40. end;
  41.  


Über Sliding wollte ich mir erstmal keine Gedanken machen. Es reicht mir erstmal, wenn ich wenigstens nicht durch die Wände laufen kann.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jan 29, 2006 10:11 
Offline
DGL Member
Benutzeravatar

Registriert: Di Nov 26, 2002 22:12
Beiträge: 259
Wohnort: Dresden
Kann es sein, dass die Variablen movX und movY lokale Variablen sind und beim Aufruf der Collisionsfunktion noch nicht den korrekten Wert enthalten?

Ich kann nur spekulieren, weil ich nicht genau weiß, wie du deine Geometrie verwaltest. Ich verstehe z.B. nicht warum du in deiner Abstandsfunktion die neuen Positionsdaten mit 1/100 skalierst. Außerdem machst du es den Helfern leichter, wenn du bestimmte Funktionen wie z.B. VectorDotProduct etc. Verwendest, denn damit machst du den Code wesentlich übersichtlicher (Kommentare machen es sicher auch).

Aus dem Grund gebe ich dir einfach mal den Code, wie ich es machen würde.

Code:
  1.  
  2. //Ermittelt den Abstand zwischen einem Punkt und einer Ebene
  3. function Distance_Point_Plane(const Point, PlaneNormal:TVector3f; const PlaneOriginDist:Single):Single;
  4. begin
  5.   Result := VectorDotProduct(Point, PlaneNormal) + PlaneOriginDist;
  6. end;
  7.  
  8. //Prüft ob eine Ebene eine Kugel schneidet
  9. function Intersection_Plane_Sphere(const PlaneNormal, SphereCenter:TVector3f; const PlaneOriginDist, SphereRadius:Single; var Distance:Single):Boolean;
  10. begin
  11.   //Entfernung Kugelmittelpunkt-Ebene < Radius
  12.   Distance := Abs(Distance_Point_Plane(SphereCenter, PlaneNormal, PlaneOriginDist));
  13.   Result := Distance < SphereRadius;
  14. end;
  15.  
  16. //prüft ob eine Kugel eine Wand schneidet
  17. function Intersection_Sphere_Wall(const SphereCenter:TVector3f; const SphereRadius:Single; const Wall:PWall) : Boolean;
  18. var
  19.   Distance:Single;
  20.   Relative:TVector3f;
  21. begin
  22.   //Test ob die Kugel die Ebene schneidet
  23.   if not Intersection_Plane_Sphere(Wall^.Normal, SphereCenter, -VectorDotProduct(Wall^.Normal, Wall^.Min), SphereRadius, Distance) then
  24.     begin
  25.       Result := False;
  26.       Exit;
  27.     end;
  28.  
  29.   //Relative Position in der Wand
  30.   Relative := VectorAdd(SphereCenter, VectorMultiplyByScaler(VectorInvert(Wall^.Normal), Distance);
  31.  
  32.   //prüfen ob der relative Punkt in der Wand liegt
  33.   Result := ((Relative[X] >= Wall^.Min[X]) and (Relative[X] <= Wall^.Max[X])) and
  34.     (Relative[Z] >= Wall^.Min[Z]) and (Relative[Z] <= Wall^.Max[Z]));
  35. end;
  36.  
  37. function Collide : Boolean;
  38. var
  39.   i:Integer;
  40. begin
  41.   for i:=0 to High(WallVectors) do    
  42.     if Intersection_Sphere_Wall(SpielerPosition, SpielerRadius, @WallVectors[i]) then
  43.       begin
  44.         Result := True;
  45.         Exit;
  46.       end;
  47.   Result:=False;
  48. end;
  49.  


Da deine Geometrie statisch ist kannst du hier und da noch optimieren. Obgleich ich deinen konkreten Fehler nicht finden konnte hoffe ich, dass dir die Codesnippets etwas weiter helfen. Da deine Geometrie jedoch wirklich sehr einfach ist empfehle ich dir einfach mal im Compiler das Kollisionssystem Schritt für Schritt nachzuvollziehen. Das dürfte sich noch recht leicht machen lassen. Vielleicht stimmen ja bei dir die Normalen nicht oder ein anderer kleiner Fehler hat sich eingeschlichen.

_________________
Nichts auf der Welt ist so gerecht verteilt wie der Verstand. Denn jederman ist überzeugt, dass er genug davon habe.
Rene Descartes, frz. Mathematiker u. Philosoph, 1596-1650


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jan 29, 2006 14:28 
Offline
DGL Member

Registriert: Mo Jan 16, 2006 16:52
Beiträge: 20
Hi.
Erstmal danke für deine Hilfe. Ich denke ich habe den Fehler schon gefunden. Ich weiß nur noch nicht so genau wie ich ihn beheben soll. Aber da werde ich schon was finden.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 14 Queries | GZIP : On ]