Homekeeping

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

 

Krischan

Betreff: Homekeeping

BeitragSo, Nov 15, 2009 12:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Homekeeping bedeutet, dass man die Welt um den Spieler herum bewegt, während sich der Spieler nur in einem begrenzten Gebiet um 0,0,0 herum bewegt. Damit kann man das "wabern" von Meshes bei grossen Distanzen, z.B. in Weltraumumgebungen verhindern und sehr grosse Cameraranges verwenden, z.B. 1,1000000. Die Idee dazu kam mir, nachdem ich erfolglos versuchte ein Sonnensystem mit halbwegs realistischen Grössenverhältnissen in Relation zum Spieler zu basteln und immer an der Camerarange gescheitert bin bzw. dynamisches Skalieren irgendwie seltsam aussah.

Das Prinzip ist ganz einfach: man hängt einfach alles, was mit der Welt zu tun hat (z.B. Sonne, Planeten, Asteroiden) an ein "masterpivot" - alles, bis auf den Spieler! Die Funktion überprüft nun, ob sich der Spieler ausserhalb seines "home bereiches", der homesize% befindet. Falls dies der Fall ist, wird die Spielerposition rückgesetzt und die Welt bzw. das masterpivot um die homesize% der entsprechenden Achse verschoben.

In den Variablen localx/y/z ist dabei die "echte" Position des Spielers innerhalb der homesize gespeichert, in den Variablen globalx/y/z die simulierte Differenz und beide Werte addiert ergibt die simulierte Spielerposition.

Homekeeping Funktion:
Code: [AUSKLAPPEN]
Function HomeKeeping(player%,world%,homesize%=100)
   
   localx=EntityX(player)
   localy=EntityY(player)
   localz=EntityZ(player)
   
   If localx>homesize Then
      globalx=globalx+homesize
      localx=localx-homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,-homesize,0,0
   EndIf
   
   If localx<-homesize Then
      globalx=globalx-homesize
      localx=localx+homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,homesize,0,0
   EndIf
   
   If localy>homesize Then
      globaly=globaly+homesize
      localy=localy-homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,-homesize,0
   EndIf
   
   If localy<-homesize Then
      globaly=globaly-homesize
      localy=localy+homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,homesize,0
   EndIf
   
   If localz>homesize Then
      globalz=globalz+homesize
      localz=localz-homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,0,-homesize
   EndIf
   
   If localz<-homesize Then
      globalz=globalz-homesize
      localz=localz+homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,0,homesize
   EndIf
   
End Function


Hier mal ein Beispiel einer Sonne mit 25.000 umliegenden Objekten im Bereich von 10.000 bis 100.000 und einer Camerarange von 1.000.000. Kommentiert man in der Hauptschleife die Homekeeping-Funktion aus, fängt das Spielermesh bei ca. 32.000 Entfernung zur Sonne an böse zu wabern, mit der Funktion bleibt es bis zum INT/Float-Limit stabil.

ACHTUNG: in diesem Code ist die Funktion bereits entkommentiert damit man zuerst den Wabereffekt sieht. Steuerung mit Maus/Pfeiltasten, RSHIFT=10x schneller fliegen und LMB=Zoom 10x:

Code: [AUSKLAPPEN]
Graphics3D 800,600,32,2

Global GameSpeed%=60
Global Screenwidth%=GraphicsWidth()
Global Screenheight%=GraphicsHeight()
Global FramePeriod%=1000/GameSpeed
Global FrameTime%=MilliSecs()-FramePeriod

Global movetarget%,masterpivot%
Global player%,cam%,ship%,sun%,light%
Global iwc%,ihc%,iwk%,ihk%
Global kreuz%,cursor%
Global localx#,localy#,localz#
Global globalx#,globaly#,globalz#

Global reichweite#            = 9000.0
Global rollspeed#            = 1.0
Global turnspeed#            = 2.0
Global maxroll#               = 20.0
Global speed#               = 100.0

Global wf%,mx%,my%,t1#,t2#,roll#,currentspeed#

InitWorld()

MoveMouse Screenwidth/2,Screenheight/2

