small demo collision 3D

Share your advanced PureBasic knowledge/code with the community.
User avatar
Comtois
Addict
Addict
Posts: 1431
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

small demo collision 3D

Post by Comtois »

You need texture

Image
Image
Image
Image

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 
Last edited by Comtois on Fri Nov 12, 2004 3:35 pm, edited 8 times in total.
CNESM
User
User
Posts: 54
Joined: Sat Jun 21, 2003 11:15 pm
Contact:

Post by CNESM »

Hi,

absolut great work. Thanxs a lot for this first (or second :?: ) example to use collision on pb.
xMystik
User
User
Posts: 10
Joined: Fri Apr 25, 2003 5:52 pm
Location: England
Contact:

Post by xMystik »

Great work. I've been looking for something like this.

Thanks

Steve.
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Very good Comtois, you are a 3D specialist. :!:

A PB built-in command to detect collisions in 3D between defined objects should be welcome, but you have made it. 8O
Fred
Administrator
Administrator
Posts: 18253
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

Impressive...
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

Post by DriakTravo »

Woo HOO! After about 20 min of trying I finnally made it to the top ;)

Great work!
dige
Addict
Addict
Posts: 1413
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Post by dige »

Amazing! Yeah PB rules :-)
User avatar
Comtois
Addict
Addict
Posts: 1431
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Post by Comtois »

very very small update with lib M3D_Matrix3D
Please correct my english
http://purebasic.developpez.com/
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

A version for Ogre 1.0.3 beta? :roll:
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Comtois
Addict
Addict
Posts: 1431
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Post by Comtois »

yes :)
and here M3D_Matrix3D for ogre 1.0.3 beta
viewtopic.php?t=17180

[EDIT]
Added shadows

Code: Select all

; **********************************************************
; * Comtois : 30/10/05 : DémoCollision for Ogre 1.0.3 Beta *
; **********************************************************

; [F1]/[F2]/[F3] => Changement Vue Caméra
; [F4] => Nombre d'images / seconde et positions du perso
; [PAgeUp]/[PageDown] => Lcve / 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

#PB_Shadow_Modulative = 1 ; Black shadow (fast)
#PB_Shadow_Additive = 2   ; Additive translucent shadow (more expensive with severl lights)

WorldShadows(#PB_Shadow_Additive) ; Set the shadow mode for the world

; The data has to be organize in this order: Vertex, COlor, Normal, UVCoordinate (per vertex)
;
#PB_Mesh_Vertex       = 1 << 0
#PB_Mesh_Color        = 1 << 1
#PB_Mesh_Normal       = 1 << 2
#PB_Mesh_UVCoordinate = 1 << 3

; Additionnnal flag to specify the faces
;
#PB_Mesh_Face         = 1 << 4
#SQRT13 = 0.57735026    
;-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 )

;-Structures
Structure BoxCollision
   No.l      ; Si le type est 1 alors ce Numéro correspond obligatoirement r 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
Camera\CameraVue = 1

;- 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

;-Mesh
CreateMesh(0)
Flag = #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate  
SetMeshData(No,Flag         ,?CubeBuffer,16)
SetMeshData(No,#PB_Mesh_face,?IndexCube,12)

;- Textures
CreateTexture(1,128,128)
StartDrawing(TextureOutput(1))
  Box(0,0,128,128,RGB(255,255,255))
  Box(2,2,124,124,RGB(200,0,0))
StopDrawing()

CreateTexture(2,128,128)
StartDrawing(TextureOutput(2))
  Box(0,0,128,128,RGB(255,255,255))
  Box(2,2,124,124,RGB(0,0,200))
StopDrawing()

CreateTexture(3,128,128)
StartDrawing(TextureOutput(3))
  Box(0,0,128,128,RGB(255,255,255))
  Box(2,2,124,124,RGB(0,200,0))
  For a = 0 To 128 Step 4
   For b = 0 To 128 Step 4
      Circle(a,b,2,RGB(10,150,10))
   Next b
Next a
StopDrawing()

;- Material
For a = 1 To 3
   CreateMaterial(a, TextureID( a ))
Next a

;-Entity
Restore Entitys
For a = 0 To 20
   If a < 5
      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
   EndIf
   CreateEntity(a , MeshID(0) ,MaterialID(MaterialId))
   ScaleEntity(a , Longueur , Hauteur , Largeur )
   If a<5
      EntityLocate(a,x,y,Z)
   Else
      EntityLocate(a,x + a * 40,y + a * 20,Z)
   EndIf
   entity(a)\AngleX = AngleX
   RotateEntity(a,entity(a)\AngleX,0,0)
   MakeBoxCollision( a , EntityX(a) , EntityY(a) , EntityZ(a) , Longueur , Hauteur , Largeur , entity(a)\AngleX , Type )
Next a
;Le sol
EntityRenderMode(1, 0)

;- Camera
CreateCamera(0, 0, 0 , 100 , 100)
CameraLocate(0,0,0,20)
AmbientColor(RGB(115,115,115))

;-Light
CreateLight(0,RGB(255,255,255))
LightLocate(0, 500, 900, 500)

;- Procédures
Procedure.f Cosd( Angle.f )
   ;calcule le cos d'un angle en degré
    
   ProcedureReturn Cos(Angle * 0.0174533)
EndProcedure

Procedure.f Sind( Angle.f )
   ;calcule le sin d'un angle en degré
   ProcedureReturn Sin(Angle  * 0.0174533)
EndProcedure

Procedure.f WrapValue( Angle.f )
   ;Permet de toujours avoir un angle compris entre 0° et 360°
	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 )
   ;a utiliser conjointement avec NewZvalue pour calculer une position de <NbUnite> dans la direction <angle>
   ProcedureReturn x + Cosd( Angle ) * NbUnite
