Page 1 sur 1

une chenille sur un terrain

Publié : jeu. 01/nov./2012 21:52
par comtois
Une bricole sans intérêt, si ce n'est que j'aime bien balader une chenille sur un terrain :)

Pour tester copiez le code dans le répertoire PureBasic\Examples\3D

Touches [F2]/[F3]/[F4] pour changer le point de vue de la caméra. [F4] est plus efficace quand la chenille grandit.

Code : Tout sélectionner

IncludeFile #PB_Compiler_Home + "Examples/3D/Screen3DRequester.pb"

Enumeration
  #ThirdPersonChase 
  #ThirdPersonFixed
  #TopView
EndEnumeration

#Nb = 100
#Size = 6
#PlayerSpeed = 0.1

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

Structure s_Key
  Left.i
  Right.i
EndStructure

Structure s_Item
  Attached.i
  Entity.i
  MainNode.i     
  SecondNode.i 
  forward.i
EndStructure

Structure s_Head
  Item.s_Item
  LastItem.i
  Key.s_Key
  SightNode.i
  CameraNode.i 
  DirectionNode.i
  Offset.Vector3
EndStructure

Structure s_Camera
  Camera.i
  Mode.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 SetVector3(V, xx, yy, zz)
  V\x = xx
  V\y = yy
  V\z = zz
EndMacro

Macro AddVector3(V, V1, V2)
  V\x = V1\x + V2\x
  V\y = V1\y + V2\y
  V\z = V1\z + V2\z
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

