Depuis que j'ai redécouvert grabsprite()
(voir http://www.purebasic.fr/french/viewtopic.php?t=9256)
ça m'a donné envie de l'utiliser pour un jeu de voiture !
Avant cela, il fallait un circuit.
Ca faisait un moment que j'entendais parler des courbes de bézier (Comtois, Cpl Bator), je n'avais pas envie de mettre le nez dedans car je voyais des équations à priori inhospitalières et manquant de souplesse

Je n'ai pas mis le nez dedans mais j'ai repris le principe sur le papier, purebasic a fait le reste ! Je ne sais pas si c'est la bonne méthode mais c'est ce que je voulais obtenir

A chaque subdivision, je découpe le segment [AB] en trois bouts [AM],[MN] et [NB] avec au niveau vectoriel |AM>=rapport*|AB> et |AN>=(1-rapport)*|AB>. Les anciens points sont remplacés par les nouveaux.

Au bout de 4 subdivisions, on obtient déjà une courbe bien lisse

Ce n'est donc pas la peine d'aller plus loin en modifiant la ligne!
Code : Tout sélectionner
#generation=3; génération 0,1, 2 et 3
J'ai pris un exemple avec 5 points de contrôle et 4 subdivisions (5*2^4=80 points au final).
J'ai mis une petite boule qui se déplace sans tenir compte de sa vitesse, juste pour voir !
Pour voir d'autres circuits, il suffit de supprimer la création des points non aléatoires et d'activer la création aléatoire:(déjà en commentaires dans le code!)
Code : Tout sélectionner
;-initialisation des 5 points de contrôle
;aléatoire
For n=0 To #nbre_de_pts_de_ctrl-1
points(n)\x=Random(#largeur_ecran)
points(n)\y=Random(#hauteur_ecran)
Next n
et de modifier éventuellement :
Code : Tout sélectionner
#nbre_de_pts_de_ctrl=5
#generation=3; génération 0,1, 2 et 3

Essayez, ça marche tout seul

Exemple:
Code : Tout sélectionner
#nbre_de_pts_de_ctrl=20
#generation=4

Je n'avais pas saisi la portée de cette méthode mais c'est impressionnant vu la simplicité et la souplesse du code (circuit, jeux de plateformes...etc!!).
En effet, on travaille avec des droites affines

Il ne reste plus qu'à coupler ça avec la mécanique, grabsprite(), les rotations et autres...
Prochaine mise à jour déplacement à vitesse constante(ou autre !).
Code : Tout sélectionner
;subdivision
;Auteur Huitbit
;PureBasic 4.30 (Windows - x86)
;*********************************
#largeur_ecran=1024
#hauteur_ecran=768
#nbre_de_pts_de_ctrl=5
#generation=3; génération 0,1, 2 et 3
#spr_decor=0
#spr=1
rapport.f=0.25
nbre_de_pts_final.l=#nbre_de_pts_de_ctrl*Pow(2,#generation+1)-1
Structure infos
x.l
y.l
a.f
b.f
EndStructure
Dim points.infos (nbre_de_pts_final)
Macro affine(a,b,xA,yA,xB,yB)
a=(yB-yA)/(xB-xA)
b=(yA*xB-yB*xA)/(xB-xA)
EndMacro
;-initialisation des 5 points de contrôle
;aléatoire
; For n=0 To #nbre_de_pts_de_ctrl-1
; points(n)\x=Random(#largeur_ecran)
; points(n)\y=Random(#hauteur_ecran)
; Next n
;non aléatoire
points(0)\x=20
points(0)\y=20
points(1)\x=1004
points(1)\y=20
points(2)\x=900
points(2)\y=748
points(3)\x=512
points(3)\y=20
points(4)\x=20
points(4)\y=748
;-subdivisions de la courbe
For generation_en_cours=0 To #generation
nbre_de_pts_provisoires.l=#nbre_de_pts_de_ctrl*Pow(2,generation_en_cours)-1
For n=nbre_de_pts_provisoires To 0 Step -1
;A, B extremités du segment à découper
xA.l=points(n)\x
yA.l=points(n)\y
If n<nbre_de_pts_provisoires
xB.l=points(n+1)\x
yB.l=points(n+1)\y
Else
xB.l=points(0)\x
yB.l=points(0)\y
EndIf
points(2*n+1)\x=xA+(xB-xA)*(1-rapport)
points(2*n+1)\y=yA+(yB-yA)*(1-rapport)
points(2*n)\x=xA+(xB-xA)*rapport
points(2*n)\y=yA+(yB-yA)*rapport
Next n
Next generation_en_cours
x_spr.l=points(0)\x
y_spr.l=points(0)\y
;-calculs des équations affines de chaque segment
For n=0 To nbre_de_pts_final
If n<nbre_de_pts_final
affine(points(n)\a,points(n)\b,points(n)\x,points(n)\y,points(n+1)\x,points(n+1)\y)
Else
affine(points(n)\a,points(n)\b,points(n)\x,points(n)\y,points(0)\x,points(0)\y)
EndIf
Next n
;-######################################
;-PROGRAMME PRINCIPAL
;-######################################
InitSprite()
InitKeyboard()
OpenWindow(0,0,0,#largeur_ecran,#hauteur_ecran,"Subdivision ",#PB_Window_ScreenCentered|#PB_Window_SystemMenu )
OpenWindowedScreen(WindowID(0),0,0,#largeur_ecran,#hauteur_ecran,0,0,0)
CreateSprite(#spr_decor,#largeur_ecran,#hauteur_ecran)
StartDrawing(SpriteOutput(#spr_decor))
For n=0 To nbre_de_pts_final
If n<nbre_de_pts_final
LineXY(points(n)\x,points(n)\y,points(n+1)\x,points(n+1)\y,RGB(255,255,0))
Else
LineXY(points(0)\x,points(0)\y,points(nbre_de_pts_final)\x,points(nbre_de_pts_final)\y,RGB(255,255,0))
EndIf
DrawText(points(n)\x,points(n)\y,Str(n))
Next n
StopDrawing()
CreateSprite(#spr,16,16)
StartDrawing(SpriteOutput(#spr))
Plot(8,8,RGB(255,0,0))
Circle(8,8,8,RGB(0,0,255))
StopDrawing()
numero.l=0
;-BOUCLE PRINCIPALE
Repeat
FlipBuffers()
DisplaySprite(#spr_decor,0,0)
If numero=nbre_de_pts_final; permet de "boucler" un tour
If points(numero)\x<points(0)\x
x_spr=x_spr+1
If x_spr>=points(0)\x
numero=0
EndIf
Else
x_spr=x_spr-1
If x_spr<=points(0)\x
numero=0
EndIf
EndIf
ElseIf points(numero)\x<points(numero+1)\x
x_spr=x_spr+1
If x_spr>=points(numero+1)\x
numero=numero+1
EndIf
Else
x_spr=x_spr-1
If x_spr<=points(numero+1)\x
numero=numero+1
EndIf
EndIf
y_spr=points(numero)\a*x_spr+points(numero)\b
DisplayTransparentSprite(#spr,x_spr-8,y_spr-8)
Repeat
Event = WindowEvent()
If Event = #PB_Event_CloseWindow
End
EndIf
Until Event = 0
Delay(1)
ForEver