  | 
					
						Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!   
						
						
					 | 
				 
			 
			 
	
		| Vorheriges Thema anzeigen :: Nächstes Thema anzeigen   | 
	 
	
	
		| Autor | 
		Nachricht | 
	 
	
		0oFreako0
 
 
  Anmeldungsdatum: 17.12.2011 Beiträge: 114
 
  | 
		
			
				 Verfasst am: 01.03.2015, 17:05    Titel: Winkel und Kollisions Frage | 
				     | 
			 
			
				
  | 
			 
			
				Hi ich stehe vor 2 Problemen das erste ist wie setze ich genau eine Kreiskollision um ich arbeite im moment mit einer Box Kollsion die auf Runden objekten aber nicht so toll aussieht.
 
 
Die 2. Frage ist ich wollte eine Kugel in einem bestimmten Winkel abschiessen wie kann ich ihn anhand der x und y koordiaten der Maus ermitteln?
 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Eternal_pain
 
  
  Anmeldungsdatum: 08.08.2006 Beiträge: 1783 Wohnort: BW/KA
  | 
		
			
				 Verfasst am: 01.03.2015, 18:10    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Zu1. 
 
Müsste so klappen (nicht vollständig getestet)
 
 
Edit: Fehler beseitigt + Beispiel
 
http://www.freebasic-portal.de/porticula/kreis-kollision-test-1795.html
 
 
 
 
Nicht perfekt so gibt es noch ein paar Physikalische Fehler so das bei einer Kollision beide Bälle 'stecken' bleiben...
 
Lässt sich aber sicher noch gut verbessern und erweitern
 
 
 	  | Code: | 	 		  'QUELLE: https://www.spieleprogrammierer.de/wiki/2D-Kollisionserkennung#Kollision_zwischen_zwei_Kreisen
 
 
'' Kollision zwischen zwei Kreisen
 
 
'' Wenn die Distanz zwischen den Mittelpunkten zweier Kreise kleiner ist als die Summe ihrer Radien,
 
'' so liegt eine Kollision vor. Also benötigen wir zum Prüfen der Kollision die Positionen und
 
'' Radien der beiden Kreise. Dabei rechnen wir mit Hilfe des Satz des Pythagoras die Distanz zwischen
 
'' den beiden Kreisen aus und prüfen zum Schluss, ob diese kleiner ist als die Summe beider Radien. 
 
 
#Define Delta(X1,Y1,X2,Y2) int(sqr(((X1-X2)*(X1-X2))+((Y1-Y2)*(Y1-Y2))))
 
 
 
Dim as Integer Punkt1_X = 100, Punkt1_Y = 100, Radius1 = 5
 
Dim as Integer Punkt2_X = 100, Punkt2_Y = 150, Radius2 = 1
 
 
Dim as Integer Dist
 
Dist = Delta(Punkt1_X,Punkt1_Y,Punkt2_X,Punkt2_Y) 'Entfernung beider mittelpunkte
 
 
If Dist < (Radius1+Radius2) Then 
 
    ?"Kollision"
 
Else
 
    ?"Keine Kollision"
 
End If
 
 
sleep
 
 | 	  
 
 
Alternative könnte vielleicht auch das helfen
 
http://www.freebasic-portal.de/code-beispiele/grafik-und-fonts/fbimage-sprite-pixelkollision-280.html
 
 
Zu 2.
 
In diesem Beispiel hab ich das mal versucht, dabei ist der Winkel 0° oben (und nicht wie sonst rechts...) 
 
 
 	  | Code: | 	 		  'Winkel zwischen zwei punkten....
 
 
Const Rad2Deg   as Double  = 45.0/Atn(1)
 
 
Dim as Integer Punkt1_X = 100, Punkt1_Y = 100
 
Dim as Integer Punkt2_X = 100, Punkt2_Y = 150
 
 
?((atan2(Punkt2_Y-Punkt1_Y,Punkt2_X-Punkt1_X)*Rad2Deg)+90)
 
 
sleep | 	 
  _________________
  
  Zuletzt bearbeitet von Eternal_pain am 02.03.2015, 07:40, insgesamt 2-mal bearbeitet | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Muttonhead
 
  
  Anmeldungsdatum: 26.08.2008 Beiträge: 571 Wohnort: Jüterbog
  | 
		
			
				 Verfasst am: 01.03.2015, 18:51    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				der erste Teil beinhaltet ein kleine Bibliothek mit ein paar mathematischen Krücken die auch helfen könnten, die meisten davon sind mit Sicherheit optimierungswürdig und eher meinem Verständnis der Materie geschuldet:
 
 	  | Code: | 	 		  
 
'******************************************************************************
 
'******************************************************************************
 
'******************************************************************************
 
 
const as single doublepi  =atn (1) * 8
 
const as single pi        =atn (1) * 4
 
const as single halfpi    =atn (1) * 2
 
const as single quarterpi =atn (1)
 
'******************************************************************************
 
type vector
 
  x as single
 
  y as single
 
end type
 
 
'******************************************************************************
 
 
 
 
'bringt ein Bogenmaß in den Bereich von 0 bis 2PI
 
'! BYREF es wir die übergebene Variable verändert
 
sub RadCorrected (byref Rad as single)
 
  if Rad>=doublepi then Rad=Rad-doublepi
 
  if Rad<0 then Rad=doublepi+Rad
 
end sub
 
 
 
 
'liefert Entfernung 2er Ortsvektoren nach Pythagoras
 
function GetDistance(origin as vector, dest as vector) As Single
 
  dim as single dx,dy
 
  dx=dest.x - origin.x
 
  dy=dest.y - origin.y
 
  function=sqr(dx*dx + dy*dy)
 
end function
 
 
 
 
'liefert das Quadrat der Entfernung 2er Ortsvektoren nach Pythagoras, erspart SQR
 
function GetDistanceP2(origin as vector, dest as vector) As Single
 
  dim as single dx,dy
 
  dx=dest.x - origin.x
 
  dy=dest.y - origin.y
 
  function=dx*dx + dy*dy
 
end function
 
 
 
 
'Richtung (als Bogenmaß) des Punktes dest vom Standpunkt origin (wird zum Ursprung) aus betrachtet
 
function GetRad overload(origin as vector,dest as vector) as single
 
  dim as single Rad
 
  dim as vector d
 
  d.x= dest.x - origin.x
 
  d.y= dest.y - origin.y
 
  Rad=atan2(d.y,d.x)
 
  if sgn(Rad)=-1 then Rad= doublepi + Rad
 
  function=Rad
 
end function
 
 
 
 
'wandelt einen Richtungsvektor zu Bogenmaß (vom Koordinatenursprung aus gesehen)
 
function GetRad (v as vector) as single
 
  dim as single Rad=atan2(v.y,v.x)
 
  if sgn(Rad)=-1 then Rad= doublepi + Rad
 
  function=Rad
 
end function
 
 
 
 
'liefert den Winkel den 3 Punkte(Vektor) bilden als Bogenmaß
 
'man beachte, GetRad liefert immer den (vom ersten Schenkel aus gesehenen!!!) Winkel mit positiver Drehrichtung:
 
'GetRad(A,B,C)
 
'1.Schenkel AB
 
'Scheitelpunkt B
 
'2. Schenkel BC
 
'<-- =zurückgegebener Winkel
 
'     C
 
'      \
 
'       \<---
 
'        \   \
 
' A-------B   \
 
'      |      /
 
'       \____/
 
'
 
'GetRad(C,B,A)
 
'1.Schenkel CB
 
'Scheitelpunkt B
 
'2. Schenkel BA
 
'<-- =zurückgegebener Winkel
 
'     C
 
'      \
 
'      /\
 
'     v  \
 
' A-------B
 
function GetRad (A as vector, B as vector, C as vector) as single
 
  dim as single BA_Rad,BC_Rad,ABC_Rad
 
  dim as vector d  
 
  
 
  'Variante A
 
  'BA_Rad=GetRad(b,a)
 
  'BC_Rad=GetRad(b,c)
 
  'ABC_Rad=BC_Rad-BA_Rad
 
  'if sgn(ABC_Rad)=-1 then ABC_Rad +=doublepi
 
  
 
  'Variante B
 
  'sollte etwas schneller sein
 
  d.x= a.x - b.x
 
  d.y= a.y - b.y  
 
  BA_Rad=atan2(d.y,d.x)
 
  d.x= c.x - b.x
 
  d.y= c.y - b.y  
 
  BC_Rad=atan2(d.y,d.x)  
 
  ABC_Rad=BC_Rad - BA_Rad
 
  if sgn(ABC_Rad)=-1 then ABC_Rad= doublepi + ABC_Rad
 
  
 
  function=ABC_Rad
 
