[PB5.00 b5] Aéroglisseur + terrain + physique

Généralités sur la programmation 3D
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par graph100 »

J'ai fait une très légère modification de ton code, et j'avoue que je ne comprend pas le résultat !

Ligne 202 :

Code : Tout sélectionner

  If yPos < TerrainHeight(0,xPos,zPos) + 1
Ligne 224 et + :

Code : Tout sélectionner

    ; apply forward/backward movement
    If forward = #True
      thrustAngle = 270 - NodeYaw(hovercraft(id)\node)
      thrust = hovercraft(id)\thrust * 50
    ElseIf backward = #True
      thrustAngle = 270 - NodeYaw(hovercraft(id)\node)
      thrust = -hovercraft(id)\thrust * 50
    EndIf
J'ai monté la force appliquée pour pouvoir escalader les montagnes, mais je ne comprend pas le rebond horrible que fait la balle lorsqu'on accélère en montée !
Pour mieux observer le truc tu peux ajouter 50 au-lieu de 1 et afficher le corps de collision.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par comtois »

comtois a écrit :
En fait, le principal truc qui me chiffonne, c'est que je n'ai pas réussi à déterminer avec précision quand le vaisseau touche le sol => sur les pentes élevées, le contact n'est pas détecté et le vaisseau ne s'adapte plus à l'angle du terrain (je n'arrive pas à m'expliquer clairement; voyez par vous-même).
C'est sans doute un bug dans la fonction TerrainHeight(), je testerai ça ce week-end.
Je viens de vérifier, j'avais un doute sur le calcul de la projection du point sur le terrain.
J'ai essayé en faisant le calcul autrement et j'ai comparé avec un lancé de rayon et j'obtiens exactement la même valeur. Je n'ai plus de doute, cette fonction renvoie bien la bonne valeur.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par kelebrindae »

comtois a écrit :C'est sans doute un bug dans la fonction TerrainHeight()
Non, non, je me suis mal exprimé.
En fait, si tu appuies sur F5, tu verras que le "body" utilisé pour la physique est juste une sphère que l'on pousse sur le terrain; je me contente d'afficher l'entity du véhicule à l'emplacement de cette sphère. Après, je me débrouille avec "TerrainHeight" pour poser le véhicule sur le sol et l'incliner selon le relief (et ça marche très bien).
Mon problème, c'est que je ne dois incliner le glisseur que si la sphère est en contact avec le sol: c'est ça que je n'arrive pas à détecter. Sur le plat, ça va car je sais où chercher le sol (à peu près à la verticale en dessous de la sphère). Par contre, sur une pente raide, ce n'est pas le dessous de la sphère qui touche le sol mais le côté; Dans ces cas-là, je ne détecte plus le contact et le glisseur n'est plus incliné en fonction du terrain (en clair, ce n'est pas PB qui bug, mais mon code).
=> ce qui me manque, c'est une commande ou un truc qui me dise: "la sphère n°X est en collision avec le terrain n°Y".
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par comtois »

kelebrindae a écrit :
comtois a écrit :C'est sans doute un bug dans la fonction TerrainHeight()
Non, non, je me suis mal exprimé.
Oui mais j'avais quand même un doute. Maintenant que j'ai vérifié ça va beaucoup mieux, je vais bien dormir cette nuit :)
=> ce qui me manque, c'est une commande ou un truc qui me dise: "la sphère n°X est en collision avec le terrain n°Y".
Ok je comprends mieux ton problème, ça manque en effet.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par blendman »

ça marche bien chez moi (xp geforce 2 GTX).

Je trouve que la physique a un peu trop "d'inertie" mais sinon, c'est pas mal ;).
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par comtois »

blendman a écrit :Je trouve que la physique a un peu trop "d'inertie" mais sinon, c'est pas mal ;).
Tu peux essayer avec RenderWorld(20) ou plus.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par Le Soldat Inconnu »

Code : Tout sélectionner

While WindowEvent()
  Delay(1)
Wend
ça par contre, c'est pas bon, faut pas mettre de Delai dans cet boucle (ne pas en mettre du tout d'ailleurs, sauf si tu ne synchronise pas le rafraichissement de l'écran)

Sinon, c'est très chouette :)
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par kelebrindae »

J'ai ajouté pleins de trucs: des arbres, des adversaires, et des checkpoints.
Prenez le zip (il y a pleins de fichiers en plus), et surtout effacez le "fichier cache du terrain" (hovercraft_00000000.dat, dans le répertoire "meshes") parce que ce n'est plus le même.
http://keleb.free.fr/codecorner/downloa ... rcraft.zip

