Page 2 of 2

Re: When moving, the speed can change unpredictably. 3d FPS

Posted: Tue Sep 16, 2025 10:37 pm
by siesit
In flight mode (#cam_type = 1) I have almost no problems.
Except for the sprite that disappears in a certain position.

Now the main problem looks like this:
Movement speed and jump height directly depend on FPS.
In the example, you can see the jump height on the graph.
With the constant #render_fps = 60 you can set FrameRate to 20 and see how the jump height has changed.

Is there something wrong with the HandleEntity procedure?

Code: Select all

;- CONST

Global scale=20*10
Global.i camR     = 1000          ;Camera range

#PlayerSpeed = 60
#CameraSpeed = 0.8
#window = 2
#kam_0 = 1

#plane = 0
#planent = 0
#cam_type = 2  ;main -2,  - 1
#Light=3

#max_ent = 5;5
#render_fps = 60
;#render_fps = 20

init=0

Global ScreenWidth, ScreenHeight

Structure s_Key
      Up.i
      Down.i
      Left.i
      Right.i
      Jump.i
EndStructure

Structure s_Entity
      EntityBody.i
      BodyOffsetY.f
      elapsedTime.f
      rot_x.f
      rot_y.f
      rot_z.f
      
      Fov.f
      Key.s_Key
      MainNode.i
      CameraNode.i
      HandNode.i
      ForwardNode.i
      StrafeNode.i
      LampNode.i
      hidelamp.i
      HideMenu.i
EndStructure
Global main_Entity.s_Entity

;-Declare
Declare HandleEntity(*Entity.s_Entity)
Declare OnGround(*Entity.s_Entity)

Define Robot.s_Entity
Global prefix$ = "main"
Global Scroll_stor, Scroll_inv

;;;;;;;;;;;;;;;;

Global global_x.l = 24;256-200
Global global_y.l = 12;32-10
Global global_z.l = 24;256-200

Global flash_on = 0

Declare g_start(type)

Structure game
      state_base_lamp.l
      wrds_id.l
      cur_save_ver.l
      item_up.l
      inv.l
      room_id.l
      inventory.s
      th_light.l
      sg.l
      flashlight.l
EndStructure
Global game.game

Structure sg_ent
      mesh.l
      ent.l
EndStructure
Global NewList sg_ent.sg_ent()

Global NewList Lines.l()
Global NewList Lines2.l()

;- INIT
InitEngine3D();#PB_Engine3D_EnableCG)
InitSprite()
InitKeyboard()
InitMouse()


If #window=1
      OpenWindow(#window, 0, 0, 1280, 1024, "FPS-Test", #PB_Window_ScreenCentered)
      OpenWindowedScreen(WindowID(#window), 10, 10, 1280-20, 1024-20, 1, 10, 10, #PB_Screen_WaitSynchronization)
EndIf

If #window=2
      ExamineDesktops()
      OpenScreen(DesktopWidth(0), DesktopHeight(0), 32, "test", #PB_Screen_SmartSynchronization);#PB_Screen_NoSynchronization
      ;AntialiasingMode(#PB_AntialiasingMode_x6)

      AntialiasingMode(#PB_AntialiasingMode_x6)
      MaterialFilteringMode(#PB_Default,#PB_Material_Trilinear,16)

      SetFrameRate(#render_fps)
EndIf

Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Scripts", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models", #PB_3DArchive_FileSystem)
;Add3DArchive("D:\~3D\m2", #PB_3DArchive_FileSystem)

Parse3DScripts()

Enumeration mesh 100 Step 10
      #mesh_baseblock
EndEnumeration

Global FPS, block$, index_cur.l, jmp
Global light2

LoadFont(0,"arial",10)


;> LoadMesh

;Robot Body
LoadMesh(0, "robot.mesh")
TransformMesh(0, 0, 0, 0, 1, 1, 1, 0, -90, 0)

LoadMesh(1, "AKM.mesh")
LoadMesh(2, "ninja.mesh")
; TransformMesh(2, 0, 0, 0, 1, 1, 1, 0, 90, 0)

LoadTexture(0, "Dirt.jpg")

;- Material
CreateMaterial(1, LoadTexture(1,"viseur-jeux.png"))
MaterialBlendingMode(1, #PB_Material_AlphaBlend)

CreateMaterial(4, LoadTexture(4, "Dirt.jpg"))
CreateMaterial(5, LoadTexture(5, "t1.jpg"))
CreateMaterial(6, LoadTexture(6, "r2skin.jpg"))
CreateMaterial(7, LoadTexture(7, "RustySteel.jpg"))

;LoadMesh(#mesh_baseblock, "Barrel.mesh");
LoadMesh(#mesh_baseblock, "chassis.mesh");
TransformMesh(#mesh_baseblock, 0, 0, 0, 10, 10, 10, 0, 0, 0)

;CreateCube(#mesh_baseblock, 180)
;TransformMesh(#mesh_baseblock, -100, 10, -100,  1.1, 1.1, 0.1,  90, 0, 0)

BuildMeshShadowVolume(#mesh_baseblock)
NormalizeMesh(#mesh_baseblock) 

;<




Procedure menu(LastFrame.l, LastFrame2.l)
Protected p=4

Macro DT(t1, etat=-1)
      DrawText(8,p,t1)
;     If etat=0:DrawText(140,p,"OFF"):ElseIf etat=1:DrawText(140,p,"ON"):EndIf
      p+17
EndMacro



CreateSprite(0,180,380,#PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(0))
DrawingMode(#PB_2DDrawing_AllChannels)
DrawingFont(FontID(0))
Box(0,0,180,380,$22ffffff)
;DrawingMode(#PB_2DDrawing_AllChannels|#PB_2DDrawing_Outlined)
; Box(0,0,180,380,$44ffffff)
BackColor($22ffffff)
FrontColor($ffffffff)

dt(block$)

dt("Triangles:"+Str(Engine3DStatus(#PB_Engine3D_NbRenderedTriangles)))
dt("Batches:"+Str(Engine3DStatus(#PB_Engine3D_NbRenderedBatches)))
dt("CurrentFPS:"+Str(Engine3DStatus(#PB_Engine3D_CurrentFPS)))

dt("")

dt("WSAD + Mouse")
dt("")
dt("FPS "+Str(FPS),0)
dt("[Esc] = Quit")



ResetList(Lines())
AddElement(Lines())
Lines() = LastFrame
line=0
max=0
min=-1

While NextElement(Lines())
      If Lines()>max
            max=Lines()
      EndIf
; If line = 0 Or (line < min And )
; 
; EndIf


      If line>160 
            ;PreviousElement(Lines())
            DeleteElement(Lines())
      Else
            ;LineXY(10, 250, 10, 200, RGBA(226, 0, 218, 150))
            LineXY(10+line, 280, 10+line, 280-Lines(), RGBA(226, 0, 218, 150))
            line+1
      EndIf
Wend

dt("fps max: "+Str(max)+" "+Str(ListSize(Lines())))






LastFrame2 = jmp; * 0.01


ResetList(Lines2())
AddElement(Lines2())
Lines2() = LastFrame2
line=0
max=0
min=-1

While NextElement(Lines2())
      If Lines2()>max
            max=Lines2()
      EndIf
      If line>160 
            ;PreviousElement(Lines2())
            DeleteElement(Lines2())
      Else
            LineXY(10+line, 360, 10+line, 360-Lines2(), RGBA(226, 0, 218, 150))
            line+1
      EndIf
Wend

dt("jump max: "+Str(max)+" "+Str(ListSize(Lines2())))


; PushListPosition(_wrd())
; SelectElement(_wrd(), index_cur)
; r_x=_wrd()\x
; r_y=_wrd()\y
; r_z=_wrd()\z
; 
; sti=_wrd()\wrd_struc


StopDrawing()


EndProcedure



Procedure Create_static(sg, mesh, Material, x, y, z, body=1, pick_mask=1, ent_grp=1, ent_mask=1, vis_mask=2);, scale=1, rot_x=0, rot_y=0, rot_z=0

ok=0
ResetList(sg_ent())
While NextElement(sg_ent())
      If sg_ent()\mesh = mesh
            ok=1
            ent = sg_ent()\ent
      EndIf
Wend

If ok=0
      ent = CreateEntity(#PB_Any, mesh, Material, 0, 0, 0, pick_mask, vis_mask)
      AddElement(sg_ent())
      sg_ent()\mesh = mesh
      sg_ent()\ent = ent

      ;EntityRenderMode(ent, #PB_Shadow_None)
      EntityRenderMode(ent, #PB_Entity_CastShadow)  
      SetRenderQueue(EntityID(ent), 50 , 1000)

      HideEntity(ent, 1)
EndIf

If ent
      If body
            Collision_ent = CreateEntity(#PB_Any, mesh, #PB_Material_None, x, y, z, pick_mask, vis_mask)
            CreateEntityBody(Collision_ent, #PB_Entity_StaticBody)
            SetEntityCollisionFilter(Collision_ent, ent_grp, ent_mask)
            HideEntity(Collision_ent, 1)
      EndIf
     
      If vis_mask=2
            AddStaticGeometryEntity(sg, EntityID(ent), x, y, z, 1, 1, 1)
            ;HideEntity(ent, 1)
      EndIf
EndIf

ProcedureReturn ent
EndProcedure

Procedure StaticGeometry()
Define rf_x, rf_y, rf_z, r_x, r_y, r_z, f, ok, inn, x, z, y
Define.i ent, sg
Define rx, ry, rz, rrx, rry, rrz, inner_room, light_lamp, room$


sg = CreateStaticGeometry(#PB_Any, global_x*scale, global_y*scale, global_z*scale, 0)
Debug "Static " + sg
  
For u = 0 To 12
For i = 0 To 12
      create_static(sg, MeshID(#mesh_baseblock), MaterialID(4), (-1+i)*scale, (0)*scale, (-1+u)*scale)
      cnt+1
Next
Next


For t = 0 To #max_ent
For u = 0 To 12
For i = 0 To 12
      create_static(sg, MeshID(#mesh_baseblock), MaterialID(4), (-12+i)*scale, (t)*scale/8, (-6+u)*scale)
      cnt+1
Next
Next
Next

Debug cnt
; ProcedureReturn sg

ProcedureReturn sg
EndProcedure

Procedure game_start()
Define.i ground, t, i

;- config
game\state_base_lamp=1
;game\state_base_lamp=3


game\sg=StaticGeometry()
Debug game\sg
BuildStaticGeometry(game\sg)
Debug "SG==="

      PosMain_x = 0*scale
      PosMain_y = 5*scale
      PosMain_z = 0*scale

     
      MoveEntity(main_Entity\EntityBody, PosMain_x, PosMain_y, PosMain_z, #PB_Absolute)
      SoundListenerLocate(PosMain_x, PosMain_y, PosMain_z)
      MoveNode(main_Entity\MainNode, PosMain_x, PosMain_y - main_Entity\BodyOffsetY, PosMain_z, #PB_Absolute)
      
      Debug main_Entity\EntityBody
      Debug EntityX(main_Entity\EntityBody)
      Debug EntityY(main_Entity\EntityBody)
      Debug EntityZ(main_Entity\EntityBody)
      
      main_Entity\rot_x = Rot_x
      main_Entity\rot_y = Rot_y
      main_Entity\rot_z = Rot_z

      RotateEntity(main_Entity\EntityBody, 0, main_Entity\Rot_y, 0, #PB_Absolute)
      RotateNode(main_Entity\CameraNode, main_Entity\Rot_x, 0, 0, #PB_Absolute)
      RotateNode(main_Entity\HandNode, main_Entity\Rot_x, 0, 0, #PB_Absolute)
      RotateNode(main_Entity\MainNode, 0, EntityYaw(main_Entity\EntityBody), 0)

EndProcedure

;- -----------------------------------------------------------------------

global_x.l = 12;256-200
global_y.l = 3;32-10
global_z.l = 12;256-200
flash_on = 1
prefix$ = "main_0"

EnableExplicit

;- START
Define.f KeyX, KeyY, MouseX, MouseY
Define nx.f, nz.f, Boost.f = 2.2, Yaw.f, Pitch.f, zaehler
Define.i ground, t, i
Define.b firster = #True

Define Mesh_plane, ent_plane, Mesh_robot, ent_robot, light1, Light.l

Mesh_plane=CreatePlane(#PB_Any, global_x*scale*2, global_z*scale*2, scale, scale, 20, 20)
ground = GetScriptMaterial(#PB_Any, "Scene/GroundBlend")
;TransformMesh(Mesh_plane, 256*10, -10, 256*10, 1, 1, 1, 0, 0, 0)
ent_plane=CreateEntity(#PB_Any, MeshID(Mesh_plane), MaterialID(ground), 0, -1.5, 0)
EntityRenderMode(ent_plane, 0)      
CreateEntityBody(ent_plane, #PB_Entity_StaticBody)

;- GAME

;WorldShadows(#PB_Shadow_Modulative, #PB_Default, RGB(205, 205, 205), 128)

AmbientColor(RGB(22, 14, 35))
Fog(RGB(126, 58, 1), 2048+5, 1*scale, 28*scale)

; WorldDebug(#PB_World_DebugBody)
; WorldDebug(#PB_World_DebugEntity)

EnableWorldCollisions(1) 
EnableWorldPhysics(1)
WorldGravity(-90.806)

AntialiasingMode(#PB_AntialiasingMode_x6)

light2 = CreateLight(#PB_Any ,RGB(255*0.4, 255*0.4,255*0.4), (1*scale), (1*scale), (1*scale), #PB_Light_Spot)
SetLightColor(light2, #PB_Light_SpecularColor, RGB(128, 50, 50))
LightAttenuation(light2, 8050, 0.9)
SpotLightRange(light2, 1, 60, 1)

Global lamp_y = -35
Global lamp_x = 15
Global lamp_z = 0
Global lamp_i = 0
Global lamp_o = 70
Global lamp_f.f = 1

Define onflore = 15



;- Gun
CreateEntity(1, MeshID(1), MaterialID(6))
ScaleEntity(1, 0.05, 0.05, 0.05)
RotateEntity(1, 90, -85, 0)

;- Body
CreateEntity(0, MeshID(0), #PB_Material_None, 5*scale-100+30, 3*scale+50, 5*scale-100)
SetEntityAttribute(0,#PB_Entity_LinearSleeping,0)
SetEntityAttribute(0,#PB_Entity_AngularSleeping, 0.0)
ScaleEntity(0, 0.8, 0.8, 0.8)    
HideEntity(0, 1)
CreateEntityBody(0, #PB_Entity_CapsuleBody, 60.00, 0.0001, 1)
; EntityAngularFactor(0, 0, 0, 0)

;-Billboard
CreateBillboardGroup(0, MaterialID(1), 0.05, 0.05, 0, 0, 13)
AddBillboard(0, 0, 0, 0)

With main_Entity
      \Fov = 70

      \rot_x = 0
      \rot_y = 0
      \rot_z = 0

      \EntityBody = 0
      \BodyOffsetY = 15
      If #cam_type = 2
            \Key\Down  = #PB_Key_S ;Down
            \Key\Left  = #PB_Key_A ;Left
            \Key\Right = #PB_Key_D;Right
            \Key\Up    = #PB_Key_W;Up
            \Key\Jump  = #PB_Key_Space
      ElseIf #cam_type = 1 
            \Key\Down  = #PB_Key_Down
            \Key\Left  = #PB_Key_Left
            \Key\Right = #PB_Key_Right
            \Key\Up    = #PB_Key_Up
            \Key\Jump  = #PB_Key_Space
      EndIf
      
      \MainNode   = CreateNode(#PB_Any) ; Entity position
      \ForwardNode= CreateNode(#PB_Any,  0,  0, -3) ; Direction normalized
      \StrafeNode = CreateNode(#PB_Any, -1,  0,  0) ; Direction normalized
      \LampNode = CreateNode(#PB_Any, 0,  50,  10) ; 

;       \LampNode = CreateNode(#PB_Any, 0,  50,  10) ; 
      \HandNode   = CreateNode(#PB_Any,  6, 43,  -8) ; Hand position

      \CameraNode = CreateNode(#PB_Any,  0, 50,  -10) ; Camera position 40

      \HideMenu = 1
      
      AttachNodeObject(\MainNode  , NodeID(\CameraNode))
      AttachNodeObject(\MainNode  , NodeID(\HandNode))
      AttachNodeObject(\MainNode  , NodeID(\ForwardNode))
      AttachNodeObject(\MainNode  , NodeID(\StrafeNode))
      AttachNodeObject(\MainNode  , NodeID(\LampNode))

      AttachNodeObject(\HandNode  , EntityID(1))

      AttachNodeObject(\CameraNode, BillboardGroupID(0))
      
      RotateNode(\HandNode, 5, 0, 0, #PB_Relative)
      MoveBillboardGroup(0, 0, 0, -15)
      MoveEntity(1, 0.1, -0.1, 0.01)

; RotateEntity(\EntityBody, 0, 90, 0, #PB_Absolute)

EndWith

Procedure.i Timer(deltatime.i); from miso
  Static.i LastTick
  If ElapsedMilliseconds()-LastTick>deltatime.i
    LastTick=ElapsedMilliseconds()
    ProcedureReturn(#True)
  EndIf
  ProcedureReturn(#False)
EndProcedure

  
;- Camera float
If #cam_type = 1  
      ;-Camera
      CreateCamera(#kam_0, 0, 0, 100, 100, 2)
      ; MoveCamera(#kam_0, -50, 50, -50, #PB_Absolute)
      MoveCamera(#kam_0, 0*scale, 5*scale, 5*scale, #PB_Absolute)
      
      
;       CameraLookAt(#kam_0, 20*scale, 0, 20*scale)
;       CameraBackColor(#kam_0, RGB(0 , 0, 0))
      CameraRange(#kam_0, 0.08, camR*4)
EndIf

;- Camera main
If #cam_type = 2   
      CreateCamera(0, 0, 0, 100, 100)
      CameraRange(0, 0.08, 2000)
      ; RotateCamera(0, 0, 0, 0)
      
      AttachNodeObject(main_Entity\CameraNode, CameraID(0))
      CameraLookAt(0, NodeX(main_Entity\ForwardNode) * 100, NodeY(main_Entity\CameraNode), NodeZ(main_Entity\ForwardNode) * 100)
EndIf

Define set_empty
Define Input$, Event
Define.i Quit
Define.f TimeSinceLastFrame, LastFrame
Define close_gui, Gadget, click_els, els, move, time, time2

;- GAME START
game_start()

Repeat
; ;     Debug "--------------------------------------------"
;     Debug "Tris: " + Engine3DStatus(#PB_Engine3D_NbRenderedTriangles)
; Debug "Batches: " + Engine3DStatus(#PB_Engine3D_NbRenderedBatches)
; Debug "FPS: " + Engine3DStatus(#PB_Engine3D_CurrentFPS)
; ;     Debug "Min FPS: " + Engine3DStatus(#PB_Engine3D_MinimumFPS)
; ;     

      If #window=1
            Repeat
            Until WindowEvent() = 0
      EndIf
            time2 = ElapsedMilliseconds()

            t=15

            If #cam_type = 1
                  If ExamineMouse()
                        Yaw   = -MouseDeltaX() * 0.05
                        Pitch = -MouseDeltaY() * 0.05
                  EndIf
                
                  If ExamineKeyboard()
                        If KeyboardPushed(#PB_Key_W)
                              MoveCamera(#kam_0, 0, 0, -1 * Boost *t)
                        ElseIf KeyboardPushed(#PB_Key_S)
                              MoveCamera(#kam_0, 0, 0, 1 * Boost *t)
                        EndIf 
                        If KeyboardPushed(#PB_Key_A)  
                              MoveCamera(#kam_0, -1 * Boost *t, 0, 0) 
                        ElseIf KeyboardPushed(#PB_Key_D)
                              MoveCamera(#kam_0, 1 * Boost *t, 0, 0)
                        EndIf 
                  EndIf
                  
                  RotateCamera(#kam_0, Pitch*t/15, Yaw*t/15, 0, #PB_Relative)
            EndIf

            If #cam_type = 2
                  HandleEntity(@main_Entity)
            EndIf

            time2 = ElapsedMilliseconds() - time2

      ;If timer(1000/#render_fps);-time



            time = ElapsedMilliseconds()
            LastFrame = RenderWorld();1000/#render_fps
            time = ElapsedMilliseconds() - time

            main_Entity\elapsedTime = 160;time

            menu(LastFrame, time2)
            DisplayTransparentSprite(0,8,8)

            FlipBuffers()
;       Else
;             Delay(1)
;       EndIf

Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1;

Procedure OnGround(*Entity.s_Entity)

Protected nx, nz, ny
Protected ent, ent1, ent2, ent3, ent4

nx=NodeX(*Entity\MainNode)
ny=NodeY(*Entity\MainNode)
nz=NodeZ(*Entity\MainNode)

; Debug nx


;Debug *Entity\BodyOffsetY
;   ProcedureReturn RayCollide(nx,  ny-*Entity\BodyOffsetY, nz, nx+10, ny-*Entity\BodyOffsetY-10,  nz)

ent=RayCollide(nx, ny-*Entity\BodyOffsetY, nz, nx, ny-*Entity\BodyOffsetY-15,  nz)
; CreateLine3D(#PB_Any, nx, ny-*Entity\BodyOffsetY, nz, $FFFF, nx, ny-*Entity\BodyOffsetY-15,  nz, $FFFF)
If ent=-1
      ent1=RayCollide(nx-2, ny-*Entity\BodyOffsetY, nz-2, nx+10, ny-*Entity\BodyOffsetY-10,  nz+10)
;       CreateLine3D(#PB_Any, nx-2, ny-*Entity\BodyOffsetY, nz-2, $FFFF, nx+10, ny-*Entity\BodyOffsetY-10,  nz+10, $FFFF)
      If ent1=-1
            ent2=RayCollide(nx-2, ny-*Entity\BodyOffsetY, nz+2, nx+10, ny-*Entity\BodyOffsetY-10,  nz-10)
;             CreateLine3D(#PB_Any, nx-2, ny-*Entity\BodyOffsetY, nz+2, $FFFF, nx+10, ny-*Entity\BodyOffsetY-10,  nz-10, $FFFF)
            If ent2=-1
                  ent3=RayCollide(nx+2, ny-*Entity\BodyOffsetY, nz-2, nx-10, ny-*Entity\BodyOffsetY-10,  nz+10)
;                   CreateLine3D(#PB_Any, nx+2, ny-*Entity\BodyOffsetY, nz-2, $FFFF, nx-10, ny-*Entity\BodyOffsetY-10,  nz+10, $FFFF)
                  If ent3=-1
                        ent4=RayCollide(nx+2, ny-*Entity\BodyOffsetY, nz+2, nx-10, ny-*Entity\BodyOffsetY-10,  nz-10)
;                         CreateLine3D(#PB_Any, nx+2, ny-*Entity\BodyOffsetY, nz+2, $FFFF, nx-10, ny-*Entity\BodyOffsetY-10,  nz-10, $FFFF)
                  EndIf
            EndIf
      EndIf
EndIf

If ent
ProcedureReturn ent
ElseIf ent1
ProcedureReturn ent1
ElseIf ent2
ProcedureReturn ent2
ElseIf ent3
ProcedureReturn ent3
ElseIf ent4
ProcedureReturn ent4
EndIf
EndProcedure

Procedure OnWall(*Entity.s_Entity, fx, fz)
Protected ent1, ent2, grp1, grp2, ent3, ent4, grp3, grp4, x, z, nx, nz, ny

If IsNode(*Entity\MainNode)

nx=NodeX(*Entity\MainNode)
ny=NodeY(*Entity\MainNode)
nz=NodeZ(*Entity\MainNode)
x=nx+10*fx
z=nz+10*fz

; CreateLine3D(#PB_Any, NodeX(*Entity\MainNode)+3, NodeY(*Entity\MainNode)+38, nz, $FFFF, NodeX(*Entity\MainNode)-3, NodeY(*Entity\MainNode)+38,  nz, $FFFF)
; CreateLine3D(#PB_Any, NodeX(*Entity\MainNode), NodeY(*Entity\MainNode)+38, nz+3, $FFFF, NodeX(*Entity\MainNode), NodeY(*Entity\MainNode)+38,  nz-3, $FFFF)

CreateLine3D(#PB_Any, nx, ny+38, nz, $FFFF, x, ny+38, z, $FFFF)

ent1=RayCollide(nx+3, ny+38, nz, nx-3, ny+38,  nz)
; Debug ent1
ent2=RayCollide(nx, ny+38, nz+3, nx, ny+38,  nz-3)
; Debug ent2
ent3=RayCollide(nx-3, ny+38, nz, nx+3, ny+38,  nz)
; Debug ent3
ent4=RayCollide(nx, ny+38, nz-3, nx, ny+38,  nz+3)
; Debug ent4

If ent1 And IsEntity(ent1)
grp1=GetEntityCollisionGroup(ent1)
EndIf
If ent2 And IsEntity(ent2)
grp2=GetEntityCollisionGroup(ent2)
EndIf
If ent3 And IsEntity(ent3)
grp3=GetEntityCollisionGroup(ent3)
EndIf
If ent4 And IsEntity(ent4)
grp4=GetEntityCollisionGroup(ent4)
EndIf
; Debug grp1
; Debug grp2
; Debug grp3
; Debug grp4


If grp1=5
ProcedureReturn ent1
ElseIf grp2=5
ProcedureReturn ent2
ElseIf grp3=5
ProcedureReturn ent3
ElseIf grp4=5
ProcedureReturn ent4
EndIf

EndIf
;  ProcedureReturn 
EndProcedure

Global jcnt=0


Macro GetNodePosition(Position, Node)
  Position\x = NodeX(Node)
  Position\y = NodeY(Node)
  Position\z = NodeZ(Node)
EndMacro

Macro SubVector3(V, V1, V2)
  V\x = V1\x - V2\x
  V\y = V1\y - V2\y
  V\z = V1\z - V2\z
EndMacro



Procedure HandleEntity(*Entity.s_Entity)
Protected.Vector3 Forward, Strafe, PosMain, PosDir, PosStrafe, PosLamp
Protected.f Speed.f, Speed2.f
Protected x, y, bx, by, bz, Ground
Protected.f MouseX, MouseY
Static Jump.f, Speedjmp.f, MemJump.i
Protected Rot.Vector3, Trans.Vector3

Protected room.Vector3, PosEnt.Vector3
Protected PlayerSpeed, PlayerSpeedS, OnWall
Protected nx, ny, nz, ent, stor

  
With *Entity
      GetNodePosition(PosMain, \MainNode)
      GetNodePosition(PosDir, \ForwardNode)
      GetNodePosition(PosStrafe, \StrafeNode)

      GetNodePosition(PosLamp, \LampNode)

      SubVector3(Forward, PosDir, PosMain)
      SubVector3(Strafe, PosStrafe, PosMain)
   
; Debug PosMain\x

jmp = PosMain\y

      bx=Round(PosMain\x / scale, #PB_Round_Up)
      by=Round(PosMain\y / scale, #PB_Round_Up)-1
      bz=Round(PosMain\z / scale, #PB_Round_Up)

;*TimeSinceLastFrame*#PlayerSpeed

      ;\elapsedTime = 2.6

      Speed = 260 * 2.3 * 0.1 ;* \elapsedTime;#PlayerSpeed * \elapsedTime
      Speed2 = Speed * 0.8;back
      Speedjmp = Speed * 0.8
  
     
      If ExamineMouse()
            MouseX = -(MouseDeltaX()/3000) * \Fov * 5.8;\elapsedTime
            MouseY = -(MouseDeltaY()/3000) * \Fov * 5.8;\elapsedTime
            \rot_y + MouseX
            \rot_x + MouseY
            \rot_z = 0
      EndIf

      If ExamineKeyboard()

            Ground=OnGround(*Entity)

            If KeyboardPushed(#PB_Key_LeftShift)
                  Speed = Speed * 2.5
            EndIf
      
            If KeyboardPushed(\Key\Jump); And OnGround(*Entity)>-1 ;KeyboardReleased
                  If Ground>-1; Or OnWall(*Entity, Forward\x, Forward\z)   ; And MemJump=0    
                        Jump = Speedjmp ;* \elapsedTime
                        MemJump = 1
                  EndIf
            EndIf

            If Ground>-1 And MemJump = 0
                  Jump = 0
                  jcnt = 0
;Debug "jcnt = 0"
            Else
      
                  If MemJump
                        Jump + 140;Speedjmp
                        If Jump > 1160
                              MemJump = 0
                              Jump = 1160
                        EndIf
;Debug "Jump + "
                  Else
;Debug "Jump - "
                        If Jump > -350
                              Jump - 320; * \elapsedTime
                              If Jump < -350
                                    Jump - 350
                              EndIf
                        EndIf
                  EndIf
            EndIf
;Debug Jump

;                   If Jump > -800
;                         jcnt + 1
;                         Jump - (20 * jcnt); * \elapsedTime
;                   EndIf


            Trans\x = 0; * 0.80
            Trans\y = Jump
            Trans\z = 0;* 0.80


; jmp = jump


            If KeyboardPushed(\Key\Up)
                  Trans\x = Forward\x * Speed
                  Trans\z = Forward\z * Speed
            ElseIf KeyboardPushed(\Key\Down)
                  Trans\x = Forward\x * -Speed2
                  Trans\z = Forward\z * -Speed2
            EndIf
            
            If KeyboardPushed(\Key\Left)
                  Trans\x = Strafe\x * Speed
                  Trans\z = Strafe\z * Speed
            ElseIf KeyboardPushed(\Key\Right)
                  Trans\x = Strafe\x * -Speed
                  Trans\z = Strafe\z * -Speed
            EndIf

            ;DisableEntityBody(\EntityBody, #False) ; Wake up entity (BugWare)

            EntityVelocity(\EntityBody,Trans\x,Trans\y,Trans\z)
            ;MoveEntity(\EntityBody, Trans\x, Trans\y, Trans\z)


            If \hidelamp=0
                  If game\flashlight Or flash_on
                        ;MoveLight(Light2, PosLamp\x+lamp_x, PosLamp\y+lamp_y, PosLamp\z+lamp_z, #PB_Absolute)
                        ; CreateLine3D(#PB_Any, PosLamp\x, PosLamp\y+40, PosLamp\z, $FFFF, PosLamp\x, PosLamp\y+41, PosLamp\z, $FFFF)
                        If #cam_type = 2   
      
                              LightAttenuation(light2, 8050, 1)
                              SpotLightRange(light2, 0, lamp_o, 1)
                              ; 
                              ; LightAttenuation(light2, 1550, 1)
                              ; SpotLightRange(light2, 1, 360, 1)
      
                              LightDirection(Light2, CameraDirectionX(0), CameraDirectionY(0), CameraDirectionZ(0))
                        EndIf
                  Else
                        \hidelamp=1
                        HideLight(Light2, \hidelamp)
                  EndIf
            EndIf



            If KeyboardReleased(#PB_Key_Back)
                  If \hidemenu=0
                        \hidemenu=1
                  Else
                        \hidemenu=0
                  EndIf
            EndIf

            If KeyboardReleased(#PB_Key_L)
                  If \hidelamp=0
                        \hidelamp=1
                  Else
                        \hidelamp=0
                  EndIf
                  HideLight(Light2, \hidelamp)
            EndIf



      EndIf
          
      If #cam_type = 2   
            CameraFOV(0, \Fov)
      EndIf      
      
      RotateEntity(\EntityBody, 0, \Rot_y, 0, #PB_Absolute)

      RotateNode(\CameraNode, \Rot_x, 0, 0, #PB_Absolute)
      RotateNode(\HandNode, \Rot_x, 0, 0, #PB_Absolute)
     
;       SoundListenerLocate(EntityX(\EntityBody), EntityY(\EntityBody) - \BodyOffsetY, EntityZ(\EntityBody))

      MoveNode(\MainNode, EntityX(\EntityBody), EntityY(\EntityBody) - \BodyOffsetY, EntityZ(\EntityBody), #PB_Absolute)
      RotateNode(\MainNode, 0, EntityYaw(\EntityBody), 0)

;       If game\flashlight Or flash_on
;             MoveLight(Light2, PosLamp\x+0, PosLamp\y+0, PosLamp\z+0, #PB_Absolute)
;       EndIf

      If \HideMenu

      EndIf

; NodeFixedYawAxis(\MainNode, #True, 0.2, 0, 0.2)
; Debug EntityYaw(\EntityBody)
; Debug EntityPitch(\EntityBody)
; Debug CameraYaw(\CameraNode)


EndWith
EndProcedure

Re: When moving, the speed can change unpredictably. 3d FPS

Posted: Tue Sep 16, 2025 10:45 pm
by siesit
miso wrote: Mon Sep 15, 2025 11:59 pm So, I made further testes. I figured, that the static geometry does not inherits visibilitymask of the parent entity, so it was rendered twice. I made a new version, removed the rendertexture camera.
This version is incredibly stable, in the previous one I sometimes noticed spontaneous speed changes.
Thanks.
For now I'll try to figure out how it works...

Re: When moving, the speed can change unpredictably. 3d FPS

Posted: Wed Sep 17, 2025 5:13 am
by miso
siesit wrote: Tue Sep 16, 2025 10:37 pm Is there something wrong with the HandleEntity procedure?
I will take a look tonight, at the moment I don't have time to check the code.
Except for the sprite that disappears in a certain position.
It's a known bug, happens when no rendered entity is on the screen and skybox is presented. Can be worked around easily.

Re: When moving, the speed can change unpredictably. 3d FPS

Posted: Wed Sep 17, 2025 7:11 pm
by miso
As a quick look, while not my style, programmatically it's ok for first glance. There are 2 things that catches my eyes. First is the drawcommands inside the main loop. They work, but very time consuming to render. Not suitable inside a game loop. Prerender your fonts before the main loop, and use only sprites.

This works over 3d too:
viewtopic.php?p=639154#p639154

Second is the geometry of those cars. Create a very lowpoly collision mesh (in a 3d editor, or programmatically) that has few polygons, but has similar shape. Use the normal ones to render, and the latter for collision and it should be fine. Collision checks can be disabled for faraway entities, but thats another long story.

Re: When moving, the speed can change unpredictably. 3d FPS

Posted: Thu Sep 18, 2025 1:08 am
by siesit
These models and textures are for demonstration purposes only.
Even if I reduce the number of cars from *25 to *1 #max_ent, I still see a problem: each test run shows a different jump height.

And even if I disable entity addition altogether: :shock: :shock: :shock:

Code: Select all

Procedure game_start()
; game\sg=StaticGeometry()
; Debug game\sg
; BuildStaticGeometry(game\sg)
The movement speed and jump height will be different with each run, as can be seen in the graph.
But the jump variable is always the same.
:o

Re: When moving, the speed can change unpredictably. 3d FPS

Posted: Thu Sep 18, 2025 1:14 am
by siesit
The running speed and jump height change every time I switch between windows with alt+tab. :shock:

Re: When moving, the speed can change unpredictably. 3d FPS

Posted: Thu Sep 18, 2025 12:06 pm
by siesit
I tested the example "PureBasic621x86\Examples\3D\Demos\FPSFirstPerson.pb"
and it has the same problem: the jump height changes every time I alt+tab.

Re: When moving, the speed can change unpredictably. 3d FPS

Posted: Thu Sep 18, 2025 6:02 pm
by miso
Those are just simple demos.
(I would like to see a separate updatephysics command, i think it's inside the renderworld procedure for performance reasons.)

Not sure, test this slightly modified code for the FPSFirstPerson:
(Changed the jumping code)

Code: Select all

;
; ------------------------------------------------------------
;
;   PureBasic - FPS First Person
;
;    (c) Fantaisie Software
;
; ------------------------------------------------------------
; WaterWorld files come from the software Deled
; http://www.delgine.com, Thanks For this great editor 3D.


Procedure.f clamp(V.f, i.f, s.f)
    If V < i :v=i:EndIf
    If V > s :v=s:EndIf
    ProcedureReturn V
EndProcedure

Dim Barrel.Vector3(2)
Barrel(0)\x =  0 : Barrel(0)\y =  0 : Barrel(0)\z = 0
Barrel(1)\x = 60 : Barrel(1)\y =  0 : Barrel(1)\z = 0
Barrel(2)\x = 30 : Barrel(2)\y = 70 : Barrel(2)\z = 0

InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()

ExamineDesktops():dx=DesktopWidth(0)*0.8:dy=DesktopHeight(0)*0.8
OpenWindow(0, 0,0, DesktopUnscaledX(dx),DesktopUnscaledY(dy), "FPS First Person - [Arrows]  [Space]  [Esc] quit",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, dx, dy, 0, 0, 0)


;- AddArchive
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures"            , #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models"              , #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts"             , #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/waterworld.zip", #PB_3DArchive_Zip)
Parse3DScripts()

;- Material
CreateMaterial(0, LoadTexture(0, "r2skin.jpg"))
CreateMaterial(1, LoadTexture(1,"viseur-jeux.png"))
MaterialBlendingMode(1, #PB_Material_AlphaBlend)
GetScriptMaterial(3, "Color/Red")
CreateMaterial(4, LoadTexture(4, "RustyBarrel.png"))

;- Bullet
CreateSphere(3,10)

;- Robot Body
LoadMesh   (0, "robot.mesh")
CreateEntity(0, MeshID(0), #PB_Material_None, -400, 300, -100)
;HideEntity(0, 1)

;- Ground
LoadMesh(2, "waterworld.mesh")
CreateEntity(2, MeshID(2), #PB_Material_None)


;- Barrel
LoadMesh(4, "Barrel.mesh")
Restore Barrel
For i = 1 To 3
  Read.f x.f
  Read.f y.f
  Read.f z.f
  For j=0 To 2
    Barrel = CreateEntity(#PB_Any, MeshID(4), MaterialID(4), x+Barrel(j)\x, y+Barrel(j)\y, z+Barrel(j)\z)
    ScaleEntity(Barrel, 8, 10, 8)
    CreateEntityBody(Barrel, #PB_Entity_CylinderBody, 5, 0, 0.5)
  Next
Next

;- Camera
CreateCamera(0, 0, 0, 100, 100)

;- Light
CreateLight(0, RGB(255, 255, 255), 200, 100, 200, #PB_Light_Point)

;- Fog
;Fog(RGB(127, 127, 127), 128, 10, 2000)

;- Water
CreateShaderMaterial(8,#PB_Material_WaterShader)
MaterialShaderTexture(8,LoadTexture(8,"waternormal.png"),0,0,0)
SetMaterialColor(8,2,$66332200)
SetMaterialColor(8,4,$ffaa8866)
MaterialShininess(8,64)
ScaleMaterial(8,20,20)
MaterialFilteringMode(8,#PB_Material_Anisotropic,4)
MaterialBlendingMode(8,#PB_Material_AlphaBlend)
CreatePlane(8,4000,4000,16,16,1,1)
CreateEntity(-1,MeshID(8),MaterialID(8),0,-250,0)


WorldGravity(-500)
;Body
CreateEntityBody(0, #PB_Entity_ConvexHullBody, 0.45,0,0)
CreateEntityBody(2, #PB_Entity_StaticBody)

CreateNode(0):AttachEntityObject(0,"",NodeID(0))
AttachNodeObject(0,CameraID(0))

Procedure EntityOnGround(entity)
  ;CreateLine3D(100,EntityX(entity),  EntityY(entity)+50, EntityZ(entity),$ffffff, EntityX(entity), EntityY(entity)-10,  EntityZ(entity),$ff)
  ;Debug ""+EntityX(entity)+"   "+  EntityY(entity)+"   "+ EntityZ(entity)
  ProcedureReturn RayCollide(EntityX(entity),  EntityY(entity)+50, EntityZ(entity), EntityX(entity), EntityY(entity)-10,  EntityZ(entity))
EndProcedure

#PlayerSpeed = 1.6
Procedure main()
  Protected.Vector3 Forward, Strafe, PosMain, PosDir, PosStrafe
  Protected.f Speed, Speed2, SpeedShoot, x, y,fov
  Protected.f anglex, angleY
  Static Jump.f, MemJump.i, Rot.Vector3, Trans.Vector3, Clic
  
Repeat
  While WindowEvent():Wend      
  ;Robot\elapsedTime = Engine3DStatus(#PB_Engine3D_CurrentFPS)
  
  ExamineKeyboard()
  ExamineMouse()
  
  Speed = #PlayerSpeed 
  Speed2 = Speed * 0.5
  SpeedShoot = Speed * 20
   
  If MouseButton(#PB_MouseButton_Left)
    If Clic = 0
      x = ScreenWidth() / 2
      y = ScreenHeight() / 2
      PointPick(0, x, y)
      Clic = 1
      Shoot = CreateEntity(#PB_Any, MeshID(3), MaterialID(3), EntityBoneX(0,"Joint18"), EntityBoneY(0,"Joint18"), EntityBoneZ(0,"Joint18"))
      CreateEntityBody(Shoot, #PB_Entity_SphereBody, 0.3)
      ApplyEntityImpulse(Shoot, PickX() * SpeedShoot, PickY() * SpeedShoot, PickZ() * SpeedShoot)
    EndIf
  Else
    Clic = 0
  EndIf
  
  fov=clamp(fov+MouseButton(#PB_MouseButton_Right)*-4+2,20,50)
  CameraFOV(0,fov)
  
  distance=clamp(distance-MouseWheel()*10,0,100)
  MoveCamera(0,-distance+10,70,0,#PB_Absolute|#PB_Parent)
  
  angley=clamp(angleY -MouseDeltaY() *0.1,-80,80)
  RotateCamera(0,  angley,-90,0,#PB_Absolute)
  RotateEntity(0,  0,angleX,0,#PB_Absolute)
  
  OnGround=EntityOnGround(0)
  
  If OnGround=-1
    counter +TimeSinceLastFrame
    vity-(43*counter/1000)
  Else
    counter = 0
    vity=0
    angleX -MouseDeltaX() *0.1
    vitx = (KeyboardPushed(#PB_Key_Right)-KeyboardPushed(#PB_Key_Left))*TimeSinceLastFrame*#PlayerSpeed/2
    vitz = (KeyboardPushed(#PB_Key_Down)-KeyboardPushed(#PB_Key_Up))*TimeSinceLastFrame*#PlayerSpeed
    If KeyboardPushed(#PB_Key_Space):vity = 100:EndIf
  EndIf
  
  MoveEntity(0, -vitz, vity, vitx, #PB_Relative|#PB_Local)

  If (vitx Or vitz) And onground>=0
    If EntityAnimationStatus(0, "Walk") = #PB_EntityAnimation_Stopped:StartEntityAnimation(0, "Walk", #PB_EntityAnimation_Manual):EndIf
    AddEntityAnimationTime(0, "Walk", TimeSinceLastFrame)
  Else
    StopEntityAnimation(0, "Walk")
  EndIf
    
  TimeSinceLastFrame=RenderWorld(100)
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
EndProcedure

main()

DataSection
  Barrel:
  Data.f -885, 300, 158
  Data.f -800, 60, -1580
  Data.f -710, 60, -1270
EndDataSection