|
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, 18: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, 19: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, 08:40, insgesamt 2-mal bearbeitet |
|
Nach oben |
|
|
Muttonhead
Anmeldungsdatum: 26.08.2008 Beiträge: 562 Wohnort: Jüterbog
|
Verfasst am: 01.03.2015, 19: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: 1211 Wohnort: Ruhrpott
|
Verfasst am: 02.03.2015, 12: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: 2507 Wohnort: Hofen SH (Schweiz)
|
Verfasst am: 02.03.2015, 19: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.
|
|