IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

Amélioration sur la rapidité d'une animation


Sujet :

Delphi

  1. #1
    Membre actif Avatar de Basile le disciple
    Homme Profil pro
    étudiant Centrale Supélec
    Inscrit en
    Avril 2013
    Messages
    147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : étudiant Centrale Supélec

    Informations forums :
    Inscription : Avril 2013
    Messages : 147
    Points : 279
    Points
    279
    Par défaut Amélioration sur la rapidité d'une animation
    Bonjour à tous,

    J'ai voulu créer un petit compteur sous la forme d'une horloge avec une trotteuse qui tourne sur elle même sur 360°. Mais le problème et que "l'animation" plombe le reste de l'application. J'aimerais avoir vos idées pour diminuer le temps d'exécution de l'animation.

    J'ai pensé à créer un TBitmap sur lequel est dessiné le fond afin de ne rien dessiné dans le OnTimer (interval = 10 ms), mais de faire un assign. J'ai aussi réussi à n'utiliser qu'un seul floodfill sur la pointe de la flèche en jouant sur les couleurs. Malheureusement, rien n'y fait.

    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
     
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls;
     
    type
      TForm1 = class(TForm)
        PaintBox1: TPaintBox;
        Timer1: TTimer;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure PaintBox1Paint(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        { Déclarations privées }
        bmp_Fond,bmp_Horloge : TBitmap;
        t : integer;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
    const DUREE_PARTIE : integer = 4000;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    var pt : Tpoint;
        r : integer;
        i : integer;
    begin
      t:=0;
      pt:=point(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
      r:=Paintbox1.ClientWidth div 2;
      bmp_Horloge := TBitmap.Create;
      With bmp_Horloge do
      begin
        Width:=Paintbox1.ClientWidth;
        Height:=Paintbox1.Clientheight;
      end;
      bmp_Fond := TBitmap.Create;
      With bmp_Fond do
      begin
        Width:=Paintbox1.ClientWidth;
        Height:=Paintbox1.Clientheight;
        With Canvas do
        begin
         Pen.Width:=4;
         For i:=0 to 135 do    //clLime -> clYellow
         begin
           Pen.Color:=rgb(round(i*255 / 135),255,0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( (i-90) * pi/180)),pt.Y + round( (r-2) * sin( (i-90) *pi/180)) );
         end;
         For i:=0 to 150 do   //clYellow -> $007EFF;
         begin
           Pen.Color:=rgb(255,round(255 - i*129 / 150),0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( ( (i+135) -90) * pi/180)),pt.Y + round( (r-2) * sin( ( (i+135) -90) *pi/180)) );
         end;
         For i:=0 to 75 do   //$007EFF -> clRed
         begin
           Pen.Color:=rgb(255,round(126 - i*126 / 75),0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( ( (i+285) -90) * pi/180)),pt.Y + round( (r-2) * sin( ( (i+285) -90) *pi/180)) );
         end;
         Pen.Color:=clBlack;
         Pen.Width:=2;
         Brush.Style:=bsClear;
         Ellipse(Paintbox1.ClientRect);
         Brush.Style:=bsSolid;
        end;
      end;
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      bmp_Horloge.Free;
      bmp_Fond.Free;
    end;
     
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    var pt : Tpoint;
        r : integer;
    begin
      pt:=point(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
      r:=Paintbox1.ClientWidth div 2;
      bmp_Horloge.Assign(bmp_Fond);
      With bmp_Horloge.Canvas do
      begin
        Pen.Color:=clMaroon; Pen.Width:=3;
        MoveTo(pt.X,pt.Y); LineTo(pt.X + round(r * cos( (( (t * 360) /DUREE_PARTIE) - 90) * pi/180)),pt.Y + round(r * sin( (( (t *360) /DUREE_PARTIE) - 90) * pi/180)));
        //flèche
        Pen.Color:=$000081;
        LineTo(pt.X + round((r-15) * cos( (( (t *360) /DUREE_PARTIE) - 95) * pi/180)),pt.Y + round((r-15) * sin( (( (t *360) /DUREE_PARTIE) - 95) * pi/180)));
        LineTo(pt.X + round((r-15) * cos( (( (t *360) /DUREE_PARTIE) - 85) * pi/180)),pt.Y + round((r-15) * sin( (( (t *360) /DUREE_PARTIE) - 85) * pi/180)));
        LineTo(pt.X + round(r * cos( (( (t *360) /DUREE_PARTIE) - 90) * pi/180)),pt.Y + round(r * sin( (( (t *360) /DUREE_PARTIE) - 90) * pi/180)));
        Brush.Color:=clMaroon;
        FloodFill(pt.X + round((r-10) * cos( (( (t *360) /DUREE_PARTIE) - 90) * pi/180)),pt.Y + round((r-10) * sin( (( (t *360) /DUREE_PARTIE)-90) * pi/180)),$000081,fsBorder);
        Ellipse(pt.X-5,pt.Y-5,pt.X+5,pt.Y+5);
      end;
      Paintbox1.Canvas.Draw(0,0,bmp_Horloge);
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      if t > DUREE_PARTIE then t:=0 else inc(t,10);
      Paintbox1.OnPaint(nil);
    end;
     
    end.
    Si vous avez aussi des conseils sur l'esthétisme du compteur, je suis preneur...

    Merci d'avance pour toutes vos réponses.

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    chez moi ça marche pas mal, mais je ferais 2 petites modifs

    Ellipse sur le bmp_Fond

    et Polygon() au lieu de FloodFill()

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    var pt : Tpoint;
        r : integer;
        pl:array[0..2] of TPoint;
    begin
      pt:=point(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
      r:=Paintbox1.ClientWidth div 2;
      bmp_Horloge.Assign(bmp_Fond);
      With bmp_Horloge.Canvas do
      begin
        Pen.Color:=clMaroon;
        Pen.Width:=3;
        MoveTo(pt.X,pt.Y); LineTo(pt.X + round(r * cos( (( (t * 360) /DUREE_PARTIE) - 90) * pi/180)),pt.Y + round(r * sin( (( (t *360) /DUREE_PARTIE) - 90) * pi/180)));
        //flèche
        Pen.Color:=$000081;
        Brush.Color:=clMaroon;
        pl[0].X := pt.X + round((r-15) * cos( (( (t *360) /DUREE_PARTIE) - 95) * pi/180));
        pl[0].Y := pt.Y + round((r-15) * sin( (( (t *360) /DUREE_PARTIE) - 95) * pi/180));
        pl[1].X := pt.X + round((r-15) * cos( (( (t *360) /DUREE_PARTIE) - 85) * pi/180));
        pl[1].Y := pt.Y + round((r-15) * sin( (( (t *360) /DUREE_PARTIE) - 85) * pi/180));
        pl[2].X := pt.X + round(r * cos( (( (t *360) /DUREE_PARTIE) - 90) * pi/180));
        pl[2].Y := pt.Y + round(r * sin( (( (t *360) /DUREE_PARTIE) - 90) * pi/180));
        Polygon(pl);
        {
        LineTo(pt.X + round((r-15) * cos( (( (t *360) /DUREE_PARTIE) - 95) * pi/180)),pt.Y + round((r-15) * sin( (( (t *360) /DUREE_PARTIE) - 95) * pi/180)));
        LineTo(pt.X + round((r-15) * cos( (( (t *360) /DUREE_PARTIE) - 85) * pi/180)),pt.Y + round((r-15) * sin( (( (t *360) /DUREE_PARTIE) - 85) * pi/180)));
        LineTo(pt.X + round(r * cos( (( (t *360) /DUREE_PARTIE) - 90) * pi/180)),pt.Y + round(r * sin( (( (t *360) /DUREE_PARTIE) - 90) * pi/180)));
        Brush.Color:=clMaroon;
        FloodFill(pt.X + round((r-10) * cos( (( (t *360) /DUREE_PARTIE) - 90) * pi/180)),pt.Y + round((r-10) * sin( (( (t *360) /DUREE_PARTIE)-90) * pi/180)),$000081,fsBorder);
        }
        //Ellipse(pt.X-5,pt.Y-5,pt.X+5,pt.Y+5);  <- sur bmp_Fond
      end;
      Paintbox1.Canvas.Draw(0,0,bmp_Horloge);
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 393
    Points : 637
    Points
    637
    Par défaut
    ce qui dois vraiment te ralentir c'est les calculs cos et sin, tu devrais peut-être les pré calculer une bonne fois pour toute, pareil pour ton pi/180

  4. #4
    Membre actif Avatar de Basile le disciple
    Homme Profil pro
    étudiant Centrale Supélec
    Inscrit en
    Avril 2013
    Messages
    147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : étudiant Centrale Supélec

    Informations forums :
    Inscription : Avril 2013
    Messages : 147
    Points : 279
    Points
    279
    Par défaut
    Merci pour la rapidité de votre réponse, je suis impressionné.

    @Paul TOTH :

    Brush.Color:=clMaroon;
    pl[0].X := pt.X + round((r-15) * cos( (( (t *360) /DUREE_PARTIE) - 95) * pi/180));
    pl[0].Y := pt.Y + round((r-15) * sin( (( (t *360) /DUREE_PARTIE) - 95) * pi/180));
    pl[1].X := pt.X + round((r-15) * cos( (( (t *360) /DUREE_PARTIE) - 85) * pi/180));
    pl[1].Y := pt.Y + round((r-15) * sin( (( (t *360) /DUREE_PARTIE) - 85) * pi/180));
    pl[2].X := pt.X + round(r * cos( (( (t *360) /DUREE_PARTIE) - 90) * pi/180));
    pl[2].Y := pt.Y + round(r * sin( (( (t *360) /DUREE_PARTIE) - 90) * pi/180));
    Polygon(pl);
    Je ne connaissais pas la procedure polygon, c'est vrai que c'est beaucoup mieux et plus lisible. J'ai aussi rajouté le petit cercle au centre de l'horloge dans bmp_Fond, c'est toujours ça de gagné....

    chez moi ça marche pas mal
    Chez moi aussi, mais le problème est qu'il doit y avoir une boucle de 0 jusqu'à 80 dans le OnMouseMove que je ne peux pas modifier, donc j'essaye de gagner du temps dans tout le reste...

    @exoseven :

    ce qui dois vraiment te ralentir c'est les calculs cos et sin, tu devrais peut-être les pré calculer une bonne fois pour toute, pareil pour ton pi/180
    C'est tellement simple! Je n'y ai même pas pensé.

    Donc voici un mixte des deux réponses :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
     
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls;
     
    type
      TForm1 = class(TForm)
        PaintBox1: TPaintBox;
        Timer1: TTimer;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure PaintBox1Paint(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        { Déclarations privées }
        bmp_Fond,bmp_Horloge : TBitmap;
        t : integer;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
    const DUREE_PARTIE : integer = 4000;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    var pt : Tpoint;
        r : integer;
        i : integer;
    begin
      t:=0;
      pt:=point(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
      r:=Paintbox1.ClientWidth div 2;
      bmp_Horloge := TBitmap.Create;
      With bmp_Horloge do
      begin
        Width:=Paintbox1.ClientWidth;
        Height:=Paintbox1.Clientheight;
      end;
      bmp_Fond := TBitmap.Create;
      With bmp_Fond do
      begin
        Width:=Paintbox1.ClientWidth;
        Height:=Paintbox1.Clientheight;
        With Canvas do
        begin
         Pen.Width:=4;
         For i:=0 to 135 do    //clLime -> clYellow
         begin
           Pen.Color:=rgb(round(i*255 / 135),255,0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( (i-90) * pi/180)),pt.Y + round( (r-2) * sin( (i-90) *pi/180)) );
         end;
         For i:=0 to 150 do   //clYellow -> $007EFF;
         begin
           Pen.Color:=rgb(255,round(255 - i*129 / 150),0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( ( (i+135) -90) * pi/180)),pt.Y + round( (r-2) * sin( ( (i+135) -90) *pi/180)) );
         end;
         For i:=0 to 75 do   //$007EFF -> clRed
         begin
           Pen.Color:=rgb(255,round(126 - i*126 / 75),0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( ( (i+285) -90) * pi/180)),pt.Y + round( (r-2) * sin( ( (i+285) -90) *pi/180)) );
         end;
         Pen.Color:=clBlack;
         Pen.Width:=2;
         Brush.Style:=bsClear;
         Ellipse(Paintbox1.ClientRect);
         Brush.Style:=bsSolid;
         Pen.Color:=clMaroon;
         Brush.Color:=clMaroon;
         Ellipse(pt.X-5,pt.Y-5,pt.X+5,pt.Y+5);
        end;
      end;
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      bmp_Horloge.Free;
      bmp_Fond.Free;
    end;
     
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    var pt : Tpoint;
        r : integer;
        pl:array[0..2] of TPoint;
        a : extended;
    const p : extended = pi/180;
    begin
      a := t*360 / DUREE_PARTIE;
     
      pt:=point(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
      r:=Paintbox1.ClientWidth div 2;
      bmp_Horloge.Assign(bmp_Fond);
     
      With bmp_Horloge.Canvas do
      begin
        Pen.Color:=clMaroon; Pen.Width:=3;
        MoveTo(pt.X,pt.Y); LineTo(pt.X + round(r * cos( (a - 90) * p)),pt.Y + round(r * sin( (a - 90) * p) ));
        //flèche
        Brush.Color:=clMaroon;
        pl[0].X := pt.X + round((r-15) * cos( (a - 95) * p));
        pl[0].Y := pt.Y + round((r-15) * sin( (a - 95) * p));
        pl[1].X := pt.X + round((r-15) * cos( (a - 85) * p));
        pl[1].Y := pt.Y + round((r-15) * sin( (a - 85) * p));
        pl[2].X := pt.X + round(r * cos( (a - 90) * p));
        pl[2].Y := pt.Y + round(r * sin( (a - 90) * p));
        Polygon(pl);
      end;
      Paintbox1.Canvas.Draw(0,0,bmp_Horloge);
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      if t > DUREE_PARTIE then timer1.Enabled:=false else inc(t,10);
      Paintbox1.OnPaint(nil);
    end;
     
    end.
    ça marche beaucoup mieux comme ça, mais ça rame toujours un peu. N'auriez-vous pas d'autres idées? N'étant pas un professionnel en maths, ne pourrait-on pas simplifier la formule??

  5. #5
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 299
    Points
    11 299
    Billets dans le blog
    6
    Par défaut
    Peut-être fais-tu trop de fois les mêmes calculs... Utilise des intermédiaires :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        ptX := pt.X;
        ptY := pt.Y;
        r_moins_15_fois_p := (r - 15) * p;
        r_fois_p := r * p;
        a_moins := a - 95;
        pl[0].X := ptX + round(r_moins_15_fois_p * cos(a_moins));
        pl[0].Y := ptY + round(r_moins_15_fois_p * sin(a_moins));
        Inc(a_moins, 10);
        pl[1].X := ptX + round(r_moins_15_fois_p * cos(a_moins));
        pl[1].Y := ptY + round(r_moins_15_fois_p * sin(a_moins));
        Dec(a_moins, 5);
        pl[2].X := ptX + round(r_fois_p * cos(a_moins));
        pl[2].Y := ptY + round(r_fois_p * sin(a_moins));
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  6. #6
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    Basile le disciple : ça marche beaucoup mieux comme ça, mais ça rame toujours un peu.
    Je n'ai pas trouvé dans ton FormCreate le précalcul des Sinus et Cosinus à placer dans des array [0..359] of Single par exemple.
    En plus, au lieu d'appeler la fonction Cos puis la fonction Sin tu peux utiliser la procédure SinCos(Theta, si, co) qui est presque deux fois plus rapide puisqu'elle renvoie les deux valeurs en un seul appel.

    En plus quand je vois des trucs comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        pl[0].X := pt.X + round((r-15) * cos( (a - 95) * p));
        pl[0].Y := pt.Y + round((r-15) * sin( (a - 95) * p));
        pl[1].X := pt.X + round((r-15) * cos( (a - 85) * p));
        pl[1].Y := pt.Y + round((r-15) * sin( (a - 85) * p));
    je calculerais une seule et unique fois les valeurs de r - 15, a - 95 et a - 85 au lieu de répéter leur calcul.

    A+.
    EDIT : Oups, pris de vitesse par Tourlourou
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 691
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 691
    Points : 13 121
    Points
    13 121
    Par défaut
    On peut aussi laisser le GPU se débrouiller en lui demandant simplement d'appliquer une transformation. On crée ainsi une fois pour toute la flèche (mais qui doit être 32 bits).
    Le fond est également créé de la même façon (par rotation successive du DC), on tire toujours la même ligne droite en modifiant uniquement la couleur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls;
     
    type
      TForm1 = class(TForm)
        PaintBox1: TPaintBox;
        Timer1: TTimer;
        procedure FormCreate(Sender: TObject);
        procedure PaintBox1Paint(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        Bk    :TBitmap;
        Arrow :TBitmap;
        t     :integer;
        procedure CreateBk;
        procedure CreateArrow;
      end;
     
    var
      Form1: TForm1;
     
    const
      Border = 4;
      DUREE_PARTIE : integer = 4000;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.CreateArrow;
    var
      i :integer;
      p :PRGBQuad;
     
    begin
      Arrow := TBitmap.Create;
      Arrow.SetSize(9, PaintBox1.Height div 2 -Border);
      Arrow.PixelFormat := pf32bit;
     
      p := Arrow.ScanLine[Arrow.Height-1];
      ZeroMemory(p, Arrow.Width *Arrow.Height *4);
     
      Arrow.Canvas.Pen.Width := 3;
      Arrow.Canvas.Pen.Color := clMaroon;
     
      Arrow.Canvas.MoveTo(Arrow.Width div 2, Arrow.Height -1);
      Arrow.Canvas.LineTo(Arrow.Width div 2, 0);
      Arrow.Canvas.LineTo(0, 15);
      Arrow.Canvas.LineTo(Arrow.Width -1, 15);
      Arrow.Canvas.LineTo(Arrow.Width div 2, 0);
     
      //Opaque sous la flèche
      for i := 0 to Arrow.Width *Arrow.Height -1 do
      begin
        if dword(p^) > 0 then
          p.rgbReserved := $FF;
     
        inc(p);
      end;
    end;
     
    procedure TForm1.CreateBk;
    var
      BkColors :array[0..359] of TColor;
      XF       :tagXForm;
      Angle    :Extended;
      i        :Integer;
     
    const
      Step   = 2 *Pi /High(BkColors);
     
    begin
      //Bitmap
      Bk := TBitmap.Create;
      Bk.SetSize(PaintBox1.Width, PaintBox1.Height);
     
      //Bordure et centre
      Bk.Canvas.Brush.Color := clMaroon;
      Bk.Canvas.Ellipse(0, 0, PaintBox1.Width, PaintBox1.Height);
     
      //Table des couleurs
      for i := 0 to 135 do
        BkColors[i] := RGB(Round(i *255 /135), 255, 0);
     
      for i := 0 to 150 do
        BkColors[i +136] := RGB(255, Round(255 -i *129 /150),0);
     
      for i := 0 to 75 do
        BkColors[i +287] := RGB(255, Round(126 -i *126 /75),0);
     
      Angle := 0;
     
      //Transformation
      with XF do
      begin
        SetGraphicsMode(Bk.Canvas.Handle, GM_Advanced);
        Bk.Canvas.Pen.Width := 3;
     
        eDX := Bk.Width div 2;
        eDY := Bk.Height div 2;
     
        for i := Low(BkColors) to High(BkColors) do
        begin
          eM11 := cos(Angle);
          eM12 := sin(Angle);
          eM21 := -eM12;
          eM22 := eM11;
     
          SetWorldTransform(Bk.Canvas.Handle, XF);
     
          Bk.Canvas.Pen.Color := BkColors[i];
          Bk.Canvas.MoveTo(0, -Border *2);
          Bk.Canvas.LineTo(0, -Bk.Height div 2 +Border);
     
          Angle := Angle +Step;
        end;
      end;
     
      ModifyWorldTransform(Bk.Canvas.Handle, XF, MWT_IDENTITY);
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      CreateBk;
      CreateArrow;
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      Bk.Free;
      Arrow.Free;
    end;
     
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    var
      XF :tagXForm;
      Angle :extended;
     
    const
      Blend :TBlendFunction = (BlendOp:AC_SRC_OVER; BlendFlags:0; SourceConstantAlpha:255; AlphaFormat:AC_SRC_ALPHA);
     
    begin
      Angle := t *2 *Pi /DUREE_PARTIE;
     
      //Fond
      PaintBox1.Canvas.Draw(0, 0, Bk);
     
      //Aiguille
      with XF do
      begin
        eM11 := cos(Angle);
        eM12 := sin(Angle);
        eM21 := -eM12;
        eM22 := eM11;
     
        eDX := Paintbox1.Width div 2  -eM11 *(Arrow.Width div 2) +eM12 *Arrow.Height;
        eDY := Paintbox1.Height div 2 -eM12 *(Arrow.Width div 2) -eM11 *Arrow.Height;
      end;
     
      SetGraphicsMode(Paintbox1.Canvas.Handle, GM_Advanced);
      SetWorldTransform(Paintbox1.Canvas.Handle, XF);
      Windows.AlphaBlend(Paintbox1.Canvas.Handle, 0, 0, Arrow.Width, Arrow.Height, Arrow.Canvas.Handle, 0, 0, Arrow.Width, Arrow.Height, Blend);
      ModifyWorldTransform(Paintbox1.Canvas.Handle, XF, MWT_IDENTITY);
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      if t > DUREE_PARTIE then t:=0 else inc(t,10);
     
      PaintBox1.Invalidate;
    end;
     
    end.

  8. #8
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par Basile le disciple Voir le message
    il doit y avoir une boucle de 0 jusqu'à 80 dans le OnMouseMove que je ne peux pas modifier
    c'est probablement aussi une source du problème, ton code force le dessin de l'image à une fréquence trop élevée, ça n'a aucun intérêt de dessiner plus d'image que l'écran est capable d'en afficher. Il semblerait que 30 images / seconde soit largement suffisant.

    Une façon relativement simple de déterminer quand il convient d'afficher l'image, c'est de laisser Windows en décider:
    1) l'image est calculée dans OnPaint sur la base du temps passé
    2) si l'mage doit être encore animée, appeler Invalidate() pour demander à Windows de redéclencher un OnPaint

    c'est la technique que j'utilise dans TetrisRun sur lequel traine un Timer qui n'a plus lieu d'être d'ailleurs
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Membre actif Avatar de Basile le disciple
    Homme Profil pro
    étudiant Centrale Supélec
    Inscrit en
    Avril 2013
    Messages
    147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : étudiant Centrale Supélec

    Informations forums :
    Inscription : Avril 2013
    Messages : 147
    Points : 279
    Points
    279
    Par défaut
    Merci pour toutes ces réponses de qualité

    @Gilbert Geyer :

    Je n'ai pas trouvé dans ton FormCreate le précalcul des Sinus et Cosinus
    Oups, je n'avais pas compris la phrase pourtant explicite d'exoseven
    tu devrais peut-être les pré calculer
    J'ai cru qu'il fallait remplacer la variable à mettre dans cos et sin, d'où
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    a := t*360 / DUREE_PARTIE;
    ...
    pl[0].X := pt.X + round((r-15) * cos( (a - 95) * p));
    J'ai donc créé un tableau à plusieurs dimensions où j'ai mis toutes les données dans le formCreate :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    procedure TForm1.FormCreate(Sender: TObject);
    var pt : Tpoint;
        r,i  : integer;
        p,c,s : extended;
    begin
     
      pt:=point(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
      r:=Paintbox1.ClientWidth div 2;
      p:=pi/180;
      For i:=0 to 360 do
      begin
        SinCos( (i-95) * p,s,c);
        tab[0,i]:=Point( round(pt.X + (r-15) * c ), round(pt.Y + (r-15) * s ) );
        SinCos((i-85) * p,s,c);
        tab[1,i]:=Point( round(pt.X + (r-15) * c ), round(pt.Y + (r-15) * s ) );
        SinCos((i-90) * p,s,c);
        tab[2,i]:=Point( round(pt.X + r * c )     , round(pt.Y + r * s ) );
      end;

    En plus, ça simplifie le dessin :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      a := trunc(t*360 / DUREE_PARTIE);
        //flèche
        Pen.Color:=clMaroon; Pen.Width:=3;
        MoveTo(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
        LineTo(tab[2,a].X,tab[2,a].Y);
        //pointe
        Brush.Color:=clMaroon;
        Polygon( [ tab[0,a],tab[1,a],tab[2,a] ] );
    Et grâce à la procédure SinCos, j'ai appris un nouveau type de procédure avec un var dans les paramètres : c'est bien pratique.

    Par contre,
    des array [0..359] of Single par exemple
    Je n'ai pas bien compris, c'est plus rapide de faire plusieurs tableaux plutôt qu'un à 2 dimensions? Et pourquoi de 0 jusqu'à 359?

    Je n'ai cependant pas remplacé quelques calculs comme r-15 ou a-95 comme propose par exemple tourlourou car tout ceci est maintenant placé dans le formCreate et j'ai peur d'avoir un code incompréhensible!

    @Andnotor

    Whaou! Vous avez dû passer un temps monstrueux à coder tout ceci! Je vous en remercie beaucoup!
    Je vais essayer de comprendre mais c'est pas gagner!

    Donc voici le code complet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, Math;
     
    type
      TForm1 = class(TForm)
        PaintBox1: TPaintBox;
        Timer1: TTimer;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure PaintBox1Paint(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        { Déclarations privées }
        bmp_Fond,bmp_Horloge : TBitmap;
        t : integer;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
      tab : array[0..2,0..360] of TPoint;
    const DUREE_PARTIE : integer = 4000;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    var pt : Tpoint;
        r,i  : integer;
        p,c,s : extended;
    begin
     
      pt:=point(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
      r:=Paintbox1.ClientWidth div 2;
      p:=pi/180;
      For i:=0 to 360 do
      begin
        SinCos( (i-95) * p,s,c);
        tab[0,i]:=Point( round(pt.X + (r-15) * c ), round(pt.Y + (r-15) * s ) );
        SinCos((i-85) * p,s,c);
        tab[1,i]:=Point( round(pt.X + (r-15) * c ), round(pt.Y + (r-15) * s ) );
        SinCos((i-90) * p,s,c);
        tab[2,i]:=Point( round(pt.X + r * c )     , round(pt.Y + r * s ) );
      end;
     
      t:=0;
      bmp_Horloge := TBitmap.Create;
      With bmp_Horloge do
      begin
        Width:=Paintbox1.ClientWidth;
        Height:=Paintbox1.Clientheight;
      end;
      bmp_Fond := TBitmap.Create;
      With bmp_Fond do
      begin
        Width:=Paintbox1.ClientWidth;
        Height:=Paintbox1.Clientheight;
        With Canvas do
        begin
         Pen.Width:=4;
         For i:=0 to 135 do    //clLime -> clYellow
         begin
           Pen.Color:=rgb(round(i*255 / 135),255,0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( (i-90) * pi/180)),pt.Y + round( (r-2) * sin( (i-90) *pi/180)) );
         end;
         For i:=0 to 150 do   //clYellow -> $007EFF;
         begin
           Pen.Color:=rgb(255,round(255 - i*129 / 150),0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( ( (i+135) -90) * pi/180)),pt.Y + round( (r-2) * sin( ( (i+135) -90) *pi/180)) );
         end;
         For i:=0 to 75 do   //$007EFF -> clRed
         begin
           Pen.Color:=rgb(255,round(126 - i*126 / 75),0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( ( (i+285) -90) * pi/180)),pt.Y + round( (r-2) * sin( ( (i+285) -90) *pi/180)) );
         end;
         Pen.Color:=clBlack;
         Pen.Width:=2;
         Brush.Style:=bsClear;
         Ellipse(Paintbox1.ClientRect);
         Brush.Style:=bsSolid;
         Pen.Color:=clMaroon;
         Brush.Color:=clMaroon;
         Ellipse(pt.X-5,pt.Y-5,pt.X+5,pt.Y+5);
        end;
      end;
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      bmp_Horloge.Free;
      bmp_Fond.Free;
    end;
     
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    var a : integer;
    const p : extended = pi/180;
    begin
     
      bmp_Horloge.Assign(bmp_Fond);
     
      With bmp_Horloge.Canvas do
      begin
        a := trunc(t*360 / DUREE_PARTIE);
        //flèche
        Pen.Color:=clMaroon; Pen.Width:=3;
        MoveTo(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
        LineTo(tab[2,a].X,tab[2,a].Y);
        //pointe
        Brush.Color:=clMaroon;
        Polygon( [ tab[0,a],tab[1,a],tab[2,a] ] );
      end;
      Paintbox1.Canvas.Draw(0,0,bmp_Horloge);
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      if t > DUREE_PARTIE then timer1.Enabled:=false else inc(t,10);
      Paintbox1.OnPaint(nil);
    end;
     
    end.
    Je n'ai pas encore essayé sur mon véritable projet mais je pense que ça doit aller beaucoup mieux!

    [Edit]

    Il semblerait que 30 images / seconde soit largement suffisant
    Donc l'interval Timer doit être de 1000/30??
    Je vais regarder le code de tetris Run, je l'avais déjà sur mon ordinateur.

  10. #10
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    voici un article qui explique très bien cette question de FPS (source)

    il pointe sur un site intéressant qui montre les combinaisons possibles entre FPS et BLUR, nous sommes manifestement plus habitués au BLUR (effet de flou) qu'à l'augmentation du FPS
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #11
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    1) Basile le disciple : (A propos des "array [0..359] of Single par exemple" )
    je n'ai pas bien compris, c'est plus rapide de faire plusieurs tableaux plutôt qu'un à 2 dimensions? Et pourquoi de 0 jusqu'à 359?
    Pour la rapidité c'est, à mon avis, kif-kif, j'avais mis ça au pluriel : un array pour les Sinus et un autre pour les Cosinus,
    mais tu as encore fait mieux en pré-calculant directement les coordonnées des points avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    For i:=0 to 360 do
      begin
        SinCos( (i-95) * p,s,c);
       tab[0,i]:=Point( round(pt.X + (r-15) * c ), round(pt.Y + (r-15) * s ) );
    2) A propos de "Et pourquoi de 0 jusqu'à 359?" : Bin tout simplement car Sinus et Cosinus de 0° sont égaux à Sinus et Cosinus de 360° (mais là c'est du pinaillage qui ne pas faire gagner en vitesse).


    3) A propos des 30 images par seconde :
    Donc l'interval Timer doit être de 1000/30?? :
    Oui de sorte qu'il s'affiche une image toutes les 33 millisecondes ... et ceci en supposant que 30 images par secondes ne soit pas excessif.
    A ta place je créerais (au moins en phase de mise au point du code) une variable NbImagesParSec dont la valeur est prélevée dans un TEdit pour ajuster le nombre d'images par seconde en fonction du rendu visuel.
    En plus dans ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      if t > DUREE_PARTIE then timer1.Enabled:=false else inc(t,10);
      Paintbox1.OnPaint(nil);
    end;
    il faudrait remplacer inc(t,10) par inc(t, Timer1.Interval)

    4) Il y a peut-être un moyen d'augmenter encore la rapidité en virant les appels répétitifs à bmp_Horloge.Assign(bmp_Fond) et à Paintbox1.Canvas.Draw(0,0,bmp_Horloge) dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    var a : integer;
    const p : extended = pi/180;
    begin
      bmp_Horloge.Assign(bmp_Fond);
      ...
      Paintbox1.Canvas.Draw(0,0,bmp_Horloge);
      ...
    en remplaçant la PaintBox par un TImage dans lequel on charge le bmp_Fond directement dans un TImage lors du FormCreate puis en réalisant les tracés de l'aiguille sur le Canvas de ce TImage avec Pen.Mode := pmXor (ou bien Pen.Mode := pmNotXor : c'est kif-kif).
    Cela nécessite de tracer l'aiguille 2 fois à chaque changement de l'image : le premier tracé efface l'aiguille dans sa position précédente et le deuxième trace l'aiguille dans sa nouvelle position et le reste du Canvas reste inchangé,
    et donc l'aiguille doit être tracée une seule fois sur le bmp_Fond lors du FormCreate de sorte qu'elle soit effacée dans cette position précédente lors du changement d'image suivant ... et on gagne les temps d'exécution liés à la gymnastique des bmp_Horloge.Assign(bmp_Fond) et des Paintbox1.Canvas.Draw(0,0,bmp_Horloge) qui portent sur la totalité de l'image alors qu'on veut seulement changer la position de l'aiguille.

    Ceci dit, comme j'ai eu la flemme de faire des tests de vitesse comparatifs avec les codes proposés par les autres participants je te laisse le soin de comparer les gains de vitesse ... en comparant sur la base d'un même nombre d'images par seconde et d'images de même taille.

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  12. #12
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Re-salut,

    Tiens voici le code avec un TImage au lieu de la PaintBox avec tracé de l'aiguille en direct sur le Canvas du TImage en mode pmNotXor et avec possibilité de faire varier le nombre d'images par seconde.
    (à mon avis 10 imges/seconde c'est suffisant, et avec 5 images/seconde l'affichage est saccadé)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    unit PenduleBasile;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, Math, StdCtrls, Buttons;
     
    type
      TForm1 = class(TForm)
        Image1: TImage;
        Timer1: TTimer;
        Edit1: TEdit;
        Label1: TLabel;
        SpeedButton1: TSpeedButton;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
        procedure SpeedButton1Click(Sender: TObject);
      private
        { Déclarations privées }
        bmp_Fond: TBitmap;
        t: integer;
        nbImagesParSec: integer;
        procedure TraceAiguille(Init: Boolean);
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
      tab: array[0..3, 0..360] of TPoint; //<- augmenté la taille du tableau
      // de sorte que le tracé de la flèche ne surchage pas celui de la pointe à cause du NotXor
    const DUREE_PARTIE: integer = 4000;
    const clAiguille: tColor = clBlue;
     
    implementation
     
    {$R *.dfm}
     
    var a: integer;
     
    procedure TForm1.TraceAiguille(Init: Boolean);
    const p: extended = pi / 180;
    begin
      with Image1.Canvas do
      begin
        if Init then begin
          Pen.Mode := pmNotXor; //
          a := trunc(t * 360 / DUREE_PARTIE);
          //flèche
          Pen.Color := clAiguille; Pen.Width := 3;
          MoveTo(Image1.ClientWidth div 2, Image1.ClientHeight div 2);
          LineTo(tab[3, a].X, tab[3, a].Y);
          //pointe
          Brush.Color := clAiguille;
          Polygon([tab[0, a], tab[1, a], tab[2, a]]);
        end else begin
          if t > DUREE_PARTIE then EXIT;
          Pen.Mode := pmNotXor;
          // Effacement ancienne position :
          // flèche
          Pen.Color := clAiguille; Pen.Width := 3;
          MoveTo(Image1.ClientWidth div 2, Image1.ClientHeight div 2);
          LineTo(tab[3, a].X, tab[3, a].Y);
          // pointe
          Brush.Color := clAiguille;
          Polygon([tab[0, a], tab[1, a], tab[2, a]]);
          // Tracé dans nouvelle position
          a := trunc(t * 360 / DUREE_PARTIE);
          // flèche
          Pen.Color := clAiguille; Pen.Width := 3;
          MoveTo(Image1.ClientWidth div 2, Image1.ClientHeight div 2);
          LineTo(tab[3, a].X, tab[3, a].Y);
          // pointe
          Brush.Color := clAiguille;
          Polygon([tab[0, a], tab[1, a], tab[2, a]]);
        end;
      end;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    var pt: Tpoint;
      r, i: integer;
      p, c, s: extended;
    begin
      nbImagesParSec := 10;
      Edit1.Text := IntToStr(nbImagesParSec);
      pt := point(Image1.ClientWidth div 2, Image1.ClientHeight div 2);
      r := Image1.ClientWidth div 2;
      p := pi / 180;
      for i := 0 to 360 do
      begin
        SinCos((i - 95) * p, s, c);
        tab[0, i] := Point(round(pt.X + (r - 25) * c), round(pt.Y + (r - 25) * s));
        SinCos((i - 85) * p, s, c);
        tab[1, i] := Point(round(pt.X + (r - 25) * c), round(pt.Y + (r - 25) * s));
        SinCos((i - 90) * p, s, c);
        tab[2, i] := Point(round(pt.X + r * c), round(pt.Y + r * s));
        tab[3, i] := Point(round(pt.X + (r - 28) * c), round(pt.Y + (r - 28) * s));
      end;
     
      t := 0;
      bmp_Fond := TBitmap.Create;
      with bmp_Fond do
      begin
        Width := Image1.ClientWidth; //Width := Paintbox1.ClientWidth;
        Height := Image1.Clientheight; //Height := Paintbox1.Clientheight;
        with Canvas do
        begin
          brush.Style:=bsSolid; brush.Color:=clSilver;
          FillRect(ClipRect);
          Pen.Width := 4;
          for i := 0 to 135 do //clLime -> clYellow
          begin
            Pen.Color := rgb(round(i * 255 / 135), 255, 0);
            MoveTo(Pt.X, Pt.Y); LineTo(pt.X + round((r - 2) * cos((i - 90) * pi / 180)), pt.Y + round((r - 2) * sin((i - 90) * pi / 180)));
          end;
          for i := 0 to 150 do //clYellow -> $007EFF;
          begin
            Pen.Color := rgb(255, round(255 - i * 129 / 150), 0);
            MoveTo(Pt.X, Pt.Y); LineTo(pt.X + round((r - 2) * cos(((i + 135) - 90) * pi / 180)), pt.Y + round((r - 2) * sin(((i + 135) - 90) * pi / 180)));
          end;
          for i := 0 to 75 do //$007EFF -> clRed
          begin
            Pen.Color := rgb(255, round(126 - i * 126 / 75), 0);
            MoveTo(Pt.X, Pt.Y); LineTo(pt.X + round((r - 2) * cos(((i + 285) - 90) * pi / 180)), pt.Y + round((r - 2) * sin(((i + 285) - 90) * pi / 180)));
          end;
          Pen.Color := clBlack;
          Pen.Width := 2;
          Brush.Style := bsClear;
          Ellipse(Image1.ClientRect);
        end;
      end;
      image1.Picture.Bitmap.Assign(bmp_Fond);
      TraceAiguille(True);
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      bmp_Fond.Free;
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      if t > DUREE_PARTIE then timer1.Enabled := FALSE
      else begin
        inc(t, Timer1.Interval);
        TraceAiguille(FALSE);
      end;
    end;
     
    procedure TForm1.SpeedButton1Click(Sender: TObject);
    begin
     t:=0;
     nbImagesParSec:=StrToIntDef(Edit1.text,10);
     timer1.Interval:=round(1000/nbImagesParSec);
     timer1.Enabled := TRUE;
    end;
     
    end.
    A+.
    Images attachées Images attachées  
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  13. #13
    Membre actif Avatar de Basile le disciple
    Homme Profil pro
    étudiant Centrale Supélec
    Inscrit en
    Avril 2013
    Messages
    147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : étudiant Centrale Supélec

    Informations forums :
    Inscription : Avril 2013
    Messages : 147
    Points : 279
    Points
    279
    Par défaut
    Merci beaucoup pour ce code, j'étais en train d'essayer avec cette histoire de Pen.Mode := pmNotXor mais c'est pas simple. Ce code tombe à pic!

    Je n'ai pas vraiment bien compris l'aide de delphi,
    Inverse de pmXor*: combinaison des couleurs appartenant soit au crayon, soit à l'arrière-plan du canevas, mais pas aux deux
    ça fait quoi exactement pmNotXor?

    Sinon, c'est une super idée, éviter de redessiner le fond à chaque fois, c'est le best.

  14. #14
    Membre actif Avatar de Basile le disciple
    Homme Profil pro
    étudiant Centrale Supélec
    Inscrit en
    Avril 2013
    Messages
    147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : étudiant Centrale Supélec

    Informations forums :
    Inscription : Avril 2013
    Messages : 147
    Points : 279
    Points
    279
    Par défaut
    @Gilbert Geyer

    J'ai essayé d'adapter mon code au vôtre (j'ai pas eu grand chose à faire), mais la couleur de l'aiguille ne reste pas uniforme. (image en bas du message)
    Cela marcherait à la perfection si le fond était uniforme, mais là, ce n'est pas le cas...

    @Paul Toth

    Une façon relativement simple de déterminer quand il convient d'afficher l'image, c'est de laisser Windows en décider:
    1) l'image est calculée dans OnPaint sur la base du temps passé
    2) si l'image doit être encore animée, appeler Invalidate() pour demander à Windows de redéclencher un OnPaint
    Donc, si j'ai bien compris, si l'angle reste le même, autant quitter le OnPaint puisque l'ordinateur va dessiner la même chose...
    Et pour avoir le temps exacte, il suffit d'utiliser QueryPerformanceCounter et QueryPerformanceFrequency. C'est beaucoup mieux qu'un TTimer!

    Mais ce que je n'ai pas compris, c'est
    sur lequel traine un Timer qui n'a plus lieu d'être d'ailleurs
    Si on dessine la même chose, l'ordinateur va quitter le OnPaint :

    (extrait de tetrisRun)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      QueryPerformanceCounter(Time);
      // Faire défiler la route en fonction du temps passé depuis le dernier rendu
      delta := Round(FSpeed * ((Time - FCount)/FFreq));
      if delta = 0 then
      begin
        InvalidateRect(Handle, nil, False);
        Exit;
      end;
    Et l’événement OnPaint ne va alors plus être appelé, donc il faut bien un FormPaint(nil) dans le OnTimer pour le ré-appeler... Non?

    Quoi qu'il en soit, voilà mon code à ce niveau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
     
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, Math;
     
    type
      TForm1 = class(TForm)
        PaintBox1: TPaintBox;
        Timer1: TTimer;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure PaintBox1Paint(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        { Déclarations privées }
        bmp_Fond,bmp_Horloge : TBitmap;
        t : extended;
        FFreq       : Int64;   // mesure du temps qui passe
        FCount      : Int64;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
      tab : array[0..2,0..359] of TPoint;
      a : integer;
    const DUREE_PARTIE : integer = 4;    //en seconde
          CL_AIGUILLE : TColor = clMaroon;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    var pt : Tpoint;
        r,i  : integer;
        c,s : extended;
    begin
      a:=-1;
      t:=0;
      QueryPerformanceCounter(FCount);
      QueryPerformanceFrequency(FFreq);
     
      pt:=point(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
      r:=Paintbox1.ClientWidth div 2;
      For i:=0 to 359 do
      begin
        SinCos( (i-95) * pi/180,s,c);
        tab[0,i]:=Point( round(pt.X + (r-15) * c ), round(pt.Y + (r-15) * s ) );
        SinCos((i-85) * pi/180,s,c);
        tab[1,i]:=Point( round(pt.X + (r-15) * c ), round(pt.Y + (r-15) * s ) );
        SinCos((i-90) * pi/180,s,c);
        tab[2,i]:=Point( round(pt.X + r * c )     , round(pt.Y + r * s ) );
      end;
     
     
      bmp_Horloge := TBitmap.Create;
      With bmp_Horloge do
      begin
        Width:=Paintbox1.ClientWidth;
        Height:=Paintbox1.Clientheight;
      end;
      bmp_Fond := TBitmap.Create;
      With bmp_Fond do
      begin
        Width:=Paintbox1.ClientWidth;
        Height:=Paintbox1.Clientheight;
        With Canvas do
        begin
         Pen.Width:=4;
         For i:=0 to 135 do    //clLime -> clYellow
         begin
           Pen.Color:=rgb(round(i*255 / 135),255,0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( (i-90) * pi/180)),pt.Y + round( (r-2) * sin( (i-90) *pi/180)) );
         end;
         For i:=0 to 150 do   //clYellow -> $007EFF;
         begin
           Pen.Color:=rgb(255,round(255 - i*129 / 150),0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( ( (i+135) -90) * pi/180)),pt.Y + round( (r-2) * sin( ( (i+135) -90) *pi/180)) );
         end;
         For i:=0 to 75 do   //$007EFF -> clRed
         begin
           Pen.Color:=rgb(255,round(126 - i*126 / 75),0);
           MoveTo(Pt.X,Pt.Y); LineTo(pt.X + round((r-2) * cos( ( (i+285) -90) * pi/180)),pt.Y + round( (r-2) * sin( ( (i+285) -90) *pi/180)) );
         end;
         Pen.Color:=clBlack;
         Pen.Width:=2;
         Brush.Style:=bsClear;
         Ellipse(Paintbox1.ClientRect);
         Brush.Style:=bsSolid;
         Pen.Color:=clMaroon;
         Brush.Color:=clMaroon;
         Ellipse(pt.X-5,pt.Y-5,pt.X+5,pt.Y+5);
        end;
      end;
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      bmp_Horloge.Free;
      bmp_Fond.Free;
    end;
     
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    var Time : int64;
    const p : extended = pi/180;
    begin
      QueryPerformanceCounter(Time);
      t:=(Time-FCount)/FFreq;
      if trunc(t*360 / DUREE_PARTIE) = a then Exit;
     
      Caption:=FloatTostr(t);
     
      a:=trunc(t*360 / DUREE_PARTIE);
      bmp_Horloge.Assign(bmp_Fond);
      With bmp_Horloge.Canvas do
      begin
        if a >= 360 then a:=0;
        //flèche
        Pen.Color:=CL_AIGUILLE; Pen.Width:=3;
        MoveTo(Paintbox1.ClientWidth div 2,Paintbox1.ClientHeight div 2);
        LineTo(tab[2,a].X,tab[2,a].Y);
        //pointe
        Brush.Color:=CL_AIGUILLE;
        Polygon( [ tab[0,a],tab[1,a],tab[2,a] ] );
      end;
      Paintbox1.Canvas.Draw(0,0,bmp_Horloge);
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      if t > DUREE_PARTIE then timer1.Enabled:=false;
      Paintbox1.OnPaint(nil);
    end;
     
    end.
    Images attachées Images attachées  

  15. #15
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    pour le XOR c'est juste une opération binaire sur la couleur qui est réversible : deux fois XOR = rien, mais tu ne peux pas choisir la couleur de ton aiguille qui va dépendre de la couleur de fond ET de la couleur de tracé via une opération XOR justement. Ce n'est pas pas forcément une bonne idée.

    Concernent TetrisRun il y a un Timer sur la fiche qui est désactivé, il ne sert à rien, c'est lui que j'avais utilisé au début du projet pour le remplacer finalement par la technique évoquée plus haut.

    "InvalidateRect(Handle, nil, False)" indique à Windows que toute la surface (2ième paramètre à nil au lieu d'un TRect), est devenue invalide et qu'il faut la redessiner sans redessiner le fond (troisième paramètre).
    Delphi propose la méthode Invalidate() mais celle-ci force le troisième paramètre à True ce qui a pour effet de faire scintiller l'image. En effet le dessin d'une fenêtre passe par deux messages WM_ERASEBKGND qui efface le fond en utilisant la propriété Color, puis un WM_PAINT qui déclenche notamment le OnPaint.

    donc en plaçant un InvalidateRect() à l'intérieur du OnPaint on programme automatiquement un nouvel appel à OnPaint, et celui-ci se fera quand Windows décidera qu'il est temps de réactualiser les fenêtres "invalides", c'est comme cela que j'obtiens ma boucle sans trop forcer sur les ressources du système, Windows à le temps de faire autre chose entre deux.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  16. #16
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    Basile : 1) J'ai essayé d'adapter mon code au vôtre (j'ai pas eu grand chose à faire), mais la couleur de l'aiguille ne reste pas uniforme. (image en bas du message)
    Cela marcherait à la perfection si le fond était uniforme, mais là, ce n'est pas le cas...
    Si tu veux absolument que la couleur de l'aiguille reste constante il faudrait augmenter la taille de tab: array[0..3, 0..360] of TPoint à tab: array[0..4, 0..360] et y stocker dans X ou Y du TPoint la couleur (*) variable de clAiguille qui correspond à la Xorisation avec la couleur variable du fond lors du FormCreate ce qui remplacerait la constante clAiguille.
    (*) : les TColor sont des Integer comme les X et Y du TPoint.

    2) Et pour avoir le temps exact, il suffit d'utiliser QueryPerformanceCounter et QueryPerformanceFrequency. C'est beaucoup mieux qu'un TTimer!
    C'est effectivement mieux, mais est-ce vraiment utile de chronométrer au milliardième de seconde près ???

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  17. #17
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Re-salut,

    Voici les quelques modifs à apporter au code de sorte que la couleur de l'aiguille reste constante et égale à clMaroon :
    (Remarque : au passage j'ai remplacé le NotXOR par un simple XOR)

    1) Avant "implementation" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var
      Form1: TForm1;
      tab: array[0..4, 0..360] of TPoint; //<- augmenté la taille du tableau 
      // de sorte que
      // - le tracé de la flèche ne surchage pas celui de la pointe à cause du XOR
      // - et pour y stocker la couleur XORisée telle que l'aiguille soit clMaroon
    const DUREE_PARTIE: integer = 4000;
    //const clAiguille: tColor = clMaroon; <- remplacée par tab[4, a]
    2) nouvelle procedure TForm1.TraceAiguille(Init: Boolean) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    procedure TForm1.TraceAiguille(Init: Boolean);
    const p: extended = pi / 180;
    begin
      with Image1.Canvas do
      begin
        if Init then begin
          Pen.Mode := pmXOR; //
          a := trunc(t * 360 / DUREE_PARTIE);
          //flèche
          Pen.Color := tab[4, a].X; //clAiguille;
          Pen.Width := 2;
          MoveTo(Image1.ClientWidth div 2, Image1.ClientHeight div 2);
          LineTo(tab[3, a].X, tab[3, a].Y);
          //pointe
          Brush.Color := tab[4, a].X; //clAiguille;
          Polygon([tab[0, a], tab[1, a], tab[2, a]]);
        end else begin
          if t > DUREE_PARTIE then EXIT;
          Pen.Mode := pmXOR;
          // Effacement ancienne position :
          // flèche
          Pen.Color := tab[4, a].X; //clAiguille;
          Pen.Width := 2;
          MoveTo(Image1.ClientWidth div 2, Image1.ClientHeight div 2);
          LineTo(tab[3, a].X, tab[3, a].Y);
          // pointe
          Brush.Color := tab[4, a].X; //clAiguille;
          Polygon([tab[0, a], tab[1, a], tab[2, a]]);
          // Tracé dans nouvelle position
          a := trunc(t * 360 / DUREE_PARTIE);
          // flèche
          Pen.Color := tab[4, a].X; //clAiguille;
          MoveTo(Image1.ClientWidth div 2, Image1.ClientHeight div 2);
          LineTo(tab[3, a].X, tab[3, a].Y);
          // pointe
          Brush.Color := tab[4, a].X; //clAiguille;
          Polygon([tab[0, a], tab[1, a], tab[2, a]]);
        end;
      end;
    end;
    3) Ajouter en fin de la procedure TForm1.FormCreate(Sender: TObject);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm1.FormCreate(Sender: TObject);
      ... 
      end;
      for i:=0 to 360 do begin
         tab[4, i].X:= bmp_fond.canvas.Pixels[tab[3, i].X,tab[3, i].Y] XOR clMaroon;
      end;
      image1.Picture.Bitmap.Assign(bmp_Fond);
      TraceAiguille(True);
    end;
    Testé : la couleur de l'aiguille reste clMaroon sur toutes ses inclinaisons excepté une position où la pointe est à cheval sur deux zones où le fond est bicolore, mais avec une aiguille et une pointe plus fine ce petit inconvénient
    devrait s'estomper.

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  18. #18
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Gilber, les méthode que tu exploses me semble d'une autre époque...de nos jours, calculer un sinus et un cosinus, copier un bitmap dans un autre...c'est pas ça qui va mettre la machine à genoux

    après si les performances étaient un critère super important, il faudrait tout simplement utiliser la GPU qui explose la CPU niveau performances graphiques. A l'époque de Delphi 2 je faisais dans la 3D en mode GDI et même avant en Turbo Pascal sous DOS avec des tableaux précalculés et des opérations sur des entiers en assembleur pour avoir un semblant de fluidité sur un 486..mais aujourd'hui tu peux tranquillement faire des animations par bones ou du multithreading au besoin. Nos machines sont des bêtes de course - et ce depuis longtemps - il reste juste à programmer proprement et le tour est joué
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  19. #19
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Re-bonjour,

    Paul TOTH : Gilbert, les méthodes que tu exposes me semblent d'une autre époque...
    Je sais, d'autant plus que j'essaye toujours de me débrouiller avec des solutions du standard basique de Delphi, et en plus ça m'évite à avoir à gérer trop d'unités ou de composants exotiques.
    Et je suis même certain que je n'utilise qu'environ 10% des possibilités de Delphi 6 mais on fait quand même des trucs intéressants avec ça.
    Je n'utilise comme unités exotiques que 2 ou 3 dont GDI+

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  20. #20
    Membre actif Avatar de Basile le disciple
    Homme Profil pro
    étudiant Centrale Supélec
    Inscrit en
    Avril 2013
    Messages
    147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : étudiant Centrale Supélec

    Informations forums :
    Inscription : Avril 2013
    Messages : 147
    Points : 279
    Points
    279
    Par défaut Merci à tous
    J'ai essayé mon code sur mon projet originel, ça marche à la perfection!
    Je vous remercie pour tout le temps passé pour moi, notamment Gilbert Geyer et Paul Toth.
    En plus, vous m'avez appris plein de choses que j'ignorais totalement(comme d'habitude d’ailleurs).

    J'ai à peu près gardé le code de mon dernier message, comme ça marche très bien je pense pouvoir mettre cette question en

    Et je suis même certain que je n'utilise qu'environ 10% des possibilités de Delphi 6
    Je ne pense pas qu'il soit né celui qui maîtrise 100% de delphi...

    Merci à tous.

    PS : J'ai regardé le site de Paul Toth, c'est vraiment

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 26/05/2010, 22h17
  2. Question sur la rapidité d'une macro
    Par johannj dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 26/06/2009, 16h29
  3. Question sur la rapidité d'une requete
    Par barok dans le forum Requêtes
    Réponses: 3
    Dernier message: 12/07/2006, 09h25
  4. [FLASH MX] Synchroniser une animation sur un long mp3
    Par calogerogigante dans le forum Flash
    Réponses: 9
    Dernier message: 05/07/2006, 11h37
  5. [FLASH MX] Le son sur une animation
    Par skyjoe dans le forum Flash
    Réponses: 4
    Dernier message: 23/08/2004, 18h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo