Page 1 of 1

Re: Use physic Sphere Body as Camera Guard

Posted: Sun Sep 22, 2013 8:51 am
by Comtois
Alexi wrote:For thrid-person Perspective the Camera has to avoid Objects. A simple and effective way would be a invisible Sphere Body, but if the mass is set to zero, the body can't move. If mass is given the Camera falls down of course. :D
If you use moveEntity() it will not fall.

ThirdPerson.pb example with fews change :

Code: Select all

;
; ------------------------------------------------------------
;
;   PureBasic - Third Person 
;
;    (c) 2011 - Fantaisie Software
;
; ------------------------------------------------------------
; 

IncludeFile "../Screen3DRequester.pb"

#PlayerSpeed = 60
#CameraSpeed = 10


Structure Vector3
  x.f
  y.f
  z.f
EndStructure

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

Structure s_Entity
  Entity.i
  EntityBody.i
  BodyOffsetY.f 
  elapsedTime.f
  Key.s_Key
  MainNode.i  
  SightNode.i
  CameraNode.i  
  ForwardNode.i
  StrafeNode.i
EndStructure

Structure s_Camera
  Camera.i
  CameraBody.i
  Tightness.f
  CameraNode.i 
  TargetNode.i
EndStructure    

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

;-Declare
Declare HandleEntity(*Entity.s_Entity)
Declare CameraTrack(*Camera.s_Camera, *Entity.s_Entity)
Declare OnGround(*Entity.s_Entity)
Declare AddObjects()

