Suivre un point : acceleration et decceleration

Sujets variés concernant le développement en PureBasic
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Suivre un point : acceleration et decceleration

Message par Thyphoon »

Ces derniers jours j'ai l'impression d'avoir un prit un sacré coup de vieux... Des trucs que j'ai déjà fait ... impossible a refaire ...Pfffffff ça me gave
depuis ce matin je me prends la tête sur un truc con !
J'ai un point A qui doit se rapprocher d'un point B. je voudrais qu'en fonction de la distance entre les 2 points, le Point A accélère puis ralentit a la proche du Point B.
Avec une vitesse Maximum a ne pas depasser

Voici ce que j'ai fait :

Code : Tout sélectionner

InitSprite()
InitMouse()
InitKeyboard()

OpenWindow(0, 0, 0, 800, 600, "Un écran dans une fenêtre...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)
  Ax=320
  Ay=200
  #VitesseMax=16
  Repeat
    ; Il est très important de traiter tous les événements restants dans la file d'attente à chaque tour
    ;
    ExamineKeyboard()
    
    If KeyboardPushed(#PB_Key_Escape)
	    End
     EndIf
    
    ExamineMouse()
    Bx=MouseX()
    By=MouseY()
    ;#############################
    ;C'est ici que ça se passe
    
    If Ax<Bx-10 Or Ax>Bx+10
      diff=Bx-Ax
      vx=(diff*32/255) ;chiffre prit un peu au hasard
      If vx>#VitesseMax:vx=#VitesseMax:EndIf
      If vx<-#VitesseMax:vx=-#VitesseMax:EndIf
      Ax+vx
    EndIf 
    If Ay<By-10 Or Ay>By+10
      diff=By-Ay
      vy=(diff*32/55) ;chiffre prit un peu au hasard
      If vy>#VitesseMax:vy=#VitesseMax:EndIf
      If vy<-#VitesseMax:vy=-#VitesseMax:EndIf
      Ay+vy
    EndIf   
    
    
    
    ;#############################

    ClearScreen(RGB(0, 0, 0))
    StartDrawing(screenoutput())
      Circle(Bx,By,5,#Blue)
      Circle(Ax,Ay,5,#Red)
    StopDrawing()
    FlipBuffers()
    Delay(1)
  ForEver

Y a surement moyen de faire mieux non ?
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

j'ai fait un code qui peut te servir, c'est tout bête

voir ici :
http://www.purebasic.fr/french/viewtopi ... pent+boule

regarde le premier code

ou le second si tu cherches un déplacement plus complexe avec prise en compte d'un rayon de courbure maximum dans les virages
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)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

en voici une version éditer pour toi

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 3.90
; 
; Explication du programme :
; Dessiner un serpent de boule qui suit la souris

; Dimension du screen
#EcranX = 1024
#EcranY= 768

#NbBoule = 100 ; Nombre de boule
#RayonBoule = 17 ; diamètre des boules

#Vitesse = 0.2 ; Vitesse de déplacement des boules

#Tete_Rotation = 3 * #PI / 120 ; Vitesse pour changer de direction de la tete du serpent
#Tete_Vitesse = 10 ; Vitesse maximum de la tete du serpent
Tete_Angle.f = 0
Tete_X.f = 0
Tete_Y.f = 0
Deplacement_X = 0
Deplacement_Y = 0

Structure BouleInfo ; Contient la position de chaque boule
  x.f
  y.f
EndStructure
Dim Boule.BouleInfo(#NbBoule)

Procedure DessineBoule(id, Couleur)
  ; ID : Identifiant du sprite
  ; Couleur : Couleur RGB de la boule

  CreateSprite(id, #RayonBoule * 2 + 1, #RayonBoule * 2 + 1)
  StartDrawing(SpriteOutput(id))
    Circle(#RayonBoule, #RayonBoule, #RayonBoule, Couleur) ; On dessine une boule
  StopDrawing()
  
EndProcedure


InitSprite()
InitKeyboard()
InitMouse()
OpenScreen(#EcranX, #EcranY, 32, "")

SetFrameRate(50)

; On crée les sprites qui représentent des boules de couleur de plus en plus claires
For n = 0 To #NbBoule
  Coef.f = n / #NbBoule
  DessineBoule(n, RGB(255, 165 + (255 - 165) * Coef, 255 * Coef))
Next

DessineBoule(2000, $FF00FF)


Repeat
  ExamineMouse()
  ExamineKeyboard()
  
  ClearScreen(0) ; On efface l'écran
  
  ; Position de la première boule que l'on calcule
  ; Il s'agit de la boule 0
  
  #Deplacement_Auto = 0
  CompilerIf #Deplacement_Auto
    If Distance.f < #Tete_Vitesse ; Si on est arrivé, on va vers un autre point en aléatoire
      Deplacement_X = Random(#EcranX)
      Deplacement_Y = Random(#EcranY)
    EndIf
    If Distance < #Tete_Vitesse * 40 ; Si on arrive pas à atteindre le point au bout d'un moment, on dis qu'on l'a eu
      Compteur_Proche + 1
      If Compteur_Proche > 200
        Deplacement_X = Random(#EcranX)
        Deplacement_Y = Random(#EcranY)
      EndIf
    Else
      Compteur_Proche = 0
    EndIf
  CompilerElse
    Deplacement_X = MouseX()
    Deplacement_Y = MouseY()
    DisplaySprite(2000, Deplacement_X, Deplacement_Y)
  CompilerEndIf
  
  ; Distance entre la boule et le point visé
  Distance.f = Sqr((Deplacement_X - Tete_X) * (Deplacement_X - Tete_X) + (Deplacement_Y - Tete_Y) * (Deplacement_Y - Tete_Y))
  
  ; Angle entre la boule et le point visé
  If Deplacement_X >= Tete_X And Deplacement_Y >= Tete_Y ; entre 0 et Pi/2
    Angle.f = ACos((Deplacement_X - Tete_X) / Distance)
  ElseIf Deplacement_X >= Tete_X And Deplacement_Y <= Tete_Y ; entre 0 et -Pi/2
    Angle.f = -ACos((Deplacement_X - Tete_X) / Distance)
  ElseIf Deplacement_X <= Tete_X And Deplacement_Y >= Tete_Y ; entre Pi/2 et Pi
    Angle.f = #PI - ACos((Tete_X - Deplacement_X) / Distance)
  Else ; entre -Pi/2 et -Pi
    Angle.f = -#PI + ACos((Tete_X - Deplacement_X) / Distance)
  EndIf
  
  If Tete_Angle > #PI ; Si l'angle est plus grand que #Pi ou plus petit que -#Pi, on le ramene est -#pi et #pi
    Tete_Angle - 2 * #PI
  EndIf
  If Tete_Angle < -#PI
    Tete_Angle + 2 * #PI
  EndIf
  
  If Tete_Angle >= Angle ; on regarde dans quel sens on doit faire évoluer l'angle
    If Tete_Angle - Angle > #PI
      Tete_Angle + #Tete_Rotation
    Else
      Tete_Angle - #Tete_Rotation
    EndIf
  Else
    If Angle - Tete_Angle > #PI
      Tete_Angle - #Tete_Rotation
    Else
      Tete_Angle + #Tete_Rotation
    EndIf
  EndIf
  
  Tete_X + Cos(Tete_Angle) * #Tete_Vitesse ; On déplace suivant l'angle
  Tete_Y + Sin(Tete_Angle) * #Tete_Vitesse
  
  Boule(0)\x = Tete_X - #RayonBoule
  Boule(0)\y = Tete_Y - #RayonBoule
   
  For n = #NbBoule To 1 Step -1 ; Pour chaque boule
    ; On part de la fin afin que la dernière boule soit en dessous des autres
  
    ; On calcul la vitesse de déplacement en x de la boule à partir de la distance entre cette boule et la précédente
    ; Le but est de permettre à cette boule de suivre la précédente
    ; Et plus la distance entre ces 2 boules est grande et plus elle ira vite pour la rattraper
    VitesseX.f = (Boule(n - 1)\x - Boule(n)\x) * #Vitesse
    
    ; De même sur les y
    VitesseY.f = (Boule(n - 1)\y - Boule(n)\y) * #Vitesse
    
    ; On détermine la nouvelle position de la boule
    Boule(n)\x + VitesseX
    Boule(n)\y + VitesseY
    
    ; On affiche la boule
    DisplayTransparentSprite(n, Boule(n)\x, Boule(n)\y)
    
  Next
  
  DisplayTransparentSprite(0, Boule(0)\x, Boule(0)\y) ; On affiche la boule qui représente la souris
  ; Elle est affiché en dernier pour être au dessus des autres
  
  FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape)
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)]
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Merci beaucoup !J'avais déjà mis ton code de côté car il me servira pour autre chose :P! j'étais tombé dessus en faisant mes recherches.

En vérité ici j'ai simplifié le problème. En réalité ce système va me servir pour le deplacement de ma Map pour suivre des objets.mes 2 points sont :
A = La position actuel de la Map
B = La position d'arrivé. (et le point B peut se déplacer ça peut être un personnage, ou bien un point bien précis dans la Map:Ex tu débloques un mécanisme qui ouvre une porte plus loin dans la map ... la map se deplace pour te montrer la porte qui s'ouvre et revient sur le personnage)

Pour que ça soit plus jolie j'aurais voulu que la vitesse de déplacement soit proportionnel a la distance entre les 2 points avec une accélération et une décélération .le pire c'est que je l'avais déjà fait une fois il y a quelques années, mais impossible de le refaire et comme un c** j'ai pas garder le code que j'avais fait :cry:
Répondre