numérique ou pavé numérique doit être précisé si on l'utilise.Frenchy Pilou a écrit :hihi
Je m'obstinais sur le clavier numérique alors que c'était les touche numérique du clavier normal
Solide glissant sur un rail (part I,II)
-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse
http://armorgames.com/play/553/the-fanc ... re-world-2
Bel exemple de la physique ! de visu , c'est des courbes de bezier , non ?
Bel exemple de la physique ! de visu , c'est des courbes de bezier , non ?
-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse
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 !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 ?

Sur le site de nitrome, ils donnent des liens vers des sites de dev de la physique en flash...
http://www.cove.org/ape/
Prise en compte de la chute libre
Voilà la deuxième partie (il y en aura d'autres
)!
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
: 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
, ce n'est pas la première fois que je galère !
Il y a encore des petits réglages à faire mais c'est sur la bonne voie
Hasta la vista !

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

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é

(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

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

Hasta la vista !
Complément d'explications...
'alut,
@Cpl. Bator
. 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
!
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
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
, je pars ce soir en vacances (en dépaysement
) à Marie-Galante (là-bas, le rhum est à 59°)
!
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à
!
http://www.myphysicslab.com/RollerFlight.html
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
). 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
. A 3,50 euros le DVD, on perd vite patience !
@Cpl. Bator
Je sais pôhttp://armorgames.com/play/553/the-fanc ... re-world-2
Bel exemple de la physique ! de visu , c'est des courbes de bezier , non ?

A part ça ...
Je suis conscient du manque de clarté du code

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

Il manque aussi la gestion des rebonds, ça viendra !
Pour l'instant, je m'éloigne de PB quelques temps



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à

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

Mon graveur (référence : TSST corp CD/DVDW TS-H652L) est sensé tout accepter


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.
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.
Code : Tout sélectionner
Je sais pô Embarassed . En tout cas, il suffit d'avoir les coordonnées du relief pour "s'amuser !"
j'retourne bossé

@++
-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse