Kugelkolision
Kugelkolision
Hi, ich habe ein Kugelkolisionserkennung im Code-Archiv schon gefunden, aber die hat nur was mit Maus und Bildschirmrand zu tun, was ist wenn aber wo ein Hinderniss ist?
Und wie frag ich ab welches Hinderniss er berührt hat (Wie bei Pinball z.B. es ja verschiedene Sachen gibt die verschiedene Punkte bringen)
Und wie frag ich ab welches Hinderniss er berührt hat (Wie bei Pinball z.B. es ja verschiedene Sachen gibt die verschiedene Punkte bringen)

kreis-kreis-kollision ist einfach. ich habs mal in eine procedure aufgetrieselt damit man es besser lesen kann.
hab mich auch grad an kreis-rechteck versucht. komme aber nicht auf simple lösungen.
hab mich auch grad an kreis-rechteck versucht. komme aber nicht auf simple lösungen.
Code: Alles auswählen
InitSprite()
hWin=OpenWindow(0, 50,50,600,600, "")
OpenWindowedScreen( hWin, 0,0,600,600, 0,0,0)
Structure circleS
x.l
y.l
r.l
EndStructure
NewList c.circleS()
AddElement( c() )
c()\x=Random(500)+50
c()\y=Random(500)+50
c()\r=Random(20)+20
AddElement( c() )
c()\x=Random(500)+50
c()\y=Random(500)+50
c()\r=Random(20)+20
AddElement( c() )
c()\x=Random(500)+50
c()\y=Random(500)+50
c()\r=Random(20)+20
Procedure collCircCirc( x1,y1,r1, x2,y2,r2 )
dx= x1-x2
dy= y1-y2
distance= Sqr( dx*dx + dy*dy )
If distance < r1+r2
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
;MOUSE
m.circleS
m\r=50
Repeat
m\x=WindowMouseX(0)
m\y=WindowMouseY(0)
m\r+Random(2)-1
StartDrawing( ScreenOutput() )
coll=0
ForEach c()
If collCircCirc( m\x, m\y, m\r, c()\x, c()\y, c()\r )
DrawingMode(#PB_2DDrawing_Outlined)
coll=1
Else
DrawingMode(#PB_2DDrawing_Default)
EndIf
Circle( c()\x, c()\y, c()\r )
Next
If coll
DrawingMode(#PB_2DDrawing_Outlined)
Else
DrawingMode(#PB_2DDrawing_Default)
EndIf
Circle( m\x, m\y, m\r)
StopDrawing()
event=WindowEvent()
Select event
Case #PB_Event_CloseWindow
quit=1
EndSelect
FlipBuffers()
ClearScreen($333333)
Until quit
-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
bei kreis-rechteck würde ich zu beginn eine fallunterscheidung machen,
in welchem der 9 möglichen quadranten der kreismittelpunkt liegt,
dann weiß ich, mit welchen eckpunkten ich wie vergleichen muss.
@sen-me
meintest du denn überhaupt kreis-kollisionen?
...weil du kugel-kollision geschrieben hattest...
in welchem der 9 möglichen quadranten der kreismittelpunkt liegt,
dann weiß ich, mit welchen eckpunkten ich wie vergleichen muss.
@sen-me
meintest du denn überhaupt kreis-kollisionen?
...weil du kugel-kollision geschrieben hattest...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.
-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
also dochn kreis... kugel is 3D...
mit den segmenten meinte ich das so:
segment 5 entspricht der position des rechtecks.
je nachdem, in welchem segment sich der mittelpunkt des kreises befindet,
muss man nun unterschiedliche koordinaten-checks vornehmen.
Kx,Ky seien die koordinaten des kreismittelpunktes und R der radius.
in segment 1 z.b. macht man einen kreis-punkt-kollisionscheck für den Punkt x1,y1
für segment 2 überprüft man lediglich, ob der kreismittelpunkt weit genug oben liegt
für die anderen segmente funktioniert es analog.
in welchem segment sich der kreis befindet, ist auch einfach zu ermitteln:
und danach die fälle per Select/Case trennen...
mit den segmenten meinte ich das so:
Code: Alles auswählen
| |
1 | 2 | 3
| |
-----+-----+-----
| |
4 | 5 | 6
| |
-----+-----+-----
| |
7 | 8 | 9
| |
je nachdem, in welchem segment sich der mittelpunkt des kreises befindet,
muss man nun unterschiedliche koordinaten-checks vornehmen.
Kx,Ky seien die koordinaten des kreismittelpunktes und R der radius.
in segment 1 z.b. macht man einen kreis-punkt-kollisionscheck für den Punkt x1,y1
Code: Alles auswählen
dx = Kx -x1
dy = Ky -y1
distq = dx*dx+dy*dy
If distq < R*R
Collsision()
Code: Alles auswählen
If Ky > y1 - R
Collision()
in welchem segment sich der kreis befindet, ist auch einfach zu ermitteln:
Code: Alles auswählen
Segment = 5
If Kx < x1
Segment -1
ElseIf Kx > x2
Segment +1
EndIf
If Ky < y1
Segment -3
ElseIf Ky > y2
Segment +3
EndIf
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.
Öhm oookayy? ^^
Nix verstanden aber aufwenig erklärt ^^
Was sind segmente?
Nochmal:
Sagen wir in E ist der Kreis (er wird als Quadrat(10*10) gerechnet)
in A und C sind jedweils ein Quadrat (16*16)
In H befindet sich ein Rechteck (75*16)
Wir nehmen an, der Kreis würde sich auf A zubewegen, und dann nach C abprallen und wiederum nach H und dort abprallen.
Ich will nun wissen
1. Wie sich die Kugeln bewegen soll (Bewegung+Abprallen)
2. Ob er A, C, den Bildschirmrand oder sonst was berührt hat (also weiß auf was er kollidiert ist und dann zurückgibt z.B. A)
3. Wie er weiß (selbsständig) ob dort etwas zum abprallen ist (weil manche sachen bewegen sich wie z.B. H)
Dies hab ich aus dem Code-Archiv: (nur etwas umgeändert damit es auf PB4 geht)
Nix verstanden aber aufwenig erklärt ^^
Was sind segmente?
Nochmal:
Code: Alles auswählen
| |
A | B | C
| |
-----+-----+-----
| |
D | E | F
| |
-----+-----+-----
| |
G | H | I
| |
in A und C sind jedweils ein Quadrat (16*16)
In H befindet sich ein Rechteck (75*16)
Wir nehmen an, der Kreis würde sich auf A zubewegen, und dann nach C abprallen und wiederum nach H und dort abprallen.
Ich will nun wissen
1. Wie sich die Kugeln bewegen soll (Bewegung+Abprallen)
2. Ob er A, C, den Bildschirmrand oder sonst was berührt hat (also weiß auf was er kollidiert ist und dann zurückgibt z.B. A)
3. Wie er weiß (selbsständig) ob dort etwas zum abprallen ist (weil manche sachen bewegen sich wie z.B. H)
Dies hab ich aus dem Code-Archiv: (nur etwas umgeändert damit es auf PB4 geht)
Code: Alles auswählen
Global Dim diff_Kollision.w(3)
Global BallX.w : BallX = 10
Global BallY.w : BallY = 10
Global BallRateY.w : BallRateY = 4 ; Ball-Geschwindigkeit in Y-Richtung
Global BallRateX.w : BallRateX = 6 ; Ball-Geschwindigkeit in X-Richtung
Global BallDirY.w : BallDirY = -1 ; Y-Richtung
Global BallDirX.w : BallDirX = 1 ; X-Richtung
Global BallRadius.w : BallRadius = 10 ; Ball-Radius ist in Wirklichkeit ein Rechteck ;)
Global BlockXL.w ; Linke X-Kante des Blocks
Global BlockXR.w ; Rechte X-Kante des Blocks
Global BlockYT.w ; Obere Y-Kante des Blocks
Global BlockYB.w ; Untere Y-Kante des Blocks
Procedure Ball_Block_Kollision()
Shared BlockXL , BlockXR , BlockYT , BlockYB
Shared BallX , BallY , BallDirX , BallDirY
If BallX >= BlockXL-BallRadius And BallX <= BlockXR+BallRadius And BallY >= BlockYT-BallRadius And BallY <= BlockYB+BallRadius
diff_XL=BallX-BlockXL : diff_XR=BlockXR-BallX : diff_YT=BallY-BlockYT : diff_YB=BlockYB-BallY
diff_Kollision(0)=diff_XL : diff_Kollision(1)=diff_XR : diff_Kollision(2)=diff_YT : diff_Kollision(3)=diff_YB
SortArray(diff_Kollision(),0)
If diff_XL = diff_Kollision(0)
BallDirX = -1
ElseIf diff_XR = diff_Kollision(0)
BallDirX = 1
ElseIf diff_YT = diff_Kollision(0)
BallDirY = -1
ElseIf diff_YB = diff_Kollision(0)
BallDirY = 1
EndIf
EndIf
EndProcedure
InitSprite() : InitKeyboard() : InitMouse() : OpenScreen(640,480,16,"Ball") : SetFrameRate(60)
CreateSprite(1,20,20,#PB_Sprite_Texture) : TransparentSpriteColor(1,$000000)
StartDrawing(SpriteOutput(1))
Box(0,0,20,20,RGB(0,0,0))
Circle(10,10,10,RGB(255,0,0))
StopDrawing()
CreateSprite(2,40,40,0)
StartDrawing(SpriteOutput(2))
Box(0,0,40,40,RGB(0,0,0))
StopDrawing()
MouseLocate(300,300)
Repeat
ExamineKeyboard()
ExamineMouse()
; Block positionieren
BlockXL = MouseX()-20
BlockXR = MouseX()+20
BlockYT = MouseY()-20
BlockYB = MouseY()+20
; Ball-Bewegung
BallX = Int(BallX + BallRateX * BallDirX)
BallY = Int(BallY + BallRateY * BallDirY)
; Ball-Screen Kollision
If BallY <= 0
BallDirY = 1
EndIf
If BallY >= 480
BallDirY = -1
EndIf
If BallX <= 0
BallDirX = 1
EndIf
If BallX >= 640
BallDirX = -1
EndIf
; Ball-Block Kollision
Ball_Block_Kollision()
ClearScreen(RGB(100,100,100))
DisplayTransparentSprite(1,BallX-BallRadius,BallY-BallRadius)
DisplaySprite(2,BlockXL,BlockYT)
FlipBuffers()
Until KeyboardPushed(1)
CloseScreen()

-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
nein. das mittlere segment ist das rechteck.
so eine proc gibt NUR zurück, ob eine kollision stattgefunden hat oder nicht.
ich hab sie so wie bisher angedacht mal ausgeführt:
http://www.purebasic.fr/german/viewtopi ... 234#129234
die ermittlung, in welche richtung wie abgeprallt werden müsste, bedarf weiterer überlegungen.
> Wie er weiß (selbsständig) ob dort etwas zum abprallen ist (weil manche sachen bewegen sich wie z.B. H)
selbständig weiß ein computer nix...
das musst du alles einzeln programmieren...
> Dies hab ich aus dem Code-Archiv:
ähm.. im Code-Archiv ist aber zumindest nen kommentar dabei, was der code eigentlich tut...
so eine proc gibt NUR zurück, ob eine kollision stattgefunden hat oder nicht.
ich hab sie so wie bisher angedacht mal ausgeführt:
http://www.purebasic.fr/german/viewtopi ... 234#129234
die ermittlung, in welche richtung wie abgeprallt werden müsste, bedarf weiterer überlegungen.
> Wie er weiß (selbsständig) ob dort etwas zum abprallen ist (weil manche sachen bewegen sich wie z.B. H)
selbständig weiß ein computer nix...

das musst du alles einzeln programmieren...
> Dies hab ich aus dem Code-Archiv:
ähm.. im Code-Archiv ist aber zumindest nen kommentar dabei, was der code eigentlich tut...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.
hier noch eine etwas andere version. die 9 fälle werden zusammengefaßt/verallgemeinert. kann sein dass es lansgamer ist, weiß ich aber nicht.
Code: Alles auswählen
Procedure collCircRect(cx,cy,cr, x1,y1,x2,y2)
If x1>x2
Swap x1,x2
EndIf
If y1>y2
Swap y1,y2
EndIf
mx= (x1+x2)/2
my= (y1+y2)/2
dx= cx-mx
If dx<0 :: dx*-1 :: EndIf
dy= cy-my
If dy<0 :: dy*-1 :: EndIf
If mx+dx-cr > x2
ProcedureReturn #False
ElseIf my+dy-cr > y2
ProcedureReturn #False
Else
dx- (mx-x1)
dy- (my-y1)
If dx>0 And dy>0 And dx*dx+dy*dy > cr*cr
ProcedureReturn #False
EndIf
EndIf
ProcedureReturn #True
EndProcedure
-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
yo, mir aber nicht....sen-me hat geschrieben:Schon klar was es tut..

das abprallen von objekten wäre im endeffekt das einzige, was du brauchst...
auch deine maus wird im endeffekt ein objekt steuern,
und auch den bildrand könntest du als objekte definieren.
also bräuchtest du ein-e objekt-liste/-array,
und die kannst du mit einer schleife durchgehen, und auf kollisionen checken,
(irgendwie optimieren, dass nicht immer sämtliche objekte gecheckt werden müssen...)
bei jedem objekt wird dann entschieden, ob es auf circle-box oder auf circle-circle kollision geprüft wird.
und die kollisionsroutine könnte auch gleich den abprallwinkel zurückliefern,
dafür müsste sie dann dementsprechend etwas komplexer gestaltet werden...
aber das wäre dann schon das grundgerüst für einen flipper....
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.