Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Winkel und Kollisions Frage

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
0oFreako0



Anmeldungsdatum: 17.12.2011
Beiträge: 114

BeitragVerfasst am: 01.03.2015, 18:05    Titel: Winkel und Kollisions Frage Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 01.03.2015, 19:10    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 562
Wohnort: Jüterbog

BeitragVerfasst am: 01.03.2015, 19:51    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 02.03.2015, 12:24    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
dreael
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 2507
Wohnort: Hofen SH (Schweiz)

BeitragVerfasst am: 02.03.2015, 19:25    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
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.

 Impressum :: Datenschutz