Deux remarques:
- Si ça rame, il y a deux constantes au début du code pour régler le nombre d'arbres et de caisses présents sur le terrain (virez plutôt les caisses, elles ne servent à rien);
- Curieusement, le format du png utilisé comme heightmap a l'air d'influer sur la physique. Avec celui qui est dans le zip, ça va: les véhicules glissent bien, sans rebond. Si je l'ouvre avec Paint Shop Pro et que je le sauvegarde sans rien changer, j'observe que le fichier obtenu est beaucoup plus petit (280Ko au lieu de 1,4 Mo) et que les glisseurs se mettent à sautiller comme s'ils rencontraient pleins de "marches" invisibles. Je ne comprends pas trop ce qui se passe... C'est un problème de compression de l'image? :?

Amusez-vous bien!

PS: Ah oui, et il faut que je refasse les arbres; les materials ne marchent pas (le canal alpha du feuillage ne fonctionne pas bien).
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par comtois »

C'est excellent, j'adore.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Fred
Site Admin
Messages : 2807
Inscription : mer. 21/janv./2004 11:03

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par Fred »

Mortel :)
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par kelebrindae »

Merci les gars! :D

Je rappelle quand même que j'ai pompé le principe et une partie du code -et même le mesh des glisseurs- sur un tuto DarkBasic de Binary Moon ("Limit Rush", ici: http://www.thegamecreators.com/?m=view_ ... rial_index ); je n'ai aucun mérite dans l'affaire.

Par contre, il faut souligner que les nouvelles fonctions 3D & Physics de PB 5.00 ont rendu l'adaptation très rapide et facile; cette version mérite vraiment le nom de "version majeure". Encore bravo à toute l'équipe !
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par comtois »

Suggestion : Ajout de particules de poussières quand l'engin touche le sol, et pourquoi pas de la fumée à l'arrière quand on accélère.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Fred
Site Admin
Messages : 2807
Inscription : mer. 21/janv./2004 11:03

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par Fred »

Et une barre de boost :)
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par comtois »

au bout d'un moment on ne voit plus les adversaires, je me demandais où ils étaient passés, alors j'ai ajouté une caméra pour les suivre.
J'ai constaté qu'en cas de collision avec un arbre ils pouvaient être désactivés par le moteur (mouvement faible).

