Homekeeping


Tweet blitz3d code-archives miscellaneous rated
(Posted 4 months ago) RonTek

Keeps the player in a given distance while the world is moving.

Moving a player mesh far away from 0,0,0 results in mesh jitter due inaccuracy of vertex float positions (or even "jumping" meshes). If you want to use very large distances like in a space game (>100.000), the homekeeping function is the answer. It just moves the player mesh in a given distance (ex. 1000 Units) and puts it back to the opposite position while moving the world instead of the player. The world must be attached to a "masterpivot", even collisions work this way.

Here is a demo, homekeeping is disabled by default to show the jitter effect first. To enable homekeeping just uncomment this line in the main loop:

Author: Krischan

Image

;HomeKeeping(player,masterpivot,1000)

Moving with mouse/arrow keys, SPACE=wireframe, LMB=Zoom 10x, RMB=Move 10x faster

Graphics3D 800,600,0,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 distance#=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#


Global localx#,localy#,localz#
Global globalx#,globaly#,globalz#
Global simx#,simy#,simz#


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 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,distance

    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 Normalize#(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 MouseDown(1) Then CameraZoom cam,10 : limit=0.1 Else CameraZoom cam,1 : limit=1.0
    If MouseDown(2) Then multi=10 Else multi=1

    currentspeed=(KeyDown(200)-KeyDown(208))*speed*multi

    MoveEntity player,0,0,currentspeed

    mx=MouseX()
    my=MouseY()

    t1=Normalize(my,0,Screenheight,-1,1)
    t2=Normalize(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



; keeps the player in a given distance while the world can move far away
Function HomeKeeping(player%,world%,homesize%=100)

    ; store local player position
    localx=EntityX(player)
    localy=EntityY(player)
    localz=EntityZ(player)

    ; check X axis
    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

    ; check Y axis
    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

    ; check Z axis
    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

    ; store simulated player position
    simx=localx+globalx
    simy=localy+globaly
    simz=localz+globalz

End Function

Reply To Topic (minimum 10 characters)

Please log in to reply