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 :

paintbox, panels, canvas


Sujet :

Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 130
    Points : 46
    Points
    46
    Par défaut paintbox, panels, canvas
    Bonjour, j'essaye de comprendre les paintbox.
    J'ai mis un panel sur la form puis un paintbox dans le panel dans le but de faire bouger des images sur un fond.

    J'ai comme bug à la compilation : "incompatible type tgraphic and timage"


    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
     
    var pacman:Array[1..6] of TImage;
         pacmansprite:Timage;
    ...
    procedure Ttp.FormCreate(Sender: TObject);
    var i,j,hasard:Integer;
        Appdir:Variant;
    begin
    ....
    for i := 1 to 6 do
      begin
        pacman[i]:=Timage.Create(nil);
        pacman[i].Parent:=Panel1;
        if i=1 then pacman[i].Picture.LoadFromFile(Appdir+'assets\pacman\pacmanleft1.bmp');
        if i=2 then pacman[i].Picture.LoadFromFile(Appdir+'assets\pacman\pacmanleft2.bmp');
        if i=3 then pacman[i].Picture.LoadFromFile(Appdir+'assets\pacman\pacmanleft3.bmp');
        if i=4 then pacman[i].Picture.LoadFromFile(Appdir+'assets\pacman\pacmanright1.bmp');
        if i=5 then pacman[i].Picture.LoadFromFile(Appdir+'assets\pacman\pacmanright2.bmp');
        if i=6 then pacman[i].Picture.LoadFromFile(Appdir+'assets\pacman\pacmanright3.bmp');
        pacman[i].Width:=60;
        pacman[i].Height:=60;
        pacman[i].Stretch:=True;
      end;
     
    ...
      pacmansprite.Assign(pacman[1]);
    ...
    end;
     
    ...
    procedure Ttp.PaintBox1Paint(Sender: TObject);
    begin
       PaintBox1.Canvas.Draw(0,0,pacmansprite);
    end;

  2. #2
    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,

    Commencer par remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if i= ... then pacman[i].Picture.LoadFromFile(Appdir+'assets\pacman\pacmanright1.bmp');
    par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if i= ... 4 then pacman[i].Picture.BitMap.LoadFromFile(Appdir+'assets\pacman\pacmanright1.bmp');
    pour charger un *.bmp

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

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 130
    Points : 46
    Points
    46
    Par défaut
    Merci, mais ça ne marche toujours pas

    Voilà l'intégralité du code. J'ai mis des // devant les lignes qui ne compilent pas :
    pacmansprite.Picture.Bitmap.Assign(pacman[1]);
    PaintBox1.Canvas.Draw(0,0,pacmansprite);

    En l'état, c'est à dire sans le positionnement du "pacman", les tiles du level s'affichent correctement sur l'écran comme prévu.

    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
    unit Unit1;
     
    interface
     
    uses
      MMSystem,Math,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, ImgList, MPlayer;
     
    type
      Ttp = class(TForm)
        Panel1: TPanel;
        PaintBox1: TPaintBox;
        procedure FormCreate(Sender: TObject);
        procedure PaintBox1Paint(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
     
    var
      tp: Ttp;
      tiles:Array [1..500] of TImage;
      level:Array [1..15] of String;
      pacman:Array[1..6] of Timage;
      pacmansprite:Timage;
     
    implementation
     
    {$R *.dfm}
     
    procedure Ttp.FormCreate(Sender: TObject);
    var i,j,hasard:Integer;
        Appdir:Variant;
    begin
      Panel1.DoubleBuffered:=True;
      Panel1.Width:=1200;
      Panel1.Height:=900;
     
      level[1]:='11111111111111111111';
      level[2]:='1                  1';
      level[3]:='1 1 111 1111 111 1 1';
      level[4]:='1 1 1   1111   1 1 1';
      level[5]:='1 1 1   1111   1 1 1';
      level[6]:='1 1 1          1 1 1';
      level[7]:='1   11 11 11 111   1';
      level[8]:='1 1    1  -1     1 1';
      level[9]:='1 1111 111111111 1 1';
     level[10]:='1   1  -----  1    1';
     level[11]:='1 1 1 1-111-1 1  1 1';
     level[12]:='1 1 1 1--S--1 1  1 1';
     level[13]:='1 1 1 1 111 1 1  1 1';
     level[14]:='1                  1';
     level[15]:='11111111111111111111';
     
     for i := 1 to 6 do
      begin
        pacman[i]:=Timage.Create(nil);
        pacman[i].Parent:=Panel1;
        pacman[i].Width:=60; pacman[i].Height:=60;
        pacman[i].Stretch:=True;
        if i=1 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanleft1.bmp');
        if i=2 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanleft2.bmp');
        if i=3 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanleft3.bmp');
        if i=4 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanright1.bmp');
        if i=5 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanright2.bmp');
        if i=6 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanright3.bmp');
      end;
     
     for i := 1 to 300 do
      begin
        tiles[i]:=Timage.Create(nil);
        tiles[i].Parent:=Panel1;
        tiles[i].Width:=60;
        tiles[i].Height:=60;
        tiles[i].Stretch:=True;
      end;
     
      for j := 1 to 15 do
        for i := 1 to 20 do
        begin
          if level[j][i]='1' then
            begin
                hasard:=random(4);
                if hasard=0 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tile.bmp');
                if hasard=1 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilebis.bmp');
                if hasard=2 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilebis2.bmp');
                if hasard=3 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilebis3.bmp');
            end;
              if (level[j][i]<>'1') then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tile2.bmp');
              tiles[j*20-20+i].Left:=i*60-60;
              tiles[j*20-20+i].Top:=j*60-60;
              tiles[j*20-20+i].Visible:=True;
            if level[j][i]='S' then
            begin
              //pacmansprite.Picture.Bitmap.Assign(pacman[1]);
            end;
        end;
    end;
     
     
    procedure Ttp.PaintBox1Paint(Sender: TObject);
    begin
       //PaintBox1.Canvas.Draw(0,0,pacmansprite);
    end;
     
    end.

  4. #4
    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,

    Voici un truc qui marche (Rectifs. en vert) :

    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
    var
      pacman: array of Timage;
      pacmansprite: Timage;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var i: integer;
    begin
      SetLength(pacman,6);
      for i := 1 to 1 do // to 6 do
      begin
        pacman[i-1] := Timage.Create(nil);
        pacman[i-1].Parent := Panel1;
        pacman[i-1].Width := 60; pacman[i - 1].Height := 60;
        pacman[i-1].Stretch := True;
        if i = 1 then pacman[i-1].Picture.Bitmap.LoadFromFile(ExtractFilePath(Application.ExeName) + 'nenuphars.bmp');
      end;
    end;
    
    procedure TfrmTradFormules.Button2Click(Sender: TObject);
    begin
      pacmansprite := Timage.Create(nil);
      with pacmansprite do begin
        parent := panel1;
        Width := 60; Height := 60; Left := 150; top := 0;
        Stretch := True;
      end;
      pacmansprite.Picture.Bitmap.Assign(pacman[0].Picture.BitMap);
    end;
    Remarques :
    1)
    Pour le faire fonctionner j'ai été obligé de remplacer le tableau statique pacman: Array[1..6] of Timage; par un tableau dynamique et je n'ai pas compris pourquoi ça ne marche pas avec un statique, mais bon.

    2) Quant à pacmansprite.Picture.Bitmap.Assign(pacman[1]); ça ne pouvait pas marcher car pacman[1] est un TImage : à remplacer par :
    pacmansprite.Picture.Bitmap.Assign(pacman[0].Picture.BitMap);

    3) Et pour PaintBox1.Canvas.Draw(0,0,pacmansprite); c'est pareil : à remplacer par :
    PaintBox1.Canvas.Draw(0,0,pacmansprite.Picture.Bitmap);

    4) Ma modif où j'ai remplacé les pacman[i] par pacman[i-1] résulte de l'utilisation d'un tableau dynamique dont le premier indice vaut 0
    ... mais tu peux conserver tes i en remplaçant for i := 1 to 6 do par for i:=Low(Pacman) to High(Pacmann) do ...

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

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 130
    Points : 46
    Points
    46
    Par défaut
    Merci pour la réponse, je vais essayer ça et donnerai un retour...

  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,

    A propos de "je n'ai pas compris pourquoi ça ne marche pas avec un tableau statique" :
    ... En fait j'ai probablement fait, hier, une erreur de manipulation car vérification faite, le code ci-après fonctionne correctement :

    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
    var
      pacman: array [1..6] of Timage; 
      pacmansprite: Timage;
    
    procedure TfrmTradFormules.Button1Click(Sender: TObject);
    var i: integer;
    begin
      for i := Low (Pacman) to high(Pacman) do
      begin
        pacman[i] := Timage.Create(nil);
        pacman[i].Parent := Panel1;
        pacman[i].Width := 60; pacman[i].Height := 60;
        pacman[i].Stretch := True;
        if i = 1 then pacman[i].Picture.Bitmap.LoadFromFile(ExtractFilePath(Application.ExeName) + 'nenuphars.bmp')
        else pacman[i].Picture.Bitmap.LoadFromFile(ExtractFilePath(Application.ExeName) + 'nenuphars.bmp');
      end;
    end;
    
    procedure TfrmTradFormules.Button2Click(Sender: TObject);
    begin
      pacmansprite := Timage.Create(nil);
      with pacmansprite do begin
        parent := panel1;
        Width := 60; Height := 60; Left := 150; top := 0;
        Stretch := True;
      end;
      pacmansprite.Picture.Bitmap.Assign(pacman[3].Picture.BitMap);
    end;
    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 130
    Points : 46
    Points
    46
    Par défaut
    Après modification du code, j'en suis là.
    J'ai donc des tiles qui s'affichent correctement et un personnage (un pacman) qui se déplace grâce au timer de gauche à droite par modification de la position de la paintbox dans laquelle le sprite est affiché :
    Paintbox1.Left:=PaintBox1.Left+1;
    et
    PaintBox1.Canvas.Draw(0,0,pacmansprite.Picture.Bitmap);
    qui dessine le sprite du pacman sur la paintbox.
    Hélas, lors du déplacement, ça clignote, un problème connu (le flickering).
    Comment pourrais je utiliser la fonction "copyrect"?
    Il me faudrait d'abord copier le fond (ce qu'il y a sous la paintbox) dans une image invisible, puis ajouter le sprite sur cette image invisible, puis enfin afficher l'image (ou la copier) dans la paintbox.
    Ca, c'est en théorie...

    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
    unit Unit1;
     
    interface
     
    uses
      MMSystem,Math,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, ImgList, MPlayer;
     
    type
      Ttp = class(TForm)
        Panel1: TPanel;
        PaintBox1: TPaintBox;
        Timer1: TTimer;
        procedure FormCreate(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
     
    var
      tp: Ttp;
      tiles:Array [1..500] of TImage;
      level:Array [1..15] of String;
      pacman:Array[1..6] of Timage;
      pacmansprite:TImage;
      test:Timage;
     
    implementation
     
    {$R *.dfm}
     
    procedure Ttp.FormCreate(Sender: TObject);
    var i,j,hasard:Integer;
        Appdir:Variant;
    begin
      pacmansprite:=Timage.Create(nil);
      Panel1.Width:=1200;
      Panel1.Height:=900;
     
      level[1]:='11111111111111111111';
      level[2]:='1                  1';
      level[3]:='1 1 111 1111 111 1 1';
      level[4]:='1 1 1   1111   1 1 1';
      level[5]:='1 1 1   1111   1 1 1';
      level[6]:='1 1 1    Y     1 1 1';
      level[7]:='1   11 11T11 111   1';
      level[8]:='1 1    1UG-1     1 1';
      level[9]:='1 1111 111111111 1 1';
     level[10]:='1   1  -----  1    1';
     level[11]:='1 1 1 1-111-1 1  1 1';
     level[12]:='1 1 1 1--S--1 1  1 1';
     level[13]:='1 1 1 1 111 1 1  1 1';
     level[14]:='1                  1';
     level[15]:='11111111111111111111';
     
     for i := 1 to 6 do
      begin
        pacman[i]:=Timage.Create(nil);
        pacman[i].Parent:=Panel1;
        pacman[i].Width:=60; pacman[i].Height:=60;
        pacman[i].Stretch:=True;
        if i=1 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanleft1.bmp');
        if i=2 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanleft2.bmp');
        if i=3 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanleft3.bmp');
        if i=4 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanright1.bmp');
        if i=5 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanright2.bmp');
        if i=6 then pacman[i].Picture.Bitmap.LoadFromFile(Appdir+'assets\pacman\pacmanright3.bmp');
      end;
     
     for i := 1 to 300 do
      begin
        tiles[i]:=Timage.Create(nil);
        tiles[i].Parent:=Panel1;
        tiles[i].Width:=60;
        tiles[i].Height:=60;
        tiles[i].Stretch:=True;
      end;
     
      for j := 1 to 15 do
        for i := 1 to 20 do
        begin
          if level[j][i]='1' then
            begin
                hasard:=random(4);
                if hasard=0 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tile.bmp');
                if hasard=1 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilebis.bmp');
                if hasard=2 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilebis2.bmp');
                if hasard=3 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilebis3.bmp');
            end;
              if (level[j][i]<>'1') then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tile2.bmp');
              tiles[j*20-20+i].Left:=i*60-60;
              tiles[j*20-20+i].Top:=j*60-60;
              tiles[j*20-20+i].Visible:=True;
            if level[j][i]='S' then
            begin
              pacmansprite.Picture.Bitmap.Assign(pacman[1].Picture.BitMap);
              PaintBox1.Width:=60; PaintBox1.Height:=60;
            end;
        end;
    end;
     
     
    procedure Ttp.Timer1Timer(Sender: TObject);
    var i:Integer;
    begin
      for i := 1 to 2 do
        begin
          pacmansprite.Left:=pacmansprite.Left+1;
          PaintBox1.Left:=PaintBox1.Left+1;
          PaintBox1.Canvas.Draw(0,0,pacmansprite.Picture.Bitmap);
        end;
    end;
     
    end.

  8. #8
    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
    Vous devriez utiliser un TImageList pour simplifier le code comme ça vous n'auriez plus à faire LoadFromFile plein de fois :

    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
     
    procedure TForm1.FormCreate(Sender: TObject);
    var i : integer;
    begin
      For i:= 1 to 6 do
      begin
        Pacman[i]:=TImage.Create(nil);
        With Pacman[i] do
        begin
          Parent:=Panel1;
          Width:=60;  Height:=60;
          Stretch:=true;
        end;
        ImageList1.Draw(Pacman[i].Canvas,0,0,i-1);
      end;
    end;

  9. #9
    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,

    Hélas, lors du déplacement, ça clignote, un problème connu (le flickering).
    Dans le FormCreate(Sender: TObject) ajouter DoubleBuffered:=true;

    Comment pourrais je utiliser la fonction "copyrect" ?
    ... Voici ce que l'Aide Delphi dit pour utiliser Copyrect :
    Copie dans le canevas une partie de l'image d'un autre canevas.

    procedure CopyRect(const Dest: TRect; Canvas: TCanvas; const Source: TRect);

    Description

    Utilisez la méthode CopyRect pour transférer une partie de l'image d'un autre canevas dans l'image de cet objet TCanvas. Dest spécifie le rectangle du canevas où l'image source doit être copiée. Le paramètre Canvas spécifie le canevas contenant l'image source. Source spécifie le rectangle délimitant la partie du canevas source à copier.

    La partie du canevas source est copiée en utilisant le mode spécifié par la propriété CopyMode.
    Il me faudrait d'abord copier le fond (ce qu'il y a sous la paintbox) dans une image invisible, puis ajouter le sprite sur cette image invisible, puis enfin afficher l'image (ou la copier) dans la paintbox.
    Moi, je remplacerais simplement cette PaintBox par un TImage de même taille et dont la propriété Transparent est basculée à True ... et hop la transparence laisse voir ce qu'il y a en-dessous.
    (PaintBox n'a pas cette propriété, et je n'ai toujours par compris l'intérêt d'un PaintBox, puisqu'on fait mieux et plus avec un TImage)

    A+.

    EDIT : L'idée de Basile est bonne à prendre vu que les Pacman[i] ont tous la même taille.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  10. #10
    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
    pourquoi ne pas tout dessiner dans un bitmap plutôt que de faire bouger des objets???

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 130
    Points : 46
    Points
    46
    Par défaut
    Voilà où j'en suis, je partage le code avec ceux que ça intéresse.
    La map s'affiche correctement, j'ai ajouté un ttimer à 10ms qui déplace le pacman de gauche à droite sur la map.
    L'intérêt est que le déplacement du personnage est fluide et sans scintillement ET sans utilisation de la formule magique doubleBuffered:=True qui résout le problème de scintillement au prix de la vitesse d'exécution qui est pourtant cruciale dans ce genre de logiciel...

    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
    unit Main;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ImgList, ExtCtrls;
     
    type
      TForm1 = class(TForm)
        Timer1: TTimer;
        procedure FormCreate(Sender: TObject);
        procedure FormPaint(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        { Déclarations privées }
        FFond : TBitmap;
        FDessin: TBitmap;
        sprite:TImage;
        level:Array [1..15] of String;
        tiles:Array [1..500] of TImage;
     
      public
        { Déclarations publiques }
      end;
     
    var Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
      hasard,i, j: Integer;
      Appdir:Variant;
    begin
      sprite:=TImage.Create(nil);
     
      //// MAP DU JEU (les 1 c'est les bords, l'espace vide où on peut circuler)
      ///  le S est le point de départ du PACMAN, les autres lettres des futurs fantômes
      ///  les - sont les endroits où il n'y a pas de pillule.
      level[1]:='11111111111111111111';
      level[2]:='1                  1';
      level[3]:='1 1 111 1111 111 1 1';
      level[4]:='1 1 1   1111   1 1 1';
      level[5]:='1 1 1   1111   1 1 1';
      level[6]:='1 1 1    Y     1 1 1';
      level[7]:='1   11 11T11 111   1';
      level[8]:='1 1    1UG-1     1 1';
      level[9]:='1 1111 111111111 1 1';
     level[10]:='1   1  -----  1    1';
     level[11]:='1 1 1 1-111-1 1  1 1';
     level[12]:='1 1 1 1--S--1 1  1 1';
     level[13]:='1 1 1 1 111 1 1  1 1';
     level[14]:='1                  1';
     level[15]:='11111111111111111111';
     for i := 1 to 300 do //Pour les tiles, créez des images BMP de dimensions 60*60, j'ai pris perso des murs en legos, un peu comme dans pacman arranged de namco
      begin
        tiles[i]:=Timage.Create(nil);
        tiles[i].Width:=60;
        tiles[i].Height:=60;
        tiles[i].Stretch:=True;
      end;
     
      // Le décor, c'est là où on va placer les Tiles (ou la map) du jeu
      FFond := TBitmap.Create;
      FFond.Width := ClientWidth;
      FFond.Height := ClientHeight;
     
      // Dessin hors écran (double buffer)
      FDessin := TBitmap.Create;
     
     
      for j := 1 to 15 do    //15 lignes, 20 colonnes (la map est lisible directement sur le code, ce qui permet avant de lancer le jeu de "voir" ce qu'il va s'afficher à l'écran
        for i := 1 to 20 do
        begin
          if level[j][i]='1' then  //Il existe 4 tiles différentes pour faire les murs, c'est pour faire joli. On pourrait en prendre qu'une...
            begin
                hasard:=random(4);
                if hasard=0 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_1.bmp');
                if hasard=1 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_2.bmp');
                if hasard=2 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_3.bmp');
                if hasard=3 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_4.bmp');
            end;
              if (level[j][i]<>'1') then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilecorridor_1.bmp');
              tiles[j*20-20+i].Left:=i*60-60;
              tiles[j*20-20+i].Top:=j*60-60;
              tiles[j*20-20+i].Visible:=True;
              Form1.FFond.Canvas.Draw(tiles[j*20-20+i].Left,tiles[j*20-20+i].Top,tiles[j*20-20+i].Picture.Bitmap);
            if level[j][i]='S' then
            begin
              Form1.sprite.Picture.LoadFromFile(Appdir+'pacmanleft1.bmp');
              sprite.Left:=i*60-60;
              sprite.Top:=j*60-60;
              sprite.Transparent:=True;
            end;
        end;
    end;
     
    procedure TForm1.FormPaint(Sender: TObject); //Cette procédure met à jour l'affiche à l'écran, il faut cliquer dans l'inspecteur de la Form -> event -> On Paint et ça crée cette procédure
    var i,j:Integer;
    begin
      FDessin.Assign(FFond); // copier le décor dans le dessin hors écran, équivalent à un doublebuffer, mais au moins ça rame pas! (donc c'est beaucoup mieux!)
      Form1.FDessin.Canvas.Draw(sprite.Left,sprite.Top,sprite.Picture.Bitmap); // Ajouter le personnage
      Canvas.Draw(0 , 0, FDessin);// Dessiner le tout à l'écran
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    var i:Integer;
    begin
    for i := 1 to 4 do //Astuce qui permet de faire déplacer le pacman 4 fois plus vite car sous les 10ms, le TTimer ne permet plus d'augmenter la vitesse d'exécution.
      begin
        sprite.Left:=sprite.Left+1;
        InvalidateRect(Handle, nil, False); //Mise à jour des images sur la form, revient à appeler la procedure FormPaint
      end;
    end;
     
    end.

  12. #12
    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
    tu pourrais remplacer ces lignes

    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
     
     for j := 1 to 15 do    //15 lignes, 20 colonnes (la map est lisible directement sur le code, ce qui permet avant de lancer le jeu de "voir" ce qu'il va s'afficher à l'écran
        for i := 1 to 20 do
        begin
          if level[j][i]='1' then  //Il existe 4 tiles différentes pour faire les murs, c'est pour faire joli. On pourrait en prendre qu'une...
            begin
                hasard:=random(4);
                if hasard=0 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_1.bmp');
                if hasard=1 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_2.bmp');
                if hasard=2 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_3.bmp');
                if hasard=3 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_4.bmp');
            end;
              if (level[j][i]<>'1') then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilecorridor_1.bmp');
              tiles[j*20-20+i].Left:=i*60-60;
              tiles[j*20-20+i].Top:=j*60-60;
              tiles[j*20-20+i].Visible:=True;
              Form1.FFond.Canvas.Draw(tiles[j*20-20+i].Left,tiles[j*20-20+i].Top,tiles[j*20-20+i].Picture.Bitmap);
            if level[j][i]='S' then
            begin
              Form1.sprite.Picture.LoadFromFile(Appdir+'pacmanleft1.bmp');
              sprite.Left:=i*60-60;
              sprite.Top:=j*60-60;
              sprite.Transparent:=True;
            end;
        end;
    par :

    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
     
      for j := 1 to 15 do    //15 lignes, 20 colonnes (la map est lisible directement sur le code, ce qui permet avant de lancer le jeu de "voir" ce qu'il va s'afficher à l'écran
        for i := 1 to 20 do
        begin
          With tiles[j*20-20+i] do
          begin
            if level[j][i]='1' then  //Il existe 4 tiles différentes pour faire les murs, c'est pour faire joli. On pourrait en prendre qu'une...
            begin
              hasard:=random(4);
              Picture.LoadFromFile(Appdir+'assets\tilewall_'+inttostr(hasard+1)+'.bmp');
            end else Picture.LoadFromFile(Appdir+'assets\tilecorridor_1.bmp');
     
            Left:=i*60-60; Top:=j*60-60;
            Visible:=True;
            FFond.Canvas.Draw(Left,Top,Picture.Bitmap);
     
            if level[j][i]='S' then
            begin
              sprite.Picture.LoadFromFile(Appdir+'pacmanleft1.bmp');
              sprite.Left:=i*60-60;
              sprite.Top:=j*60-60;
              sprite.Transparent:=True;
            end;
          end;
        end;
    Mais je maintient que ce serait beaucoup plus facile avec un TImageList!

  13. #13
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par Basile le disciple Voir le message
    pourquoi ne pas tout dessiner dans un bitmap plutôt que de faire bouger des objets???
    voilà ce que ça donne
    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
     
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls;
     
    type
      TForm1 = class(TForm)
        Timer1: TTimer;
        procedure FormCreate(Sender: TObject);
        procedure FormPaint(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        { Déclarations privées }
     
        // on ne charge les bitmaps qu'une fois pour toute !
        FTiles : array[0..4] of TBitmap;
        FSprite: TBitmap;
        FPos   : TPoint;
     
        FFond : TBitmap;
        FDessin: TBitmap;
        //sprite:TImage;
        level:Array [1..15] of String;
        //tiles:Array [1..500] of TImage;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
      hasard,i, j: Integer;
      //Appdir:Variant; <- ne sert à rien :)
      tile: Integer;
    begin
      // précharger les Tiles
      for i := 0 to 3 do
      begin
        FTiles[i] := TBitmap.Create;
        FTiles[i].LoadFromFile('assets\tilewall_' + IntToStr(i + 1) + '.bmp');
      end;
      FTiles[4] := TBitmap.Create;
      FTiles[4].LoadFromFile('assets\tilecorridor_1.bmp');
     
      // chargement du pacman
      FSprite := TBitmap.Create;
      FSprite.LoadFromFile('pacmanleft1.bmp');
     
     
     //sprite:=TImage.Create(nil);
     
      //// MAP DU JEU (les 1 c'est les bords, l'espace vide où on peut circuler)
      ///  le S est le point de départ du PACMAN, les autres lettres des futurs fantômes
      ///  les - sont les endroits où il n'y a pas de pillule.
      level[1]:='11111111111111111111';
      level[2]:='1                  1';
      level[3]:='1 1 111 1111 111 1 1';
      level[4]:='1 1 1   1111   1 1 1';
      level[5]:='1 1 1   1111   1 1 1';
      level[6]:='1 1 1    Y     1 1 1';
      level[7]:='1   11 11T11 111   1';
      level[8]:='1 1    1UG-1     1 1';
      level[9]:='1 1111 111111111 1 1';
     level[10]:='1   1  -----  1    1';
     level[11]:='1 1 1 1-111-1 1  1 1';
     level[12]:='1 1 1 1--S--1 1  1 1';
     level[13]:='1 1 1 1 111 1 1  1 1';
     level[14]:='1                  1';
     level[15]:='11111111111111111111';
     
     { ne sert à rien !
     for i := 1 to 300 do //Pour les tiles, créez des images BMP de dimensions 60*60, j'ai pris perso des murs en legos, un peu comme dans pacman arranged de namco
      begin
        tiles[i]:=Timage.Create(nil);
        tiles[i].Width:=60;
        tiles[i].Height:=60;
        tiles[i].Stretch:=True;
      end;
     }
     
      // Le décor, c'est là où on va placer les Tiles (ou la map) du jeu
      FFond := TBitmap.Create;
      FFond.Width := ClientWidth;
      FFond.Height := ClientHeight;
     
      // Dessin hors écran (double buffer)
      FDessin := TBitmap.Create;
     
     
      for j := 1 to 15 do    //15 lignes, 20 colonnes (la map est lisible directement sur le code, ce qui permet avant de lancer le jeu de "voir" ce qu'il va s'afficher à l'écran
        for i := 1 to 20 do
        begin
          if level[j][i]='1' then  //Il existe 4 tiles différentes pour faire les murs, c'est pour faire joli. On pourrait en prendre qu'une...
            begin
                hasard:=random(4);
                {
                if hasard=0 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_1.bmp');
                if hasard=1 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_2.bmp');
                if hasard=2 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_3.bmp');
                if hasard=3 then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_4.bmp');
                }
            end else
              hasard := 4;
              {
              if (level[j][i]<>'1') then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilecorridor_1.bmp');
              tiles[j*20-20+i].Left:=i*60-60;
              tiles[j*20-20+i].Top:=j*60-60;
              tiles[j*20-20+i].Visible:=True;
              Form1.FFond.Canvas.Draw(tiles[j*20-20+i].Left,tiles[j*20-20+i].Top,tiles[j*20-20+i].Picture.Bitmap);
              }
            FFond.Canvas.Draw(i * 60 - 60, j * 60 - 60, FTiles[hasard]);
            if level[j][i]='S' then
            begin
              FPos.x := i * 60 - 60;
              FPos.y := j * 60 - 60;
              {Form1.sprite.Picture.LoadFromFile(Appdir+'pacmanleft1.bmp');
              sprite.Left:=i*60-60;
              sprite.Top:=j*60-60;
              sprite.Transparent:=True;}
              //FFond.Canvas.Draw(i * 60 - 60, j * 60 - 60, FSprite);
            end;
        end;
    end;
     
    procedure TForm1.FormPaint(Sender: TObject);
    begin
      FDessin.Assign(FFond); // copier le décor dans le dessin hors écran, équivalent à un doublebuffer, mais au moins ça rame pas! (donc c'est beaucoup mieux!)
      //Form1.FDessin.Canvas.Draw(sprite.Left,sprite.Top,sprite.Picture.Bitmap); // Ajouter le personnage
     
     
      //FDessin.Canvas.Draw(FPos.X, FPos.Y, FSprite);
     
      // dessiner avec une couleur de transparence (Windows 2000+)
      TransparentBlt(
        FDessin.Canvas.Handle,
        FPos.X, FPos.Y, 60, 60,
        FSprite.Canvas.Handle,
        0, 0, 60, 60,
        FSprite.Canvas.Pixels[0, 0]
      );
     
      Canvas.Draw(0 , 0, FDessin);// Dessiner le tout à l'écran
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    //var i:Integer;
    begin
    {for i := 1 to 4 do //Astuce qui permet de faire déplacer le pacman 4 fois plus vite car sous les 10ms, le TTimer ne permet plus d'augmenter la vitesse d'exécution.
      begin
        sprite.Left:=sprite.Left+1;
      end;
    }
      Inc(FPos.X, 4);
        InvalidateRect(Handle, nil, False); //Mise à jour des images sur la form, revient à appeler la procedure FormPaint
    end;
     
    end.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  14. #14
    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,

    Oups, ça a sacrément évolué depuis hier !!!
    Bonne continuation et meilleurs voeux pour 2014.

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

  15. #15
    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,

    En remplaçant la procedure TForm1.Timer1Timer(Sender: TObject) par la suivante j'obtiens le déplacement du sprite dans le corridor avec changement aléatoire de direction lorsque la configuration du corridor change :

    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
     
    p: set of char; // < Dans private 
    p := [' ', '-'];   // < Dans FormCreate
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    var
      li, co: byte; valse: integer; Dep: ShortString; CDep, CDepPrec: char;
      poNord, poSud, poEst, poOuest: boolean;
     
     
      function DepsPossibles(const L, C: byte): ShortString;
      begin
        Result := '';
        if (level[L - 1][C] in p) then Result := Result + 'N';
        if (level[L + 1][C] in p) then Result := Result + 'S';
        if (level[L][C + 1] in p) then Result := Result + 'E';
        if (level[L][C - 1] in p) then Result := Result + 'O';
      end;
     
      function DepPossVers(const L, C: byte; Vers: char): boolean;
      begin
        Result := false;
        case Vers of
          'N': Result := (level[L - 1][C] in p);
          'S': Result := (level[L + 1][C] in p);
          'E': Result := (level[L][C + 1] in p);
          'O': Result := (level[L][C - 1] in p);
        end;
      end;
     
    begin
      li := 1 + FPos.Y div 60; co := 1 + FPos.X div 60;
      Dep := DepsPossibles(li, co);
      valse := Random(length(Dep));
      CDep := Dep[valse + 1]; CDepPrec := CDep;
      case CDep of
        'N': while DepPossVers(li, co, 'N') do begin
            Dec(li); Dec(FPos.Y, 60);
            Dep := DepsPossibles(li, co);
            valse := Random(length(Dep));
            CDep := Dep[valse + 1]; if CDep <> CDepPrec then break;
          end;
        'S': while DepPossVers(li, co, 'S') do begin
            inc(li); Inc(FPos.Y, 60);
            Dep := DepsPossibles(li, co);
            valse := Random(length(Dep));
            CDep := Dep[valse + 1]; if CDep <> CDepPrec then break;
          end;
        'E': while DepPossVers(li, co, 'E') do begin
            inc(co); Inc(FPos.X, 60);
            Dep := DepsPossibles(li, co);
            valse := Random(length(Dep));
            CDep := Dep[valse + 1]; if CDep <> CDepPrec then break;
          end;
        'O': while DepPossVers(li, co, 'O') do begin
            Dec(co); Dec(FPos.X, 60);
            Dep := DepsPossibles(li, co);
            valse := Random(length(Dep));
            CDep := Dep[valse + 1]; if CDep <> CDepPrec then break;
          end;
      end;
      InvalidateRect(Handle, nil, False); //Mise à jour des images sur la form, revient à appeler la procedure FormPaint
    end;
    Les mouvements sont assez rigolos et ressemblent à une "valse hésitation".
    C'est quoi les règles du code de la route pour circuler dans le corridor, mise à part l'interdiction de traverser les murs ???

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

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 130
    Points : 46
    Points
    46
    Par défaut
    Les progrès du jour :
    J'ai remplacé les images du pacman par une Imagelist dimensionnée en 60*60 pour chaque image.
    Les images du pacman sont chargées dans le sprite pacman à intervalles réguliers (un TTimer chargé de l'animation du pacman à 100ms).
    Plus fort, j'ai réussi à faire déplacer mon pacman de façon hyperfluide sans qu'il franchisse les murs avec les flèches du clavier, et le tout avec une variable tampon qui garde en mémoire la dernière direction vers laquelle le joueur veut aller (comme sur le vrai pacman). Pour détecter la position du pacman et la possibilité d'aller vers le haut/droite/gauche/bas, j'ai utilisé les fonctions mathématiques d'arrondis (ceil, trunc...). Dès que les coordonnées x,y du pacman sont = aux coordonnées arrondies, ça veut dire que le pacman se trouve au centre d'une case (ou tile), donc l'autorisation de changer de direction devient possible.
    Voilà le code source :
    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
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    unit Main;
     
    interface
     
    uses
      Math,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ImgList, ExtCtrls;
     
    type
      TForm1 = class(TForm)
        Timer1: TTimer;
        Timer2: TTimer;
        ImageList1: TImageList;
        procedure FormCreate(Sender: TObject);
        procedure FormPaint(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
        procedure Timer2Timer(Sender: TObject);
      private
        { Déclarations privées }
        FFond : TBitmap;
        FDessin: TBitmap;
        sprite:TImage;
     
      public
        { Déclarations publiques }
      end;
     
    var Form1: TForm1;
        level:Array [1..15] of String;
        tiles:Array [1..500] of TImage;
     
        wish_direction,une_action:String;
        anim:Integer;
     
    implementation
     
    {$R *.dfm}
    function deplacement_joueur():Boolean;
    var n,x,y:Integer;
        xx,yy:Double;
    begin
      x:=Round(Form1.sprite.Left/60)+1;
      y:=Round(Form1.sprite.Top/60)+1;
      xx:=Form1.sprite.Left/60+1;
      yy:=Form1.sprite.Top/60+1;
      if une_action='' then une_action:=wish_direction;
      if (x=xx) and (y=yy) then
      begin
        if (wish_direction='left') and (une_action<>'left') then if (level[y][x-1]<>'1') then une_action:='left';
        if (wish_direction='right') and (une_action<>'right') then if (level[y][x+1]<>'1') then une_action:='right';
        if (wish_direction='up') and (une_action<>'up') then if (level[y-1][x]<>'1') then une_action:='up';
        if (wish_direction='down') and (une_action<>'down') then if (level[y+1][x]<>'1') then une_action:='down';
      end;
     
      x:=Ceil(Form1.sprite.Left/60)+1;
      if (une_action='left') then if (level[y][x-1]<>'1') then
        begin
          for n := 1 to 4 do
          begin
            if anim>=4 then anim:=0;
            if anim=0 then Form1.ImageList1.GetBitmap (anim, Form1.sprite.Picture.Bitmap);
            if anim=1 then Form1.ImageList1.GetBitmap (anim, Form1.sprite.Picture.Bitmap);
            if anim=2 then Form1.ImageList1.GetBitmap (anim, Form1.sprite.Picture.Bitmap);
            if anim=3 then Form1.ImageList1.GetBitmap (anim-1, Form1.sprite.Picture.Bitmap);
            Form1.sprite.Left:=Form1.sprite.Left-1; InvalidateRect(Form1.Handle, nil, False);
          end;
          exit;
        end else une_action:='';
      x:=Trunc(Form1.sprite.Left/60)+1;
      if (une_action='right') then if (level[y][x+1]<>'1') then
        begin
          for n := 1 to 4 do
          begin
            if anim>=4 then anim:=0;
            if anim=0 then Form1.ImageList1.GetBitmap (3, Form1.sprite.Picture.Bitmap);
            if anim=1 then Form1.ImageList1.GetBitmap (4, Form1.sprite.Picture.Bitmap);
            if anim=2 then Form1.ImageList1.GetBitmap (5, Form1.sprite.Picture.Bitmap);
            if anim=3 then Form1.ImageList1.GetBitmap (4, Form1.sprite.Picture.Bitmap);
            Form1.sprite.Left:=Form1.sprite.Left+1; InvalidateRect(Form1.Handle, nil, False);
          end;
          exit;
        end else une_action:='';
      y:=Ceil(Form1.sprite.Top/60)+1;
      if (une_action='up') then if (level[y-1][x]<>'1') then
        begin
          for n := 1 to 4 do
          begin
            if anim>=4 then anim:=0;
            if anim=0 then Form1.ImageList1.GetBitmap (anim, Form1.sprite.Picture.Bitmap);
            if anim=1 then Form1.ImageList1.GetBitmap (anim, Form1.sprite.Picture.Bitmap);
            if anim=2 then Form1.ImageList1.GetBitmap (anim, Form1.sprite.Picture.Bitmap);
            if anim=3 then Form1.ImageList1.GetBitmap (anim-1, Form1.sprite.Picture.Bitmap);
            Form1.sprite.Top:=Form1.sprite.Top-1; InvalidateRect(Form1.Handle, nil, False);
          end;
          exit;
        end else une_action:='';
      y:=Trunc(Form1.sprite.Top/60)+1;
      if (une_action='down') then if (level[y+1][x]<>'1') then
        begin
          for n := 1 to 4 do
          begin
            if anim>=4 then anim:=0;
            if anim=0 then Form1.ImageList1.GetBitmap (3, Form1.sprite.Picture.Bitmap);
            if anim=1 then Form1.ImageList1.GetBitmap (4, Form1.sprite.Picture.Bitmap);
            if anim=2 then Form1.ImageList1.GetBitmap (5, Form1.sprite.Picture.Bitmap);
            if anim=3 then Form1.ImageList1.GetBitmap (4, Form1.sprite.Picture.Bitmap);
            Form1.sprite.Top:=Form1.sprite.Top+1; InvalidateRect(Form1.Handle, nil, False);
          end;
          exit;
        end else une_action:='';
       une_action:=wish_direction;
     
      une_action:=wish_direction;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
      hasard,i, j: Integer;
      Appdir:Variant;
    begin
      sprite:=TImage.Create(nil);
     
      //// MAP DU JEU (les 1 c'est les bords, l'espace vide où on peut circuler)
      ///  le S est le point de départ du PACMAN, les autres lettres des futurs fantômes
      ///  les - sont les endroits où il n'y a pas de pillule.
      level[1]:='11111111111111111111';
      level[2]:='1                  1';
      level[3]:='1 1 111 1111 111 1 1';
      level[4]:='1 1 1   1111   1 1 1';
      level[5]:='1 1 1   1111   1 1 1';
      level[6]:='1 1 1    Y     1 1 1';
      level[7]:='1   11 11T11 111   1';
      level[8]:='1 1    1UG-1     1 1';
      level[9]:='1 1111 111111111 1 1';
     level[10]:='1   1  -----  1    1';
     level[11]:='1 1 1 1-111-1 1  1 1';
     level[12]:='1 1 1 1--S--1 1  1 1';
     level[13]:='1 1 1 1 111 1 1  1 1';
     level[14]:='1                  1';
     level[15]:='11111111111111111111';
     for i := 1 to 300 do //Pour les tiles, créez des images BMP de dimensions 60*60, j'ai pris perso des murs en legos, un peu comme dans pacman arranged de namco
      begin
        tiles[i]:=Timage.Create(nil);
        tiles[i].Width:=60;
        tiles[i].Height:=60;
        tiles[i].Stretch:=True;
      end;
     
      // Le décor, c'est là où on va placer les Tiles (ou la map) du jeu
      FFond := TBitmap.Create;
      FFond.Width := ClientWidth;
      FFond.Height := ClientHeight;
     
      // Dessin hors écran (double buffer)
      FDessin := TBitmap.Create;
     
     
      for j := 1 to 15 do    //15 lignes, 20 colonnes (la map est lisible directement sur le code, ce qui permet avant de lancer le jeu de "voir" ce qu'il va s'afficher à l'écran
        for i := 1 to 20 do
        begin
          if level[j][i]='1' then  //Il existe 4 tiles différentes pour faire les murs, c'est pour faire joli. On pourrait en prendre qu'une...
            begin
                hasard:=random(4);
                tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilewall_'+IntToStr(hasard+1)+'.bmp');
            end;
              if (level[j][i]<>'1') then tiles[j*20-20+i].Picture.LoadFromFile(Appdir+'assets\tilecorridor_1.bmp');
              tiles[j*20-20+i].Left:=i*60-60;
              tiles[j*20-20+i].Top:=j*60-60;
              tiles[j*20-20+i].Visible:=True;
              Form1.FFond.Canvas.Draw(tiles[j*20-20+i].Left,tiles[j*20-20+i].Top,tiles[j*20-20+i].Picture.Bitmap);
            if level[j][i]='S' then
            begin
              Form1.sprite.Picture.LoadFromFile(Appdir+'pacmanleft1.bmp');
              sprite.Left:=i*60-60;
              sprite.Top:=j*60-60;
              sprite.Transparent:=True;
            end;
        end;
    end;
     
    procedure TForm1.FormPaint(Sender: TObject); //Cette procédure met à jour l'affiche à l'écran, il faut cliquer dans l'inspecteur de la Form -> event -> On Paint et ça crée cette procédure
    var i,j:Integer;
    begin
      FDessin.Assign(FFond); // copier le décor dans le dessin hors écran, équivalent à un doublebuffer, mais au moins ça rame pas! (donc c'est beaucoup mieux!)
      Form1.FDessin.Canvas.Draw(sprite.Left,sprite.Top,sprite.Picture.Bitmap); // Ajouter le personnage sur le dessin hors écran
      Canvas.Draw(0 , 0, FDessin);// Dessiner le tout à l'écran (transfère le dessin hors écran sur la form aux coordonnées 0,0
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    var i:Integer;
    begin
      if GetKeyState(VK_RIGHT) and $80=$80 then begin wish_direction:='right';  if une_action='left' then une_action:='right'; end;
      if GetKeyState(VK_LEFT) and $80=$80 then begin wish_direction:='left';  if une_action='right' then une_action:='left';  end;
      if GetKeyState(VK_UP) and $80=$80 then begin wish_direction:='up';  if une_action='down' then une_action:='up';  end;
      if GetKeyState(VK_DOWN) and $80=$80 then begin wish_direction:='down';  if une_action='up' then une_action:='down';  end;
     
      deplacement_joueur();
    end;
     
    procedure TForm1.Timer2Timer(Sender: TObject);
    begin
      anim:=anim+1;
    end;
     
    end.

  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
    Bonjour,

    Sys1 : J'ai remplacé les images du pacman par une Imagelist dimensionnée en 60*60 pour chaque image.
    ... Oups, pas toutes, pourquoi donc tous ces Picture.LoadFromFile(Appdir+'assets\...) ???
    Plus fort, j'ai réussi à faire déplacer mon pacman de façon hyperfluide sans qu'il franchisse les murs avec les flèches du clavier, ...
    Cela c'est déjà mieux, par contre en testant le code, vu d'une part la vitesse de déplacement du sprite, et d'autre part la faible distance qui sépare les carrefours les plus rapprochés cela demande à l'utilisateur d'être hyper-rapide sinon il loupe le virage en supposant en plus qu'il ne se trompe pas de touche-clavier dans la précipitation.
    Mais ceci pourrait être amélioré en utilisant la touche de la Souris au lieu des 4 touches-clavier pour les changements de direction :
    - au MouseDown dans une allée perpendiculaire à celle où le sprite se déplace on mémorise les coordonnées du MousDown,
    - l'intersection de ces deux perpendiculaires donne la position PC du carrefour où il demandé de changer de direction,
    - et si le sprite se trouve alors dans une allée horizontale, c'est le signe du DeltaY = Y(MouseDown) - Y(Sprite) qui dira s'il faut aller vers le haut ou le bas au carrefour en question,
    - sinon c'est le signe du DeltaX qui dira s'il faut aller vers la gauche ou la droite au carrefour.

    En prime ça donne à l'utilisateur une longueur d'avance puisqu'il n'a pas à cliquer sur le carrefour dont la position PC est obtenue par l'intersection des perpendiculaires ... donc il gagnera 50% d'apuis-touches par rapport à la solution actuelle.

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

  18. #18
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 130
    Points : 46
    Points
    46
    Par défaut
    Oups, pas toutes, pourquoi donc tous ces Picture.LoadFromFile(Appdir+'assets\...) ???
    Les LoadFromFile ne correspondent pas aux phases d'animations du sprite de pacman mais au tiles composant le niveau. Bien sûr, ces tiles peuvent être elles-même présentes dans une imagelist distincte (par souci de clarté)
    J'utiliserai une autre imagelist pour les fantômes.

    Concernant le déplacement du pacman, il faut en effet être très rapide, mais dans la mesure où je joue beaucoup aux jeux vidéo, ça ne m'a pas posé de problème. Cependant, je souhaiterais plus tard que le contrôle se fasse avec une manette, bien plus naturel et efficace...

  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,

    OK, vu. Par contre moi je ne joue pas beaucoup aux jeux vidéo. Mais ce qui m'intéresse c'est plutôt la résolution des problèmes rencontrés lors de leur réalisation ... En comparaison, jouer c'est vite lassant voire ennuyeux.
    Par contre une fois le logiciel terminé ce serait sympa de placer ici le Zip de son code histoire de voir comment les problèmes ont été résolus.

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

Discussions similaires

  1. Charger un canvas dans un panel de ma fenetre
    Par zarohn dans le forum AWT/Swing
    Réponses: 3
    Dernier message: 18/11/2010, 15h43
  2. mettre des panels ou des lables dans un canvas
    Par mehdiing dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 17/04/2008, 18h20
  3. question sur le canvas d'un panel?
    Par Mickey.jet dans le forum Delphi
    Réponses: 16
    Dernier message: 29/09/2006, 22h55
  4. PaintBox et canvas
    Par eln_francois dans le forum Composants VCL
    Réponses: 3
    Dernier message: 14/10/2005, 09h49
  5. Comment acceder au Canvas d'un Panel
    Par meli0207 dans le forum C++Builder
    Réponses: 3
    Dernier message: 13/02/2005, 15h36

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