Dazu noch eine kleine Kollisionsdemo oder wie man es nennen soll...
Einfach mal ausprobieren

Code: Alles auswählen
;-#################################### START OF INTERFACE ####################################
Interface iTERRAIN
GenerateTerrain() ; berechnet Terrain
GetTerrain.l() ; gibt Pointer auf Terrain-Array zurück
SetTerrain(*Terrain, CountOfPoints.l) ; kopiert ein Terrain-Array in die Klasse
SetCountOfPoints(Count.l) ; setzt, wieviele Punkte berechnet werden sollen
GetCountOfPoints.l()
SetZoomFactor(Factor.f) ; setzt einen Vergrösserungsfaktor
GetZoomFactor.f()
SetTransFactor(Factor.f) ; setzt einen Verschiebungsfaktor
GetTransFactor.f()
SetRandomSeed(Seed.l) ; setze Startwert für Terrain
GetRandomSeed.l()
SetPoint(Index.l, Value.f)
GetPoint.f(Index.l)
EndInterface
Structure cTERRAIN_VTABLE
GenerateTerrain.l
GetTerrain.l
SetTerrain.l
SetCountOfPoints.l
GetCountOfPoints.l
SetZoomFactor.l
GetZoomFactor.l
SetTransFactor.l
GetTransFactor.l
SetRandomSeed.l
GetRandomSeed.l
SetPoint.l
GetPoint.l
EndStructure
Structure cTERRAIN
*VTable.cTERRAIN_VTABLE
; Data
ZoomFactor.f
TransFactor.f
CountOfPoints.l
pTerrain.l
RndSeed.l
EndStructure
;- Hilfsprozeduren
Global terrain_mv.f, terrain_d.l, terrain_max.l, terrain_array.l
Global terrain_transl.f, terrain_zoom.f
Procedure terrain_Split(low.l, high.l)
Protected m.l
m = (high + low) / 2
terrain_d = high - low
If terrain_d <= 1
ProcedureReturn 0
EndIf
terrain_mv = (PeekF(terrain_array + high * #SizeOf_Float) + PeekF(terrain_array + low * #SizeOf_Float)) / 2.0
PokeF(terrain_array + m * #SizeOf_Float, terrain_mv - (Random(10000) / 10000.0 - terrain_transl) * terrain_zoom * terrain_d / Sqr(terrain_max))
terrain_Split(m, high)
terrain_Split(low, m)
EndProcedure
;- Methoden
Procedure terrain_GenerateTerrain(*this.cTERRAIN) ; berechnet Terrain
Protected *mem
*mem = ReAllocateMemory(*this\pTerrain, *this\CountOfPoints)
If *mem
*this\pTerrain = *mem
Else
ProcedureReturn #False
EndIf
; Globale Variablen setzen
terrain_mv = 0
terrain_d = 0
terrain_max = *this\CountOfPoints - 1
terrain_array = *this\pTerrain
terrain_transl = *this\TransFactor
terrain_zoom = *this\ZoomFactor
RandomSeed(*this\RndSeed)
; Aufruf:
terrain_Split(0, *this\CountOfPoints - 1)
EndProcedure
Procedure.l terrain_GetTerrain(*this.cTERRAIN) ; gibt Pointer auf Terrain-Array zurück
ProcedureReturn *this\pTerrain
EndProcedure
Procedure terrain_SetTerrain(*this.cTERRAIN, *Terrain, CountOfPoints.l) ; kopiert ein Terrain-Array in die Klasse
Protected *mem
*mem = ReAllocateMemory(*this\pTerrain, CountOfPoints * #SizeOf_Float)
If *mem
*this\pTerrain = *mem
Else
ProcedureReturn #False
EndIf
CopyMemory(*Terrain, *this\pTerrain, CountOfPoints * #SizeOf_Float)
EndProcedure
Procedure terrain_SetCountOfPoints(*this.cTERRAIN, Count.l) ; setzt, wieviele Punkte berechnet werden sollen
*this\CountOfPoints = Count
EndProcedure
Procedure.l terrain_GetCountOfPoints(*this.cTERRAIN)
ProcedureReturn *this\CountOfPoints
EndProcedure
Procedure terrain_SetZoomFactor(*this.cTERRAIN, Factor.f) ; setzt einen Vergrösserungsfaktor
*this\ZoomFactor = Factor
EndProcedure
Procedure.f terrain_GetZoomFactor(*this.cTERRAIN)
ProcedureReturn *this\ZoomFactor
EndProcedure
Procedure terrain_SetTransFactor(*this.cTERRAIN, Factor.f) ; setzt einen Verschiebungsfaktor
*this\TransFactor = Factor
EndProcedure
Procedure.f terrain_GetTransFactor(*this.cTERRAIN)
ProcedureReturn *this\TransFactor
EndProcedure
Procedure terrain_SetRandomSeed(*this.cTERRAIN, Seed.l)
*this\RndSeed = Seed
EndProcedure
Procedure.l terrain_GetRandomSeed(*this.cTERRAIN)
ProcedureReturn *this\RndSeed
EndProcedure
Procedure terrain_SetPoint(*this.cTERRAIN, Index.l, Value.f)
PokeF(*this\pTerrain + Index * #SizeOf_Float, Value)
EndProcedure
Procedure.f terrain_GetPoint(*this.cTERRAIN, Index.l)
ProcedureReturn PeekF(*this\pTerrain + Index * #SizeOf_Float)
EndProcedure
Procedure.l new_terrain()
Protected *temp.cTERRAIN
*temp = AllocateMemory(SizeOf(cTERRAIN))
If *temp
*temp\ZoomFactor = 200
*temp\TransFactor = 0.5
*temp\VTable = AllocateMemory(SizeOf(cTERRAIN_VTABLE))
If *temp\VTable
*temp\VTable\GenerateTerrain = @terrain_GenerateTerrain()
*temp\VTable\GetTerrain = @terrain_GetTerrain()
*temp\VTable\SetTerrain = @terrain_SetTerrain()
*temp\VTable\SetCountOfPoints = @terrain_SetCountOfPoints()
*temp\VTable\GetCountOfPoints = @terrain_GetCountOfPoints()
*temp\VTable\SetZoomFactor = @terrain_SetZoomFactor()
*temp\VTable\GetZoomFactor = @terrain_GetZoomFactor()
*temp\VTable\SetTransFactor = @terrain_SetTransFactor()
*temp\VTable\GetTransFactor = @terrain_GetTransFactor()
*temp\VTable\SetRandomSeed = @terrain_SetRandomSeed()
*temp\VTable\GetRandomSeed = @terrain_GetRandomSeed()
*temp\VTable\SetPoint = @terrain_SetPoint()
*temp\VTable\GetPoint = @terrain_GetPoint()
Else
FreeMemory(*temp)
*temp = 0
EndIf
EndIf
ProcedureReturn *temp
EndProcedure
Procedure delete_terrain(*terrain.cTERRAIN)
If *terrain
If *terrain\pTerrain
FreeMemory(*terrain\pTerrain)
EndIf
If *terrain\VTable
FreeMemory(*terrain\VTable)
EndIf
FreeMemory(*terrain)
EndIf
EndProcedure
;-#################################### END OF INTERFACE ####################################
;- nicht mehr Interface -> Programm
Structure XY
x.f
y.f
EndStructure
Procedure.f LineLineCol(*P.XY, *r.XY, *A.XY, *B.XY, *OUT.XY)
Protected t.f, s.f
Protected AB.XY
s = *A\x * *r\y - *A\y * *r\x
t = (s - *P\x * *r\y + *P\y * *r\x) / (s - *B\x * *r\y + *B\y * *r\x)
AB\x = *B\x - *A\x
AB\y = *B\y - *A\y
If t >= -0.0001 And t <= 1.0001
*OUT\x = *A\x + t * AB\x
*OUT\y = *A\y + t * AB\y
ProcedureReturn Pow(*OUT\x - *P\x, 2) + Pow(*OUT\y - *P\y, 2)
EndIf
ProcedureReturn 99999999.0
EndProcedure
Procedure.l LineCollideArray(terrain.iTERRAIN, *Start.XY, *Dir.XY, *Out.XY)
Protected i.l, shortestDis.f, t.f
Protected A.XY, B.XY, Out2.XY, max.l
max = terrain\GetCountOfPoints()
shortestDis = 99999999.0
For i = 1 To max - 1
A\y = 1.0 + terrain\GetPoint(i - 1) + 250.0
A\x = 1.0 * (i - 1) / max * 500
B\y = 1.0 + terrain\GetPoint(i) + 250.0
B\x = 1.0 * i / max * 500
t = LineLineCol(*Start, *Dir, @A, @B, @Out2)
If t < shortestDis
shortestDis = t
*Out\x = Out2\x
*Out\y = Out2\y
EndIf
Next
EndProcedure
terr.iTERRAIN = new_terrain()
terr\SetCountOfPoints(100)
terr\SetZoomFactor(50)
;terr\SetRandomSeed(30)
terr\GenerateTerrain()
CreateImage(0, 500, 500)
OpenWindow(0, 200, 200, 500, 500, #PB_Window_SystemMenu|#PB_Window_ScreenCentered, "Drawing")
CreateGadgetList(WindowID())
ImageGadget(1, 0, 0, 500, 500, UseImage(0))
SetGadgetState(1, UseImage(0))
Repeat
UseImage(0)
hdc = StartDrawing(ImageOutput())
Box(0,0, 500,500, 0)
px.l = terr\GetCountOfPoints()
For z = 1 To px - 1
LineXY(1.0 * (z - 1) / px * 500, terr\GetPoint(z - 1) + 250, 1.0 * z / px * 500, terr\GetPoint(z) + 250, $FF)
Next
P.XY
P\x = 250
P\y = 0
Dir.XY
Dir\x = WindowMouseX() - 250
Dir\y = WindowMouseY()
Out.XY
LineCollideArray(terr, @P, @Dir, @Out)
Circle(Out\x, Out\y, 10, $FF00)
Line(P\x, P\y, Dir\x, Dir\y, $FF0000)
StopDrawing()
SetGadgetState(1, UseImage(0))
Delay(10)
Until WindowEvent() = #PB_Event_CloseWindow
Remi