While Not KeyHit(1)
   
   Local FrameElapsed%,FrameTicks%,FrameTween#,t%
   
   Repeat FrameElapsed=MilliSecs()-FrameTime Until FrameElapsed
   FrameTicks=FrameElapsed/FramePeriod
   FrameTween=Float(FrameElapsed Mod FramePeriod)/Float(FramePeriod)
   
   For t=1 To FrameTicks
      
      FrameTime=FrameTime+FramePeriod : If t=FrameTicks Then CaptureWorld
      
      Movement()
      
      localx=EntityX(player)
      localy=EntityY(player)
      localz=EntityZ(player)
      
      ;HomeKeeping(player,masterpivot,1000)
      
      UpdateWorld
      
   Next
   
   RenderWorld FrameTween
   
   CameraProject cam,EntityX(movetarget,1),EntityY(movetarget,1),EntityZ(movetarget,1)
   DrawImage kreuz,ProjectedX()-iwk,ProjectedY()-ihk
   DrawImage cursor,mx-iwc,my-ihc
   
   Text 0, 0,"Local Position....: "+localx+" | "+localy+" | "+localz
   Text 0,15,"Global Position...: "+globalx+" | "+globaly+" | "+globalz
   Text 0,30,"Simulated Position: "+(globalx+localx)+" | "+(globaly+localy)+" | "+(globalz+localz)
   Text 0,45,"Distance to Sun...: "+EntityDistance(player,sun)
   
   Flip 0
   
Wend

End


Function HomeKeeping(player%,world%,homesize%=100)
   
   If localx>homesize Then
      globalx=globalx+homesize
      localx=localx-homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,-homesize,0,0
   EndIf
   
   If localx<-homesize Then
      globalx=globalx-homesize
      localx=localx+homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,homesize,0,0
   EndIf
   
   If localy>homesize Then
      globaly=globaly+homesize
      localy=localy-homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,-homesize,0
   EndIf
   
   If localy<-homesize Then
      globaly=globaly-homesize
      localy=localy+homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,homesize,0
   EndIf
   
   If localz>homesize Then
      globalz=globalz+homesize
      localz=localz-homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,0,-homesize
   EndIf
   
   If localz<-homesize Then
      globalz=globalz-homesize
      localz=localz+homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,0,homesize
   EndIf
   
End Function


Function InitWorld()
   
   Local mesh%,surf%,cube%,i%,s#,d#
   
   masterpivot=CreatePivot()
   
   player=CreatePivot()
   PositionEntity player,0,1000,-10000
   
   ship=CreateCube(player)
   EntityFX ship,1
   EntityColor ship,0,128,255
   ScaleEntity ship,1,0.05,1
   PositionEntity ship,0,-0.5,1.5
   EntityOrder ship,-1000
   
   movetarget=CreatePivot(player)
   MoveEntity movetarget,0,0,reichweite
   
   cam=CreateCamera(player)
   PositionEntity cam,0,0.5,-1.5
   CameraFogMode cam,True
   CameraRange cam,1,1000000
   CameraFogRange cam,500000,1000000
   CameraZoom cam,1
   CameraClsColor cam,0,0,0
   CameraFogColor cam,0,0,0
   
   cursor=CreateImage(33,33)
   Color 255,0,0
   SetBuffer ImageBuffer(cursor)
   Rect 0,0,33,33,0
   iwc=ImageWidth(cursor)/2
   ihc=ImageHeight(cursor)/2
   
   kreuz=CreateImage(33,33)
   Color 0,255,0
   SetBuffer ImageBuffer(kreuz)
   Line 16,0,16,33
   Line 0,16,33,16
   iwk=ImageWidth(kreuz)/2
   ihk=ImageHeight(kreuz)/2
   
   SetBuffer BackBuffer()
   
   mesh=CreateMesh(masterpivot)
   surf=CreateSurface(mesh)
   EntityFX mesh,2
   
   sun=CreateSphere(32,masterpivot)
   EntityFX sun,1+8
   EntityColor sun,255,255,224
   ScaleMesh sun,6000,6000,6000
   
   light=CreateLight(2,masterpivot)
   LightRange light,50000
   AmbientLight 32,32,32
   
   cube=CreateCube()
   
   For i=1 To 25000
      
      s#=Rnd(10,100)
      If Rnd(1)>0.999 Then s=Rnd(100,1000)
      d#=Rnd(10000,100000)
      ScaleEntity cube,s,s,s
      PositionEntity cube,0,0,0
      
      RotateEntity cube,0,0,0
      TurnEntity cube,Rnd(-Rnd(0,90),Rnd(0,90)),Rnd(0,360),0
      MoveEntity cube,0,0,d
      PointEntity cube,sun
      
      AddToMesh(cube,mesh,128,128,128,1)
      
   Next
   
   FreeEntity cube
   
   UpdateNormals mesh
   
   PointEntity player,sun
   
End Function


Function Normalisieren#(value#=128.0,value_min#=0.0,value_max#=255.0,norm_min#=0.0,norm_max#=1.0)
   
   Return ((value-value_min)/(value_max-value_min))*(norm_max-norm_min)+norm_min
   
End Function


