Here's the closest I got to achieving my goal:
CountGfxModes()
CountGfxModes3D()
Graphics3D 640,480,16,1
;[Block] Tweening stuff
Const TargetFrameRate = 60
Global TwElapsed,TwPeriod,TwTicks,TwTime,TwTween#,UpdateLoops
TwPeriod = 1000 / TargetFrameRate
TwTime = MilliSecs() - TwPeriod
;[End block]
Global Wire
Const LevelColl = 1,SonicSoulColl = 2,SonicWheelColl = 3
Collisions SonicSoulColl,LevelColl,2,3
Collisions SonicWheelColl,LevelColl,2,3
Global Gravity#
Global Ground = LoadTerrain("gfx\heightmap_256.bmp")
ScaleEntity Ground,1000/TerrainSize(Ground),70,1000/TerrainSize(Ground)
TerrainDetail Ground,1000,True
TerrainShading Ground,True
PositionEntity Ground,-500,-100,-500
Global MossTex = LoadTexture("tex\terrain-1.jpg")
ScaleTexture MossTex,32,32
EntityTexture Ground,MossTex
EntityType Ground,LevelColl
Global SonicSoul = CreateSphere()
Global SoulTex = CreateTexture(64,64)
SetBuffer TextureBuffer(SoulTex)
Color 0,0,255
Rect 0,0,64,64
Color 255,0,0
Line 0,0,0,63
Line 15,0,15,63
Line 31,0,31,63
Line 47,0,47,63
Line 0,31,63,31
EntityTexture SonicSoul,SoulTex
RotateEntity SonicSoul,0,0,0
;ScaleEntity SonicSoul,2,2,2
;PositionEntity SonicSoul,0,2,0
EntityType SonicSoul,SonicSoulColl
;EntityAlpha SonicSoul,.5
;EntityFX SonicSoul,16;Flags: No backface culling
;FlipMesh SonicSoul
Global PrevYaw# = EntityYaw(SonicSoul)
Global wheels[4]
Local Cnt=1,X#,Z#
For Z=1 To -1 Step -2
For X=-1 To 1 Step 2
wheels[Cnt]=CreateSphere(8,SonicSoul)
EntityAlpha wheels[Cnt],.5
ScaleEntity wheels[Cnt],.5,.5,.5
EntityRadius wheels[Cnt],.5
PositionEntity wheels[Cnt],X,0,Z
EntityType wheels[Cnt],SonicWheelColl
Cnt=Cnt+1
Next
Next
Global MainCameraTarget = CreatePivot(SonicSoul)
PositionEntity MainCameraTarget,0,5,-13
;PositionEntity MainCameraHinge,0,4,0
Global MainCameraPivot = CreatePivot();MainCameraHinge)
Global MainCamera = CreateCamera(MainCameraPivot)
;PositionEntity MainCamera,0,4,0
CameraViewport MainCamera,0,0,GraphicsWidth(),GraphicsHeight()
CameraClsColor MainCamera,0,128,255
Global MainLight = CreateLight()
SetBuffer BackBuffer()
SeedRnd MilliSecs()
While Not KeyHit(1)
Cls
If KeyHit(17) Then Wire = Not Wire
WireFrame Wire
Repeat
TwElapsed = MilliSecs() - TwTime
Until TwElapsed
TwTicks = TwElapsed / TwPeriod
TwTween = Float(TwElapsed Mod TwPeriod) / Float(TwPeriod)
For UpdateLoops = 1 To TwTicks
TwTime = TwTime + TwPeriod
If UpdateLoops = TwTicks Then CaptureWorld
CORE()
Next
RenderWorld TwTween
Color 255,255,255
Rect 0,0,100,100
Color 0,0,0
Text 0,0,EntityYaw(MainCamera)
Text 0,15,EntityYaw(SonicSoul)
Flip
Wend
End
Function CORE()
UpdateCamera()
UpdateSonicsSoul()
UpdateWorld
End Function
Function UpdateCamera()
;TurnEntity MainCameraHinge,(EntityPitch(SonicSoul) - EntityPitch(MainCameraHinge)) / 50,(EntityYaw(SonicSoul) - EntityYaw(MainCameraHinge)) / 50,(EntityRoll(SonicSoul) - EntityRoll(MainCameraHinge)) / 50
;PositionEntity MainCameraHinge,EntityX(SonicSoul),EntityY(SonicSoul),EntityZ(SonicSoul),True
;MoveEntity MainCameraHinge,0,(EntityY(SonicSoul) - EntityY(MainCameraHinge)) / 10,0
PointEntity MainCameraPivot,MainCameraTarget
;Keep camera in range
If EntityDistance(MainCameraPivot,MainCameraTarget) < 5
MoveEntity MainCameraPivot,0,0,EntityDistance(MainCameraPivot,MainCameraTarget) / 50
Else
MoveEntity MainCameraPivot,0,0,EntityDistance(MainCameraPivot,MainCameraTarget) - 5
EndIf
PointEntity MainCamera,SonicSoul
End Function
Function UpdateSonicsSoul()
PrevYaw = EntityYaw(SonicSoul)
;Align Sonic's "soul" to his "wheels"... Oh my GAWD, that sounds so weird!!! @_@
Local ZX# = (EntityX(wheels[2],True) + EntityX(wheels[4],True)) / 2
ZX=ZX - (EntityX(wheels[1],True) + EntityX(wheels[3],True)) / 2
Local ZY# = (EntityY(wheels[2],True) + EntityY(wheels[4],True)) / 2
ZY=ZY - (EntityY(wheels[1],True) + EntityY(wheels[3],True))/2
Local ZZ# = (EntityZ(wheels[2],True) + EntityZ(wheels[4],True)) / 2
ZZ=ZZ - (EntityZ(wheels[1],True) + EntityZ(wheels[3],True)) / 2
AlignToVector SonicSoul,ZX,ZY,ZZ,1
ZX = (EntityX(wheels[1],True) + EntityX(wheels[2],True)) / 2
ZX = ZX - (EntityX(wheels[3],True) + EntityX(wheels[4],True)) / 2
ZY# = (EntityY(wheels[1],True) + EntityY(wheels[2],True)) / 2
ZY = ZY - (EntityY(wheels[3],True) + EntityY(wheels[4],True)) / 2
ZZ# = (EntityZ(wheels[1],True) + EntityZ(wheels[2],True)) / 2
ZZ = ZZ - (EntityZ(wheels[3],True) + EntityZ(wheels[4],True)) / 2
AlignToVector SonicSoul,ZX,ZY,ZZ,3
RotateEntity SonicSoul,EntityPitch(SonicSoul),PrevYaw,EntityRoll(SonicSoul)
;resposition wheels
Local Cnt = 1,Z#,X#
For Z = 1 To -1 Step -2
For X = -1 To 1 Step 2
; PositionEntity wheels[cnt],0,0,0
; ResetEntity wheels[cnt]
PositionEntity wheels[Cnt],X,-1,Z
Cnt=Cnt+1
Next
Next
If KeyDown(200);Up
If KeyDown(203);Left
RotateEntity SonicSoul,EntityPitch(SonicSoul),EntityYaw(MainCamera,True) + 45,EntityRoll(SonicSoul)
ElseIf KeyDown(205);Right
RotateEntity SonicSoul,EntityPitch(SonicSoul),EntityYaw(MainCamera,True) - 45,EntityRoll(SonicSoul)
Else
RotateEntity SonicSoul,EntityPitch(SonicSoul),PrevYaw,EntityRoll(SonicSoul)
EndIf
MoveEntity SonicSoul,0,0,.3
ElseIf KeyDown(208);Down
If KeyDown(203);Left
RotateEntity SonicSoul,EntityPitch(SonicSoul),EntityYaw(MainCamera,True) + 135,EntityRoll(SonicSoul)
ElseIf KeyDown(205);Right
RotateEntity SonicSoul,EntityPitch(SonicSoul),EntityYaw(MainCamera,True) - 135,EntityRoll(SonicSoul)
Else
RotateEntity SonicSoul,EntityPitch(SonicSoul),EntityYaw(MainCamera,True) + 180,EntityRoll(SonicSoul)
EndIf
MoveEntity SonicSoul,0,0,.3
Else
If KeyDown(203);Left
RotateEntity SonicSoul,EntityPitch(SonicSoul),EntityYaw(MainCamera,True) + 90,EntityRoll(SonicSoul)
MoveEntity SonicSoul,0,0,.3
ElseIf KeyDown(205);Right
RotateEntity SonicSoul,EntityPitch(SonicSoul),EntityYaw(MainCamera,True) - 90,EntityRoll(SonicSoul)
MoveEntity SonicSoul,0,0,.3
Else
EndIf
EndIf
If EntityCollided(SonicSoul,LevelColl)
Gravity = 0
Else
If Gravity > -1 Then Gravity = Gravity - .005
TranslateEntity SonicSoul,0,Gravity,0
EndIf
End FunctionYou can see for yourself how it won't work. I used the wheel code from Mark Sibly's "driver.bb" demo, in the B3D samples. The terrain heightmap and texture are from the same demo.
This demo from Stevie G is pretty close to what I need:
Graphics3D 640,480,16,1
Global LIGHT = CreateLight()
Global PLANE = CreatePlane()
EntityColor PLANE, 200,100,100
texture = CreateTexture( 32, 32 )
SetBuffer TextureBuffer( texture )
For y = 0 To 1
For x = 0 To 1
Color 100, 150+25*( ( x+y) Mod 2 ) , 100
Rect x*16,y*16,16,16,1
Next
Next
SetBuffer BackBuffer()
ScaleTexture texture, 50,50
EntityTexture PLANE, texture
FreeTexture texture
Global CUBE = CreateCube() : FitMesh CUBE, -2,0,-2,4,10,4
Tmp = CreateCube() : FitMesh Tmp, -1,7,2,2,2,2 : AddMesh Tmp, CUBE : FreeEntity Tmp
Global TARGET = CreatePivot()
Global CAMERApivot = CreatePivot()
Global CAMERA = CreateCamera( CAMERApivot )
PositionEntity CAMERA, 0,50,-50
PointEntity CAMERA , CAMERApivot
While Not KeyDown(1)
PositionEntity CAMERApivot , EntityX( CUBE ) , 0, EntityZ( CUBE )
TurnEntity CAMERApivot, 0 , KeyDown(31) - KeyDown(30) , 0
;move relative to camera
Mx# = KeyDown(205) - KeyDown(203)
Mz# = KeyDown(200) - KeyDown(208 )
If Mx <> 0 Or Mz <> 0
;move relative to camera
TFormVector Mx, 0, Mz , CAMERApivot , 0
TranslateEntity CUBE, TFormedX(), 0, TFormedZ()
;turn relative to movement
PositionEntity TARGET, EntityX( CUBE ) + TFormedX() , 0, EntityZ( CUBE ) + TFormedZ()
TurnEntity CUBE, 0 , DeltaYaw( CUBE, TARGET ) * .25, 0
EndIf
RenderWorld()
Flip
Wend
The only problem here is that the camera stays statically in whatever position it's placed by the user. In other words, if you turn in this demo, the camera doesn't move back behind you as I need it to.