EndProcedure

Procedure.f NewZValue( Z.f , Angle.f , NbUnite.f )
   ;a 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 a 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 a 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 paramctres 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 r 45° r 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 considere 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égerement 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 parametres ( 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
   ResetList( BoxCollision() )
   While NextElement( BoxCollision() )
      If BoxCollision()\No = No1

         ; Mise a 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écupere 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 a 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écupere 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

   Wend

   ; Il manque au moins une box
   If Trouve < 2
      ProcedureReturn -1
   EndIf

   ;****************************** Changement de reperes ****************************************
   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 repcre
   ;
   ; 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 surement 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 repcre 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()

   ; 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

   ClearScreen(0, 0, 0)

   If ExamineKeyboard()

      ; Touches du joueur a mettre dans une procédure  et gérer un fichier préférence pour configurer les touches
      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 attraction=0
	Vit=12
Else
	Vit=400
EndIf
      If KeyboardPushed(#PB_Key_Up)
         Pas = curvevalue(Pas, 2 , Vit)
      ElseIf KeyboardPushed(#PB_Key_Down)
         Pas = curvevalue(Pas, -2 , Vit)
      Else
         Pas = curvevalue(Pas, 0 , 200)
      EndIf

      If KeyboardPushed(#PB_Key_Space) And Attraction = 0 And  AutoriseSaut
         Attraction = 1.8 : 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
   MoveEntity( 0 , Cosd( entity(0)\AngleX ) * Pas , Attraction, -Sind( entity(0)\AngleX ) * Pas )

   ; LE perso apres
   PosY0 = EntityY(0)
   PosX0 = EntityX(0)
   PosZ0 = EntityZ(0)

   ; Gestion de l'attraction
   Attraction - DecAttraction

   ; Test des collisions

   ResetList(BoxCollision())
   While NextElement(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)

   Wend

   ; Repositionne le perso
   EntityLocate(0,PosX0 ,PosY0 ,PosZ0 )

   ; 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 2,1 ; matérial
Data.f 6,6,6 ; 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,25,10 ; Dimension longueur , hauteur , largeur
Data.f 400,17,400,45 ; positions X,Y,Z et angle
; Un autre mur
Data.l 1,0 ; matérial
Data.f 100,25,10 ; Dimension longueur , hauteur , largeur
Data.f 600,17,600,0 ; positions X,Y,Z et angle
; et un escalier
Data.l 1,0 ; matérial
Data.f 35,5,35 ; Dimension longueur , hauteur , largeur
Data.f 200,-80,700,0 ; positions X,Y,Z et angle


CubeBuffer: 
Data.f -0.5,-0.5,-0.5 
Data.f -1,0,-1 
Data.f 0,1 
Data.f -0.5,-0.5,0.5 
Data.f -1,0,1 
Data.f 1,1 
Data.f 0.5,-0.5,0.5 
Data.f 1,0,1 
Data.f 0,1 
Data.f 0.5,-0.5,-0.5 
Data.f 1,0,-1 
Data.f 1,1 
Data.f -0.5,0.5,-0.5 
Data.f -1,0,-1 
Data.f 0,0 
Data.f -0.5,0.5,0.5 
Data.f -1,0,1 
Data.f 1,0 
Data.f 0.5,0.5,0.5 
Data.f 1,0,1
Data.f 0,0 
Data.f 0.5,0.5,-0.5 
Data.f 1,0,-1 
Data.f 1,0 
Data.f -0.5,-0.5,-0.5 
Data.f 0,-1,0 
Data.f 0,0
Data.f -0.5,-0.5,0.5 
Data.f 0,-1,0 
Data.f 1,0 
Data.f 0.5,-0.5,0.5 
Data.f 0,-1,0 
Data.f 1,1 
Data.f 0.5,-0.5,-0.5 
Data.f 0,-1,0 
Data.f 0,1 
Data.f -0.5,0.5,-0.5 
Data.f 0,1,0 
Data.f 0,0
Data.f -0.5,0.5,0.5 
Data.f 0,1,0 
Data.f 1,0 
Data.f 0.5,0.5,0.5 
Data.f 0,1,0 
Data.f 1,1
Data.f 0.5,0.5,-0.5 
Data.f 0,1,0 
Data.f 0,1 

IndexCube: 
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 
EndDataSection
Please correct my english
http://purebasic.developpez.com/
User avatar
Comtois
Addict
Addict
Posts: 1431
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Post by Comtois »

added shadows , see preview post.
Please correct my english
http://purebasic.developpez.com/
Nik
Addict
Addict
Posts: 1017
Joined: Fri May 13, 2005 11:45 pm
Location: Germany
Contact:

Post by Nik »

Could you please put the things needed for the demo in a rar or zip file it will make things much easier :wink:
User avatar
Comtois
Addict
Addict
Posts: 1431
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Post by Comtois »

all you need can be found here

viewtopic.php?t=16337

Direct link
http://www.purebasic.com/beta/Ogre1.0.3.zip

You just need lib for Ogre 1.0.3 beta.
Please correct my english
http://purebasic.developpez.com/
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Post by Polo »

He meant the textures and the code in a rar, I think :)
User avatar
Comtois
Addict
Addict
Posts: 1431
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Post by Comtois »

you dont need texture , just copy the code source and run.(the last code of course)
Please correct my english
http://purebasic.developpez.com/
Post Reply