Solide glissant sur un rail (part I,II)

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

Frenchy Pilou a écrit :hihi
Je m'obstinais sur le clavier numérique alors que c'était les touche numérique du clavier normal :roll:
numérique ou pavé numérique doit être précisé si on l'utilise.
Anonyme

Message par Anonyme »

http://armorgames.com/play/553/the-fanc ... re-world-2

Bel exemple de la physique ! de visu , c'est des courbes de bezier , non ?
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

Cpl.Bator a écrit :http://armorgames.com/play/553/the-fanc ... re-world-2

Bel exemple de la physique ! de visu , c'est des courbes de bezier , non ?
Le chargement du jeu est des plus laborieux chez moi... mais il mérite l'effort d'attendre, il est très bon, de belles animations bien fluide, et les plate-formes sont tout en courbe... on peux même utiliser la coquille pour réaliser une série de jongle avec la tête ! :)
Sur le site de nitrome, ils donnent des liens vers des sites de dev de la physique en flash...
http://www.cove.org/ape/
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Prise en compte de la chute libre

Message par Huitbit »

Voilà la deuxième partie (il y en aura d'autres :P )!

On va s'occuper de la deuxième équation :

m * v²/r = m * g * Sin(a) – R

Autrement dit :

R = m * g * Sin(a) - m * v² / r

La voiture décolle dès que R = 0 (le sol ne réagit pas car il n'y a plus de contact !)
Ce petit r est TRES IMPORTANT, c'est le rayon de courbure de la trajectoire.
Dans la base de Frenet, la courbe est approximée à chaque instant par un cercle de rayon r.
On a accès à cette valeur de r grâce à la formule ds = dphi_en_radian * r (en fait, c'est la formule "déguisée" de la longueur d'un arc de cercle utilisée depuis l'Antiquité
exemple : pour un cercle, P = 2*pi*r, pour un demi-cercle, P = pi*r , etc).
ds joue le rôle de la longueur, dphi est un angle de valeur quelconque exprimé EN RADIANS !

Remarque : la base de Frenet change en permanence (activez le commentaire : test du signe du rayon de courbure et vous verrez).
Quoiqu'il en soit, les calculs donnent au final:

décollage si : Sin(a) < v² / ( r * g )

Après le décollage, il y a la chute libre :
m * |a> = |P>
Rien à signaler !

Puis ... la partie infernale :twisted: : l'atterrisage !
Les problèmes :
-les points de la courbe ne sont pas tous espacés de la même manière
-le décollage n'est pas assez net
-l'abscisse de l'objet, ne varie pas de la même manière que celle de la courbe
-les obstacles sont différents (creux, bosse, looping)
-les propriétés de l'arctangente avec les angles
-...etc
Pour m'en sortir :
-Selon l'obstacle, je décale l'objet pour éviter qu'un atterrisage précoce ait lieu !
-je garde deux valeurs de x pour l'objet et deux valeurs correspondantes de x pour la courbe
-cela me donne deux segments de droite et je vérifie s'ils se croisent
-si le point d'intersection se trouve entre x_ancien et x_nouveau alors il y a contact !

Ca à l'air bête mais avant ça j'ai beaucoup bricolé :? . Ce qui marchait avec une partie de la courbe, ne marchait pas avec les autres...
(activez les StartDrawing() qui traînent et vous verrez !)

Dans les autres messages, je compte m'occuper du rebond (je n'en tiens pas compte ici), et le plus utile, un système de tiles où chaque partie est
traîtée à part (bosse, creux, looping,...).

Je dois m'absenter pour une vingtaine de jours, c'est pour ça que je mets ce code, même s'il est encore une peu brouillon, ça peut servir !

En informatique, les collisions c'est chaud :x , ce n'est pas la première fois que je galère !

Code : Tout sélectionner

;solide guidé motorisé
;auteur Huitbit
;pb v4.20
;-déclarations*********************************
#largeur_ecran=1024
#hauteur_ecran=768
#dim_sprite=32 ;sprite carré de 32*32
Enumeration
  #spr_decor
  #spr_car_droite
  #spr_car_gauche
  #chute_libre
  #solide_guide
EndEnumeration
Structure donnees
  x.f
  y.f
  dx.f
  dy.f
  s.f ; abscisse curviligne s(t)
  cosinus.f ; cosinus de l'angle vecteur poids |P> et le vecteur tangent à la courbe
  sinus.f ; sinus de l'angle vecteur poids |P> et le vecteur tangent à la courbe
  phi_radian.f ;angle correspondant à la pente locale de la courbe, en radians
EndStructure
x_libre_ancien.f 
y_libre_ancien.f
x_libre.f
y_libre.f
x_decalage.f
y_decalage.f
angle0_libre.f
t0_libre.w
tx_libre.w
tx_libre_ancien.w
v0s.f
v0x_libre.f
vx_libre.f
vy_libre.f
angle_rotation_libre.w
a_libre.f
b_libre.f
a_courbe.f
b_courbe.f
x_contact.f
y_contact.f
retard_detection.b
acceleration_moteur.f
#acceleration_moteur_max=8
#dt=0.2
#coeff_frot=0.1
spr_car.b
#g=9.8
x_car.f
y_car.f

Macro collision
a_libre= (y_libre- y_libre_ancien)/(x_libre-x_libre_ancien)
b_libre=y_libre-a_libre*x_libre
If tx_libre<>tx_libre_ancien
  a_courbe=(courbe(tx_libre)\y-courbe(tx_libre_ancien)\y)/(courbe(tx_libre)\x-courbe(tx_libre_ancien)\x)
  b_courbe=courbe(tx_libre)\y-a_courbe*courbe(tx_libre)\x
EndIf
;-zone de la courbe survolée
; StartDrawing(SpriteOutput(#spr_decor))
; LineXY(courbe(tx_libre)\x,courbe(tx_libre)\y,courbe(tx_libre_ancien)\x,courbe(tx_libre_ancien)\y,RGB(255,0,0))
; StopDrawing()
    
x_contact=(b_courbe-b_libre)/(a_libre-a_courbe)
;y_contact=a_courbe*x_contact+b_courbe

If courbe(tx_libre)\x>courbe(tx_libre_ancien)\x
  If x_contact< courbe(tx_libre)\x And x_contact>courbe(tx_libre_ancien)\x
    t=tx_libre
    s=courbe(tx_libre)\s
    vs=Sqr(vx_libre*vx_libre+vy_libre*vy_libre)*Abs(Cos(angle_rotation_libre*#PI/180))
    retard_detection=0
    modele=#solide_guide
    ;-tracé du point d'impact
    ;     StartDrawing(SpriteOutput(#spr_decor))
    ;     DrawingMode(#PB_2DDrawing_Outlined   )
    ;     Circle(courbe(tx_libre)\x,courbe(tx_libre)\y,8,RGB(0,255,255))
    ;     StopDrawing()
  EndIf
EndIf

If courbe(tx_libre)\x<courbe(tx_libre_ancien)\x
  If x_contact> courbe(tx_libre)\x And x_contact<courbe(tx_libre_ancien)\x
    t=tx_libre
    s=courbe(tx_libre)\s
    vs=-Sqr(vx_libre*vx_libre+vy_libre*vy_libre)*Abs(Cos(angle_rotation_libre*#PI/180))
    retard_detection=0
    modele=#solide_guide
    ;tracé du point d'impact    
    ;     StartDrawing(SpriteOutput(#spr_decor))
    ;     DrawingMode(#PB_2DDrawing_Outlined   )
    ;     Circle(courbe(tx_libre)\x,courbe(tx_libre)\y,8,RGB(0,255,0))
    ;     StopDrawing()
  EndIf
EndIf

EndMacro

;-création de la piste
Dim courbe.donnees(5000)
#y_depart=64
e.f=2.718281828 ; valeur de exp(1)
#parametre_gaussienne=0.001
#parametre_bosse=0.0004
#parametre_creux=0.0004
#hauteur_bosse=64
#profondeur_creux=48
t.w = 0 ;paramètre pour les fonctions x(t), y(t) et s(t) sur tout le parcours
t_max.w ; dernière valeur de t
p.w = 0 ; paramètre provisoire pour chaque portion de courbes
x_point_precedent.f=0
y_point_precedent.f=#y_depart
angle.w
#rayon=100
longueur_courbe.f = 0

s.f ; abscisse curviligne s(t)
s_max.w ; abscisse curviligne s(t) maximale
int_s.w; valeur entière de s(t)
vs.f ; vitesse curviligne 
angle_rotation.w
rayon.f;  rayon de courbure de la trajectoire r=ds/dphi
modele.b=#solide_guide

;-première demi-gaussienne
While courbe(t)\x<#largeur_ecran/8
  t=t+1
  p=p+1
  courbe(t)\x=p
  courbe(t)\y=#y_depart+(#hauteur_ecran*2/3-#y_depart)*(1-Pow(e,-#parametre_gaussienne*p*p))
  courbe(t)\dx=1
  courbe(t)\dy=(#hauteur_ecran*2/3-#y_depart)*#parametre_gaussienne*2*p*Pow(e,-#parametre_gaussienne*p*p)
  longueur_courbe=longueur_courbe+Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy)
  courbe(t)\s=longueur_courbe
  courbe(t)\cosinus=courbe(t)\dy / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\sinus=courbe(t)\dx / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\phi_radian =ATan(courbe(t)\dy/courbe(t)\dx)
Wend
t_max=t

;- creux
While courbe(t)\x<3/8*#largeur_ecran
  t=t+1
  p=p+1
  courbe(t)\x=p
  courbe(t)\y=courbe(t_max)\y+#profondeur_creux*Pow(e,-#parametre_creux*(p-#largeur_ecran/4)*(p-#largeur_ecran/4))
  courbe(t)\dx=1
  courbe(t)\dy=-#profondeur_creux*2*#parametre_creux*(p-#largeur_ecran/4)*Pow(e,-#parametre_creux*(p-#largeur_ecran/4)*(p-#largeur_ecran/4))
  longueur_courbe=longueur_courbe+Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy)
  courbe(t)\s=longueur_courbe
  courbe(t)\cosinus=courbe(t)\dy / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\sinus=courbe(t)\dx / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\phi_radian =ATan(courbe(t)\dy/courbe(t)\dx)
  
Wend
t_max=t

;-bosse 
While courbe(t)\x<5*#largeur_ecran/8
  t=t+1
  p=p+1
  courbe(t)\x=p
  courbe(t)\y=courbe(t_max)\y-#hauteur_bosse*Pow(e,-#parametre_bosse*(p-#largeur_ecran/2)*(p-#largeur_ecran/2))
  courbe(t)\dx=1
  courbe(t)\dy=#hauteur_bosse*2*#parametre_bosse*(p-#largeur_ecran/2)*Pow(e,-#parametre_bosse*(p-#largeur_ecran/2)*(p-#largeur_ecran/2))
  longueur_courbe=longueur_courbe+Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy)
  courbe(t)\s=longueur_courbe
  courbe(t)\cosinus=courbe(t)\dy / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\sinus=courbe(t)\dx / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\phi_radian =ATan(courbe(t)\dy/courbe(t)\dx)
  
Wend
t_max=t

;- portion horizontale 
While courbe(t)\x<0.75*#largeur_ecran
  t=t+1
  p=p+1
  courbe(t)\x=p
  courbe(t)\y=courbe(t_max)\y
  courbe(t)\dx=1
  courbe(t)\dy=0
  longueur_courbe=longueur_courbe+Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy)
  courbe(t)\s=longueur_courbe
  courbe(t)\cosinus=courbe(t)\dy / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\sinus=courbe(t)\dx / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\phi_radian =ATan(courbe(t)\dy/courbe(t)\dx)
  
Wend
t_max=t

;-cercle 
For angle=0 To 360 
  t=t+1
  courbe(t)\x=courbe(t_max)\x+#rayon*Cos(#PI*(-angle+90)/180); décalage de 90° pour partir du bon endroit sur l'ellipse !
  courbe(t)\y=courbe(t_max)\y-#rayon+#rayon*Sin(#PI*(-angle+90)/180)
  courbe(t)\dx=#rayon*#PI/180*Sin(#PI*(-angle+90)/180)
  courbe(t)\dy=-#rayon*#PI/180*Cos(#PI*(-angle+90)/180)
  longueur_courbe=longueur_courbe+Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy)
  courbe(t)\s=longueur_courbe
  courbe(t)\cosinus=courbe(t)\dy / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\sinus=courbe(t)\dx / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  ; prise en compte des valeurs +INF et -INF dans le calcul de arctangente(phi)
  If courbe(t)\dx<>0 
    courbe(t)\phi_radian =ATan(courbe(t)\dy/courbe(t)\dx)
  Else
    If  courbe(t)\dy>0
      courbe(t)\phi_radian=#PI/2
    Else
      courbe(t)\phi_radian=-#PI/2
    EndIf
  EndIf
Next angle
t_max=t

;-deuxième demi-gaussienne
While courbe(t)\x<#largeur_ecran-1
  t=t+1
  p=p+1
  courbe(t)\x=p
  courbe(t)\y=courbe(t_max)\y-(#hauteur_ecran*2/3-#y_depart)*Pow(e,-#parametre_gaussienne*(p -#largeur_ecran)*(p -#largeur_ecran))
  courbe(t)\dx=1
  courbe(t)\dy=(#hauteur_ecran*2/3-#y_depart)*2*#parametre_gaussienne*(p -#largeur_ecran)*Pow(e,-#parametre_gaussienne*(p -#largeur_ecran)*(p -#largeur_ecran))
  longueur_courbe=longueur_courbe+Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy)
  courbe(t)\s=longueur_courbe
  courbe(t)\cosinus=courbe(t)\dy / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\sinus=courbe(t)\dx / Sqr(courbe(t)\dx*courbe(t)\dx+courbe(t)\dy*courbe(t)\dy) 
  courbe(t)\phi_radian =ATan(courbe(t)\dy/courbe(t)\dx)
  
Wend
t_max=t

;-correspondance s <===> t
s_max=Round(longueur_courbe,#PB_Round_Nearest)
Dim t_correspondant_a_s.l(s_max);tableau qui va permettre de faire le lien entre abscisse curviligne s et coordonnées cartésiennes x,y par le biais du paramètre t
; à chaque valeur de s on va faire correspondre une valeur t
For int_s=1 To s_max
  For i=1 To t_max
    If int_s=Round(courbe(i)\s,#PB_Round_Nearest)
      t_correspondant_a_s(int_s)=i
    EndIf
  Next i
Next int_s

For int_s=1 To s_max
  If  t_correspondant_a_s(int_s)=0
    t_correspondant_a_s(int_s)=t_correspondant_a_s(int_s-1)
  EndIf
  
Next int_s

;-PROGRAMME PRINCIPAL
InitSprite()
InitSprite3D()
InitKeyboard()
OpenWindow(0,0,0,#largeur_ecran,#hauteur_ecran,"solide guidé motorisé | <= et => pour se déplacer !",#PB_Window_ScreenCentered|#PB_Window_SystemMenu  )
OpenWindowedScreen(WindowID(0),0,0,#largeur_ecran,#hauteur_ecran,0,0,0)

;-sprite décor
CreateSprite(#spr_decor,#largeur_ecran,#hauteur_ecran)
StartDrawing(SpriteOutput(#spr_decor))
For etoile=1 To 500
Plot(5+Random(#largeur_ecran-10),5+Random(#hauteur_ecran-10),RGB(25,255,255))
Next etoile
For t=1 To t_max
  LineXY(x_point_precedent, y_point_precedent, courbe(t)\x, courbe(t)\y,RGB(0,255,255))
  x_point_precedent.f=courbe(t)\x
  y_point_precedent.f=courbe(t)\y
Next t
FillArea(10,600,RGB(0,255,255),RGB(0,55,55))
StopDrawing()

;-sprite voiture
CreateSprite(#spr_car_droite,32,32,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(#spr_car_droite))
Box(0,4,16,12,RGB(75, 241, 75))
Ellipse(16,16,16,12,RGB(248, 241, 7))
Circle(8,24,8,RGB(15, 109, 240))
Circle(24,26,6,RGB(15, 109, 240))
Box(20,11,6,5,RGB(174, 192, 248))
StopDrawing()
CreateSprite3D(#spr_car_droite, #spr_car_droite)

CreateSprite(#spr_car_gauche,32,32,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(#spr_car_gauche))
Box(16,4,16,12,RGB(75, 241, 75))
Ellipse(16,16,16,12,RGB(248, 241, 7))
Circle(24,24,8,RGB(15, 109, 240))
Circle(8,26,6,RGB(15, 109, 240))
Box(6,11,6,5,RGB(174, 192, 248))
StopDrawing()
CreateSprite3D(#spr_car_gauche, #spr_car_gauche)

;-abscisse curviligne initiale
s=1129
t=t_correspondant_a_s(Int(s))

;-BOUCLE PRINCIPALE

;gestion des évènements de la fenêtre
Repeat
  Repeat
    Event = WindowEvent()      
    If  Event = #PB_Event_CloseWindow
      End 
    EndIf
  Until Event = 0
  
  ;-gestion du clavier
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Left)
    acceleration_moteur=acceleration_moteur-2
    If acceleration_moteur<-#acceleration_moteur_max
      acceleration_moteur=-#acceleration_moteur_max
    EndIf
  ElseIf  KeyboardPushed(#PB_Key_Right)
    acceleration_moteur=acceleration_moteur+2
    If acceleration_moteur>#acceleration_moteur_max
      acceleration_moteur=#acceleration_moteur_max
    EndIf
  Else 
    acceleration_moteur=0
  EndIf
  
  ;-équations du mouvement
  
  If modele=#solide_guide
    vs=vs+(#g*courbe(t)\cosinus-#coeff_frot*vs+acceleration_moteur)*#dt
    s=s+vs*#dt

    If s<1
      s=1
    EndIf
    If s>s_max
      s=s_max
    EndIf
    ;recherche de la valeur de t
    t=t_correspondant_a_s(Int(s))
    
    angle_rotation=180*courbe(t)\phi_radian /#PI 
    If courbe(t)\dx<0 
      angle_rotation=angle_rotation+180
    EndIf
    ;choix du sprite en fonction du sens de parcours
    If vs >=0 
      spr_car=#spr_car_droite
    Else
      spr_car=#spr_car_gauche
    EndIf
    
  EndIf
  
  If modele=#chute_libre
    retard_detection=retard_detection+1
    x_libre_ancien=x_libre
    y_libre_ancien=y_libre
    tx_libre_ancien=tx_libre
    vy_libre=vy_libre+#g*#dt
    x_libre=x_libre+vx_libre*#dt
    y_libre=y_libre+vy_libre*#dt
    angle_rotation_libre=ATan(vy_libre/vx_libre)*180/#PI
    If courbe(t0_libre)\dx<0
      angle_rotation_libre=angle_rotation_libre+180
    EndIf
    
    ;-reprise de contact avec le sol  
    ;- bosse sens retour
    If  v0s<0 And v0x_libre<0  
      For t_test=  tx_libre_ancien To 0 Step -1
        If courbe(t_test)\x< x_libre
          tx_libre=t_test
          Break
        EndIf
      Next t_test
      collision   
    EndIf
    
    ;- bosse  sens aller
    If v0s>0 And v0x_libre>0 
      For t_test=tx_libre_ancien To t_max
        If  courbe(t_test)\x>x_libre
          tx_libre=t_test
          Break
        EndIf
      Next t_test
      collision   
    EndIf
    
    ;-looping sens aller
    If  v0s>=0 And v0x_libre=<0  And retard_detection>1
      For t_test=  tx_libre_ancien To 0 Step -1
        If courbe(t_test)\x<= x_libre
          tx_libre=t_test
          Break
        EndIf
      Next t_test
      collision   
    EndIf
    
    ;-looping sens retour  
    If  v0s=<0 And v0x_libre>=0  And retard_detection>1
      For t_test=tx_libre_ancien To t_max
        If  courbe(t_test)\x>=x_libre
          tx_libre=t_test
          Break
        EndIf
      Next t_test
      collision      
    EndIf
    
    ;réinitialisation en cas de non détection
    If y_libre>750
      modele=#solide_guide
      s=1129
      t=t_correspondant_a_s(Int(s))
      vs=0
      v0s=0
      v0x_libre=0
      retard_detection=0
    EndIf
  EndIf
  
  ;-gestion de la perte de contact avec le sol
  ; condition sur la variation d'angle pour empêcher le passage de -90° à +90°
  If (courbe(t+1)\phi_radian-courbe(t-1)\phi_radian)<1  And modele=#solide_guide 
    ;calcul du rayon de courbure
    rayon=(courbe(t+1)\s-courbe(t-1)\s)/(courbe(t+1)\phi_radian-courbe(t-1)\phi_radian)
    
    ;-test du signe du rayon de courbure (nous renseigne sur le sens du vecteur |en>)
    ;             StartDrawing(SpriteOutput(#spr_decor))
    ;             If rayon>0 
    ;               Box(courbe(t)\x,courbe(t)\y-20,2,4,RGB(255,0,0))
    ;             Else
    ;               Box(courbe(t)\x,courbe(t)\y-20,2,4,RGB(0,255,0))
    ;             EndIf
    ;             StopDrawing()
    
    ;-condition de la perte de contact
    If  courbe(t)\sinus<vs*vs/(rayon*#g) 
      ;conditions initiales de la chute libre
      angle0_libre=courbe(t)\phi_radian
      If courbe(t)\dx<0
        angle0_libre=angle0_libre+#PI
      EndIf
      t0_libre=t
      tx_libre=t
      v0s=vs
      v0x_libre=vs*Cos(angle0_libre)
      vx_libre=v0x_libre
      vy_libre=vs*Sin(angle0_libre)
      
      ;léger décalage pour améliorer la détection 
      If  v0s* v0x_libre>0  ;bosse et creux
        x_decalage=0
        y_decalage=-#dim_sprite*0.2
      Else ;looping
        x_decalage=0
        y_decalage=0
      EndIf  
      
      x_libre=courbe(t)\x+x_decalage
      y_libre=courbe(t)\y+y_decalage
      
      x_libre_ancien=x_libre
      y_libre_ancien=y_libre
      angle_rotation_libre=angle0_libre*180/#PI
      modele=#chute_libre
      ;-visualisation du point de décollage     
      ;       StartDrawing(SpriteOutput(#spr_decor))
      ;       DrawingMode(#PB_2DDrawing_Outlined   )
      ;       Circle(courbe(tx_libre)\x,courbe(tx_libre)\y,4,RGB(255,0,0))
      ;       StopDrawing()
      
    EndIf
  EndIf
  
  DisplaySprite(#spr_decor,0,0)
  If modele=#solide_guide
    x_car=courbe(t)\x-16
    y_car=courbe(t)\y-16
    angle_rotation_car=angle_rotation
  ElseIf modele=#chute_libre
    x_car=x_libre-16
    y_car=y_libre-16
    angle_rotation_car=angle_rotation_libre
  EndIf
  Start3D()
  RotateSprite3D(spr_car,angle_rotation_car,0)
  DisplaySprite3D(spr_car,x_car,y_car)
  Stop3D()
  
  Delay(10)
  FlipBuffers() 
ForEver

End
Il y a encore des petits réglages à faire mais c'est sur la bonne voie :wink:

Hasta la vista !
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Complément d'explications...

Message par Huitbit »

'alut,

@Cpl. Bator
http://armorgames.com/play/553/the-fanc ... re-world-2
Bel exemple de la physique ! de visu , c'est des courbes de bezier , non ?
Je sais pô :oops: . En tout cas, il suffit d'avoir les coordonnées du relief pour "s'amuser !"




A part ça ...

Je suis conscient du manque de clarté du code :oops: !
En fait pour l'instant, c'est un débroussaillage des lois physiques.

Une courbe complète, c'est la manière la moins fine de fonctionner (à mon avis)!

L'objectif, c'est de faire un truc fonctionnel :P que tout le monde puisse utiliser sans se prendre la tête. C'est à dire des zones sur l'écran où le personnage adopte tel ou tel comportement (pente verglacée, bosse, looping, roue...)!

Il manque aussi la gestion des rebonds, ça viendra !

Pour l'instant, je m'éloigne de PB quelques temps :cry: , je pars ce soir en vacances (en dépaysement :mrgreen: ) à Marie-Galante (là-bas, le rhum est à 59°) :twisted: !


En attendant, pour ceux qui ont le courage de mettre le nez dans le code, un petit complément sur le retour au sol du véhicule :

Pendant le "vol" du véhicule (on dit "la chute libre" si seul le poids intervient dans le mouvement), à chaque boucle du programme,
l'abscisse x passe de x_libre_ancien à x_libre. A la verticale de ces coordonnées on trouve un x qui correspond sur la courbe, courbe(t)\x (attention, pour le looping, il y a deux possibiltés !).
Avec les couples (x_ancien, y_ancien)_libre, (x, y)_libre et (x_ancien, y_ancien)_courbe, (x, y)_courbe, j'obtiens deux segments.
Il n' y a plus qu'à tester si les segments se coupent pour savoir s'il y a eu atterissage entre les instants t_ancien et t.

Petits rappels de mathématiques :

Soient deux points A1(x1,y1) et A2(x2,y2)
La droite qui passe par ces points a pour équation : y = a * x + b
Avec a = (y2 - y1) / (x2 - x1) et b = y1 - a * x1 ou b = y2 - a * x2

Soient deux droites d'équations
y = a * x +b
y= c * x + d
(Remarque : Si a = c, ce sont deux droites parallèles => pas d'intersection !)
Pour savoir où elles se coupent , il suffit de résoudre ce système.
On obtient après résolution :
x_intersection = (d - b) / (a - c)
y_intersection = (a *d -b * c) / (a - c)

Dans le programme, je teste si x_ancien_courbe < x_intersection < x_courbe

L'intérêt de cette méthode, c'est qu'elle ne tient pas compte de l'espacement qu'il peut y avoir entre les points de la courbe (dans la première partie,
"la descente", il peut y avoir des écarts de 30 pixels ou plus). Avec les autres méthodes, la voiture passait au travers !
Par contre, je me suis aperçu que lorsque les pentes des droites étaient voisines(décollage, côtés des bosses,...), la détection se faisait mal. Pour corriger ça,
je "dope" le décollage du véhicule en rajoutant quelques pixels de plus !

Si quelqu'un a dans ses cartons un test plus efficace, n'hésitez pas !
En fait, je me suis arrêté sur celui-là, car c'est celui qui demandait le moins de bidouilles !

Si vous essayez, n'oubliez pas ce qu'on vous dit là :wink: !
http://www.myphysicslab.com/RollerFlight.html
Limitations of this Simulation
Unlike the other roller coaster simulations, this one does not have the option to use various tracks. The reason is that having a track that doesn't loop simplified the code considerably. For example, to determine whether there is a collision, we only test whether the ball is below the track. With a looped track there would be more complicated criteria for deciding if the ball has collided with the track, such as checking if it is inside or outside the track. So if you are looking for a programming project, grab the source code and go to work!


Hasta la vista !

PS : comme je me méfie de mes amis cambrioleurs, j'ai voulu sauvegarder sur DVD mes données (chose que je devrais faire régulièrement :roll: ). Hé bien, j'ai grillé trois FUJIFILM DVD+R, un maxell DVD+R,un maxell DVD-R avant de trouver mon ami Sony DVD-R !
Mon graveur (référence : TSST corp CD/DVDW TS-H652L) est sensé tout accepter :x :x . A 3,50 euros le DVD, on perd vite patience !
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

En programmation "traditionnelle", on a une approche plus temps réel des calculs; à chaque frame, on recalcule la trajectoire suivant les paramètres actuels. S'il y a une collision (testé en direct grâce à des bounding box ou des images), on sait comment réagir par rapport aux vecteurs vitesses précédents. C'est moins déterministe, et donc sujet à erreurs.
Je suis très intéressé par l'approche mathématique, d'autant que quand les frames-rates sont différents, comme dans les jeux en 3d ou réseau, il faut pouvoir calculer plusieurs frames pour n'en afficher qu'une.
Anonyme

Message par Anonyme »

Code : Tout sélectionner

Je sais pô Embarassed . En tout cas, il suffit d'avoir les coordonnées du relief pour "s'amuser !" 
j'en prend bonne note , je ponderais un chti code avec des tiles de 64x64 pixels , chaque tile possèdera son "relief".

j'retourne bossé :D
@++
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

pour moi je n'arrive tout simplement pas à graver sur dvd, alors je me contente des bon vieux CD-R... Mais je te conseille quand même une clé USB, j'en ai acheté encore une autre à 4 GO, comme ma précédente, mais en beaucoup plus rapide( un PNY attaché, pour 20 euros en grande surface).
Répondre