Here's the main loop
; The actual level execution
UI_Object=ODE_object_list\head\next_node\next_node
EntityTexture buttons(UI_STOPGO)\sprite, buttons(UI_STOPGO)\texture2
ShowEntity buttons(UI_BLANKER)\sprite
ShowEntity buttons(UI_TRYAGAIN)\sprite
ShowEntity buttons(UI_STOPGO)\sprite
buttons(UI_TRYAGAIN)\active=True
buttons(UI_STOPGO)\active=True
buttons(UI_EXIT_MISSION)\active=True
EntityAlpha buttons(UI_TRYAGAIN)\sprite,1.0
FlushKeys()
shiftycam\move_spd=30.0
frame=0 : objects_stopped=0 : run_time=0
mouse\current_object=0
mouse\holding_object=0
;Apply initial forces
temp=ODE_Object_list\head
While temp<>Null
If temp\body
v#=temp\force\x
v#=temp\force\y
v#=temp\force\z
dBodyAddRelForce (temp\body, temp\force\x, 0.0, 0.0)
dBodyVectorToWorld(temp\body, 1.0,0.0,0.0)
dBodySetLinearVel (temp\body, dVectorX()*temp\force\y,dVectorY()*temp\force\y,dVectorZ()*temp\force\y)
EndIf
temp=temp\next_node
Wend
start_time=MilliSecs()
While program_state=STATE_RUNNING
frame_time=MilliSecs()-start_time
start_time=MilliSecs()
update_time=update_time+frame_time
UPDATE_CUSTOM_PHYSICS=False
If update_time/20>0
UPDATE_CUSTOM_PHYSICS=True
update_time=update_time Mod 20
CaptureWorld()
EndIf
If UPDATE_CUSTOM_PHYSICS
Shiftycam_Update(shiftycam)
EndIf
tween#=(update_time Mod 20)/20.0
mouseupdate()
If play_state>0
run_time=run_time+frame_time
;#Region Per object entry check
temp=ODE_Object_list\head
While temp<>Null
If Not temp\on_set
If frame>=temp\entry_time*5; And run_time<(temp\entry_time*100)+20
enter_stage_left(temp)
EndIf
EndIf
temp=temp\next_node
Wend
;#End Region
;#Region Advance animation and camera
frame=advance_simulation(frame)
If UPDATE_CUSTOM_PHYSICS
;#Region Update anims
angle#=angle#+10
angle#=wrapfloat(angle#,0,360)
TurnTex(tex_fan,angle#)
;#End Region
EndIf
;#End Region
clock_text$=(frame/50)+"."+(((frame Mod 50)*2)/10)
TG_Change_Text(UI_TIME_TEXT,clock_text$)
EndIf
;#Region Per object respositioning
temp=ODE_Object_list\head
While temp<>Null
If temp\body
If dBodyIsEnabled(temp\body)
update_object(temp)
EndIf
EndIf
If Abs(shiftycam\zoom-shiftycam\zoom_target)>0.01
If temp\outline_mesh
rescale_outlines(temp,shiftycam\zoom)
EndIf
EndIf
temp=temp\next_node
Wend
;#End Region
;#Region Camera controls
If mouse\speedz<>0
mouse_z#=mouse\speedz*0.25
Shiftycam_zoom(shiftycam,mouse_z)
EndIf
If mouse\x<TG_cam\siz_x ; if in view window
If mouse\bl\down And (Not mouse\br\down)
If mouse\bl\downtime>100
Shiftycam_Turn_Camera(shiftycam,mouse\speedy / 25.0,-mouse\speedx / 25.0,0)
Else
found_object=get_object(shiftycam\camera)
If found_object=1000
If shiftycam\target_object<>ODE_object_list\current\mesh
Shiftycam_Set_Tracking_Target(shiftycam,ODE_object_list\current\mesh)
shiftycam\motion_state=CAMERA_TRACKING
Else
; Shiftycam_Turn_Camera(shiftycam,mouse\speedy / 25.0,-mouse\speedx / 25.0,0)
EndIf
Else
; Shiftycam_Set_Tracking_Target(shiftycam,0)
; shiftycam\motion_state=CAMERA_TRACKING
EndIf
EndIf
mouse\x=mx
mouse\y=my
MoveMouse mx,my
UI_object=ODE_object_list\head
ElseIf mouse\br\down And (Not mouse\bl\down)
shiftycam\motion_state=CAMERA_TRACKING
PositionEntity shiftycam\target,0,50,0,1
Shiftycam_Turn_Rostrum(shiftycam,mouse\speedy / 10.0,-mouse\speedx / 10.0,0)
mouse\x=mx
mouse\y=my
MoveMouse mx,my
Else If mouse\br\down And mouse\bl\down
Shiftycam_zoom(shiftycam,mouse\speedy*-0.01)
mouse\x=mx
mouse\y=my
MoveMouse mx,my
EndIf
EndIf
;#End Region
;#Region Keyboard Shortcuts
If KeyHit(57)
play_state=play_state*-1
If play_state=-1
EntityTexture buttons(UI_STOPGO)\sprite, buttons(UI_STOPGO)\texture2
If AUDIO_FLAG
chnl_Bing=PlaySound(snd_Bing)
ChannelPitch chnl_Bing,32000
EndIf
Else
EntityTexture buttons(UI_STOPGO)\sprite, buttons(UI_STOPGO)\texture1
If AUDIO_FLAG
chnl_Bing=PlaySound(snd_Bing)
ChannelPitch chnl_Bing,44100
EndIf
EndIf
EndIf
If KeyHit(31)
debug_break=True
EndIf
;#End Region
;#Region Level End
If current_level=13
; Determine if goals have been achieved
; For each target, test Objects in group satisfy requirement
win=True
For n=1 To 2
; Loop through Object list
; Set win to 0 and exit if violation found
temp=ODE_Object_list\head\next_node
While temp<>Null
If temp\group=targets(n)\group
Select targets(n)\class
Case TARGET_INCLUSION
x_distance#=EntityX(temp\mesh,1)-targets(n)\pos\x
z_distance#=EntityZ(temp\mesh,1)-targets(n)\pos\z
x_distance#=Sqr((x_distance*x_Distance)+(z_distance*z_Distance))
If x_distance>targets(n)\radius
win=False
EndIf
End Select
EndIf
temp=temp\next_node
Wend
Next
test#=clock_text
If test<17.5
win=win*2
EndIf
If win Or frame>TIMEOUT
program_state=STATE_LEVEL_END
EndIf
Else If objects_stopped>=STOP_PERIOD Or frame>TIMEOUT
; Determine if goals have been achieved
; For each target, test Objects in group satisfy requirement
win=True
n=0
While n<=MAX_TARGETS And win>0
; Loop through Object list
; Set win to 0 and exit if violation found
If targets(n)\radius>1
temp=ODE_Object_list\head\next_node
While temp<>Null
If temp\group=targets(n)\group
Select targets(n)\class
Case TARGET_INCLUSION
x_distance#=EntityX(temp\mesh,1)-targets(n)\pos\x
z_distance#=EntityZ(temp\mesh,1)-targets(n)\pos\z
x_distance#=Sqr((x_distance*x_Distance)+(z_distance*z_Distance))
If x_distance>targets(n)\radius
win=False
EndIf
Case TARGET_EXCLUSION
x_distance#=EntityX(temp\mesh,1)-targets(n)\pos\x
z_distance#=EntityZ(temp\mesh,1)-targets(n)\pos\z
x_distance#=Sqr((x_distance*x_Distance)+(z_distance*z_Distance))
If x_distance<targets(n)\radius
win=False
EndIf
Case TARGET_ROT_SPEED
If Abs(temp\joint\rot_force1\x)/Abs(targets(n)\pos\x)>0.95 And Abs(temp\joint\rot_force1\x)/Abs(targets(n)\pos\x)<1.05 ; 5% deviation
win=win*2 ; Multiply win is Passed
EndIf
End Select
EndIf
temp=temp\next_node
Wend
EndIf
n=n+1
Wend
;Hard coded conditions
Select current_level
Case 2
temp=ODE_Object_list\head\next_node
While temp<>Null
If temp\geom_type=GEOM_ROBOHEAD
If EntityInView (temp\mesh, shiftycam\camera)
x#=EntityX(shiftycam\camera)
y#=EntityY(shiftycam\camera)
z#=EntityZ(shiftycam\camera)
dx#=EntityX(temp\mesh)
dy#=EntityY(temp\mesh)
dz#=EntityZ(temp\mesh)
dx#=(dx-x)*2
dy#=(dy-y)*2
dz#=(dz-z)*2
found_object = LinePick (x,y,z,dx,dy,dz)
If found_object=temp\mesh
win=win*2
EndIf
EndIf
EndIf
temp=temp\next_node
Wend
Case 3
If EntityX(shiftycam\camera)>-120.0
win=win*2
EndIf
Case 4
If Int(buttons(4)\val)=5
win=win*2
EndIf
End Select
program_state=STATE_LEVEL_END
EndIf
;#End Region
If mouse\bl\hit
control_test=TG_Mouse_Over()
If control_test<>mouse\current_object
mouse\current_object=control_test
EndIf
If control_test>0
Select mouse\current_object
Case UI_EXIT_GADGET
UI_Confirm_Exit()
Case UI_EXIT_MISSION
program_state=STATE_SELECT_LEVEL
If AUDIO_FLAG
chnl_Bing=PlaySound(snd_Bing)
EndIf
Case UI_STOPGO
If play_state=1
play_state=-1
EntityTexture buttons(UI_STOPGO)\sprite, buttons(UI_STOPGO)\texture1
If AUDIO_FLAG
chnl_Bing=PlaySound(snd_Bing)
ChannelPitch chnl_Bing,32000
EndIf
Else
play_state=1
EntityTexture buttons(UI_STOPGO)\sprite, buttons(UI_STOPGO)\texture2
If AUDIO_FLAG
chnl_Bing=PlaySound(snd_Bing)
ChannelPitch chnl_Bing,44100
EndIf
EndIf
Case UI_TRYAGAIN
play_state=-1
erase_list()
restore_scene(shiftycam)
program_state=STATE_LEVEL_SETUP
If AUDIO_FLAG
chnl_Bing=PlaySound(snd_Beeou)
EndIf
End Select
EndIf
EndIf
mx = mouse\X
my = mouse\Y
TG_Draw_UI()
frame_time=MilliSecs()-start_time
If frame_time<12 Then Delay 2
VWait
Flip False
Wend
End Function
Here's the ODE update...
Function advance_simulation(t%)
; Advances the simluation, incrementing frame count
; Performs friction calculations
; Disables 'non-existant' objects
; Perform custom force processing 50 times a second
If UPDATE_CUSTOM_PHYSICS
dSpaceCollide(ODE_space,ODE_world,ODE_contactGroup)
If t>100
stop_time=1
EndIf
temp=ODE_object_list\head
While temp<>Null
If temp\prop And temp\magnetism>0
collision_object=ODE_object_list\head
While collision_object<>Null
If collision_object\body
If collision_object\magnetism>0 And dBodyIsEnabled(collision_object\body) And collision_object\on_set
apply_magnetism(temp, collision_object)
EndIf
EndIf
collision_object=collision_object\next_node
Wend
EndIf
Select temp\geom_type
Case GEOM_FAN
;if it's a fan, apply fan forces to all other objects...
;Collision_object is used as a temp
collision_object=ODE_object_list\head\next_node
While collision_object<>Null
If collision_object\body
If collision_object\prop=False And collision_object\on_set
apply_blower(temp, collision_object)
EndIf
EndIf
collision_object=collision_object\next_node
Wend
; Case GEOM_MAGNET
;if it's a magnet, apply magnet forces to all other objects...
;Collision_object is used as a temp
Default
; Disable out of bounds objects
; check if all objects have stoped
; accumulate magnetic charges
; rolling resistance for spheres
If temp\on_set
If temp\gravity>0
collision_object=ODE_object_list\head
While collision_object<>Null
If collision_object\body
If collision_object\prop=False And dBodyIsEnabled(collision_object\body) And collision_object\on_set
Apply_Gravity(temp, collision_object)
EndIf
EndIf
collision_object=collision_object\next_node
Wend
EndIf
If temp\body
; *** Disable out of bounds objects ###############################
If Abs(dBodyGetPositionX(temp\body))>ARENA_X_RADIUS Or Abs(dBodyGetPositionZ(temp\body))>ARENA_Z_RADIUS
dBodyDisable(temp\body)
HideEntity temp\mesh
HideEntity temp\outline_mesh
EndIf
If dBodyIsEnabled(temp\body)
; *** Object stopped ########################################
If debug_break=True Then Stop
If stop_time And (temp\joint\joint_type<=0)
bx#=dBodyGetLinearVelX(temp\body)
by#=dBodyGetLinearVelY(temp\body)
bz#=dBodyGetLinearVelZ(temp\body)
b#=Sqr((bx*bx)+(by*by)+(bz*bz))
If b>0.02
stop_time=0 ; record if all objects are static
End If
EndIf
; *** Detect magnetism #####################################
magnetic_collision=False
numCollisions=dGeom1CountCollisions(temp\geom)
If numCollisions>0
For p=1 To numCollisions
collision_geom=dGeom1CollisionGeom(temp\geom,p)
collision_object=ODE_object_list\head
While collision_object<>Null
If collision_object\geom=collision_geom
Exit
EndIf
collision_object=collision_object\next_node
Wend ; Fetch collision object
If collision_object<>Null
If collision_object\geom_type=GEOM_MAGNET Or collision_object\magnetism=MAGNETIC_TIME
magnetic_collision=True
Exit
EndIf
EndIf
Next
EndIf
If Not magnetic_collision
numCollisions=dGeom2CountCollisions(temp\geom)
If numCollisions>0
For p=1 To numCollisions
collision_geom=dGeom2CollisionGeom(temp\geom,p)
collision_object=ODE_object_list\head
While collision_object<>Null
If collision_object\geom=collision_geom
Exit
EndIf
collision_object=collision_object\next_node
Wend ; Fetch collision object
If collision_object<>Null
If collision_object\geom_type=GEOM_MAGNET Or collision_object\magnetism=MAGNETIC_TIME
magnetic_collision=True
Exit
EndIf
EndIf
Next
EndIf
EndIf ; Magnetic collision
; magnetic_collision=True if collided with magnetic object
If magnetic_collision And temp\magnetism>0
If temp\magnetism<MAGNETIC_TIME
temp\magnetism=temp\magnetism+1
If temp\magnetism=2
; dGeomContactSetMu(temp\geom,10000)
EndIf
Else
dBodyDisable(temp\body)
EndIf
Else
If (Not temp\magnetism) And temp\magnetism>=MAGNETIC_TIME
temp\magnetism=1
EndIf
EndIf
; *** Sphere Rotation Dampening #################################
If temp\geom_type=GEOM_SPHERE
hit_ground=False
numCollisions=dGeom1CountCollisions(temp\geom)
If numCollisions>0
; For each collision, test if with ground
For p=1 To numCollisions
collision_geom=dGeom1CollisionGeom(temp\geom,p)
collision_object=ODE_object_list\head
While collision_object<>Null
If collision_object\geom=collision_geom
Exit
EndIf
collision_object=collision_object\next_node
Wend ; Fetch collision object
If collision_object<>Null
If collision_object\geom_type=GEOM_TABLE
hit_ground=True
Exit
EndIf
EndIf
Next
EndIf
numCollisions=dGeom2CountCollisions(temp\geom)
If numCollisions>0 And hit_ground=False
; For each collision, test if with ground
For p=1 To numCollisions
collision_geom=dGeom2CollisionGeom(temp\geom,p)
collision_object=ODE_object_list\head
While collision_object<>Null
If collision_object\geom=collision_geom
Exit
EndIf
collision_object=collision_object\next_node
Wend ; Fetch collision object
If collision_object<>Null
If collision_object\geom_type=GEOM_TABLE
hit_ground=True
Exit
EndIf
EndIf
Next
EndIf
If hit_ground
dBodyGetAngularVel(temp\body)
xa#=dVectorX()
ya#=dVectorY()
za#=dVectorZ()
angular_vel#=Sqr(xa^2+ya^2+za^2)*10
If angular_vel>0
; normalize vector
xa=xa/angular_vel
ya=ya/angular_vel
za=za/angular_vel
EndIf
dBodyGetLinearVel(temp\body)
xl#=dVectorX()
yl#=dVectorY()
zl#=dVectorZ()
linear_vel#=Sqr(xl^2+yl^2+zl^2)*10
If linear_vel>0
; normalize vector
xl=xl/linear_vel
yl=yl/linear_vel
zl=zl/linear_vel
EndIf
d#=Abs(Abs(linear_vel)-(temp\siz\x*Abs(angular_vel)))
If d< 0.02 And d>=0.0 ; angular and linear velocities matched
; Perform slowdown
reduction#=(temp\mat\rotational_friction)/(Log(temp\weight)+1)
d=linear_vel-reduction
If d>0
xa=xa*(angular_vel-reduction);/ode\size
ya=ya*(angular_vel-reduction);/ode\size
za=za*(angular_vel-reduction);/ode\size
dBodySetAngularVel(temp\body,xa,ya,za)
xl=xl*(linear_vel-reduction);/ode\size
yl=yl*(linear_vel-reduction);/ode\size
zl=zl*(linear_vel-reduction);/ode\size
dBodySetLinearVel(temp\body,xl,yl,zl)
Else
dBodySetAngularVel(temp\body,0,0,0)
dBodySetLinearVel(temp\body,0,0,0)
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
End Select
temp=temp\next_node
Wend
NUM_UPDATE_CUSTOM_PHYSICS=NUM_UPDATE_CUSTOM_PHYSICS+1
dWorldQuickStep(ODE_world,ODE_Resolution#)
dJointGroupEmpty(ODE_contactGroup)
dSpaceCollide(ODE_space,ODE_world,ODE_contactGroup)
dWorldQuickStep(ODE_world,ODE_Resolution#)
dJointGroupEmpty(ODE_contactGroup)
dSpaceCollide(ODE_space,ODE_world,ODE_contactGroup)
dWorldQuickStep(ODE_world,ODE_Resolution#)
dJointGroupEmpty(ODE_contactGroup)
objects_stopped=objects_stopped+stop_time
t=t+1
EndIf
Return t
End Function
I've just tried on a PIII 600 MHz and things were much, much better. My target machine of an 800 MHz PIII should be reached. I don't know what the K6 is all about, and I was surprised the P3 is so much faster (both have 256 Mb RAM, Win98). Of course, now I'm getting random MAVs to worry about, so I'll have to stick Blitz on there and investigate. Hopefully this problem can be laid to rest without us ever having to solve it!