RayCollide() : Détection d'une entité physique dans un rayon

Généralités sur la programmation 3D
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

RayCollide() : Détection d'une entité physique dans un rayon

Message par falsam »

la fonction RayCollide() crée un rayon entre deux points et vérifie si une entité physique (avec un corps body) croise ce rayon.

Pour illustrer cette fonctionnalité, Je vous propose un code avec comme objectif.
- Bouger le cube avec les flèches gauche et droite du curseur.
- Descendre quatre plateformes en partant sur la droite.
- Arrivée sur la dernière plateforme, une impulsion vous renverra le cube sur la première plateforme.

Code : Tout sélectionner

;RayCollide


EnableExplicit

;Scene
Global Camera, Light

;Summary
Declare GameLoad()
Declare RenderGame3D()
Declare RenderGame2D() 
Declare Exit()

GameLoad()

Procedure GameLoad()
  Protected Window 
  
  If InitEngine3D() And  InitKeyboard() And InitSprite() And InitMouse() And InitSound()
    Window = OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_Maximize | #PB_Window_BorderLess)
    SetWindowColor(Window, 0)
    
    ;-[Screen]
    OpenWindowedScreen(WindowID(Window),0, 0, WindowWidth(Window) , WindowHeight(Window))    
    KeyboardMode(#PB_Keyboard_International)  
        
    ;-[3D]
    Add3DArchive(#PB_Compiler_Home + "Examples\3D\Data\Textures", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Packs/waterworld.zip", #PB_3DArchive_Zip)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/desert.zip", #PB_3DArchive_Zip)
    
    SkyBox("desert07.jpg")
    
    ;-Camera
    CreateCamera(0, 0, 0, 100, 100)
    CameraBackColor(0, RGB(0, 0, 0))

    ; Light
    CreateLight(#PB_Any, RGB(151, 251, 151), -200, 100, -500)
    WorldShadows(#PB_Shadow_Additive)
    
    ; Materials
    CreateMaterial(0, TextureID(LoadTexture(-1, "Dirt.jpg")))
    ScaleMaterial(0, 0.2, 0.2)
    CreateMaterial(1, TextureID(LoadTexture(-1, "Floor02.jpg")))
    
    ; Platform
    CreateCube(0, 10)
    
    CreateEntity(1, MeshID(0), MaterialID(0), 0, 10, 0)
    CreateEntityBody(1, #PB_Entity_StaticBody)
    
    CreateEntity(2, MeshID(0), MaterialID(0), 5, 0, 0)
    CreateEntityBody(2, #PB_Entity_StaticBody)
    
    CreateEntity(3, MeshID(0), MaterialID(0), 10, -10, 0)
    CreateEntityBody(3, #PB_Entity_StaticBody)
    
    CreateEntity(4, MeshID(0), MaterialID(0), 15, -20, 0)
    CreateEntityBody(4, #PB_Entity_StaticBody)
    
    ;Player 
    CreateEntity(5, MeshID(CreateCube(-1, 1)), MaterialID(1), 0, 20, 0)
    CreateEntityBody(5, #PB_Entity_BoxBody, 1, 0.5, 0.5) 
    EntityAngularFactor(5, 0, 90, 0)   
    
    ;-Loop
    While #True
      Repeat : Until WindowEvent() = 0
      FlipBuffers()  
      RenderGame3D()
      RenderWorld()
    Wend
  Else
    
  EndIf 
EndProcedure

Procedure RenderGame3D()    
  Protected Target, Speed.f, x1.f, y1.f, z1.f, x2.f, y2.f, z2.f   
  
  If ExamineKeyboard()  
    If KeyboardReleased(#PB_Key_Escape)
      Exit()
    EndIf    
    If KeyboardPushed(#PB_Key_Right)
      Speed = 2
    ElseIf KeyboardPushed(#PB_Key_Left)
      Speed = -2
    Else
      Speed = 0
    EndIf    
  EndIf
  
  CameraFollow(0, EntityID(5), 0, EntityY(5) + 1.5, 20, 0.1, 0.1)
  
  ;RayCollide : Casts a ray between the first point and the second point, and checks if an entity is colliding the ray. 
  x1 = EntityX(5)
  y1 = EntityY(5) - 0.4
  z1 = EntityZ(5)
  x2 = x1
  y2 = y1 - 0.2
  z2 = z1  
  Target = RayCollide(x1, y1, z1, x2, y2, z2)
  
  ;We reached the last platform (Entity 4).
  If Target = 4 
    Target = -1
    ;An impulse To reach the first platform
    ApplyEntityImpulse(5, -4, 42, 0)
    
  ;An entity crosses the ray  
  ElseIf Target <> -1    
    MoveEntity(5, Speed, 0, 0, #PB_Absolute|#PB_Local)   
  EndIf     
EndProcedure

Procedure Exit()
  End
EndProcedure
Remarque : Parfois l'impulsion renvoie le cube trop haut.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
venom
Messages : 3071
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: RayCollide() : Détection d'une entité physique dans un r

Message par venom »

:P Super, chez moi ça fonctionne niquel. Merci pour ce "petit" code très efficace.






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Répondre