Buchempfehlung
Windows-Programmierung. Das Entwicklerhandbuch zur WIN32-API
Windows-Programmierung. Das Entwicklerhandbuch zur WIN32-API
"Der" Petzold, das über 1000 Seiten starke Standardwerk zum Win32-API - besonders nützlich u. a. bei der GUI-Programmierung in FreeBASIC! [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

fb:porticula NoPaste

Info
Info / Hilfe
Liste
Übersicht / Liste
Neu
Datei hochladen
Suche
Quellcode suchen
Download
Dateidownload

Achsenmodell die 6. mit Eigenkollisionserkennung

Uploader:MitgliedMuttonhead
Datum/Zeit:23.11.2011 22:03:29

'Achsenmodel_06.bas
'weit entfernt von Physik und Realität
screen 19,32

dim shared as integer scrnw,scrnh
screeninfo  scrnw,scrnh

dim shared as integer Xo,Yo
Xo=scrnw\2
Yo=scrnh\2
const as single pi =atn (1) * 4
const as single doublepi=pi*2
const as single scale=8

Dim shared as integer ptr CollisionS

CollisionS=imagecreate(scrnw,scrnh)

if CollisionS=0 then end

type vector
  x as single
  y as single
end type



'Als axle werden alle Punkte auf der
'Fahrzeugmittelachse definiert:
'das können tatsächlich Achsen als auch Anhängerkupplungen sein
type axle
  used      as single '"Flag" ob Achse da ist oder nicht
  mounting  as single 'Entfernung dieser Achsezu einem vorhergehenden Aufhängungspunkt, also Achse/Anhängerkupplung
  position  as vector  'Position der Achse
end type



'Die Lage dieser Punkte wird durch den relativen Winkel zur Fahreugmittelachse
'und der Entfernung zum Null-Punkt definiert.
'Kollisionspunkte und später die Grafik wird aus solchen Punkten aufgebaut
type bodypoint
  align    as single 'Winkel
  distance as single 'Entfernung zum NullPunkt
  position as vector 'Position dieses Punktes
end type



'Container für die Fahrzeugdefinition
'Null-Punkt ist immer axl(0)
/'
      c(1)------------------------------c(2)
      |  ---                   ---         |
      |   |                     |          |
  <---|-axl(0)----------------axl(1)--axl(2)
      |   |                     |          |
      |  ---                   ---         |
      c(0)------------------------------c(3)

'/

type vessel
  prevvessel as vessel ptr
  nextvessel as vessel ptr

  vtype         as integer

  align         as single
  axl(2)        as axle '0 und 1 für Achsen
  collision(3)  as bodypoint'beschreibt KollisionsFläche, für Kollisionen zwischen den Vessels
  collisioncolor as integer 'Farbe für Collisionsüberprüfung
end type



declare function GetDistance(b as vector, d as vector) as single
declare function GetArcus(b as vector,v as vector) as single
declare function GetVector(arcus as single) as vector

declare sub SetTractorA (v as vessel ptr)
'declare sub SetTractorB (v as vessel ptr)
declare sub SetTrailerA (v as vessel ptr)
declare sub SetTrailerB (v as vessel ptr)



'gesamter Zug
type set
  steer       as single   'Lenkwinkel/ Bewegungsrichtung der ersten Achse
  steermax    as single   'max. Einlenkwinkel in Bogenmaß, gesetzt im Constructor
  steercontrol as integer '1=Links  0=Gerade   2=Rechts

  velocity    as single   'Geschwindigkeit Einheiten/Sekunde im Koordinatensystem
  velocontrol as integer  '1=Beschleunigen  0=Ausrollen  2=Abbremsen

  dircontrol  as integer  '1=Vorwärts -1=Rückwärts

  timer_this  as single   'aktuell vergangene Zeit seit timer_last
  timer_last  as single   'Systemzeit letzten Bewegung/Berechnung


  firstvessel  as vessel ptr 'erstes Objekt
  lastvessel   as vessel ptr 'letztes Objekt

  gamemsg      as string

  rotcolor    as integer   'rotierender Farbwert für Eigenkollision wird ins Vessel eingetragen

  'Hilfsvariablen
  oldpoint    as vector
  v           as vector
  l           as vector
  d           as vector

  t           as single
  distance    as single
  steertmp    as single
  vess        as vessel ptr



  declare constructor
  declare destructor

  declare function AddVessel(vtype as integer) as integer
  declare sub HitchUpVessel (vess as vessel ptr)

  declare sub MoveSet

  declare sub Acceleration
  declare sub Deceleration
  declare sub ToLeft
  declare sub ToRight
  declare sub Foreward
  declare sub Reverse

  declare sub DrawVessels
  declare function CheckSelfCollision as integer
end type

constructor set
  timer_this=0
  timer_last=0
  dircontrol=1
  steermax=45/360 * doublepi
  rotcolor=0
end constructor



destructor set
  dim as vessel ptr nv,v=firstvessel
  if v then
    do
      nv=v->nextvessel
      delete v
      v=nv
    loop until v=0
  end if
end destructor



function set.AddVessel(vtype as integer) as integer
  function=0
  dim as vessel ptr tmp
  dim as integer possible=0

  if lastvessel=0 then  'Als erstes muß immer ein Zugfahrzeug gewählt werden
    if vtype<5 then possible=1
  else                  'an nächster Stelle
    if vtype>4 then     'nur noch Anhänger möglich
      possible=1
      'if lastvessel->vtype=1 and vtype<>5 then possible=0'an Sattelschlepper ist nur Auflieger möglich
      if lastvessel->vtype=2 and vtype<>6 then possible=0'an Traktor ist nur 2achsiger Anhänger möglich

      'if lastvessel->vtype=5 and vtype=5 then possible=0'Auflieger an Auflieger nicht möglich

    end if
  end if

  if possible then
    tmp= new vessel
    if tmp then
      tmp->vtype=vtype

      select case vtype
        case 1
          SetTractorA (tmp)
        case 2
          'SetTractorB (tmp)
        case 5
          SetTrailerA (tmp)
        case 6
          SetTrailerB (tmp)
      end select

      if vtype<5 then
        'Verlinken
        firstvessel=tmp
        lastvessel=tmp
      else
        'Verlinken
        lastvessel->nextvessel=tmp
        tmp->prevvessel=lastvessel
        lastvessel=tmp
        'zur Anhängekupplung des Vorgängers bewegen
        HitchUpVessel(lastvessel)
      end if
      function=1
    end if
  end if
end function



sub set.HitchUpVessel (vess as vessel ptr)
  l=vess->prevvessel->axl(2).position'Position der Kupplung vom vorhergehenden Vessel
  d=GetVector(vess->align - pi)

  vess->axl(0).position.x=l.x + d.x*vess->axl(0).mounting
  vess->axl(0).position.y=l.y + d.y*vess->axl(0).mounting

  'd=GetVector(vess->align)

  for i as integer=1 to 2
    vess->axl(i).position.x=vess->axl(0).position.x + d.x*vess->axl(i).mounting
    vess->axl(i).position.y=vess->axl(0).position.y + d.y*vess->axl(i).mounting
  next i

  for i as integer=0 to 3
    d=GetVector(vess->align+vess->collision(i).align)
    vess->collision(i).position.x=vess->axl(0).position.x + d.x * vess->collision(i).distance
    vess->collision(i).position.y=vess->axl(0).position.y + d.y * vess->collision(i).distance
  next i
end sub



sub set.MoveSet

  if CheckSelfCollision=0 then
    'Timersteuerung
    if timer_last then timer_this = timer-timer_last

    'Geschwindigkeit berechnen
    if velocontrol=0 and velocity>0 then
      velocity -=5*timer_this
      if velocity<0 then velocity=0
    end if

    if velocontrol=1 and velocity<200 then
      velocity +=10*timer_this
      if velocity>200 then velocity=200
    end if

    if velocontrol=2 and velocity>0 then
      velocity -=100*timer_this
      if velocity<0 then velocity=0
    end if


    'Lenkeinschlag berechnen
    if steercontrol=0 and steer<>0 then 'gerade
      steertmp=abs(steer)
      steertmp -= 1.2*timer_this
      if steertmp<0 then steer=0 else steer=steertmp*sgn(steer)
    end if

    if steercontrol=1 and steer<>steermax then 'links
      steer += 1*timer_this
      if steer>steermax then steer=steermax
    end if

    if steercontrol=2 and steer<>-steermax then 'rechts
      steer -= 1*timer_this
      if steer<-steermax then steer=-steermax
    end if


    vess=firstvessel
    do
      if vess=firstvessel then 'Zugfahrzeug

        distance=velocity*timer_this   'Weg aus Geschwindigkeit und Zeit ermitteln
        d=GetVector(vess->align + steer) 'Summe aus Richtungswinkel der 1. Achse und der Steuerungswinkel ergibt

        'neue Position 1.Achse berechnen
        oldpoint=vess->axl(0).position'alte Position 1.Achse merken
        vess->axl(0).position.x +=d.x*distance * dircontrol
        vess->axl(0).position.y +=d.y*distance * dircontrol

        'neue Position 2.Achse berechnen (mit Zwischenposition)
        d=GetVector(GetArcus(oldpoint,vess->axl(1).position))
        l.x=oldpoint.x + d.x * (vess->axl(1).mounting - distance)
        l.y=oldpoint.y + d.y * (vess->axl(1).mounting - distance)
        d=GetVector(GetArcus(vess->axl(0).position,l))'Vektor d ist gleichzeitig auch die Richtung für die Kupplung
        vess->axl(1).position.x=vess->axl(0).position.x + d.x * vess->axl(1).mounting
        vess->axl(1).position.y=vess->axl(0).position.y + d.y * vess->axl(1).mounting

        'neue Position Kupplung berechnen
        oldpoint=vess->axl(2).position'alte Position hintere Kupplung merken
        vess->axl(2).position.x=vess->axl(0).position.x + d.x * vess->axl(2).mounting
        vess->axl(2).position.y=vess->axl(0).position.y + d.y * vess->axl(2).mounting

        'neue Ausrichtung des Vessels berechnen
        vess->align=GetArcus(vess->axl(1).position,vess->axl(0).position)

      else 'Anhänger

        'neue Position 1.Achse berechnen (mit Zwischenposition)
        d=GetVector(GetArcus(oldpoint,vess->axl(0).position))
        l.x=oldpoint.x + d.x * (vess->axl(0).mounting - distance)
        l.y=oldpoint.y + d.y * (vess->axl(0).mounting - distance)
        d=GetVector(GetArcus(vess->prevvessel->axl(2).position,l))'Vektor d ist gleichzeitig auch die Richtung für die Kupplung
        oldpoint=vess->axl(0).position'alte Position 1.Achse merken
        vess->axl(0).position.x=vess->prevvessel->axl(2).position.x + d.x * vess->axl(0).mounting
        vess->axl(0).position.y=vess->prevvessel->axl(2).position.y + d.y * vess->axl(0).mounting

        if vess->axl(1).used then 'wenn 2achsiger Anhänger

          'neue Position 2.Achse berechnen (mit Zwischenposition)
          d=GetVector(GetArcus(oldpoint,vess->axl(1).position))
          l.x=oldpoint.x + d.x * (vess->axl(1).mounting - distance)
          l.y=oldpoint.y + d.y * (vess->axl(1).mounting - distance)
          d=GetVector(GetArcus(vess->axl(0).position,l))'Vektor d ist gleichzeitig auch die Richtung für die Kupplung
          vess->axl(1).position.x=vess->axl(0).position.x + d.x * vess->axl(1).mounting
          vess->axl(1).position.y=vess->axl(0).position.y + d.y * vess->axl(1).mounting

          'neue Ausrichtung des Vessels berechnen
          vess->align=GetArcus(vess->axl(1).position,vess->axl(0).position)

        else 'wenn 1achsiger Anhänger

          'neue Ausrichtung des Vessels berechnen
          vess->align=GetArcus(vess->axl(0).position,vess->prevvessel->axl(2).position)

        end if

      end if

      'neue Position Kupplung berechnen
      oldpoint=vess->axl(2).position'alte Position hintere Kupplung merken
      vess->axl(2).position.x=vess->axl(0).position.x + d.x * vess->axl(2).mounting
      vess->axl(2).position.y=vess->axl(0).position.y + d.y * vess->axl(2).mounting

      'Kollisionspunkte berechnen
      for i as integer=0 to 3
        d=GetVector(vess->align + vess->collision(i).align)
        vess->collision(i).position.x=vess->axl(0).position.x + d.x * vess->collision(i).distance
        vess->collision(i).position.y=vess->axl(0).position.y + d.y * vess->collision(i).distance
      next i

      vess=vess->nextvessel
    loop until vess=0

    timer_last=timer   'aktuelle Zeit für das nächstemal merken
    steercontrol=0
    velocontrol=0
  else
    gamemsg="Lastzug durch Eigenkollision zerstoert"
  end if

end sub


sub set.Acceleration
  velocontrol=1
end sub



sub set.Deceleration
  velocontrol=2
end sub



sub set.ToLeft
  steercontrol=1
end sub



sub set.ToRight
  steercontrol=2
end sub



sub set.Foreward
  if velocity=0 then dircontrol=1
end sub



sub set.Reverse
  if velocity=0 then dircontrol=-1
end sub



sub set.DrawVessels
  vess=firstvessel
  if vess then
    do
      line(Xo + vess->collision(0).position.x,Yo - vess->collision(0).position.y)-_
          (Xo + vess->collision(1).position.x,Yo - vess->collision(1).position.y),&HFF7F00
      line-(Xo + vess->collision(2).position.x,Yo - vess->collision(2).position.y),&HFF7F00
      line-(Xo + vess->collision(3).position.x,Yo - vess->collision(3).position.y),&HFF7F00
      line-(Xo + vess->collision(0).position.x,Yo - vess->collision(0).position.y),&HFF7F00

      paint(Xo+ vess->axl(0).position.x,Yo - vess->axl(0).position.y),&HFF7F00
      vess=vess->nextvessel
    loop until vess=0
  end if

  locate (1,1)
  print gamemsg
end sub



function set.CheckSelfCollision as integer
  dim as integer selfcollision=0
  function=0

  if firstvessel then
    'Zeichenrichtung firstvessel->lastvessel
    vess=firstvessel
    do
      'Farbrotation
      rotcolor +=1
      if rotcolor>&HFFFFFF then rotcolor=1

      vess->collisioncolor=rotcolor

      line CollisionS,(Xo + vess->collision(0).position.x,Yo - vess->collision(0).position.y)-_
          (Xo + vess->collision(1).position.x,Yo - vess->collision(1).position.y),vess->collisioncolor
      line CollisionS,-(Xo + vess->collision(2).position.x,Yo - vess->collision(2).position.y),vess->collisioncolor
      line CollisionS, -(Xo + vess->collision(3).position.x,Yo - vess->collision(3).position.y),vess->collisioncolor
      line CollisionS,-(Xo + vess->collision(0).position.x,Yo - vess->collision(0).position.y),vess->collisioncolor
      paint CollisionS,(Xo+ vess->axl(0).position.x,Yo - vess->axl(0).position.y),vess->collisioncolor
      vess=vess->nextvessel
    loop until vess=0

    'Überprüfung ob jeder Kollisionspunkt die richtige Farbe hat
    vess=firstvessel
    do
      for i as integer=0 to 3
        if point (Xo + vess->collision(i).position.x,Yo - vess->collision(i).position.y,CollisionS)<>_
                            vess->collisioncolor then selfcollision=1
      next i
      vess=vess->nextvessel
    loop until (vess=0) or (selfcollision=1)

    if selfcollision=0 then
      'Zeichenrichtung lastvessel->firstvessel
      vess=lastvessel
      do
        'Farbrotation
        rotcolor +=1
        if rotcolor>&HFFFFFF then rotcolor=1

        vess->collisioncolor=rotcolor

        line CollisionS,(Xo + vess->collision(0).position.x,Yo - vess->collision(0).position.y)-_
            (Xo + vess->collision(1).position.x,Yo - vess->collision(1).position.y),vess->collisioncolor
        line CollisionS,-(Xo + vess->collision(2).position.x,Yo - vess->collision(2).position.y),vess->collisioncolor
        line CollisionS, -(Xo + vess->collision(3).position.x,Yo - vess->collision(3).position.y),vess->collisioncolor
        line CollisionS,-(Xo + vess->collision(0).position.x,Yo - vess->collision(0).position.y),vess->collisioncolor
        paint CollisionS,(Xo+ vess->axl(0).position.x,Yo - vess->axl(0).position.y),vess->collisioncolor
        vess=vess->prevvessel
      loop until vess=0

      'Überprüfung ob jeder Kollisionspunkt die richtige Farbe hat
      vess=firstvessel
      do
        for i as integer=0 to 3
          if point (Xo + vess->collision(i).position.x,Yo - vess->collision(i).position.y,CollisionS)<>_
                              vess->collisioncolor then selfcollision=1
        next i
        vess=vess->nextvessel
      loop until (vess=0) or (selfcollision=1)
    end if
  end if
  function=selfcollision
end function

'**************************************



'**************************************
'Punktedefinition aller möglichen Fahrzeuge und Anhänger

sub SetTractorA (v as vessel ptr)
  'Vesseltyp festlegen
  v->vtype=1

  'Ausrichtung nach links 180 grd
  v->align=pi

  '************************************

  'Achsen
  v->axl(0).used=1
  v->axl(0).mounting=0

  v->axl(1).used=1
  v->axl(1).mounting=4

  v->axl(2).used=1
  v->axl(2).mounting=3

  'Kollision
  v->collision(0).position.x=-1.5
  v->collision(0).position.y=-1.25

  v->collision(1).position.x=-1.5
  v->collision(1).position.y=1.25

  v->collision(2).position.x=0.5'4.97
  v->collision(2).position.y=1.25

  v->collision(3).position.x=0.5'4.97
  v->collision(3).position.y=-1.25

  '************************************

  'Achsen verorten
  v->axl(0).position.x=0
  v->axl(0).position.y=0
  v->axl(0).mounting *=scale
  for i as integer=1 to 2
    v->axl(i).mounting *=scale
    v->axl(i).position.x=v->axl(0).position.x + v->axl(i).mounting
    v->axl(i).position.y=v->axl(0).position.y
  next i

  'Bezug zum NullPunkt(axl(0)) herstellen
  for i as integer=0 to 3
    v->collision(i).position.x *=scale
    v->collision(i).position.y *=scale
    v->collision(i).align=v->align-GetArcus(v->axl(0).position,v->collision(i).position)
    v->collision(i).distance=GetDistance(v->axl(0).position,v->collision(i).position)
  next i
end sub



sub SetTrailerA (v as vessel ptr)
  'Vesseltyp festlegen
  v->vtype=5

  'Ausrichtung nach links 180 grd
  v->align=pi

  '************************************

  'Achsen
  v->axl(0).used=1
  v->axl(0).mounting=8
  v->axl(1).used=0
  v->axl(1).mounting=0
  v->axl(2).used=1
  v->axl(2).mounting=4

  'Kollision
  v->collision(0).position.x=-9.5
  v->collision(0).position.y=-1.25

  v->collision(1).position.x=-9.5
  v->collision(1).position.y=1.25

  v->collision(2).position.x=4
  v->collision(2).position.y=1.25

  v->collision(3).position.x=4
  v->collision(3).position.y=-1.25

  '************************************

  'Achsen verorten
  v->axl(0).position.x=0
  v->axl(0).position.y=0
  v->axl(0).mounting *=scale
  for i as integer=1 to 2
    v->axl(i).mounting *=scale
    v->axl(i).position.x=v->axl(0).position.x + v->axl(i).mounting
    v->axl(i).position.y=v->axl(0).position.y
  next i

  'Bezug zum NullPunkt(axl(0)) herstellen
  for i as integer=0 to 3
    v->collision(i).position.x *=scale
    v->collision(i).position.y *=scale
    v->collision(i).align=v->align-GetArcus(v->axl(0).position,v->collision(i).position)
    v->collision(i).distance=GetDistance(v->axl(0).position,v->collision(i).position)
  next i
end sub



sub SetTrailerB (v as vessel ptr)
  'Vesseltyp festlegen
  v->vtype=6

  'Ausrichtung nach links 180 grd
  v->align=pi

  '************************************

  'Achsen
  v->axl(0).used=1
  v->axl(0).mounting=3
  v->axl(1).used=1
  v->axl(1).mounting=4
  v->axl(2).used=1
  v->axl(2).mounting=5.5

  'Kollision
  v->collision(0).position.x=-1
  v->collision(0).position.y=-1.25

  v->collision(1).position.x=-1
  v->collision(1).position.y=1.25

  v->collision(2).position.x=5.5
  v->collision(2).position.y=1.25

  v->collision(3).position.x=5.5
  v->collision(3).position.y=-1.25

  '************************************

  'Achsen verorten
  v->axl(0).position.x=0
  v->axl(0).position.y=0
  v->axl(0).mounting *=scale
  for i as integer=1 to 2
    v->axl(i).mounting *=scale
    v->axl(i).position.x=v->axl(0).position.x + v->axl(i).mounting
    v->axl(i).position.y=v->axl(0).position.y
  next i

  'Bezug zum NullPunkt(axl(0)) herstellen
  for i as integer=0 to 3
    v->collision(i).position.x *=scale
    v->collision(i).position.y *=scale
    v->collision(i).align=v->align-GetArcus(v->axl(0).position,v->collision(i).position)
    v->collision(i).distance=GetDistance(v->axl(0).position,v->collision(i).position)
  next i
end sub
'******************************************************************************



'**************************************
'Hilfsfunktionen

'liefern Entfernung 2er Ortsvektoren nach Pythagoras
function GetDistance(b as vector, d as vector) as single
  dim as single dx,dy
  dx=d.x - b.x
  dy=d.y - b.y
  function=sqr(dx*dx + dy*dy)
end function



'liefert die globale Richtung(in Bogenmaß) eines Punktes v vom Standpunkt b aus gesehen
function GetArcus(b as vector,v as vector) as single
  dim as single arcus
  dim as vector d
  d.x= v.x - b.x
  d.y= v.y - b.y
  arcus=atan2(d.y,d.x)
  if sgn(arcus)=-1 then arcus= doublepi + arcus
  function=arcus
end function



'liefert eine Richtung (in Bogenmaß) als Richtungsvektor
function GetVector(arcus as single) as vector
  dim as vector v
  if arcus>=doublepi then arcus=arcus-doublepi
  if arcus<0 then arcus=doublepi+arcus
  v.x=cos(arcus)
  v.y=sin(arcus)
  function=v
end function
'******************************************************************************


dim as set truck
truck.AddVessel(1)
truck.AddVessel(5)
truck.AddVessel(6)


do
  sleep 1
  if multikey(&H11) then truck.Acceleration
  if multikey(&H1F) then truck.Deceleration
  if multikey(&H1E) then truck.ToLeft
  if multikey(&H20) then truck.ToRight
  if multikey(&H13) then truck.Reverse
  if multikey(&H21) then truck.Foreward
  truck.MoveSet
  screenlock
    cls
    truck.DrawVessels
    'Koordinatensystem
    line (0,Yo)-(Xo*2-1,Yo),&H007f00
    line (Xo,0)-(Xo,Yo*2-1),&H7F0000

  screenunlock
loop until inkey=chr(27)
end

imagedestroy CollisionS