Ok, the comments are in German, I apologize for that, a self-steering thing that always heads for a certain target marker.
it's exciting to watch the whole thing:
Code: Select all
screen 19,32
randomize timer
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
'******************************************************************************
type vector
x as single
y as single
end type
'******************************************************************************
type axle
mounting as single 'Entfernung dieser Achse zu einem vorhergehenden Aufhängungspunkt,
position as vector 'Position der Achse
end type
'******************************************************************************
'Die Lage dieser Punkte wird durch den relativen Winkel zur Kameramittelachse
'und der Entfernung zum Null-Punkt definiert.
'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
'******************************************************************************
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 function Rotation (v1 as vector, v2 as vector, v3 as vector) as integer
'******************************************************************************
type target
radius as integer
position as vector
declare constructor
declare sub RandomSet
declare sub DrawTarget
end type
constructor target
radius=10
RandomSet
end constructor
sub target.RandomSet
dim as integer w,h
w=scrnw-radius*10
h=scrnh-radius*10
position.x=rnd*(w)-(w/2)
position.y=rnd*(h)-(h/2)
end sub
sub target.DrawTarget
circle(Xo+position.x,Yo-position.y),radius,&H006600
end sub
'******************************************************************************
'Kameraobjekt
type cameraobj
align as single 'globaler Winkel/Richtung der Kamera
axl(1) as axle '0 und 1 für Achsen definiert die Richtung
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
vmax as single 'Höchstgeschwindigkeit
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 double 'aktuell vergangene Zeit seit timer_last
timer_last as double 'Systemzeit letzten Bewegung/Berechnung
'Hilfsvariablen
oldpoint as vector
v as vector
l as vector
d as vector
t as single
distance as single
steertmp as single
sccoords(4) as vector
declare constructor
declare destructor
declare sub MoveCamera
declare sub Deceleration
declare sub RollOut
declare sub Acceleration
declare sub ToLeft
declare sub ToRight
declare sub SteerToTarget(t as target)
declare function TargetAchieved (t as target) as integer
declare sub Drawcamera(t as target)
end type
constructor cameraobj
timer_this=0
timer_last=0
vmax=200
dircontrol=1
steermax=45/360 * doublepi
'Ausrichtung nach links 180 grd
align=pi
'Achsen
axl(0).mounting=0
axl(1).mounting=10
'Achsen verorten
axl(0).position.x=0
axl(0).position.y=0
axl(1).position.x=axl(0).position.x + axl(1).mounting
axl(1).position.y=axl(0).position.y
end constructor
destructor cameraobj
end destructor
sub cameraobj.MoveCamera
'Timersteuerung
if timer_last then timer_this = timer-timer_last
'Geschwindigkeit berechnen
select case velocontrol
case -2
if velocity>0 then
velocity -=vmax*2*timer_this
if velocity<0 then velocity=0
end if
case -1
if velocity>0 then
velocity -=5*timer_this
if velocity<0 then velocity=0
end if
case 0
case 1
if velocity<vmax then
velocity +=vmax*timer_this
if velocity>vmax then velocity=vmax
end if
end select
'Lenkeinschlag berechnen
if steercontrol=0 and steer<>0 then 'steer=0'gerade
steertmp=abs(steer)
steertmp -= 100*timer_this
if steertmp<0 then steer=0 else steer=steertmp*sgn(steer)
end if
if steercontrol=1 and steer<>steermax then 'links
if steer<0 then steer += 10*timer_this else steer += .11*timer_this
if steer>steermax then steer=steermax
end if
if steercontrol=-1 and steer<>-steermax then 'rechts
if steer>0 then steer -= 10*timer_this else steer -= .11*timer_this
if steer<-steermax then steer=-steermax
end if
distance=velocity*timer_this 'Weg aus Geschwindigkeit und Zeit ermitteln
d=GetVector(align + steer) 'Summe aus Richtungswinkel der 1. Achse und der Steuerungswinkel ergibt
'neue Position 1.Achse berechnen
oldpoint=axl(0).position'alte Position 1.Achse merken
axl(0).position.x +=d.x*distance * dircontrol
axl(0).position.y +=d.y*distance * dircontrol
'neue Position 2.Achse berechnen (mit Zwischenposition)
d=GetVector(GetArcus(oldpoint,axl(1).position))
l.x=oldpoint.x + d.x * (axl(1).mounting - distance)
l.y=oldpoint.y + d.y * (axl(1).mounting - distance)
d=GetVector(GetArcus(axl(0).position,l))
axl(1).position.x=axl(0).position.x + d.x * axl(1).mounting
axl(1).position.y=axl(0).position.y + d.y * axl(1).mounting
'neue Ausrichtung der Kamera berechnen
align=GetArcus(axl(1).position,axl(0).position)
timer_last=timer 'aktuelle Zeit für das nächstemal merken
steercontrol=0
velocontrol=0
end sub
sub cameraobj.Deceleration
velocontrol=-2
end sub
sub cameraobj.Acceleration
velocontrol=1
end sub
sub cameraobj.ToLeft
steercontrol=1
end sub
sub cameraobj.ToRight
steercontrol=-1
end sub
sub cameraobj.SteerToTarget(t as target)
dim as integer turn
if velocity>vmax/2 then
if abs(steer)< steermax/2 then Acceleration else Deceleration
else
Acceleration
end if
turn=Rotation(axl(0).position, t.position, axl(1).position)
if turn =1 then ToLeft
if turn=-1 then ToRight
end sub
function cameraobj.TargetAchieved (t as target) as integer
function=0
if GetDistance(axl(1).position,t.position)<=t.radius then function=1
end function
sub cameraobj.DrawCamera(t as target)
line (Xo + axl(0).position.x,Yo - axl(0).position.y)-(Xo + axl(1).position.x,Yo - axl(1).position.y),&HFF3F00
'pset (Xo + axl(0).position.x,Yo - axl(0).position.y),&HFFFFFF
end sub
'******************************************************************************
'Hilfsfunktionen
'liefert 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)
'AsmBooster von Volta
Asm
mov eax, dword Ptr [d]
mov ebx, dword Ptr [b]
fld dword Ptr [eax]
fsub dword Ptr [ebx]
fmul ST(0), ST(0)
fld dword Ptr [eax+4]
fsub dword Ptr [ebx+4]
fmul ST(0), ST(0)
faddp
fsqrt
fstp dword Ptr [Function]
End Asm
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)
'AsmBooster von Volta
Asm
mov eax, dword Ptr [v]
mov ebx, dword Ptr [b]
fld dword Ptr [eax+4]
fsub dword Ptr [ebx+4]
fld dword Ptr [eax]
fsub dword Ptr [ebx]
fpatan
fstp dword Ptr [arcus]
End Asm
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)
'AsmBooster von Volta
Asm
fld dword Ptr [arcus]
fsincos 'compute sin AND cos
fstp dword Ptr [v] 'cos -> v.x
fstp dword Ptr [v+4] 'sin -> v.y
End Asm
Function=v
End Function
function Rotation (v1 as vector, v2 as vector, v3 as vector) as integer
'benutzt das sog. Kreuzprodukt von Vektoren
'um heraus zu bekommen, ob die Reihenfolge der Vectoren
'links- oder rechtsherum ist.
'nach M.Apetri; dont ask me!!!
function=0
dim as single t
t=(v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)
if t<0 then function=1
if t>0 then function=-1
end function
'******************************************************************************
'******************************************************************************
'******************************************************************************
dim as cameraobj cam
dim as target t
do
sleep 1
cam.SteerToTarget(t)
cam.MoveCamera
if cam.TargetAchieved(t) then t.RandomSet'Wenn Ziel erreicht, Ziel neu positionieren
screenlock
'cls
cam.DrawCamera (t)
t.DrawTarget
'Koordinatensystem
line (0,Yo)-(Xo*2-1,Yo),&H007F00
line (Xo,0)-(Xo,Yo*2-1),&H7F0000
screenunlock
loop until inkey=chr(27)
end