Function Movement()
   
   Local multi#,limit#
   
   roll=0
   
   If KeyDown(203) Then roll=rollspeed
   If KeyDown(205) Then roll=-rollspeed
   If KeyHit(57) Then wf=1-wf : WireFrame wf
   If KeyDown(54) Then multi=10 Else multi=1
   
   If MouseDown(1) Then CameraZoom cam,10 : limit=0.1 Else CameraZoom cam,1 : limit=1.0
   
   currentspeed=(KeyDown(200)-KeyDown(208))*speed*multi
   
   MoveEntity player,0,0,currentspeed
   
   mx=MouseX()
   my=MouseY()
   
   t1=Normalisieren(my,0,Screenheight,-1,1)
   t2=Normalisieren(mx,0,Screenwidth,1,-1)
   
   RotateEntity ship,t1*maxroll,t2*maxroll,t2*maxroll*2
   TurnEntity player,t1*turnspeed*limit,t2*turnspeed*limit,roll*turnspeed
   
End Function


Function AddToMesh(source%,target%,r%,g%,b%,a#)
   
   Local vert%[2],vr%[2],vg%[2],vb%[2],va#[2]
   Local oldvert%,i1%,i2%,v1%,v2%
   Local surf%,surf1%=GetSurface(source,1),surf2%
   
   v1=CountVertices(surf1)
   For v2=1 To CountSurfaces(target)
      
      surf=GetSurface(target,v2)
      If CountVertices(surf)+v1<64000 Then surf2=surf : Goto skip
      
   Next
   
   surf2=CreateSurface(target)
   
   .skip
   
   For i1=0 To CountTriangles(surf1)-1
      
      For i2=0 To 2
         
         oldvert = TriangleVertex(surf1,i1,i2)
         
         vr[i2]=r
         vg[i2]=g
         vb[i2]=b
         va[i2]=a
         
         TFormPoint VertexX(surf1,oldvert),VertexY(surf1,oldvert),VertexZ(surf1,oldvert),source,target
         vert[i2]=AddVertex(surf2,TFormedX(),TFormedY(),TFormedZ(),VertexU(surf1,oldvert),VertexV(surf1,oldvert))
         VertexColor surf2,vert[i2],r,g,b,a
         VertexNormal surf2,vert[i2],VertexNX(surf1,oldvert),VertexNY(surf1,oldvert),VertexNZ(surf1,oldvert)
         
      Next
      
      AddTriangle(surf2,vert[0],vert[1],vert[2])
      
   Next
   
End Function

ToeB

BeitragSo, Nov 15, 2009 12:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Sehr schön das ganze, aber was ist bei Kollisionserkennung ? weil die kann man in Blitz jetzt komplett in die Pfanne hauen, da beide Mesches sich bewegen.


mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

Silver_Knee

BeitragSo, Nov 15, 2009 13:30
Antworten mit Zitat
Benutzer-Profile anzeigen
ne kolli kommt immer vor dem rücksetzten
was vorher nicht kollidiert ist kollidiert auch nacher nicht, da die relativen positionen immer gleich bleiben.

Ich kenne das ganze als Systemcubes und habs von Evo in cnRS benutzt. Eine Erkenntnis will ich euch nicht vorenthalten:

Nimm while anstatt if. Dann kannst du auch mit geschwindigkeiten > 2* homezone ohne ein Nachziehen (da pro frame sonst max. 1 homezone gsprungen wird) arbeiten.
 

Krischan

BeitragMo, Nov 23, 2009 18:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Hast Recht, Silver_Knee, hatte später das Problem beim Positionieren des Spielers weit ausserhalb der Homezone (z.B. 0,0,-1000000). Hat das gedauert, bis sich die Welt repositioniert hatte Shocked . Hier also nochmal die Funktion mit While statt If:

Code: [AUSKLAPPEN]
Function HomeKeeping(player%,world%,homesize%=100)
   
   While localx>homesize
      globalx=globalx+homesize
      localx=localx-homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,-homesize,0,0
   Wend
   
   While localx<-homesize
      globalx=globalx-homesize
      localx=localx+homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,homesize,0,0
   Wend
   
   While localy>homesize
      globaly=globaly+homesize
      localy=localy-homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,-homesize,0
   Wend
   
   While localy<-homesize
      globaly=globaly-homesize
      localy=localy+homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,homesize,0
   Wend
   
   While localz>homesize
      globalz=globalz+homesize
      localz=localz-homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,0,-homesize
   Wend
   
   While localz<-homesize
      globalz=globalz-homesize
      localz=localz+homesize
      PositionEntity player,localx,localy,localz
      MoveEntity world,0,0,homesize
   Wend
   
End Function

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group