Tu devrais ajouter un DisableEntityBody(x, #false) lorsque tu demandes un mouvement sur un engin pour le réactiver.

Voici ma modif avec la caméra de surveillance - Touche [F8] pour changer d'adversaire à surveiller.

Code : Tout sélectionner

;************************************************************************************
;  Hovercraft race (inspired by the Binary Moon tutorials for DarkBasic)
;  PB version: 5.00 b6
;  Date: October, 23, 2012
;- F1 -> F4 change camera view
;- F5 : Display physic body
;************************************************************************************

;************************************************************************************
;-                          ---- Constants and structure ----
;************************************************************************************

#NUMTERRAIN = 0
#TerrainMiniX = 0
#TerrainMiniY = 0
#TerrainMaxiX = 0
#TerrainMaxiY = 0

#CAMERA = 0
#CAMERA2 = 1
#NB_HOVERCRAFT = 3
#NB_CRATESTACKS = 20
#NB_TREES = 600
Enumeration
  #RearView
  #SideView
  #FrontView
  #TopView
EndEnumeration


Structure hover_struct
  node.i
  frontNode.i
  backNode.i
  leftNode.i
  rightNode.i
  cameraNode.i
  
  hovercraftMesh.i
  hovercraftEntity.i
  
  physicsEntity.i
  physicsMesh.i
  mass.f
  restitution.f
  friction.f
  
  radius.f
  centerHeight.f
  
  thrust.f
EndStructure
Global Dim hovercraft.hover_struct(#NB_HOVERCRAFT+1)

Structure checkpoint_struct
  node.i
  
  x.f
  y.f
  z.f
  
  radius.f
EndStructure
Global currentCheckpoint.checkpoint_struct

Global Dim treeMesh.i(4)
Global Dim scoreSprite.i(#NB_HOVERCRAFT+1)
Global Dim score.i(#NB_HOVERCRAFT+1)
Global Dim scoreColor.i(#NB_HOVERCRAFT+1)
Global Dim cameraAngle.f(2)

scoreColor(0) = $0000FF
scoreColor(1) = $FF0000
scoreColor(2) = $00FF00
scoreColor(3) = $00FFFF
Global arrowMesh.i,arrowEntity.i
Define idToView

EnableExplicit

;************************************************************************************
;-                                 ---- Macros ----
;************************************************************************************

; Les deux macros ci-dessous sont de Comtois. Merci Comtois !
Macro NEWXVALUE(x, Angle, Distance)
  ((x) + Cos(Radian(Angle+90)) * (Distance))
EndMacro

Macro NEWZVALUE(z, Angle, Distance)
  ((z) - Sin(Radian(Angle+90)) * (Distance))
EndMacro

Macro ANGLE2CHECKPOINT(idHovercraft)
  Degree(ATan2(NodeZ(hovercraft(idHovercraft)\node) - currentCheckpoint\z , NodeX(hovercraft(idHovercraft)\node) - currentCheckpoint\x ))
EndMacro

;************************************************************************************
;-                                 ---- Procedures ----
;************************************************************************************

; Gestion des blendmaps du terrain, par Comtois 
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 InitBlendMaps()
  Protected minHeight1.f,fadeDist1.f,minHeight2.f,fadeDist2.f
  Protected x.i,y.i,tx.i,ty.i,size.i
  Protected height.f, val.f
  
  minHeight1 = 0
  fadeDist1 = 15
  minHeight2 = 25
  fadeDist2 = 15
  
  For ty = #TerrainMiniY To #TerrainMaxiY
    For tx = #TerrainMiniX To #TerrainMaxiX
      Size = TerrainTileLayerMapSize(#NUMTERRAIN, tx, ty)
      For y = 0 To Size-1
        For x = 0 To Size-1
          Height = TerrainTileHeightAtPosition(#NUMTERRAIN, tx, ty, 1, x, y)
          
          val = (Height - minHeight1) / fadeDist1
          Clamp(@val, 0, 1)
          SetTerrainTileLayerBlend(#NUMTERRAIN, tx, ty, 1, x, y, val)
          
          val = (Height - minHeight2) / fadeDist2
          Clamp(@val, 0, 1)
          SetTerrainTileLayerBlend(#NUMTERRAIN, tx, ty, 2, x, y, val)
        Next
      Next
      UpdateTerrainTileLayerBlend(#NUMTERRAIN, tx, ty, 1)
      UpdateTerrainTileLayerBlend(#NUMTERRAIN, tx, ty, 2)
    Next
  Next  
EndProcedure  

; ************** end of terrain procs *************


; Keep angle in the 0-360 range
Procedure.f wrapValue(angle.f)
  If angle < 0
    angle + 360
  ElseIf angle >=360
    angle-360
  EndIf
  
  ProcedureReturn angle
EndProcedure

; La procédure ci-dessous est de Comtois. Merci Comtois !
; Calcule une valeur progressive allant de la valeur actuelle à la valeur cible
Procedure.f curveValue(actuelle.f, Cible.f, P.f)
  If P > 1000.0
    P = 1000.0
  EndIf
  ProcedureReturn (actuelle + ( (Cible - actuelle) * P / 1000.0))
EndProcedure


Procedure createTrees(nbTrees.i)
  Protected i.i,tree.i,numMesh.i
  Protected posX.f,posY.f,posZ.f
  
  treeMesh(0) = LoadMesh(#PB_Any,"arbol_mort.mesh")
  treeMesh(1) = LoadMesh(#PB_Any,"arbol_sec.mesh")
  treeMesh(2) = LoadMesh(#PB_Any,"arbol.mesh")
  treeMesh(3) = LoadMesh(#PB_Any,"sapin.mesh")
  BuildMeshShadowVolume(treeMesh(0))
  BuildMeshShadowVolume(treeMesh(1))
  BuildMeshShadowVolume(treeMesh(2))
  BuildMeshShadowVolume(treeMesh(3))
  
  For i= 1 To nbTrees
    posX = Random(900) - 450
    posZ = Random(900) - 450
    posY = TerrainHeight(#NUMTERRAIN,posX,posZ)-0.2
    numMesh = Round(posY / 10, #PB_Round_Down)
    Clamp(@numMesh,0,3)
    If numMesh > 3
      numMesh = 3
    EndIf
    
    tree = CreateEntity(#PB_Any,MeshID(treeMesh(numMesh)),#PB_Material_None,posX,posY,posZ)
    RotateEntity(tree,-90,Random(360),0)
    ScaleEntity(tree,(70 + Random(60))/100.0,(70 + Random(60))/100.0,(70 + Random(60))/100.0)
    EntityRenderMode(tree,#PB_Entity_CastShadow)
    EntityPhysicBody(tree,#PB_Entity_StaticBody,99,1.0,1.0)
    
  Next i
  
EndProcedure

Procedure createCrates(nbStacks.i)
  Protected i.i,j.i,temp.i
  Protected cubeMesh.i,txCrate.i,mtCrate.i
  Protected oriX.f,oriZ.f,posX.f,posY,posZ.f
  
  cubeMesh = CreateCube(#PB_Any,1)
  txCrate = LoadTexture(#PB_Any,"crate.png")
  mtCrate = CreateMaterial(#PB_Any,TextureID(txCrate))
  
  For j=1 To nbStacks
    posX = Random(900) - 450
    oriZ = Random(900) - 450
    For i = 1 To 3
      temp = CreateEntity(#PB_Any, MeshID(cubeMesh), MaterialID(mtCrate))
      posZ = oriZ + (i*1.1)
      EntityLocate(temp,posX,TerrainHeight(#NUMTERRAIN,posX,posZ)+0.5,posZ)
      EntityPhysicBody(temp, #PB_Entity_BoxBody, 0.25)
    Next i
    For i = 1 To 2
      temp = CreateEntity(#PB_Any, MeshID(cubeMesh), MaterialID(mtCrate))
      posZ = oriZ + 0.5 + (i*1.1)
      EntityLocate(temp,posX,TerrainHeight(#NUMTERRAIN,posX,posZ)+1.5,posZ)
      EntityPhysicBody(temp, #PB_Entity_BoxBody, 0.25)
    Next i
    
    temp = CreateEntity(#PB_Any, MeshID(cubeMesh), MaterialID(mtCrate))
    posZ = oriZ + 1 + 1.1
    EntityLocate(temp,posX,TerrainHeight(#NUMTERRAIN,posX,posZ)+2.5,posZ)
    EntityPhysicBody(temp, #PB_Entity_BoxBody, 0.25)
    
  Next j
  
EndProcedure

; Créer un hovercraft et initialise ses paramètres: position, friction, hauteur de son pivot, accélération...
Procedure createHovercraft(id.i,nomMesh.s,nomMat.s,posX.f, posZ.f, mass.f, restitution.f, friction.f, thrust.f, centerHeight.f)
  Protected numMat.i
  
  ; Material
  numMat = GetScriptMaterial(#PB_Any,nomMat)
  
  ; Hovercraft entity
  hovercraft(id)\hovercraftMesh = LoadMesh(#PB_Any,"hovercraft.mesh")  
  hovercraft(id)\hovercraftEntity = CreateEntity(#PB_Any,MeshID(hovercraft(id)\hovercraftMesh),MaterialID(numMat))
  EntityRenderMode(hovercraft(id)\hovercraftEntity,#PB_Entity_CastShadow)
  EntityPhysicBody(hovercraft(id)\hovercraftEntity,#PB_Entity_None)
  
  ; Hovercraft parameters
  hovercraft(id)\thrust = thrust
  hovercraft(id)\radius = MeshRadius(hovercraft(id)\hovercraftMesh)*1.33
  hovercraft(id)\centerHeight = centerHeight
  hovercraft(id)\mass = mass
  hovercraft(id)\restitution = restitution
  hovercraft(id)\friction = friction
  
  ; Main node
  hovercraft(id)\node = CreateNode(#PB_Any)
  AttachNodeObject(hovercraft(id)\node,EntityID(hovercraft(id)\hovercraftEntity))
  
  ; These nodes are used to get terrain height at different points of the hovercraft, according to its rotation
  hovercraft(id)\frontNode = CreateNode(#PB_Any,0,0,-hovercraft(id)\radius)
  hovercraft(id)\backNode = CreateNode(#PB_Any,0,0,hovercraft(id)\radius)
  hovercraft(id)\leftNode = CreateNode(#PB_Any,-hovercraft(id)\radius,0,0)
  hovercraft(id)\rightNode = CreateNode(#PB_Any,hovercraft(id)\radius,0,0)
  
  AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\frontNode))
  AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\backNode))
  AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\leftNode))
  AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\rightNode))
  
  ; Camera Node
  hovercraft(id)\cameraNode = CreateNode(#PB_Any,0,1,5)
  AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\cameraNode))
  
  ; Physics entity for the hovercraft
  hovercraft(id)\physicsMesh = CreateSphere(#PB_Any,hovercraft(id)\radius * 0.8)
  hovercraft(id)\physicsEntity = CreateEntity(#PB_Any,MeshID(hovercraft(id)\physicsMesh),MaterialID(999),posX,TerrainHeight(#NUMTERRAIN,posX,posZ)+1,posZ)
  EntityRenderMode(hovercraft(id)\physicsEntity,0)
  EntityPhysicBody(hovercraft(id)\physicsEntity,#PB_Entity_SphereBody,hovercraft(id)\mass,hovercraft(id)\restitution,hovercraft(id)\friction)
  HideEntity(hovercraft(id)\physicsEntity,#True)
  
EndProcedure


; Apply thrust and steering, and reposition the hovercraft
Procedure moveHovercraft(id.i ,forward.i, backward.i, left.i, right.i)
  Protected xPos.f, yPos.f, zPos.f
  Protected frontHeight.f,backHeight.f,leftHeight.f,rightHeight.f
  Protected xAng.f,yAng.f, zAng.f
  Protected xSlide.f,zSlide.f
  Protected thrustAngle.f, thrust.f
  
  ; Position the hovercraft and get its yaw
  xPos = EntityX(hovercraft(id)\physicsEntity)
  yPos = EntityY(hovercraft(id)\physicsEntity) - hovercraft(id)\radius
  zPos = EntityZ(hovercraft(id)\physicsEntity)
  yAng = NodeYaw(hovercraft(id)\node)
  
  ; The hovercraft can rotate left/right, even in the air
  If left = #True
    RotateNode(hovercraft(id)\node,0,wrapvalue(yAng+4),0)
  ElseIf right = #True
    RotateNode(hovercraft(id)\node,0,wrapvalue(yAng-4),0)
  EndIf
  
  ; If the player is on ground:
  ;   - its rotation must change according to terrain slope;
  ;   - it can accelerate / deccelerate;
  ClearDebugOutput()
  If yPos < TerrainHeight(#NUMTERRAIN,xPos,zPos)
    
    ; Friction
    ; J'aimerais bien que la friction soit plus importante, mais avec un body "Sphere", on ne peut pas (?)
    
    ; Put the hovercraft on the ground
    yPos = TerrainHeight(#NUMTERRAIN,xPos,zPos)
    
    ; Positions of the front, back, left and right nodes
    frontHeight = TerrainHeight(#NUMTERRAIN,NodeX(hovercraft(id)\frontNode),NodeZ(hovercraft(id)\frontNode))
    backHeight  = TerrainHeight(#NUMTERRAIN,NodeX(hovercraft(id)\backNode),NodeZ(hovercraft(id)\backNode))
    leftHeight  = TerrainHeight(#NUMTERRAIN,NodeX(hovercraft(id)\leftNode),NodeZ(hovercraft(id)\leftNode))
    rightHeight = TerrainHeight(#NUMTERRAIN,NodeX(hovercraft(id)\rightNode),NodeZ(hovercraft(id)\rightNode))
    
    ; Quick hack to estimate hovercraft's angle
    xAng = (frontHeight - backHeight) * 30
    zAng = (rightHeight - leftHeight) * 30
    
    ; Update the vehicle rotation
    RotateEntity(hovercraft(id)\hovercraftEntity,xAng,0,0,#PB_Absolute)
    RotateEntity(hovercraft(id)\hovercraftEntity,0,0,zAng,#PB_Relative)
    
    ; apply forward/backward movement
    If forward = #True
      thrustAngle = 270 - NodeYaw(hovercraft(id)\node)
      thrust = hovercraft(id)\thrust
    ElseIf backward = #True
      thrustAngle = 270 - NodeYaw(hovercraft(id)\node)
      thrust = -hovercraft(id)\thrust
    EndIf
    
    ; Adjust thrust according to front/back angle
    thrust * (1 - (xAng/30))
    ;Debug StrF(xpos,2)+" , "+StrF(zpos,2)
    ;Debug "Angle = " + StrF(xAng,2) + "° | Thrust factor = " + StrF((1 - (xAng/30)),2)
    
    ; Move the hovercraft
    ApplyEntityForce(hovercraft(id)\physicsEntity,thrust * Cos(Radian(thrustAngle)),0,thrust * Sin(Radian(thrustAngle)) )
    SetEntityAttribute(hovercraft(id)\physicsEntity, #PB_Entity_MaxVelocity, hovercraft(id)\thrust)
  EndIf
  
  ; Reposition the player object
  NodeLocate(hovercraft(id)\node,xPos,yPos + hovercraft(id)\centerHeight,zPos)
  
  ;   xang = Degree(ATan2(NodeZ(hovercraft(id)\node) - currentCheckpoint\z , NodeX(hovercraft(id)\node) - currentCheckpoint\x )    )
  ;   Debug wrapValue(xang - NodeYaw(hovercraft(id)\node))
  
EndProcedure


Procedure moveAiHovercraft()
  Protected id.i
  Protected forward.b = #True, backward.b, left.b, right.b
  Protected angle.f
  
  For id = 1 To #NB_HOVERCRAFT
    
    If wrapValue(ANGLE2CHECKPOINT(id) - NodeYaw(hovercraft(id)\node)) < 180
      left=#True
      right=#False
    Else
      left=#False
      right=#True
    EndIf
    
    moveHovercraft(id,forward,backward,left,right)
  Next id
  
EndProcedure


Procedure manageCheckpoint(*ptrCheckPoint.checkpoint_struct)
  Protected x.f = *ptrCheckPoint\x + *ptrCheckPoint\radius * Cos(Radian(ElapsedMilliseconds()*2))
  Protected z.f = *ptrCheckPoint\z + *ptrCheckPoint\radius * Sin(Radian(ElapsedMilliseconds()*2))
  Protected i.i
  
  NodeLocate(*ptrCheckPoint\node,x,TerrainHeight(#NUMTERRAIN,x,z)+ *ptrCheckPoint\y,z)
  
  ; If an hovercraft reach the checkpoint, change its position
  For i=0 To #NB_HOVERCRAFT
    If (*ptrCheckPoint\x - NodeX(hovercraft(i)\node)) * (*ptrCheckPoint\x - NodeX(hovercraft(i)\node)) + (*ptrCheckPoint\z - NodeZ(hovercraft(i)\node)) * (*ptrCheckPoint\z - NodeZ(hovercraft(i)\node)) < *ptrCheckPoint\radius * *ptrCheckPoint\radius
      *ptrCheckPoint\x = Random(900) - 450
      *ptrCheckPoint\z = Random(900) - 450
      
      score(i) + 10
      StartDrawing(SpriteOutput(scoreSprite(i)))
      Box(0,0,20,20,scoreColor(i))
      DrawText(32,2,RSet(Str(score(i)),3,"0"))
      StopDrawing()
      
    EndIf  
  Next i
  
EndProcedure

; Position the camera
Procedure manageCamera(cam, mode.i,id.i)
  Protected Px.f, Py.f, Pz.f
  
  Select Mode
      
    Case #FrontView
      cameraAngle(Cam) = CurveValue(cameraAngle(Cam), NodeYaw(hovercraft(id)\node), 100)
      Px = CurveValue(CameraX(Cam), NEWXVALUE(NodeX(hovercraft(id)\node), cameraAngle(Cam), 6), 100)
      Py = CurveValue(CameraY(Cam), NodeY(hovercraft(id)\node) + 3, 100)
      Pz = CurveValue(CameraZ(Cam), NEWZVALUE(NodeZ(hovercraft(id)\node), cameraAngle(Cam), 6), 100)
      
    Case #TopView
      cameraAngle(Cam) = CurveValue(cameraAngle(Cam), NodeYaw(hovercraft(id)\node) + 180, 100)
      Px = CurveValue(CameraX(Cam), NEWXVALUE(NodeX(hovercraft(id)\node), cameraAngle(Cam), 4), 30)
      Py = CurveValue(CameraY(Cam), NodeY(hovercraft(id)\node) + 30, 30)
      Pz = CurveValue(CameraZ(Cam), NEWZVALUE(NodeZ(hovercraft(id)\node), cameraAngle(Cam), 4), 30)
      
    Case #RearView
      cameraAngle(Cam) = CurveValue(cameraAngle(Cam), NodeYaw(hovercraft(id)\node) + 180, 100)
      Px = CurveValue(CameraX(Cam), NodeX(hovercraft(id)\cameraNode), 100)
      Pz = CurveValue(CameraZ(Cam), NodeZ(hovercraft(id)\cameraNode), 100)
      Py = CurveValue(CameraY(Cam), NodeY(hovercraft(id)\node) + 1, 100)
      If Py < TerrainHeight(#NUMTERRAIN,Px,Pz) + 1
        Py = TerrainHeight(#NUMTERRAIN,Px,Pz) + 1
      EndIf
      
    Case #SideView
      cameraAngle(Cam) = CurveValue(cameraAngle(Cam), NodeYaw(hovercraft(id)\node) + 90, 100)
      Px = CurveValue(CameraX(Cam), NEWXVALUE(NodeX(hovercraft(id)\node), cameraAngle(Cam), 8), 100)
      Py = CurveValue(CameraY(Cam), NodeY(hovercraft(id)\node) + 4, 100)
      Pz = CurveValue(CameraZ(Cam), NEWZVALUE(NodeZ(hovercraft(id)\node), cameraAngle(Cam), 8), 100)
      
  EndSelect
  
  CameraLocate(Cam, Px, Py, Pz)
  CameraLookAt(Cam, NodeX(hovercraft(id)\node), NodeY(hovercraft(id)\node), NodeZ(hovercraft(id)\node))
  
EndProcedure

DisableExplicit


;************************************************************************************
;-                                 ---- Main program ----
;************************************************************************************

If InitEngine3D() = 0
  MessageRequester( "Error" , "Can't initialize 3D, check if engine3D.dll is available" , 0 )
  End
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  MessageRequester( "Error" , "Can't find DirectX 7.0 or above" , 0 )
  End
EndIf

OpenWindow(0,0, 0, 800 , 500 ,"Hovercraft")
OpenWindowedScreen(WindowID(0),0,0, 800, 500,0,0,0,#PB_Screen_SmartSynchronization)

;- 3d archives
Add3DArchive("meshes/", #PB_3DArchive_FileSystem)
Add3DArchive("materials/", #PB_3DArchive_FileSystem)
Add3DArchive("textures/", #PB_3DArchive_FileSystem)
Add3DArchive("medias/", #PB_3DArchive_FileSystem)
Parse3DScripts()  

;- Lighting
light = CreateLight(#PB_Any ,$FFFFFF, 500, 1000, 500,#PB_Light_Directional)
LightColor(light, $555555, #PB_Light_SpecularColor)
LightDirection(light, 0.55, -0.5, -0.75)
AmbientColor($222222)
; light = CreateLight(#PB_Any ,$FFFFFF, 500, 750, 500)
; AmbientColor($333333)
WorldShadows(#PB_Shadow_Modulative)
Fog($C2AF80,20,10,1000)

;- Camera 
CreateCamera(#CAMERA, 0, 0, 100, 100)
CameraRange(#CAMERA, 1, 10000)
CameraBackColor(#CAMERA,$FF7755)

CreateCamera(#CAMERA2, 70, 0, 30, 30)
CameraRange(#CAMERA2, 1, 10000)
CameraBackColor(#CAMERA2,$FF7755)

; Arrow
arrowMesh = LoadMesh(#PB_Any,"arrow.mesh")
arrowEntity = CreateEntity(#PB_Any,MeshID(arrowMesh),#PB_Material_None)
ScaleEntity(arrowEntity,0.5,0.5,0.5)


;- Terrain definition
SetupTerrains(LightID(light), 3000, #PB_Terrain_NormalMapping)
CreateTerrain(#NUMTERRAIN, 1025, 1000, 50, 3, "hovercraft", "dat")
AddTerrainTexture(#NUMTERRAIN,  0, 10, "sand.jpg", "sand_n.jpg")
AddTerrainTexture(#NUMTERRAIN,  1,  20, "grass.jpg", "grass_n.jpg")
AddTerrainTexture(#NUMTERRAIN,  2, 30, "rock.jpg",  "rock_n.jpg")

; Build terrains
For ty = #TerrainMiniY To #TerrainMaxiY
  For tx = #TerrainMiniX To #TerrainMaxiX
    imported = DefineTerrainTile(#NUMTERRAIN, tx, ty, "heightmap_2.png", ty % 2, tx % 2)  
  Next
Next  
BuildTerrain(#NUMTERRAIN)
TerrainPhysicBody(#NUMTERRAIN,0.1,2.0)

If imported = #True
  InitBlendMaps() 
  UpdateTerrain(#NUMTERRAIN)
  ;SaveTerrain(#NUMTERRAIN, #False)
EndIf  

;- Wireframe material 
; (used To display the hovercraft's physics entity)
CreateTexture(999,16,16)
StartDrawing(TextureOutput(999))
Box(0,0,16,16,$FFFF00)
StopDrawing()
CreateMaterial(999,TextureID(999))
DisableMaterialLighting(999, State)
MaterialShadingMode(999, #PB_Material_Wireframe)


;- Hovercraft
createHovercraft(0,"hovercraft.mesh","hoverred",200,150,1,0.1,2.0,15,0.4)     ; player
createHovercraft(1,"hovercraft.mesh","hoverblue",210,150,1,0.1,2.0,14.5,0.4)  ; opponents (slightly slower)
createHovercraft(2,"hovercraft.mesh","hovergreen",200,160,1,0.1,2.0,14.5,0.4)
createHovercraft(3,"hovercraft.mesh","hoveryellow",210,160,1,0.1,2.0,14.5,0.4)

;- Crates
cubeMesh = CreateCube(#PB_Any,1)
createCrates(#NB_CRATESTACKS)

;- Trees
createTrees(#NB_TREES)

;- Checkpoint
ringsParticle = GetScriptParticleEmitter(#PB_Any,"flareFountain")
currentCheckpoint\x = 0
currentCheckpoint\z = 0
currentCheckpoint\radius = 3
currentCheckpoint\node = CreateNode(#PB_Any)
AttachNodeObject(currentCheckpoint\node,ParticleEmitterID(ringsParticle))

; Score sprites
For i = 0 To #NB_HOVERCRAFT
  scoreSprite(i) = CreateSprite(#PB_Any,64,20)
  StartDrawing(SpriteOutput(scoreSprite(i)))
  Box(0,0,20,20,scoreColor(i))
  DrawText(32,2,"000")
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(0,0,64,20,scoreColor(i))  
  StopDrawing()
Next i

;- Main loop
hidePhysicBody = #True
wireframe = #False
Repeat
  While WindowEvent()
  Wend
  
  forward = #False:backward=#False:left=#False:right=#False
  If ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Up)
      forward = #True
    ElseIf KeyboardPushed(#PB_Key_Down)
      backward=#True
    EndIf    
    If KeyboardPushed(#PB_Key_Left)
      left = #True
    ElseIf KeyboardPushed(#PB_Key_Right)
      right=#True
    EndIf
    
    ; Display physic body
    If KeyboardReleased(#PB_Key_F5)
      hidePhysicBody = 1 - hidePhysicBody
      HideEntity(hovercraft(0)\physicsEntity, hidePhysicBody)
    EndIf
    ; Display physic body
    If KeyboardReleased(#PB_Key_F6)
      wireframe = 1 - wireframe
      If wireframe = #True
        CameraRenderMode(#CAMERA,#PB_Camera_Wireframe)
      Else
        CameraRenderMode(#CAMERA,#PB_Camera_Textured)
      EndIf
    EndIf
    ;Select id
    If KeyboardReleased(#PB_Key_F8)
      idToView + 1
      If idToView > #NB_HOVERCRAFT
        idToView = 1
      EndIf
    EndIf  
    
    ;Change camera view
    If KeyboardReleased(#PB_Key_F1)
      ModeCamera = #RearView
    ElseIf KeyboardReleased(#PB_Key_F2)
      ModeCamera = #SideView
    ElseIf KeyboardReleased(#PB_Key_F3)
      ModeCamera = #FrontView
    ElseIf KeyboardReleased(#PB_Key_F4)
      ModeCamera = #TopView
    EndIf  
  EndIf
  
  ;- Checkpoints
  manageCheckpoint(@currentCheckpoint)
  
  ;- Move the hovercrafts
  moveHovercraft(0,forward,backward,left,right)
  moveAiHovercraft()
  
  ;- Move the camera
  ManageCamera(#CAMERA,modeCamera,0)
  ManageCamera(#CAMERA2,modeCamera, idToView)
  
  ;- Hud
  MoveCamera(#CAMERA,0,1.60,-5)
  EntityLocate(arrowEntity,CameraX(#CAMERA),CameraY(#CAMERA),CameraZ(#CAMERA))
  RotateEntity(arrowEntity,30,ANGLE2CHECKPOINT(O),0)
  MoveCamera(#CAMERA,0,-1.60,5)
  
  RenderWorld(20)
  
  ;- Scores
  For i = 0 To #NB_HOVERCRAFT
    DisplayTransparentSprite(scoreSprite(i),i*80,8)
  Next i
  
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Torp
Messages : 360
Inscription : lun. 22/nov./2004 13:05

Re: [PB5.00 b5] Aéroglisseur + terrain + physique

Message par Torp »

Superbe ! Cela me rappelle les courses baja de motocross madness :)
Par contre j'ai essayé de mettre plus d'adversaires (#NB_HOVERCRAFT) et ça ne semble pas fonctionner. J'ai toujours 3 adversaires.

Bravo
Répondre