This demo use lib M3D_Matrix3D
http://perso.wanadoo.fr/comtois/M3D_Mat ... 130704.zip
Code: Select all
; ******************************************* 
; * Comtois : 10/11/04 : DémoCollisionV0.2  * 
; ******************************************* 
; [F1]/[F2]/[F3] => Changement Vue Caméra 
; [F4] => Nombre d'images / seconde et positions du perso 
; [PAgeUp]/[PageDown] => Lève / Baisse la caméra 
; [Fin] => Position par défaut de la caméra 
; [Espace] => Saut du perso 
;-Initialisation 
#ScreenWidth = 800 : #ScreenHeight = 600 : #ScreenDepth = 32 
If InitEngine3D() = 0 
  MessageRequester( "Erreur" , "Impossible d'initialiser la 3D , vérifiez la présence de engine3D.dll" , 0 ) 
  End 
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or InitSound() = 0 
  MessageRequester( "Erreur" , "Impossible d'initialiser DirectX 7 Ou plus" , 0 ) 
  End 
ElseIf OpenScreen( #ScreenWidth , #ScreenHeight , #ScreenDepth , "Démo PlateForme" ) = 0 
  MessageRequester( "Erreur" , "Impossible d'ouvrir l'écran " , 0 ) 
  End 
EndIf 
;-Declare procedures 
Declare MakeBoxCollision( No.l , x.f , y.f , z.f , longueur.f , Hauteur.f , Largeur.f , AngleX.f , Type.l ) 
Declare.f WrapValue( Angle.f ) 
Declare.f Cosd( Angle.f ) 
Declare.f Sind( Angle.f ) 
Declare MakeColimacon(NoEntity.l,PX.f,PY.f,PZ.f,longueur.l,Hauteur.l,Largeur.l,Nbmarche.l) 
Declare  MakeEscalier(NoEntity.l,PX.f,PY.f,PZ.f,longueur.l,Hauteur.l,Largeur.l,Angle.f,Nbmarche.l) 
Declare.f NewXValue( x.f , Angle.f , NbUnite.f ) 
Declare.f NewZValue( x.f , Angle.f , NbUnite.f ) 
;-Structures 
Structure BoxCollision 
  No.l      ; Si le type est 1 alors ce Numéro correspond obligatoirement à l'entity , sinon c'est un numéro différent des entitys existantes 
  x.f       ; Position en X de la Box 
  y.f       ; Position en Y de la Box 
  z.f       ; Position en Z de la Box 
  AngleX.f  ; Angle de la Box sur le Plan XZ 
  MinX.f    ; Dimension de la Box 
  MinY.f    ; Dimension de la Box 
  MinZ.f    ; Dimension de la Box 
  MaxX.f    ; Dimension de la Box 
  MaxY.f    ; Dimension de la Box 
  MaxZ.f    ; Dimension de la Box 
  Type.l    ; Type = 0 => Box Statique ; Type = 1 => Box Dynamique ( presque plus utile avec la nouvelle méthode ) 
EndStructure 
Structure Camera 
  AngleX.f 
  AngleY.f 
  CameraVue.l 
  CameraDist.f 
  CameraHaut.f 
  LookAtY.f 
EndStructure 
Structure Parametres 
  AngleX.f 
  AngleY.f 
  AngleZ.f 
EndStructure 
Dim entity.Parametres(100) 
NewList BoxCollision.BoxCollision() 
Global Camera.Camera 
;- Variables globales 
Global GetCollisionX.f , GetCollisionY.f , GetCollisionZ.f 
Global OldPosX.f , OldPosY.f , OldPosZ.f , Pas.f 
Global PosX0.f , PosY0.f , PosZ0.f 
Global AngleVague.f,Vitesse.f 
Vitesse.f = 1 
;-Mesh 
CreateMesh(0) ; Cube 
SetMeshData(0, 0, ?CubePoints       , 16) 
SetMeshData(0, 1, ?CubeTriangles    , 12) 
SetMeshData(0, 2, ?CubeTextures     , 16) 
SetMeshData(0, 3, ?CubeNormales     , 16) 
M3D_CreateMeshMatrix(100,1000,1000,50,50,1) 
M3D_CreateMeshMatrix(101,1000,1000,20,20,0) 
;- Textures 
LoadTexture(1,"Bois1.png") 
LoadTexture(2,"swater03.png") 
LoadTexture(3,"scave01.png") 
LoadTexture(4,"sceram03.png") 
;- Material 
For a = 1 To 4 
  CreateMaterial(a, TextureID( a )) 
Next a 
MaterialBlendingMode(2,#PB_Material_Add) 
;-Entity 
Restore Entitys 
For a = 0 To 3 
  Read materialID.l : Read Type.l 
  Read longueur.f : Read Hauteur.f : Read Largeur.f 
  Read x.f : Read y.f : Read z.f 
  Read AngleX.f 
  CreateEntity(a , MeshID(0) ,MaterialID(materialID)) 
  ScaleEntity(a , longueur , Hauteur , Largeur ) 
  EntityLocate(a,x,y,z) 
  entity(a)\AngleX = AngleX 
  RotateEntity(a,entity(a)\AngleX,0,0) 
  If a<>1 
    MakeBoxCollision( a , EntityX(a) , EntityY(a) , EntityZ(a) , longueur, Hauteur , Largeur, entity(a)\AngleX , Type ) 
  EndIf 
Next a 
FreeEntity(1) 
h=7  
MakeEscalier(5,300,5,200+14*10,14,h,36,90,10) 
MakeEscalier(16,300+11,5+11*h,200-25,14,h,36,0,10) 
MakeEscalier(43,300,5+10*h,200+11,36,h,36,90,1) 
MakeColimacon(27,500,5,500,50,7,33,15) 
;Eau 
CreateEntity(100,MeshID(100),MaterialID(2)) 
EntityLocate(100,500,18,500) 
;Fond 
CreateEntity(101,MeshID(101),MaterialID(4)) 
EntityLocate(101,500,0,500) 
M3D_PrepareMatrixTexture(100,2,50,50) 
For zz=0 To 49 
  For xx=0 To 49 
    No = xx + 50 * zz 
    M3D_TextureFacette(100,xx,zz,No) 
    If (xx=0 Or xx=19) Or (zz=0 Or zz=19) 
      M3D_SetFacetteHeight(101,xx,zz,50) 
    EndIf  
  Next xx 
Next zz 
M3D_UpDateTexture(100) 
M3D_UpDateTexture(101) 
M3D_UpDateVertex(101) 
;- Camera 
CreateCamera(0, 0, 0 , 100 , 100) 
CameraLocate(0,0,0,20) 
AmbientColor(RGB(125,125,125)) 
Camera\CameraVue = 2 
;-Lumières 
CreateLight(0,RGB(255,255,255)) 
LightLocate(0 , 100, 500 ,500) 
;- Procédures 
Procedure vagues() 
  decaleX.f=19 
  decaleZ.f=17 
  Hauteur.f=4 
  AngleVague = WrapValue(AngleVague + Vitesse) 
  For z = 0 To 50 
    For x = 0 To 50 
      Sommet.f = Sind(AngleVague + (x * decaleX) + (z * decaleZ)) * Hauteur 
      M3D_SetVertexHeight(100,x,z,Sommet) 
    Next x 
  Next z 
  M3D_UpDateVertex(100) 
EndProcedure 
Procedure MakeEscalier(NoEntity.l,PX.f,PY.f,PZ.f,longueur.l,Hauteur.l,Largeur.l,Angle.f,Nbmarche.l) 
  For a = 1 To Nbmarche 
    CreateEntity(NoEntity , MeshID(0) ,MaterialID(1)) 
    ScaleEntity(NoEntity , longueur , Hauteur , Largeur ) 
    EntityLocate(NoEntity,NewXValue(PX,Angle, a * longueur),PY + (a-1) * Hauteur,NewZValue(PZ,Angle, a * longueur)) 
    entity(NoEntity)\AngleX = Angle 
    RotateEntity(NoEntity,entity(NoEntity)\AngleX,0,0) 
    MakeBoxCollision( NoEntity , EntityX(NoEntity) , EntityY(NoEntity) , EntityZ(NoEntity) , longueur , Hauteur , Largeur , entity(NoEntity)\AngleX , 0 ) 
    NoEntity + 1 
  Next a 
EndProcedure  
Procedure MakeColimacon(NoEntity.l,PX.f,PY.f,PZ.f,longueur.l,Hauteur.l,Largeur.l,Nbmarche.l) 
  Angle.f = 0  
  For a= 1 To Nbmarche 
    CreateEntity(NoEntity,MeshID(0),MaterialID(1)) 
    ScaleEntity(NoEntity,longueur,Hauteur,Largeur) 
    EntityLocate(NoEntity,PX + Cosd(Angle) * Largeur,PY + (a-1) * Hauteur,PZ -Sind(Angle) * Largeur) 
    RotateEntity(NoEntity,Angle,0,0) 
    MakeBoxCollision( NoEntity , EntityX(NoEntity) , EntityY(NoEntity) , EntityZ(NoEntity) , longueur ,Hauteur, Largeur , Angle , 0) 
    Angle = WrapValue( Angle + 30 ) 
    NoEntity + 1 
  Next a 
  
  ;Colonne 
  h.f = (a-1) * Hauteur 
  CreateEntity( NoEntity ,MeshID(0) , MaterialID(1) ) 
  longueur1=2 + Largeur / 2 
  Largeur1=2 + Largeur / 2 
  ScaleEntity( NoEntity ,longueur1 , h ,Largeur1 ) 
  EntityLocate( NoEntity , PX , PY + (h-Hauteur)  / 2 , PZ ) 
  MakeBoxCollision( NoEntity , EntityX(NoEntity) , EntityY(NoEntity) , EntityZ(NoEntity) , longueur1 ,h,Largeur1, 0 , 0) 
EndProcedure 
Procedure.f Cosd( Angle.f ) 
  ;calcule le cos d'un angle en degré 
  a.f = Angle * 0.0174533 
  ProcedureReturn Cos( a ) 
EndProcedure 
Procedure.f Sind( Angle.f ) 
  ;calcule le sin d'un angle en degré 
  a.f = Angle  * 0.0174533 
  ProcedureReturn Sin( a ) 
EndProcedure 
Procedure.f WrapValue(Angle.f) 
  Angle/360 
  Angle-Int(Angle) 
  If Angle<0 
    ProcedureReturn (Angle+1)*360 
  Else 
    ProcedureReturn Angle*360 
  EndIf 
EndProcedure 
Procedure.f NewXValue( x.f , Angle.f , NbUnite.f ) 
  ;à utiliser conjointement avec NewZvalue pour calculer une position de <NbUnite> dans la direction <angle> 
  Valeur.f = x + Cosd( Angle ) * NbUnite 
  ProcedureReturn Valeur 
EndProcedure 
Procedure.f NewZValue( z.f , Angle.f , NbUnite.f ) 
  ;à utiliser conjointement avec NewXvalue pour calculer une position de <NbUnite> dans la direction <angle> 
  Valeur.f = z - Sind( Angle ) * NbUnite 
  ProcedureReturn Valeur 
EndProcedure 
Procedure.f EcartAngle( Angle1.f , Angle2.f ) 
  Delta.f=Angle2-Angle1 
  If Delta>180 
    ProcedureReturn Delta-360 
  ElseIf Delta<=-180 
    ProcedureReturn Delta+360 
  Else 
    ProcedureReturn Delta 
  EndIf    
EndProcedure 
Procedure.f CurveAngle( Actuelle.f , Cible.f , P.f ) 
  ;Calcule un angle progressif allant de la valeur actuelle à la valeur cible 
  Delta.f = EcartAngle( Actuelle , Cible ) 
  If P > 1000 : P = 1000 : EndIf 
  Valeur.f = Actuelle + ( Delta * P / 1000 ) 
  ProcedureReturn WrapValue( Valeur ) 
EndProcedure 
Procedure.f CurveValue( Actuelle.f , Cible.f , P.f ) 
  ;Calcule une valeur progressive allant de la valeur actuelle à la valeur cible 
  Delta.f = Cible - Actuelle 
  If P > 1000 : P = 1000 : EndIf 
  Valeur.f = Actuelle + ( Delta * P / 1000 ) 
  ProcedureReturn Valeur 
EndProcedure 
Procedure MakeBoxCollision( No.l , x.f , y.f , z.f , longueur.f , Hauteur.f , Largeur.f , AngleX.f , Type.l ) 
  ; X , Y et Z => Coordonnées de la Box 
  ; Longueur   => Longueur de la Box 
  ; Hauteur    => Hauteur de la Box 
  ; Largeur    => Largeur de la Box 
  ; AngleX     => Angle de la Box sur le plan XZ ( je n'ai pas besoin des autres plans pour l'instant ) 
  ; Type = 0   => Box statique ( calculée une seule fois , exemple pour un mur , un décor quelconque ) 
  ; Type = 1   => Box dynamique ( calculée avant de tester une collision selon la position de l'entity ) 
  
  
  ; MinZ .........|.......... 
  ;      .        |         . 
  ;      .        |         . 
  ;    -----------0-------------- 
  ;      .        |         . 
  ;      .        |         . 
  ; MaxZ .........|.......... 
  ; 
  ;    MinX               MaxX 
  
  ; Les paramètres MinX.f , MinY.f , MinZ.f , MaxX.f , MaxY.f , MaxZ.f , correspondent aux dimensions de la box en prenant 
  ; le centre de l'entity comme référence (0) . 
  
  ; Exemple pour un mur de longueur x = 400 , hauteur y = 100 et largeur z = 30 
  ; ensuite si on veut placer le mur à 45° à la position 1500,50,300 
  ; EntityLocate(#Mur,1500,50,300) 
  ; RotateEntity(#Mur,45,0,0) 
  ; Entity(#Mur)\\AngleX = 45 
  ; et on appelle la Procedure 
  ; MakeBoxCollision( #Mur , EntityX(#Mur) , EntityY(#Mur) , EntityZ(#Mur) , 400 , 100 , 30 , Entity(#Mur)\\AngleX , 0 ) 
  
  ; Pour l'instant je considère que la Box est centré sur l'entity , si ça devait par la suite se révéler trop contraignant 
  ; il sera toujours possible de modifier légèrement cette procédure ainsi : 
  ; Procedure MakeBoxCollision( No.l, X.f, Y.f, Z.f, MinX.f, MinY.f, MinZ.f, MaxX.f, MaxY.f, MaxZ.f, AngleX.f, Type.l ) 
  
  AddElement( BoxCollision() ) 
  BoxCollision()\No = No 
  BoxCollision()\x = x 
  BoxCollision()\y = y 
  BoxCollision()\z = z 
  BoxCollision()\MinX = -longueur/2 
  BoxCollision()\MinY = -Hauteur/2 
  BoxCollision()\MinZ = -Largeur/2 
  BoxCollision()\MaxX = longueur/2 
  BoxCollision()\MaxY = Hauteur/2 
  BoxCollision()\MaxZ = Largeur/2 
  BoxCollision()\AngleX = AngleX 
  BoxCollision()\Type = Type 
  
EndProcedure 
Procedure.l EntityCollision( No1.l , No2.l ) 
  ; La procedure renvoit -1 en cas d'erreur de paramètres ( Box inexistante , Box 1 et 2 identiques ) 
  ; La procedure renvoit 0 si aucune Collision 
  ; La procedure renvoit 1 si la Box No1 est en Collision avec la Box No2 
  
  If No1 = No2 :  ProcedureReturn -1 : EndIf 
  
  ;************************************** Cherche Box ******************************************* 
  
  Trouve = 0 
  ForEach BoxCollision() 
    If BoxCollision()\No = No1 
      
      ; Mise à Jour des caractériques de la Box 
      If BoxCollision()\Type = 1 
        BoxCollision()\x = EntityX(No1) 
        BoxCollision()\y = EntityY(No1) 
        BoxCollision()\z = EntityZ(No1) 
        BoxCollision()\AngleX = entity(No1)\AngleX 
      EndIf 
      
      ; On récupère les caractéristiques de la Box No1 
      PosX1.f = BoxCollision()\x 
      PosY1.f = BoxCollision()\y 
      PosZ1.f = BoxCollision()\z 
      MinX1.f = BoxCollision()\MinX 
      MinY1.f = BoxCollision()\MinY 
      MinZ1.f = BoxCollision()\MinZ 
      MaxX1.f = BoxCollision()\MaxX 
      MaxY1.f = BoxCollision()\MaxY 
      MaxZ1.f = BoxCollision()\MaxZ 
      AngleX1.f = BoxCollision()\AngleX 
      
      Trouve + 1 
      
    ElseIf BoxCollision()\No = No2 
      
      ; Mise à Jour des caractériques de la Box 
      If BoxCollision()\Type = 1 
        BoxCollision()\x = EntityX(No2) 
        BoxCollision()\y = EntityY(No2) 
        BoxCollision()\z = EntityZ(No2) 
        BoxCollision()\AngleX = entity(No2)\AngleX 
      EndIf 
      
      ; On récupère les caractéristiques de la Box No2 
      PosX2.f = BoxCollision()\x 
      PosY2.f = BoxCollision()\y 
      PosZ2.f = BoxCollision()\z 
      MinX2.f = BoxCollision()\MinX 
      MinY2.f = BoxCollision()\MinY 
      MinZ2.f = BoxCollision()\MinZ 
      MaxX2.f = BoxCollision()\MaxX 
      MaxY2.f = BoxCollision()\MaxY 
      MaxZ2.f = BoxCollision()\MaxZ 
      AngleX2.f = BoxCollision()\AngleX 
      
      Trouve + 1 
      
    EndIf 
    
    If Trouve = 2 : Break : EndIf 
    
  Next 
  
  ; Il manque au moins une box 
  If Trouve < 2 
    ProcedureReturn -1 
  EndIf 
  
  ;****************************** Changement de repères **************************************** 
  CosA1.f = Cosd( AngleX1 ) 
  SinA1.f = -Sind( AngleX1 ) 
  CosA2.f = Cosd( AngleX2 ) 
  SinA2.f = Sind( AngleX2 ) 
  PosX.f  = PosX1 - PosX2 
  PosY.f  = PosY1 - PosY2 
  PosZ.f  = PosZ1 - PosZ2 
  a1.f    = (CosA1 * CosA2 - SinA1 * SinA2) 
  a2.f    = (SinA1 * CosA2 + CosA1 * SinA2) 
  A3.f    = (PosX * CosA2 - PosZ * SinA2) 
  A4.f    = (PosX * SinA2 + PosZ * CosA2) 
  
  ; Calcul les 4 coins de la Box sur le plan XZ en tenant compte du changement de repère 
  ; 
  ; MinX1/MinZ1(0)  ______    MaxX1/MinZ1(1) 
  ;                 \     \ 
  ;                  \     \ 
  ;                   \     \ 
  ; MinX1/MaxZ1(3)     \_____\ MaxX1/MaxZ1(2) 
  ; 
  
  ; Et ensuite on détermine une Box qui englobe le tout ( pas précis , mais plus simple ) 
  ; BoxMinX/BoxMinZ.............BoxMaxX/BoxMinZ 
  ;                . ______    . 
  ;                . \     \   . 
  ;                .  \     \  . 
  ;                .   \     \ . 
  ;                .    \_____\. 
  ; BoxMinX/BoxMaxZ.............BoxMaxX/BoxMaxZ 
  ; 
  ;MinX1/MinZ1 
  X0.f = MinX1 * a1 - MinZ1 * a2 + A3 
  Z0.f = MinX1 * a2 + MinZ1 * a1 + A4 
  
  BoxMinX.f = X0 
  BoxMinZ.f = Z0 
  BoxMaxX.f = X0 
  BoxMaxZ.f = Z0 
  
  ;MaxX1/MinZ1 
  x1.f = MaxX1 * a1 - MinZ1 * a2 + A3 
  z1.f = MaxX1 * a2 + MinZ1 * a1 + A4 
  
  If x1 < BoxMinX 
    BoxMinX = x1 
  ElseIf  x1 > BoxMaxX 
    BoxMaxX = x1 
  EndIf 
  If z1 < BoxMinZ 
    BoxMinZ = z1 
  ElseIf  z1 > BoxMaxZ 
    BoxMaxZ = z1 
  EndIf 
  
  ;MaxX1/MaxZ1 
  X2.f = MaxX1 * a1 - MaxZ1 * a2 + A3 
  z2.f = MaxX1 * a2 + MaxZ1 * a1 + A4 
  
  If X2 < BoxMinX 
    BoxMinX = X2 
  ElseIf  X2 > BoxMaxX 
    BoxMaxX = X2 
  EndIf 
  If z2 < BoxMinZ 
    BoxMinZ = z2 
  ElseIf  z2 > BoxMaxZ 
    BoxMaxZ = z2 
  EndIf 
  
  ;MinX1/MaxZ1 
  x3.f = MinX1 * a1 - MaxZ1 * a2 + A3 
  z3.f = MinX1 * a2 + MaxZ1 * a1 + A4 
  
  If x3 < BoxMinX 
    BoxMinX = x3 
  ElseIf  x3 > BoxMaxX 
    BoxMaxX = x3 
  EndIf 
  If z3 < BoxMinZ 
    BoxMinZ = z3 
  ElseIf  z3 > BoxMaxZ 
    BoxMaxZ = z3 
  EndIf 
  BoxMinY.f = MinY1 + PosY 
  BoxMaxY.f = MaxY1 + PosY 
  
  ;**************************** Test si Collision ************************************************* 
  ; BoxMinX/BoxMinZ.............BoxMaxX/BoxMinZ    MinX2/MinZ2.............MaxX2/MaxZ2 
  ;                . ______    .                              .           . 
  ;                . \     \   .                              .           . 
  ;                .  \     \  .                              .           . 
  ;                .   \     \ .                              .           . 
  ;                .    \_____\.                              .           . 
  ; BoxMinX/BoxMaxZ.............BoxMaxX/BoxMaxZ    MinX2/MaxZ2.............MaxX2/MaxZ2 
  
  CondX = (BoxMaxX >= MinX2 And BoxMinX <= MaxX2) 
  CondY = (BoxMaxY >= MinY2 And BoxMinY <= MaxY2) 
  CondZ = (BoxMaxZ >= MinZ2 And BoxMinZ <= MaxZ2) 
  
  ;Utilisé pour les collisions glissantes 
  GetCollisionX = 0 
  GetCollisionY = 0 
  GetCollisionZ = 0 
  
  If CondY And CondX And CondZ 
    ; il serait sûrement plus judicieux de ne faire ces calculs que s'ils sont demandés 
    ; en effet , dans de nombreux cas , on a seulement besoin de savoir s'il y a une collision 
    ; et pas forcément de calculer une collision glissante ! 
    ;Collision en X 
    If BoxMinX < MaxX2 And BoxMinX > MinX2 And BoxMaxX > MaxX2 
      GetCollisionXa.f =  BoxMinX - MaxX2 
    ElseIf BoxMaxX < MaxX2 And BoxMaxX > MinX2 And BoxMinX < MinX2 
      GetCollisionXa.f =  BoxMaxX - MinX2 
    EndIf 
    
    ; a voir pour traiter ça autrement ! > c'est pour éviter de tomber quand on s'approche trop du bord d'une box ! 
    If Abs(GetCollisionXa) > 3 
      GetCollisionXa = 0 
    EndIf 
    
    ; Collision en Z 
    If BoxMinZ < MaxZ2 And BoxMaxZ > MaxZ2 And BoxMaxZ > MaxZ2 
      GetCollisionZa.f =  BoxMinZ - MaxZ2 
    ElseIf BoxMaxZ < MaxZ2 And BoxMaxZ > MinZ2 And BoxMinZ < MinZ2 
      GetCollisionZa.f =  BoxMaxZ - MinZ2 
    EndIf 
    
    ; A voir pour traiter ça autrement ! > c'est pour éviter de tomber quand on s'approche trop du bord d'une box ! 
    If Abs(GetCollisionZa) > 3 
      GetCollisionZa = 0 
    EndIf 
    
    ;Collision en Y 
    If BoxMinY < MaxY2 And BoxMinY > MinY2 And BoxMaxY > MaxY2 And GetCollisionXa = 0 And GetCollisionZa = 0 
      GetCollisionY =  BoxMinY - MaxY2 
    ElseIf BoxMaxY < MaxY2 And BoxMaxY> MinY2 And BoxMinY < MinY2 And OldPosY < PosY0 
      GetCollisionY =  BoxMaxY - MinY2 
    EndIf 
    
    ;Changement de repère des valeurs Collisions glissantes 
    CosA2.f = Cosd( -AngleX2 ) 
    SinA2.f = Sind( -AngleX2 ) 
    GetCollisionX = GetCollisionXa * CosA2 - GetCollisionZa * SinA2 
    GetCollisionZ = GetCollisionXa * SinA2 + GetCollisionZa * CosA2 
    
    ProcedureReturn 1 
    
  Else 
    
    ProcedureReturn 0 
    
  EndIf 
  
EndProcedure 
Procedure GestionCamera() 
  ;Ajouter collision à la caméra . 
  ; Touches de la Caméra 
  If KeyboardReleased(#PB_Key_F1) : Camera\CameraVue = 1 : EndIf 
  If KeyboardReleased(#PB_Key_F2) : Camera\CameraVue = 2 : EndIf 
  If KeyboardReleased(#PB_Key_F3) : Camera\CameraVue = 3 : EndIf 
  
  If KeyboardPushed(#PB_Key_PageUp) 
    Camera\AngleY + 0.1 
  EndIf 
  
  If KeyboardPushed(#PB_Key_PageDown) 
    Camera\AngleY - 0.1 
  EndIf 
  
  If KeyboardPushed(#PB_Key_End) 
    Camera\AngleY = CurveValue(Camera\AngleY,0,20) 
  EndIf 
  
  If Camera\CameraVue = 1 
    
    Camera\CameraDist = CurveValue(Camera\CameraDist ,85 , 20) 
    Camera\CameraHaut = CurveValue(Camera\CameraHaut ,25 , 20) 
    Camera\LookAtY = CurveValue(Camera\LookAtY ,0 , 20) 
    Camera\AngleX = CurveAngle(Camera\AngleX , entity(0)\AngleX , 20 ) 
    PosXCamera.f = CurveValue(CameraX(0) , NewXValue(EntityX(0) , Camera\AngleX + 180 , Camera\CameraDist) , 280) 
    PosYCamera.f = CurveValue(CameraY(0) , EntityY(0) + Camera\CameraHaut , 30) 
    PosZCamera.f = CurveValue(CameraZ(0) , NewZValue(EntityZ(0) , Camera\AngleX + 180 , Camera\CameraDist) , 280) 
    CameraLocate(0 , PosXCamera , PosYCamera , PosZCamera) 
    CameraLookAt(0 , EntityX(0), EntityY(0) + Camera\LookAtY + Camera\AngleY  ,EntityZ(0)) 
    
  ElseIf Camera\CameraVue = 2 
    
    Camera\CameraDist = CurveValue(Camera\CameraDist ,45 , 20) 
    Camera\CameraHaut = CurveValue(Camera\CameraHaut ,25 , 20) 
    Camera\LookAtY = CurveValue(Camera\LookAtY , 8 , 20) 
    Camera\AngleX = CurveAngle(Camera\AngleX , entity(0)\AngleX , 20 ) 
    PosXCamera.f = CurveValue(CameraX(0) , NewXValue(EntityX(0) , Camera\AngleX + 180 , Camera\CameraDist) , 280) 
    PosYCamera.f = CurveValue(CameraY(0) , EntityY(0) + Camera\CameraHaut , 30) 
    PosZCamera.f = CurveValue(CameraZ(0) , NewZValue(EntityZ(0) , Camera\AngleX + 180 , Camera\CameraDist) , 280) 
    CameraLocate(0 , PosXCamera , PosYCamera , PosZCamera) 
    CameraLookAt(0 , EntityX(0), EntityY(0) + Camera\LookAtY + Camera\AngleY  ,EntityZ(0)) 
    
  ElseIf Camera\CameraVue = 3 
    
    Camera\CameraDist = CurveValue(Camera\CameraDist ,15 , 20) 
    Camera\CameraHaut = CurveValue(Camera\CameraHaut ,95 , 20) 
    Camera\LookAtY = CurveValue(Camera\LookAtY , 0 , 20) 
    Camera\AngleX = CurveAngle(Camera\AngleX , entity(0)\AngleX , 20 ) 
    PosXCamera.f = CurveValue(CameraX(0) , NewXValue(EntityX(0) , Camera\AngleX + 180 , Camera\CameraDist) , 280) 
    PosYCamera.f = CurveValue(CameraY(0) , EntityY(0) + Camera\CameraHaut , 30) 
    PosZCamera.f = CurveValue(CameraZ(0) , NewZValue(EntityZ(0) , Camera\AngleX + 180 , Camera\CameraDist) , 280) 
    CameraLocate(0 , PosXCamera , PosYCamera , PosZCamera) 
    CameraLookAt(0 , EntityX(0) , EntityY(0) + Camera\LookAtY + Camera\AngleY  , EntityZ(0)) 
    
  EndIf 
  
EndProcedure 
Procedure Affaide() 
  StartDrawing(ScreenOutput()) 
  Locate(10,10) 
  DrawText("Nombre d'images Minimum = " + StrF(Engine3DFrameRate(#PB_Engine3D_Minimum )) + " / Nombre d'images Maximum = " + StrF(Engine3DFrameRate(#PB_Engine3D_Maximum))) 
  Locate(10,30) 
  DrawText("Nombre d'images par seconde = " + StrF(Engine3DFrameRate(#PB_Engine3D_Current))) 
  Locate(10,50) 
  DrawText(StrF(EntityX(0)) + " / " + StrF(EntityY(0)) + " / " + StrF(EntityZ(0))) 
  StopDrawing() 
EndProcedure 
;- Boucle principale 
DecAttraction.f = 0.05 
Attraction.f = 0 
Pas.f = 0 
Repeat 
  vagues() 
  ;ScrollMaterial(3,Random(1)-1,Random(1)-1,#PB_Material_Animated) 
  If ExamineKeyboard() 
    If KeyboardPushed(#PB_Key_Left) 
      entity(0)\AngleX = WrapValue( entity(0)\AngleX + 1 ) 
      RotateEntity(0,1 , 0, 0 ) 
    ElseIf KeyboardPushed(#PB_Key_Right) 
      entity(0)\AngleX = WrapValue( entity(0)\AngleX - 1 ) 
      RotateEntity(0, -1 , 0, 0 ) 
    EndIf 
    If KeyboardPushed(#PB_Key_Up)  
      Pas = CurveValue(Pas, 2 , 120) 
    ElseIf KeyboardPushed(#PB_Key_Down) 
      Pas = CurveValue(Pas, -2 , 120) 
    Else 
      Pas = CurveValue(Pas, 0 , 200) 
    EndIf 
    If KeyboardPushed(#PB_Key_Space) And Attraction = 0 And  AutoriseSaut 
      Attraction = 1.6 : DecAttraction = 0.05 
    EndIf 
    If KeyboardReleased(#PB_Key_F4) : AfficheAide = 1 - AfficheAide : EndIf 
  EndIf 
  ; LE perso avant 
  OldPosY = EntityY(0) 
  OldPosX = EntityX(0) 
  OldPosZ = EntityZ(0) 
  ; LE perso pendant 
  If Attraction=0 
    M3D_MoveEntityXZ(100, 0 , entity(0)\AngleX ,Pas)  
  Else  
    MoveEntity( 0 , Cosd( entity(0)\AngleX ) * Pas , Attraction, -Sind( entity(0)\AngleX ) * Pas ) 
  EndIf  
  ; LE perso après 
  PosY0 = EntityY(0) 
  PosX0 = EntityX(0) 
  PosZ0 = EntityZ(0) 
  ; Gestion de l'attraction 
  Attraction - DecAttraction 
  ; Test des collisions 
  
  ForEach BoxCollision() 
    
    NoBox = BoxCollision()\No 
    IndexBoxCollision = ListIndex(BoxCollision()) 
    
    If EntityCollision( 0 , NoBox ) > 0 
      
      ; Collision glissante 
      PosY0 - GetCollisionY 
      PosX0 - GetCollisionX 
      PosZ0 - GetCollisionZ 
      
      If GetCollisionY <> 0 
        If OldPosY < PosY0 And GetCollisionY > 0; pour ne pas rester coller sous une dalle quand on saute !! 
          Attraction = -0.1 
          AutoriseSaut = 0 
        Else 
          Attraction = 0 
          AutoriseSaut = 1 
        EndIf 
      EndIf 
    EndIf 
    SelectElement(BoxCollision(), IndexBoxCollision) 
  Next  
  ; Repositionne le perso 
  EntityLocate(0,PosX0 ,PosY0 ,PosZ0 ) 
  If EntityY(0)<M3D_GetGroundHeight(101,PosX0,PosZ0)+5 
    EntityLocate(0,PosX0 ,M3D_GetGroundHeight(101,PosX0,PosZ0)+5,PosZ0 ) 
    Attraction = 0 
    AutoriseSaut = 1 
  EndIf  
  ; Gestion de la caméra 
  GestionCamera() 
  
  RenderWorld() 
  If AfficheAide : Affaide(): EndIf 
  FlipBuffers() 
  
Until KeyboardPushed(#PB_Key_Escape) 
;-Datas du Cube 
DataSection 
Entitys: 
; le perso 
Data.l 1,1 ; matérial 
Data.f 15,10,15 ; Dimension longueur , hauteur , largeur 
Data.f 200,30,200,0 ; positions X,Y,Z et angle 
; le sol 
Data.l 3,0 ; matérial 
Data.f 1000,8,1000 ; Dimension longueur , hauteur , largeur 
Data.f 500,0,500,0 ; positions X,Y,Z et angle 
; Un mur 
Data.l 1,0 ; matérial 
Data.f 100,10,50 ; Dimension longueur , hauteur , largeur 
Data.f 700,125,700,45 ; positions X,Y,Z et angle 
; Une plateforme 
Data.l 1,0 ; matérial 
Data.f 100,10,100 ; Dimension longueur , hauteur , largeur 
Data.f 600,115,600,0 ; positions X,Y,Z et angle 
CubePoints: 
Data.f -0.5,-0.5,-0.5 
Data.f -0.5,-0.5,0.5 
Data.f 0.5,-0.5,0.5 
Data.f 0.5,-0.5,-0.5 
Data.f -0.5,0.5,-0.5 
Data.f -0.5,0.5,0.5 
Data.f 0.5,0.5,0.5 
Data.f 0.5,0.5,-0.5 
Data.f -0.5,-0.5,-0.5 
Data.f -0.5,-0.5,0.5 
Data.f 0.5,-0.5,0.5 
Data.f 0.5,-0.5,-0.5 
Data.f -0.5,0.5,-0.5 
Data.f -0.5,0.5,0.5 
Data.f 0.5,0.5,0.5 
Data.f 0.5,0.5,-0.5 
CubeNormales: 
Data.f -1,0,-1 
Data.f -1,0,1 
Data.f 1,0,1 
Data.f 1,0,-1 
Data.f -1,0,-1 
Data.f -1,0,1 
Data.f 1,0,1 
Data.f 1,0,-1 
Data.f 0,-2,0 
Data.f 0,-2,0 
Data.f 0,-2,0 
Data.f 0,-2,0 
Data.f 0,2,0 
Data.f 0,2,0 
Data.f 0,2,0 
Data.f 0,2,0 
CubeTriangles: 
Data.w 0,4,7 
Data.w 0,7,3 
Data.w 1,5,4 
Data.w 1,4,0 
Data.w 2,6,5 
Data.w 2,5,1 
Data.w 3,7,6 
Data.w 3,6,2 
Data.w 9,8,11 
Data.w 9,11,10 
Data.w 12,13,14 
Data.w 12,14,15 
CubeTextures: 
;original 
Data.f 0,1 
Data.f 1,1 
Data.f 0,1 
Data.f 1,1 
Data.f 0,0 
Data.f 1,0 
Data.f 0,0 
Data.f 1,0 
Data.f 0,0 
Data.f 1,0 
Data.f 1,1 
Data.f 0,1 
Data.f 0,0 
Data.f 1,0 
Data.f 1,1 
Data.f 0,1 
EndDataSection 