end function
 
 
 
 
'wandelt Bogenmaß zu Richtungsvektor
 
'distance stellt ein Skalar dar, der optional benutzt werden kann
 
function GetVector overload(Rad as single,distance as single=1) as vector
 
  dim as vector v
 
  RadCorrected(Rad)
 
  v.x=cos(Rad)*distance
 
  v.y=sin(Rad)*distance
 
  function=v
 
end function
 
 
 
 
'Liefert die Richtung zu dest als Vector mit Länge 1
 
'eine Lösung ohne Längenermittlung und Wurzelziehen, vermutlich nicht schneller
 
function GetVector (origin as vector,dest as vector) as vector
 
  dim as single Rad
 
  dim as vector d
 
  d.x= dest.x - origin.x
 
  d.y= dest.y - origin.y
 
  Rad=atan2(d.y,d.x)
 
  if sgn(Rad)=-1 then Rad= doublepi + Rad
 
  'Vektor d brauchen wir nicht mehr und nutzen ihn anders:
 
  d.x=cos(Rad)
 
  d.y=sin(Rad)
 
  'd zeigt immernoch von origin aus gesehen in Richtung dest, hat aber jetzt die Länge von 1
 
  function=d
 
end function
 
 
 
 
'liefert die nach links zeigende Normale als Vektor mit Länge 1
 
function GetLeftNormal (origin as vector,dest as vector) as vector
 
  dim as single Rad
 
  dim as vector d
 
  d.x= dest.x - origin.x
 
  d.y= dest.y - origin.y
 
  Rad=atan2(d.y,d.x)
 
  if sgn(Rad)=-1 then Rad= doublepi + Rad
 
 
  'Vektor d brauchen wir nicht mehr und nutzen ihn anders:
 
  'd.x=cos(Rad)
 
  'd.y=sin(Rad)
 
  'd zeigt immernoch von origin aus gesehen in Richtung dest, hat aber jetzt die Länge von 1
 
  'Normale nach links:
 
  'dim as vector n
 
  'n.x=-d.y
 
  'n.y=d.x
 
 
  'oder direkt und kürzer
 
  d.x=-sin(Rad)
 
  d.y=cos(Rad)
 
 
  function=d
 
end function
 
 
 
 
'liefert die nach rechts zeigende Normale als Vektor mit Länge 1
 
function GetRightNormal (origin as vector,dest as vector) as vector
 
  dim as single Rad
 
  dim as vector d,n
 
  d.x= dest.x - origin.x
 
  d.y= dest.y - origin.y
 
  Rad=atan2(d.y,d.x)
 
  if sgn(Rad)=-1 then Rad= doublepi + Rad
 
  'Vektor d brauchen wir nicht mehr und nutzen ihn anders:
 
  'd.x=cos(Rad)
 
  'd.y=sin(Rad)
 
  'd zeigt immernoch von origin aus gesehen in Richtung dest, hat aber jetzt die Länge von 1
 
  'Normale nach rechts:
 
  'dim as vector n
 
  'n.x=d.y
 
  'n.y=-d.x
 
  
 
  'oder direkt und kürzer
 
  d.x=sin(Rad)
 
  d.y=-cos(Rad)
 
 
  function=d
 
end function
 
 
 
 
'liefert eine 1 wenn sich der Punkt cpoint linksseits einer Geraden, die durch linestart und lineend definiert ist, befindet.
 
'man steht also auf der Geraden im Punkt linestart und blickt in Richtung lineend.
 
'linestart und lineend dienen nur der Ausrichtung der Geraden und der Festlegung der Blickrichtung und sind keine Begrenzungen.
 
'
 
'meine Version basiert auf einem C++Code aus folgendem Buch:
 
'"3D-Grafik Programmierung" von Marius Apetri(sS:367) isbn:978-3-8266-1767-6
 
'später habe ich im englischen Forum eine gleichnamige Routine entdeckt die auch noch das gleiche tut :) :
 
'http://www.freebasic.net/forum/viewtopic.php?f=3&t=11423&p=99760&hilit=isleft#p99760
 