Macro NodeOnTerrain(p, Node)
  p\x = NodeX(Node)
  p\z = NodeZ(Node)
  p\y = TerrainHeight(0, p\x, p\z) + #Size
  MoveNode(Node, p\x, p\y, p\z, #PB_Absolute)
EndMacro

Define camera.s_Camera
Define p.Vector3
Define Head.s_Head
Global Dim Item.s_Item(#Nb)
Global NewList Chenille.i() ; Stock l'index du tableau
Global Speed.f


#CameraSpeed = 1
#TerrainMiniX = 0
#TerrainMiniY = 0
#TerrainMaxiX = 0
#TerrainMaxiY = 0

;-Declare
Declare HandleEntity(*Head.s_Head)
Declare CameraMode(*Camera.s_Camera, *Head.s_Head)
Declare CameraTrack(*Camera.s_Camera, *Head.s_Head)
Declare CameraInstantUpdate(*Camera.s_Camera, *CameraPosition.Vector3, *TargetPosition.Vector3)
Declare CameraUpdate(*Camera.s_Camera, *CameraPosition.Vector3, *TargetPosition.Vector3)
Declare.f Distance(*v1.Vector3, *v2.Vector3)
Declare MoveItem()
Declare TestItem(*Head.s_Head)

Declare InitBlendMaps()
Declare Clamp(*var.float, min.f, max.f)

; OpenGL needs to have CG enabled to work (Linux and OS X have OpenGL by default)
;
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
  Flags = #PB_Engine3D_EnableCG
CompilerEndIf

If InitEngine3D(3)
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    
    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/Textures/nvidia", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/GUI", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Packs/desert.zip", #PB_3DArchive_Zip)    
    Parse3DScripts()
    
    WorldShadows(#PB_Shadow_Modulative, -1, RGB(127, 127, 127))
    
    ;- Light
    ;
    
    light = CreateLight(#PB_Any ,RGB(185, 185, 185), 4000, 1200, 1000, #PB_Light_Directional)
    SetLightColor(light, #PB_Light_SpecularColor, RGB(255, 255,255))
    LightDirection(light ,0.55, -0.3, -0.75)
    AmbientColor(RGB(5, 5,5))
    
    ;----------------------------------
    ; terrain definition
    SetupTerrains(LightID(Light), 3000, #PB_Terrain_NormalMapping)
    ; initialize terrain
    CreateTerrain(0, 513, 12000, 600, 3, "Terrain04", "Dat")
    ; set all texture will be use when terrrain will be constructed
    AddTerrainTexture(0,  0, 100, "dirt_grayrocky_diffusespecular.jpg",  "dirt_grayrocky_normalheight.jpg")
    AddTerrainTexture(0,  1,  30, "grass_green-01_diffusespecular.jpg", "grass_green-01_normalheight.jpg")
    AddTerrainTexture(0,  2, 200, "growth_weirdfungus-03_diffusespecular.jpg", "growth_weirdfungus-03_normalheight.jpg")
    
    ;- define terrains
    For ty = #TerrainMiniY To #TerrainMaxiY
      For tx = #TerrainMiniX To #TerrainMaxiX
        imported = DefineTerrainTile(0, tx, ty, "terrain513.png", ty % 2, tx % 2) 
      Next
    Next 
    BuildTerrain(0) 
    
    If imported = #True
      InitBlendMaps()
      UpdateTerrain(0)
      ;SaveTerrain(0, #False)
    EndIf 
    
    ; SkyBox
    ;
    SkyBox("desert07.jpg")
    
    ;- Materials
    ;
    CreateMaterial(0, LoadTexture(0, "Wood.jpg"))
    GetScriptMaterial(1, "SphereMap/SphereMappedRustySteel")
    CreateMaterial(2, LoadTexture(2, "Dirt.jpg"))
    GetScriptMaterial(3, "Scene/GroundBlend")
    ;- Head
    ;
    CreateSphere(1, #Size)
    
    With Head
      \Item\Entity = CreateEntity(#PB_Any, MeshID(1), MaterialID(1))
      \Key\Left  = #PB_Key_Left
      \Key\Right = #PB_Key_Right
      \Offset\x = 0
      \Offset\y = 50 ; Offset could be needed for FirstPerson
      \Offset\z = 130 
      ; Entity use 5 nodes 
      \Item\MainNode=CreateNode(#PB_Any, 0, #Size, 0) ; Entity position
      \Item\SecondNode=CreateNode(#PB_Any, 0, 0, 2 * #Size)
      \DirectionNode=CreateNode(#PB_Any, 0, 0, -1) ; Direction normalized
      
      \SightNode=CreateNode(#PB_Any, 0, 20, -120) ; For cameraLookAt
      \CameraNode=CreateNode(#PB_Any, 0, 100, 140) ; Camera position
      
      CopyStructure(Head\Item, Item(0), s_Item)
      \LastItem = 0
      
      AttachNodeObject(\Item\MainNode, NodeID(\SightNode))
      AttachNodeObject(\Item\MainNode, NodeID(\CameraNode))   
      AttachNodeObject(\Item\MainNode, NodeID(\DirectionNode))
      AttachNodeObject(\Item\MainNode, NodeID(\Item\SecondNode))
      AttachNodeObject(\Item\MainNode, EntityID(\Item\Entity))
      
      NodeOnTerrain(p, \Item\MainNode)
    EndWith
    
    
    ;- Item
    ;
    For i=1 To #Nb
      With Item(i)
        \Entity = CreateEntity(#PB_Any, MeshID(1), MaterialID(1))
        ; Entity use 2 nodes   
        \MainNode=CreateNode(#PB_Any, Random(6000)-3000, #Size, Random(6000)-3000) ; Entity position
        \SecondNode=CreateNode(#PB_Any, 0, 0, 2 * #Size) ; Direction normalized
        AttachNodeObject(\MainNode, NodeID(\SecondNode))
        AttachNodeObject(\MainNode, EntityID(\Entity))
        
        NodeOnTerrain(p, \MainNode)
      EndWith
    Next 
    
    ;- Camera
    ;
    CreateCamera(0, 0, 0, 100, 100)
    With Camera 
      \Camera = 0
      \Mode = -1
      \Tightness = 0.01
      ; Camera use 2 nodes
      \CameraNode = CreateNode(#PB_Any, -3000, 700, 0) ; Camera position
      \TargetNode = CreateNode(#PB_Any) ; For cameraLookAt
      AttachNodeObject(\CameraNode, CameraID(\Camera))
    EndWith 
    
    Repeat
      Screen3DEvents()
      
      If ExamineKeyboard()
        CameraMode(@Camera, @Head)     
        HandleEntity(@Head)
      EndIf
      TestItem(@Head)
      MoveItem()
      
      CameraTrack(@Camera, @Head)
      
      Speed.f = RenderWorld() * #PlayerSpeed
      
      Screen3DStats()
      FlipBuffers()
      
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
    
    End
    
  EndIf
Else
  MessageRequester("Error","Can't initialize engine3D")
EndIf

Procedure InitBlendMaps()
  minHeight1.f = 70
  fadeDist1.f = 40
  minHeight2.f = 70
  fadeDist2.f = 15   
  For ty = #TerrainMiniY To #TerrainMaxiY
    For tx = #TerrainMiniX To #TerrainMaxiX
      Size = TerrainTileLayerMapSize(0, tx, ty)
      For y = 0 To Size-1
        For x = 0 To Size-1
          Height.f = TerrainTileHeightAtPosition(0, tx, ty, 1, x, y)
          
          val.f = (Height - minHeight1) / fadeDist1
          Clamp(@val, 0, 1)
          SetTerrainTileLayerBlend(0, tx, ty, 1, x, y, val)
          
          val.f = (Height - minHeight2) / fadeDist2
          Clamp(@val, 0, 1)
          SetTerrainTileLayerBlend(0, tx, ty, 2, x, y, val)
        Next
      Next
      UpdateTerrainTileLayerBlend(0, tx, ty, 1)
      UpdateTerrainTileLayerBlend(0, tx, ty, 2)
    Next
  Next 
EndProcedure 

Procedure Clamp(*var.float, min.f, max.f)
  If *var\f < min
    *var\f = min
  ElseIf *var\f > max
    *var\f = max
  EndIf
EndProcedure


Procedure.f Distance(*v1.Vector3, *v2.Vector3)
  ProcedureReturn Sqr((*v1\x-*v2\x)*(*v1\x-*v2\x)+(*v1\y-*v2\y)*(*v1\y-*v2\y)+(*v1\z-*v2\z)*(*v1\z-*v2\z))
EndProcedure

Procedure MoveItem()
  Protected.Vector3  d, p, v1, v2
  Protected Dist.f
  ForEach Chenille()
    item = Chenille()
    forward = Item(item)\forward
    
    GetNodePosition(v1, Item(item)\MainNode)
    GetNodePosition(d, Item(forward)\MainNode)
    Dist = (1.8 * #Size) - Distance(@v1, @d)
    
    NodeLookAt(Item(item)\MainNode, d\x, d\y, d\z)
    MoveNode(Item(item)\MainNode, 0, 0, Dist, #PB_Local)
    
    NodeOnTerrain(p, Item(item)\MainNode)
  Next
EndProcedure

Procedure TestItem(*Head.s_Head)
  Protected.Vector3 v1, v2, d, p
  
  For i = 1 To #Nb
    If Not Item(i)\Attached
      GetNodePosition(v1, *Head\Item\MainNode)
      GetNodePosition(v2, Item(i)\MainNode)
      If Distance(@v1, @v2) < 2 * #Size
        AddElement(Chenille())
        Chenille() = i
        
        Item(i)\forward = *Head\LastItem
        
        GetNodePosition(p, Item(*Head\LastItem)\SecondNode)
        GetNodePosition(d, Item(*Head\LastItem)\MainNode)
        MoveNode(Item(i)\MainNode, p\x, p\y, p\z, #PB_Absolute)
        NodeLookAt(Item(i)\MainNode, d\x, d\y, d\z)
        
        *Head\LastItem    = i
        Item(i)\Attached = #True
      EndIf 
    EndIf 
  Next 
EndProcedure

Procedure HandleEntity( *Head.s_Head)
  Protected.Vector3 PosMain, PosDir , p
  Protected Node
  
  With *Head
    
    MoveNode(\Item\MainNode, 0, 0, -Speed, #PB_Local)
    NodeOnTerrain(p, \Item\MainNode)
    
    If KeyboardPushed(\Key\Left)
      RotateNode(\Item\MainNode, 0,Speed, 0, #PB_Relative)
    ElseIf KeyboardPushed(\Key\Right)
      RotateNode(\Item\MainNode, 0, -Speed, 0, #PB_Relative)
    EndIf
  EndWith   
EndProcedure

Procedure CameraMode(*Camera.s_Camera, *Head.s_Head)
  Protected.Vector3 CameraPosition, TargetPosition, Temp
  
  If KeyboardReleased(#PB_Key_F2)  Or *Camera\Mode = -1
    *Camera\Mode = #ThirdPersonChase
    HideEntity(*Head\Item\Entity, #False)
    GetNodePosition(CameraPosition, *Head\CameraNode)
    GetNodePosition(TargetPosition, *Head\SightNode)
    CameraInstantUpdate(*Camera, @CameraPosition, @TargetPosition)
    *Camera\Tightness = 0.01
    
  ElseIf KeyboardReleased(#PB_Key_F3)
    *Camera\Mode = #ThirdPersonFixed
    HideEntity(*Head\Item\Entity, #False)
    SetVector3(CameraPosition, 0, TerrainHeight(0, 0, 0) + 200, 0)
    GetNodePosition(TargetPosition, *Head\SightNode)
    CameraInstantUpdate(*Camera, @CameraPosition, @TargetPosition)
    *Camera\Tightness = 0.01
    
  ElseIf KeyboardReleased(#PB_Key_F4) 
    *Camera\Mode = #TopView
    HideEntity(*Head\Item\Entity, #True)
    GetNodePosition(CameraPosition, Item(*Head\LastItem)\MainNode)
    CameraPosition\y + 200
    GetNodePosition(TargetPosition, *Head\SightNode)
    CameraInstantUpdate(*Camera, @CameraPosition, @TargetPosition)
    *Camera\Tightness = 1   
    
  EndIf
EndProcedure

Procedure CameraTrack(*Camera.s_Camera, *Head.s_Head)
  Protected.Vector3 CameraPosition, TargetPosition, Temp
  
  Select *Camera\Mode
    Case #ThirdPersonChase
      GetNodePosition(CameraPosition, *Head\CameraNode)
      GetNodePosition(TargetPosition, *Head\SightNode)
      CameraUpDate(*Camera, @CameraPosition, @TargetPosition)
      
    Case #ThirdPersonFixed
      SetVector3(CameraPosition, 0,  TerrainHeight(0, 0, 0) + 200, 0)
      GetNodePosition(TargetPosition, *Head\SightNode)
      CameraUpDate(*Camera, @CameraPosition, @TargetPosition)
      
    Case #TopView
      GetNodePosition(CameraPosition, Item(*Head\LastItem)\MainNode)
      CameraPosition\y + 200
      GetNodePosition(TargetPosition, *Head\Item\MainNode)
      CameraUpDate(*Camera, @CameraPosition, @TargetPosition)
      
  EndSelect
EndProcedure

Procedure CameraInstantUpdate(*Camera.s_Camera, *CameraPosition.Vector3, *TargetPosition.Vector3)
  Protected V1.Vector3, V2.Vector3
  
  MoveNode(*Camera\CameraNode, *CameraPosition\x, *CameraPosition\y, *CameraPosition\z, #PB_Absolute)
  
  MoveNode(*Camera\TargetNode, *TargetPosition\x, *TargetPosition\y, *TargetPosition\z, #PB_Absolute)
  
  CameraLookAt(*Camera\Camera, NodeX(*Camera\TargetNode), NodeY(*Camera\TargetNode), NodeZ(*Camera\TargetNode))
EndProcedure

Procedure CameraUpdate(*Camera.s_Camera, *CameraPosition.Vector3, *TargetPosition.Vector3)
  Protected V1.Vector3, V2.Vector3
  
  V1\x = (*CameraPosition\x - NodeX(*Camera\CameraNode)) *  *Camera\Tightness
  V1\y = (*CameraPosition\y - NodeY(*Camera\CameraNode)) *  *Camera\Tightness
  v1\z = (*CameraPosition\z - NodeZ(*Camera\CameraNode)) *  *Camera\Tightness
  MoveNode(*Camera\CameraNode, V1\x, V1\y, V1\z)
  
  V2\x = (*TargetPosition\x - NodeX(*Camera\TargetNode)) *  *Camera\Tightness
  V2\y = (*TargetPosition\y - NodeY(*Camera\TargetNode)) *  *Camera\Tightness
  V2\z = (*TargetPosition\z - NodeZ(*Camera\TargetNode)) *  *Camera\Tightness
  MoveNode(*Camera\TargetNode, V2\x, V2\y, V2\z)
  
  CameraLookAt(*Camera\Camera, NodeX(*Camera\TargetNode), NodeY(*Camera\TargetNode), NodeZ(*Camera\TargetNode))
EndProcedure

Re: une chenille sur un terrain

Publié : jeu. 01/nov./2012 23:15
par Fred
Excellent la chenille :D

Re: une chenille sur un terrain

Publié : ven. 02/nov./2012 4:23
par graph100
c'est sympa, et c'est un bon exemple de l'utilisation des nodes.

J'vais le regarder de plus près :D

Merci Comtois

j'avoue que quand j'ai vu le titre du post, j'ai pensé à une chenille qui avance en marchant (avec son bout avant et son bout arrière)

Re: une chenille sur un terrain

Publié : dim. 04/nov./2012 11:15
par comtois
graph100 a écrit :j'avoue que quand j'ai vu le titre du post, j'ai pensé à une chenille qui avance en marchant (avec son bout avant et son bout arrière)
Exact, c'est plutôt un 'snake'.
c'est sympa, et c'est un bon exemple de l'utilisation des nodes.

J'vais le regarder de plus près :D
les nodes sont la base de tout :)
Il suffit d'attacher un node pour indiquer où doit se placer la caméra, et c'est tout, la caméra se débrouille pour suivre ce node, pas besoin de faire des calculs d'angle.
Dans l'exemple ci-dessus, j'avais ajouté un node pour indiquer où placer l'élément suivant, mais finalement je l'ai supprimé, et voici le code simplifié :

Code : Tout sélectionner

IncludeFile "Screen3DRequester.pb"

Enumeration 
  #ThirdPersonChase  
  #ThirdPersonFixed
  #TopView
EndEnumeration

Enumeration
  #Object_Entity
  #Object_Node
  #Object_Last
EndEnumeration

#Nb = 100
#Size = 6
#Ecart = 1.5 * #Size
#PlayerSpeed = 0.15

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

Structure s_Key
  Left.i
  Right.i
EndStructure

Structure s_Item
  Entity.i
  forward.i 
EndStructure

Structure s_Head
  Entity.i
  LastItem.i
  Key.s_Key
  MainNode.i
  SightNode.i
  CameraNode.i  
  Offset.Vector3 
EndStructure

Structure s_Camera
  Camera.i
  Mode.i
  Tightness.f
  CameraNode.i 
  TargetNode.i
EndStructure    
Structure s_Object
  Position.i
  Locate.i
  Move.i
EndStructure

Macro GetObjectPosition(Position, Object, type)
  If Type = #Object_Node
    Position\x = NodeX(Object)  
    Position\y = NodeY(Object)  
    Position\z = NodeZ(Object)  
  ElseIf Type = #Object_Entity
    Position\x = EntityX(Object)  
    Position\y = EntityY(Object)  
    Position\z = EntityZ(Object)  
  EndIf
  
EndMacro

Macro SetVector3(V, xx, yy, zz)
  V\x = xx
  V\y = yy
  V\z = zz
EndMacro

Macro AddVector3(V, V1, V2)
  V\x = V1\x + V2\x
  V\y = V1\y + V2\y
  V\z = V1\z + V2\z
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

Macro ObjectOnTerrain(p, Object, Type)
  If Type = #Object_Node
    p\x = NodeX(Object)
    p\z = NodeZ(Object)
    p\y = TerrainHeight(0, p\x, p\z) + #Size    
    NodeLocate(Object, p\x, p\y, p\z)
  ElseIf Type = #Object_Entity
    p\x = EntityX(Object)
    p\z = EntityZ(Object)
    p\y = TerrainHeight(0, p\x, p\z) + #Size
    EntityLocate(Object, p\x, p\y, p\z)
  EndIf  
EndMacro

Define camera.s_Camera
Define p.Vector3
Define Head.s_Head
Prototype.f PositionX(Object)
Global NewList Item.s_Item()
Global NewList Chenille.s_Item() 
Global Speed.f 


#CameraSpeed = 1
#TerrainMiniX = 0
#TerrainMiniY = 0
#TerrainMaxiX = 0
#TerrainMaxiY = 0

;-Declare
Declare HandleEntity(*Head.s_Head)
Declare CameraMode(*Camera.s_Camera, *Head.s_Head)
Declare CameraTrack(*Camera.s_Camera, *Head.s_Head)
Declare CameraInstantUpdate(*Camera.s_Camera, *CameraPosition.Vector3, *TargetPosition.Vector3)
Declare CameraUpdate(*Camera.s_Camera, *CameraPosition.Vector3, *TargetPosition.Vector3)
Declare.f Distance(*v1.Vector3, *v2.Vector3)
Declare MoveItem()
Declare TestItem(*Head.s_Head)

Declare InitBlendMaps()
Declare Clamp(*var.float, min.f, max.f)

; OpenGL needs to have CG enabled to work (Linux and OS X have OpenGL by default)
;
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
  Flags = #PB_Engine3D_EnableCG
CompilerEndIf

If InitEngine3D(Flags)
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    Add3DArchive("Data/Textures/", #PB_3DArchive_FileSystem)
    Add3DArchive("Data/Scripts",#PB_3DArchive_FileSystem)
    Add3DArchive("Data/Textures/nvidia", #PB_3DArchive_FileSystem)
    Add3DArchive("Data/GUI", #PB_3DArchive_FileSystem) 
    Add3DArchive("Data/Packs/desert.zip", #PB_3DArchive_Zip)
    Parse3DScripts()
    
    WorldShadows(#PB_Shadow_Modulative, -1, RGB(127, 127, 127))
    
    ;- Light
    ; 
    light = CreateLight(#PB_Any ,RGB(185, 185, 185), 4000, 1200, 1000, #PB_Light_Directional)
    LightColor(light, RGB(255*0.4, 255*0.4,255*0.4), #PB_Light_SpecularColor) 
    LightDirection(light ,0.55, -0.3, -0.75) 
    AmbientColor(RGB(5, 5, 5))
    
    ; terrain definition
    SetupTerrains(LightID(Light), 3000, #PB_Terrain_NormalMapping)
    ; initialize terrain 
    CreateTerrain(0, 513, 12000, 600, 3, "Terrain04", "Dat")
    ; set all texture will be use when terrrain will be constructed 
    AddTerrainTexture(0,  0, 100, "dirt_grayrocky_diffusespecular.dds",  "dirt_grayrocky_normalheight.dds")
    AddTerrainTexture(0,  1,  30, "grass_green-01_diffusespecular.dds", "grass_green-01_normalheight.dds")
    AddTerrainTexture(0,  2, 200, "growth_weirdfungus-03_diffusespecular.dds", "growth_weirdfungus-03_normalheight.dds")
    
    ;- define terrains
    For ty = #TerrainMiniY To #TerrainMaxiY
      For tx = #TerrainMiniX To #TerrainMaxiX
        imported = DefineTerrainTile(0, tx, ty, "terrain513.png", ty % 2, tx % 2)  
      Next
    Next  
    BuildTerrain(0)  
    
    If imported = #True
      InitBlendMaps() 
      UpdateTerrain(0)
      SaveTerrain(0, #False)
    EndIf  
    
    ; SkyBox
    ;
    SkyBox("desert07.jpg")
    
    ;- Materials
    ;
    CreateMaterial(0, LoadTexture(0, "Wood.jpg"))
    GetScriptMaterial(1, "SphereMap/SphereMappedRustySteel")
    CreateMaterial(2, LoadTexture(2, "Dirt.jpg"))
    GetScriptMaterial(3, "Scene/GroundBlend")
    
    ;- Head
    ;
    CreateSphere(1, #Size)
    
    With Head
      \Entity = CreateEntity(#PB_Any, MeshID(1), MaterialID(1))
      \Key\Left  = #PB_Key_Left
      \Key\Right = #PB_Key_Right
      \Offset\x = 0
      \Offset\y = 50 ; Offset could be needed for FirstPerson
      \Offset\z = 130  
      ; Entity use 3 nodes  
      \MainNode=CreateNode(#PB_Any, 0, #Size, 0) ; Entity position
      \SightNode=CreateNode(#PB_Any, 0, 20, -120) ; For cameraLookAt 
      \CameraNode=CreateNode(#PB_Any, 0, 100, 140) ; Camera position
      
      \LastItem = \Entity
      
      AttachNodeObject(\MainNode, NodeID(\SightNode))
      AttachNodeObject(\MainNode, NodeID(\CameraNode))   
      AttachNodeObject(\MainNode, EntityID(\Entity))
      
      ObjectOnTerrain(p, \MainNode, #Object_Node)
    EndWith
    
    
    ;- Item 
    ;
    For i=1 To #Nb
      AddElement(Item())
      Item()\Entity = CreateEntity(#PB_Any, MeshID(1), MaterialID(1), Random(6000)-3000, #Size, Random(6000)-3000)
      ObjectOnTerrain(p, Item()\Entity, #Object_Entity)
    Next  
    
    ;- Camera
    ;
    CreateCamera(0, 0, 0, 100, 100)
    With Camera  
      \Camera = 0
      \Mode = -1
      \Tightness = 0.01
      ; Camera use 2 nodes
      \CameraNode = CreateNode(#PB_Any, -3000, 700, 0) ; Camera position
      \TargetNode = CreateNode(#PB_Any) ; For cameraLookAt 
      AttachNodeObject(\CameraNode, CameraID(\Camera))
    EndWith  
    
    ;- --- Main loop ----
    Repeat
      Screen3DEvents()
      
      If ExamineKeyboard()
        CameraMode(@Camera, @Head)     
        HandleEntity(@Head)
      EndIf
      
      TestItem(@Head)
      MoveItem()
      
      CameraTrack(@Camera, @Head)
      
      Speed.f = RenderWorld() * #PlayerSpeed 
      
      Screen3DStats()
      FlipBuffers()
      
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
    
    End 
    
  EndIf 
Else
  MessageRequester("Error","Can't initialize engine3D")
EndIf 

Procedure InitBlendMaps()
  minHeight1.f = 70
  fadeDist1.f = 40
  minHeight2.f = 70
  fadeDist2.f = 15    
  For ty = #TerrainMiniY To #TerrainMaxiY
    For tx = #TerrainMiniX To #TerrainMaxiX
      Size = TerrainTileLayerMapSize(0, tx, ty)
      For y = 0 To Size-1
        For x = 0 To Size-1
          Height.f = TerrainTileHeightAtPosition(0, tx, ty, 1, x, y)
          
          val.f = (Height - minHeight1) / fadeDist1
          Clamp(@val, 0, 1)
          SetTerrainTileLayerBlend(0, tx, ty, 1, x, y, val)
          
          val.f = (Height - minHeight2) / fadeDist2
          Clamp(@val, 0, 1)
          SetTerrainTileLayerBlend(0, tx, ty, 2, x, y, val)
        Next
      Next
      UpdateTerrainTileLayerBlend(0, tx, ty, 1)
      UpdateTerrainTileLayerBlend(0, tx, ty, 2)
    Next
  Next  
EndProcedure  

Procedure Clamp(*var.float, min.f, max.f)
  If *var\f < min
    *var\f = min
  ElseIf *var\f > max
    *var\f = max
  EndIf
EndProcedure 


Procedure.f Distance(*v1.Vector3, *v2.Vector3)
  ProcedureReturn Sqr((*v1\x-*v2\x)*(*v1\x-*v2\x)+(*v1\y-*v2\y)*(*v1\y-*v2\y)+(*v1\z-*v2\z)*(*v1\z-*v2\z))
EndProcedure

Procedure TestItem(*Head.s_Head)
  Protected.Vector3 v1, v2, d, p
  
  ForEach Item() 
    
    GetObjectPosition(v1, *Head\Entity, #Object_Entity)
    GetObjectPosition(v2, Item()\Entity, #Object_Entity)
    
    If Distance(@v1, @v2) < 2 * #Size
      AddElement(Chenille())
      Chenille()\Entity = Item()\Entity
      Chenille()\forward = *Head\LastItem 
      *Head\LastItem    = Item()\Entity
      DeleteElement(Item())
    EndIf
    
  Next  
EndProcedure

Procedure MoveItem()
  Protected.Vector3  d, p, v1, v2
  Protected Dist.f
  ForEach Chenille()
    
    GetObjectPosition(v1, Chenille()\Entity, #Object_Entity)
    GetObjectPosition(d, Chenille()\Forward, #Object_Entity)
    Dist = #Ecart - Distance(@v1, @d)  
    
    EntityLookAt(Chenille()\Entity, d\x, d\y, d\z)
    MoveEntity(Chenille()\Entity, 0, 0, Dist, #PB_Local)
    
    ObjectOnTerrain(p, Chenille()\Entity, #Object_Entity)
  Next 
EndProcedure

Procedure HandleEntity( *Head.s_Head)
  Protected.Vector3 PosMain, PosDir , p
  Protected Node
  
  With *Head
    If KeyboardPushed(\Key\Left)
      RotateNode(\MainNode, 0,Speed, 0, #PB_Relative)
    ElseIf KeyboardPushed(\Key\Right)
      RotateNode(\MainNode, 0, -Speed, 0, #PB_Relative)
    EndIf 
    
    MoveNode(\MainNode, 0, 0, -Speed, #PB_Local)
    ObjectOnTerrain(p, \MainNode, #Object_Node)
    
  EndWith   
EndProcedure

Procedure CameraMode(*Camera.s_Camera, *Head.s_Head)
  Protected.Vector3 CameraPosition, TargetPosition, Temp
  
  If KeyboardReleased(#PB_Key_F2)  Or *Camera\Mode = -1
    *Camera\Mode = #ThirdPersonChase
    HideEntity(*Head\Entity, #False)
    GetObjectPosition(CameraPosition, *Head\CameraNode, #Object_Node)
    GetObjectPosition(TargetPosition, *Head\SightNode, #Object_Node)
    CameraInstantUpdate(*Camera, @CameraPosition, @TargetPosition)
    *Camera\Tightness = 0.01
    
  ElseIf KeyboardReleased(#PB_Key_F3)
    *Camera\Mode = #ThirdPersonFixed
    HideEntity(*Head\Entity, #False)
    SetVector3(CameraPosition, 0, TerrainHeight(0, 0, 0) + 200, 0)
    GetObjectPosition(TargetPosition, *Head\SightNode, #Object_Node)
    CameraInstantUpdate(*Camera, @CameraPosition, @TargetPosition)
    *Camera\Tightness = 0.01
    
  ElseIf KeyboardReleased(#PB_Key_F4)  
    *Camera\Mode = #TopView
    HideEntity(*Head\Entity, #True)
    GetObjectPosition(CameraPosition, *Head\LastItem, #Object_Entity)
    CameraPosition\y + 400
    GetObjectPosition(TargetPosition, *Head\SightNode, #Object_Node)
    CameraInstantUpdate(*Camera, @CameraPosition, @TargetPosition)
    *Camera\Tightness = 1   
    
  EndIf 
EndProcedure

Procedure CameraTrack(*Camera.s_Camera, *Head.s_Head)
  Protected.Vector3 CameraPosition, TargetPosition, Temp
  
  Select *Camera\Mode
    Case #ThirdPersonChase
      GetObjectPosition(CameraPosition, *Head\CameraNode, #Object_Node)
      GetObjectPosition(TargetPosition, *Head\SightNode, #Object_Node)
      CameraUpDate(*Camera, @CameraPosition, @TargetPosition)
      
    Case #ThirdPersonFixed
      SetVector3(CameraPosition, 0,  TerrainHeight(0, 0, 0) + 200, 0)
      GetObjectPosition(TargetPosition, *Head\SightNode, #Object_Node)
      CameraUpDate(*Camera, @CameraPosition, @TargetPosition)
      
    Case #TopView
      GetObjectPosition(CameraPosition, *Head\LastItem, #Object_Entity)
      CameraPosition\y + 400
      GetObjectPosition(TargetPosition, *Head\MainNode, #Object_Node)
      CameraUpDate(*Camera, @CameraPosition, @TargetPosition)
      
  EndSelect
EndProcedure

Procedure CameraInstantUpdate(*Camera.s_Camera, *CameraPosition.Vector3, *TargetPosition.Vector3)
  Protected V1.Vector3, V2.Vector3
  
  NodeLocate(*Camera\CameraNode, *CameraPosition\x, *CameraPosition\y, *CameraPosition\z)
  
  NodeLocate(*Camera\TargetNode, *TargetPosition\x, *TargetPosition\y, *TargetPosition\z)
  
  CameraLookAt(*Camera\Camera, NodeX(*Camera\TargetNode), NodeY(*Camera\TargetNode), NodeZ(*Camera\TargetNode)) 
EndProcedure

Procedure CameraUpdate(*Camera.s_Camera, *CameraPosition.Vector3, *TargetPosition.Vector3)
  Protected.Vector3 V1, V2, p 
  
  V1\x = (*CameraPosition\x - NodeX(*Camera\CameraNode)) *  *Camera\Tightness
  V1\y = (*CameraPosition\y - NodeY(*Camera\CameraNode)) *  *Camera\Tightness
  v1\z = (*CameraPosition\z - NodeZ(*Camera\CameraNode)) *  *Camera\Tightness
  MoveNode(*Camera\CameraNode, V1\x, V1\y, V1\z)
  
  If NodeY(*Camera\CameraNode) < TerrainHeight(0, NodeX(*Camera\CameraNode), NodeZ(*Camera\CameraNode)) + #Size
    ObjectOnTerrain(p, *Camera\CameraNode, #Object_Node)
  EndIf  
  
  V2\x = (*TargetPosition\x - NodeX(*Camera\TargetNode)) *  *Camera\Tightness
  V2\y = (*TargetPosition\y - NodeY(*Camera\TargetNode)) *  *Camera\Tightness
  V2\z = (*TargetPosition\z - NodeZ(*Camera\TargetNode)) *  *Camera\Tightness
  MoveNode(*Camera\TargetNode, V2\x, V2\y, V2\z)
  
  CameraLookAt(*Camera\Camera, NodeX(*Camera\TargetNode), NodeY(*Camera\TargetNode), NodeZ(*Camera\TargetNode)) 
EndProcedure

Re: une chenille sur un terrain

Publié : lun. 05/nov./2012 9:21
par djes
C'est beau :o

Re: une chenille sur un terrain

Publié : lun. 05/nov./2012 19:04
par venom
Bonjour,

j'aurais voulu savoir, a chaque foi que je lance ce type de code, PureBasic ne trouve pas "Screen3DRequester.pb" dans le fichier temporaire. (il n'est pas dedans et je souhaiterais éviter si possible.)Je doit toujours lui montrer le chemin. Il y a pas une option dans purebasic pour lui indiquer ou il est ?

Et pareil dans le fichier "Screen3DRequester.pb" il me renvoie une erreur a la ligne : 49 il me dit "Sources\PureBasic3DLogo.png" Hors je n'est pas ce type de fichier j'ai juste 2 .BMP du nom de "PureBasicLogo" Est-ce normale aussi ça ?

D'avance merci






@++

Re: une chenille sur un terrain

Publié : lun. 05/nov./2012 20:51
par comtois
venom a écrit :Bonjour,

j'aurais voulu savoir, a chaque foi que je lance ce type de code, PureBasic ne trouve pas "Screen3DRequester.pb" dans le fichier temporaire. (il n'est pas dedans et je souhaiterais éviter si possible.)Je doit toujours lui montrer le chemin. Il y a pas une option dans purebasic pour lui indiquer ou il est ?

Et pareil dans le fichier "Screen3DRequester.pb" il me renvoie une erreur a la ligne : 49 il me dit "Sources\PureBasic3DLogo.png" Hors je n'est pas ce type de fichier j'ai juste 2 .BMP du nom de "PureBasicLogo" Est-ce normale aussi ça ?

D'avance merci@++
Tu as copié le code dans ton répertoire PureBasic\Examples\3D ?
J'utilise les médias et le fichier Screen3DRequester.pb déjà présents. Et il faut utiliser la version 5.00.

Re: une chenille sur un terrain

Publié : lun. 05/nov./2012 21:15
par venom
comtois a écrit :Tu as copié le code dans ton répertoire PureBasic\Examples\3D ?
En effet ça tourne impeccable. :oops: En faite comme j'utilise l'addon de RX14 pour copier du code il créer un code dans le dossier temporaire d'ou ce message.
Merci c'est pas mal en effet.






@++

Re: une chenille sur un terrain

Publié : mar. 06/nov./2012 18:02
par GallyHC
Bonjour comtois,

Vraiment sympa ce petit code, me suis bien amusé.

Cordialement,
GallyHC

Re: une chenille sur un terrain

Publié : mar. 06/nov./2012 19:32
par graph100
je suis bien embêté parce que sur l'ordi que j'utilise je ne peux pas compiler les exemples 3D (dans la 4.61 non plus).

J'ai un message disant que d3dx9_42.dll manque sur mon pc. J'ai déjà réinstallé DirectX9.c mais bon, dxdiag me dit que j'ai la version 11...
Je vais essayer de trouver un direct X depuis internet.. A priori Purebasic utilise la version 9 c'est ça ?

Re: une chenille sur un terrain

Publié : mar. 06/nov./2012 19:35
par comtois

Re: une chenille sur un terrain

Publié : mar. 06/nov./2012 19:37
par graph100
ça te met à jour toutes les versions ?
parce que j'ai des jeux qui tournent déjà sur mon pc !

[edit] it works. merci comtois

Re: une chenille sur un terrain

Publié : mar. 06/nov./2012 21:46
par Ar-S
Yeah ultra fluide, :) ça poutre :mrgreen:

Re: une chenille sur un terrain

Publié : jeu. 08/nov./2012 22:59
par Atlante
Hello,

Pas mal du tout ;)
Par contre je ne sais pas si c'est propre à Pure Basic mais quand je bouge la fenêtre avec le jeu de lancer sur mon deuxième écran alors là c'est le drame : Ecran noir et plantage ensuite.