Define Robot.s_Entity
Define Camera.s_Camera
Define.f TimeSinceLastFrame = 0
If InitEngine3D()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    
    Add3DArchive("../Data/Textures"        , #PB_3DArchive_FileSystem)
    Add3DArchive("../Data/Models"          , #PB_3DArchive_FileSystem)
    Add3DArchive("../Data/Scripts"          , #PB_3DArchive_FileSystem)
    Add3DArchive("../Data/GUI"             , #PB_3DArchive_FileSystem)
    Add3DArchive("../Data/Packs/desert.zip", #PB_3DArchive_Zip)
    Parse3DScripts()
    
    WorldShadows(#PB_Shadow_Modulative, 3000, RGB(150, 150, 150))
    
    ;Texture
    CreateTexture(1, 256, 256)
    StartDrawing(TextureOutput(1))
    Box(0, 0, 256, 256, RGB(0, 34, 85))
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(0, 0, 256, 256, RGB(255, 255, 255))
    Box(10, 10, 236, 236, RGB(0, 255, 255))
    StopDrawing()
    
    ;Material
    CreateMaterial(0, LoadTexture(0, "r2skin.jpg"))
    CreateMaterial(1, TextureID(1))
    MaterialFilteringMode(1, 2)
    
    CreateMaterial(2, LoadTexture(2, "Dirt.jpg"))
    CreateMaterial(3, LoadTexture(3, "Wood.jpg"))
    GetScriptMaterial(4, "Scene/GroundBlend")
    
    MaterialFilteringMode(1, #PB_Material_Anisotropic, 8) 
    
    ;Robot
    LoadMesh   (0, "robot.mesh")
    CreateEntity (0, MeshID(0), #PB_Material_None);
    StartEntityAnimation(0, "Walk")
    
    ;Robot Body
    CreateEntity(1, MeshID(0), #PB_Material_None, 0, 26, 0)
    HideEntity(1, 1)
    
    ;Ground
    CreatePlane(2, 5000, 5000, 100, 100, 100, 100)
    CreateEntity(2, MeshID(2), MaterialID(1), 0, 0, 0)
    
    ;Body
    EntityPhysicBody(1, #PB_Entity_CapsuleBody, 1, 0, 0) 
    EntityPhysicBody(2, #PB_Entity_StaticBody)
    
    ;Add some statics and dynamics objects
    CreateCube(3, 1)
    AddObjects()  
    
    ;-Light
    CreateLight(0,RGB(155,155,155),700,500,0)
    AmbientColor(RGB(85,85,85))
    
    ;- Fog
    Fog(RGB(210, 210, 210), 1, 0, 10000)
    
    ; Skybox
    SkyBox("desert07.jpg")
    
    ;
    With Robot
      \Entity = 0
      \EntityBody = 1
      \BodyOffsetY = 43 
      
      \Key\Down        = #PB_Key_Down
      \Key\Left        = #PB_Key_Left
      \Key\Right       = #PB_Key_Right
      \Key\Up          = #PB_Key_Up
      \Key\StrafeLeft  = #PB_Key_X
      \Key\StrafeRight = #PB_Key_C
      \Key\Jump        = #PB_Key_Space
      
      \MainNode    = CreateNode(#PB_Any) ; Entity position
      \SightNode   = CreateNode(#PB_Any,  120,  20,  0) ; For cameraLookAt 
      \CameraNode  = CreateNode(#PB_Any, -140, 100,  0) ; Camera position
      \ForwardNode = CreateNode(#PB_Any,    1,   0,  0) ; Direction normalized 
      \StrafeNode  = CreateNode(#PB_Any,    0,   0, -1) ; Direction normalized 
      
      AttachNodeObject(\MainNode, NodeID(\SightNode))
      AttachNodeObject(\MainNode, NodeID(\CameraNode))   
      AttachNodeObject(\MainNode, NodeID(\ForwardNode))     
      AttachNodeObject(\MainNode, NodeID(\StrafeNode))    
      AttachNodeObject(\MainNode, EntityID(\Entity))
    EndWith
    
    ;-Camera
    CreateCamera(0, 0, 0, 100, 100)
    Sphere = CreateSphere(#PB_Any, 10)
    With Camera  
      \Camera = 0
      \Tightness = 0.5
      ; Camera use 2 nodes
      \CameraNode = CreateNode(#PB_Any, -30, 70, 0) ; Camera position
      \TargetNode = CreateNode(#PB_Any) ; For cameraLookAt 
      \CameraBody = 20
      CreateEntity(20, MeshID(Sphere), #PB_Material_None, -30, 70, 0)
      EntityPhysicBody(20, #PB_Entity_SphereBody, 0.5, 0, 1)
      
      HideEntity(\CameraBody, #True)
      AttachEntityObject(\CameraBody, "",CameraID(\Camera))
    EndWith  
    
    ;-Main loop    
    ;
    Repeat
      Screen3DEvents()
      
      Robot\elapsedTime = TimeSinceLastFrame * 40
      
      HandleEntity(@Robot)
      
      CameraTrack(@Camera, @Robot)
      
      TimeSinceLastFrame = RenderWorld(50) / 1000
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
  
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf

End

Procedure OnGround(*Entity.s_Entity)
  With *Entity
    ProcedureReturn RayCollide(NodeX(\MainNode),  NodeY(\MainNode)+3, NodeZ(\MainNode), NodeX(\MainNode), NodeY(\MainNode),  NodeZ(\MainNode)) 
  EndWith  
EndProcedure

Procedure IsStair(*Entity.s_Entity)
  Protected.f x, y, z
  With *Entity
    x = (NodeX(\ForwardNode) - NodeX(\MainNode))*30
    y = (NodeY(\ForwardNode) - NodeY(\MainNode))*30
    z = (NodeZ(\ForwardNode) - NodeZ(\MainNode))*30
    ;CreateLine3D(20, NodeX(\MainNode), NodeY(\MainNode)+20, NodeZ(\MainNode), $FFFF, NodeX(\MainNode)+x, NodeY(\MainNode)+y+20,  NodeZ(\MainNode)+z, $FFFF) 
    Ray1 = RayCollide(NodeX(\MainNode), NodeY(\MainNode)+10, NodeZ(\MainNode),  NodeX(\MainNode)+x, NodeY(\MainNode)+y+10,  NodeZ(\MainNode)+z) 
    Ray2 = RayCollide(NodeX(\MainNode), NodeY(\MainNode)+20, NodeZ(\MainNode),  NodeX(\MainNode)+x, NodeY(\MainNode)+y+20,  NodeZ(\MainNode)+z) 
    If Ray1>-1 And Ray2=-1
      ProcedureReturn 1
    EndIf
    ProcedureReturn 0
  EndWith  
EndProcedure

Procedure HandleEntity(*Entity.s_Entity)
  Protected.Vector3 Forward, Strafe, PosMain, PosDir, PosStrafe
  Protected.f Speed, Speed2, x, y, MouseX, MouseY
  Static Jump.f, MemJump.i, Rot.Vector3, Trans.Vector3, Clic
  
  With *Entity
    GetNodePosition(PosMain, \MainNode)
    GetNodePosition(PosDir, \ForwardNode)
    GetNodePosition(PosStrafe, \StrafeNode)
    SubVector3(Forward, PosDir, PosMain)
    SubVector3(Strafe, PosStrafe, PosMain)
    
    Speed = #PlayerSpeed * \elapsedTime 
    Speed2 = Speed / 2
    
    If ExamineKeyboard()
      
      If KeyboardReleased(#PB_Key_F5)
        WorldDebug(#PB_World_DebugBody)
      ElseIf KeyboardReleased(#PB_Key_F6)
        WorldDebug(#PB_World_DebugEntity)
      ElseIf KeyboardReleased(#PB_Key_F7)
        WorldDebug(#PB_World_DebugNone)
      EndIf
      
      If KeyboardPushed(\Key\Jump) And OnGround(*Entity)>-1
        Jump = 4
        MemJump = 1
      EndIf  
      
      Rot\x * 0.30
      Rot\y * 0.30
      Rot\z * 0.30
      Trans\x * 0.20
      Trans\y = Jump
      Trans\z * 0.20
      
      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)
        Rot\y + 2 * \elapsedTime
      ElseIf KeyboardPushed(\Key\Right)
        Rot\y - 2 * \elapsedTime
      EndIf 
      
      If KeyboardPushed(\Key\StrafeLeft)
        Trans\x + Strafe\x * Speed2
        Trans\z + Strafe\z * Speed2
      ElseIf KeyboardPushed(\Key\StrafeRight)
        Trans\x + Strafe\x * -Speed2
        Trans\z + Strafe\z * -Speed2
      EndIf 
      
      If OnGround(*Entity) > -1 
        Jump = 0
      ElseIf MemJump  
        Jump + 20
        If Jump > 80 
          MemJump = 0
        EndIf  
      Else  
        Jump - 9 
      EndIf  
      
      If IsStair(*Entity) And Jump = 0 And ( Abs(Trans\x)>=Speed / 2 Or Abs(Trans\z)>=Speed / 2)
        Jump = 22 ; Or more 
      EndIf 
      
    EndIf
    
    MoveEntity  (\EntityBody, Trans\x, Trans\y, Trans\z)
    RotateEntity(\EntityBody, 0, Rot\y, 0, #PB_Relative)   
    
    MoveNode(\MainNode, EntityX(\EntityBody), EntityY(\EntityBody)-\BodyOffsetY, EntityZ(\EntityBody), #PB_Absolute) 
    RotateNode(\MainNode, 0, EntityYaw(\EntityBody), 0) 
  EndWith   
EndProcedure


Procedure CameraTrack(*Camera.s_Camera, *Entity.s_Entity)
  Protected.Vector3 CameraPosition, TargetPosition 
  Protected.f x, y, z
  
  GetNodePosition(CameraPosition, *Entity\CameraNode)
  GetNodePosition(TargetPosition, *Entity\SightNode)
  x = EntityX(*Camera\CameraBody)
  y = EntityY(*Camera\CameraBody)
  z = EntityZ(*Camera\CameraBody)
  x = (CameraPosition\x - x) *  *Camera\Tightness
  y = (CameraPosition\y - y) *  *Camera\Tightness
  z = (CameraPosition\z - z) *  *Camera\Tightness
  MoveEntity(*Camera\CameraBody, x, y, z)
  
  x = NodeX(*Camera\TargetNode)
  y = NodeY(*Camera\TargetNode)
  z = NodeZ(*Camera\TargetNode)
  x = (TargetPosition\x - x) *  *Camera\Tightness
  y = (TargetPosition\y - y) *  *Camera\Tightness
  z = (TargetPosition\z - z) *  *Camera\Tightness
  MoveNode(*Camera\TargetNode, x, y, z)
  
  CameraLookAt(*Camera\Camera, NodeX(*Camera\TargetNode), NodeY(*Camera\TargetNode), NodeZ(*Camera\TargetNode))
  
EndProcedure

Procedure AddObjects()
  Protected Size.Vector3
  Protected.f x, z
  Protected.i Ent, i  
  
  Ent=CreateEntity(#PB_Any, MeshID(3), MaterialID(2), -400, 100, 0)
  ScaleEntity(Ent, 5, 200, 800)
  EntityPhysicBody(Ent, #PB_Entity_StaticBody)   
  Ent=CreateEntity(#PB_Any, MeshID(3), MaterialID(2), 400, 100, 0)
  ScaleEntity(Ent, 5, 200, 800)
  EntityPhysicBody(Ent, #PB_Entity_StaticBody)     
  Ent=CreateEntity(#PB_Any, MeshID(3), MaterialID(2), 0, 100, -400)
  ScaleEntity(Ent, 800, 200, 5)
  EntityPhysicBody(Ent, #PB_Entity_StaticBody)     
  Ent=CreateEntity(#PB_Any, MeshID(3), MaterialID(2), 0, 100, 400)
  ScaleEntity(Ent, 800, 200, 5)
  EntityPhysicBody(Ent, #PB_Entity_StaticBody)  
EndProcedure