function IsLeft(linestart as vector, lineend as vector, cpoint as vector) as integer
 
  function=0
 
  if ((linestart.x - cpoint.x) * (lineend.y - cpoint.y) - _
 
      (linestart.y - cpoint.y) * (lineend.x - cpoint.x))>0 then function=1
 
end function
 
'******************************************************************************
 
'******************************************************************************
 
'******************************************************************************
 
 
screen 19,32
 
 
dim as integer screenwidth,screenheight
 
screeninfo  screenwidth,screenheight
 
dim shared as integer Xo,Yo
 
Xo=screenwidth/2
 
Yo=screenheight/2
 
 
'Eigenschaften Ball,Linie
 
dim as vector linestart,lineend,ball
 
dim as integer mx,my,ballradius,ballradiusP2
 
 
'Kollisionszeug
 
dim as integer collision
 
dim as vector normal,ballleft,ballright
 
dim as single diststart, distend
 
 
linestart.x=-200
 
linestart.y=-200
 
lineend.x=300
 
lineend.y=100
 
ballradius=50
 
ballradiusP2=ballradius * ballradius
 
 
do
 
  sleep 1
 
 
  getmouse(mx,my)
 
  ball.x =mx -Xo
 
  ball.y =Yo - my
 
 
  collision=0
 
 
  'Ausrichtung der beiden KollisionsCheckPunkte des Balles zu den Normalen der zu untersuchenden Linie
 
  normal=GetLeftNormal(linestart,lineend)
 
  ballleft.x=ball.x + normal.x * BallRadius
 
  ballleft.y=ball.y + normal.y * BallRadius
 
  'Negation der linken Normalen
 
  ballright.x=ball.x - normal.x * BallRadius
 
  ballright.y=ball.y - normal.y * BallRadius
 
  'Quadrate der Entfernungen Ballzentrum -> Linienstart/-ende
 
  diststart=GetDistanceP2(ball,linestart)
 
  distend=GetDistanceP2(ball,lineend)
 
 
 
  'Kollisionserkennung
 
  if ( IsLeft(ballleft,ballright,linestart)=0 ) and ( IsLeft(ballleft,ballright,lineend)=1 ) then'wenn Ballmittelpunkt zwischen start und ende der linie ist
 
    if ( IsLeft(linestart, lineend, ballleft)=1 ) and ( IsLeft(linestart, lineend, ballright)=0 ) then collision=1
 
  elseif collision=0 then
 
    if (diststart<BallRadiusP2) or (distend<BallRadiusP2) then collision=1
 
  end if
 
 
  screenlock
 
    cls
 
    locate(1,1)
 
    if collision then print "!!! Kollision !!!"
 
 
    'globaler Koordinatenursprung
 
    line(Xo-10,Yo)-(Xo+9,Yo),&H00FF00
 
    line(Xo,Yo-10)-(Xo,Yo+9),&HFF0000
 
 
    'Linie
 
    line(Xo+linestart.y , Yo-linestart.y) - (Xo+lineend.x , Yo-lineend.y),&H00FF00
 
 
    'Ball (direkte Mauskoordinaten)
 
    circle(mx,my),ballradius
 
  screenunlock
 
 
loop until inkey<>""
 
 | 	  
 
 
Mutton | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		grindstone
 
 
  Anmeldungsdatum: 03.10.2010 Beiträge: 1283 Wohnort: Ruhrpott
  | 
		
			
				 Verfasst am: 02.03.2015, 11:24    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Hallo 0oFreako0!
 
 
Ganz allgemein kann ich dir zu dem Thema auch noch dieses Werk empfehlen.
 
 
Gruß
 
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		dreael Administrator
  
  Anmeldungsdatum: 10.09.2004 Beiträge: 2531 Wohnort: Hofen SH (Schweiz)
  | 
		
			
				 Verfasst am: 02.03.2015, 18:25    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Von mir noch das berühmte Beispiel:
 
 
http://www.dreael.ch/Deutsch/Download/Billard-Simulation.html
 
 
Beinhaltet ebenfalls eine Kreiskollision + wie Du bei vielen Kugeln bestimmt, welche Kollision als nächstes nun tatsächlich stattfindet.
 
 
Formeln seinerzeit selber mit Gleichungen hergeleitet (ist übrigens nicht so kompliziert). _________________ Teste die PC-Sicherheit mit www.sec-check.net | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
	 
	    
	   | 
	
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
  | 
   
 
     |