Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

11.03.2010, 22:12

Circle LineSeg Collision

Hallo Gemeinde,
derzeit sitzen wir an einem kleinem Spiel, was mit dem GameMake gemacht wird. Es ist ein Volleyballspiel, ähnlich BlobbyVolley, nur dass man auch auf die andere Seite des Netztes (also zum gegner) kann und auf dem netz "bouncen".
Da hängt das Problem. Für die Collisionsberechnung von Spieler (Kreis) und Netz nutzen wir im Moment einen Code, der mal in einem Flashforum aufgetaucht ist.
Zum besseren Verständnis des Problems, habe ich hier mal die aktuelle Spieledatei hochgeladen:
http://rapidshare.com/files/362047536/Sumos-0.1.exe.html
Man sollte einfach mal probieren auf dem Netz hin und her zu pendeln um sich immer höher zu bewegen (man braucht nicht "sprung" drücken, auf dem Netz passiert der Bounce von alleine)
Im Moment sieht diese Kollisionsberechnung dafür so aus:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// function CL_Intersect(argument0, arugment1)
{
    x0 = argument0.tempx;
    y0 = argument0.tempy;
    x1 = argument1.x1;
    y1 = argument1.y1;
    x2 = argument1.x2;
    y2 = argument1.y2;
    n = abs((x2-x1)*(y1-y0)-(x1-x0)*(y2-y1));
    d = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
    dist = n/d;
   if(dist > argument0.radius)      return false;
   
   d1 = sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
   if((d1-argument0.radius) > d)   return false;
   
   d2 = sqrt((x0-x2)*(x0-x2)+(y0-y2)*(y0-y2));
   if((d2-argument0.radius) > d)   return false;
   
   return true;
}


und die Reaction:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// function CL_Reaction(argument0, argument1)
{
   dx = 0;
   dy = 0;
   px = 0;
   py = 0;
   pen = 0;
 
   xx = argument0.tempx;
    yy = argument0.tempy;
    r = argument0.radius;
    x0 = argument1.x1;
    y0 = argument1.y1;
    x1 = argument1.x2;
    y1 = argument1.y2;
    lx = x1 - x0;   //lx,ly is a vector parallel to the line
   ly = y1 - y0;
   len = sqrt(lx*lx + ly*ly);
   if(len == 0)
   {
      return 0;
   }
    rx = lx/len;   //rx,ry is the unit direction vector of the lineseg
    ry = ly/len;
   
    nx = -ry;   //nx,ny is a vector perpendicular to the line
    ny = rx;
   
    dx = (xx - x0);   //dx,dy is the vector from x0,y0 to the circle
    dy = (yy - y0);

    dpPerp = dx*rx + dy*ry;   //length of dx,dy projected onto the lineseg's direction
   if(dpPerp < 0)
   {
      //circle is closer to the endpoint x0,y0 than the line, project out of point x0,y0
       len = sqrt(dx*dx + dy*dy);
       pen = r - len;
      if(0 < pen)
      {
         //project out of the endpoint
         dx /= len;
         dy /= len;
         px = dx*pen;
         py = dy*pen;   
      }
   }
   else
   {
      if(len < dpPerp)
      {
         //circle is closer to the endpoint x1,y1 than the line, project out of point x1,y1
         dx -= lx;   //dx,dy is now the vector from x1,y1 to the circle
         dy -= ly;
         len = sqrt(dx*dx + dy*dy);
         pen = r - len;
         if(0 < pen)
         {
            //project out of the endpoint
            dx /= len;
            dy /= len;            
            px = dx*pen;
            py = dy*pen;
         }
         
      }
      else
      {
         //circle is closer to the lineseg; project out of it
         dp = dx*nx + dy*ny;//dp is length of dx,dy when measured/projected onto the line's normal
         
         pen = abs(dp) - r;
         if(pen < 0)
         {
            //circle is inside the line; project it out along the normal
            if(0 < dp)
            {
               //circle is on the RHside of the line, should be projected out the +ve normal
               pen *= -1;      
            }
             px = nx*pen;//px,py is the penetration vector which pushes the circle out of the line
             py = ny*pen;
         }               
      }
   }

   argument0.vel_x += px;
    argument0.vel_y += py;      
}


Das ganze System funktioniert auch ganz gut und es ist so, wie wir uns das vorstellen. Allerdings sind die "Bounces" also die rückschläge vom netz noch zu stark. Mann sollte nicht mit so einer hohen Geschwindigkeit zurückgeschleudert werden sondern anfangs "sachter".

Vielleicht kann uns jemand hier einen Tipp geben? Ist diese Kollisionsberechnung überhaupt so sinnvoll (denn es geht ja hier auch um eine gewisse "Eindringtiefe")

Vielen Dank schonmal.

Gruß[/code]

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

2

11.03.2010, 22:16

Ich habe mir den Code jetzt nicht genau angschaut, aber warum machst du die Stärke des Rückstosses nicht abhängig von der Geschwindigkeit?

3

11.03.2010, 22:43

Welche Geschwindigkeit meinst genau?
Das Problem, ist, dass ich über diesen Code da oben, einfach nicht die Stärke varieren kann :-/

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

4

11.03.2010, 23:15

Naja, wenn du einigermassen realistisches Verhalten haben willst, dann kommst du nicht drum herum da Masse und Geschwindigkeit rein zu bringen.

Siehe dazu:
http://de.wikipedia.org/wiki/Sto%C3%9F_%28Physik%29

5

11.03.2010, 23:18

Also wie gesagt, die Sache da oben funktioniert ja, allerdings sind die Rückschläge vom Netz noch zu stark. Ich weiß leider nicht (mir fehlt warscheinlich auch das mathematische Talent), wie ich diese kleiner machen kann aus dem Code von oben.

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

6

11.03.2010, 23:22

Naja. px und py verändern dir Geschwindigkeit, wenn ich das da richtig herauslese. Also musst du da halt einen Faktor abziehen oder so.

7

11.03.2010, 23:30

Ja, habe ich schon probiert, ziehe ich da allerdings um eine feste Zahl ab oder addiere hinzu, stimmt das ganze System überhaupt nicht mehr wirklich, und die Bounces werden nicht wirklich weniger.

8

12.03.2010, 16:43

Gibt es sonst noch eine Möglichkeit, dass ganze etwas zu reduzieren?
Wenn nicht, gibt es eine andere Engine, die das gleich bewirkt, wo aber einzelne Dinge besser zu bearbeiten sind?

Grüße Paul

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

9

12.03.2010, 17:02

Du könntest z.B Box2D benutzen:
http://www.box2d.org/

10

12.03.2010, 17:09

Ich finde es spielt sich spaßiger wenn der Überbounce erhalten bleibt. Sieht wohl nur nach einem Rechenfehler aus. Willst du, dass du dort stehen bleibst, so musst du einfach noch eine Art Reibung mit berücksichtigen, welche du anhand der aktuellen Geschwindigkeit/Kollidionsvektor berechnest. So oder so eine Reibung würde die Abpraller sanfter machen und bei Bodenkontrakt zu einem schnelleren Stillstand führen.

Werbeanzeige