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 :

Comment faire un 'gameloop' dans delphi + VCL


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 45
    Par défaut Comment faire un 'gameloop' dans delphi + VCL
    Bonjour a tous,

    J'aimerai savoir comment faire un 'gameloop' rapide et efficace pour des jeux avec Directx ?

    Tout les livres de programmation des jeux Directx ou opengl sont ecrit pour le c++, le code en lui-meme peut-etre traduit ou adapter en Delphi mais le coeur de tout programme de jeu, le gameloop, est tres complique a realiser avec Delphi.
    Delphi ne possede aucun systeme pour cree une boucle 'temps reel' a ma connaissance sous Delphi-VCL

    Ma version source du livre est la suivante (c++):

    Code C++ : 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
    GameInit();                                                // Perform all game console specific initialization
     
    while(1)                                                   // Enter main event loop
    {if (PeekMessage(&WindowsMessage,NULL,0,0,PM_REMOVE))
        {if (WindowsMessage.message == WM_QUIT)                // Test if this is a quit
            break;
        TranslateMessage(&WindowsMessage);                     // Translate any accelerator keys
        DispatchMessage(&WindowsMessage);                      // Send the message to the window proc
       }                       
     GameMain();    // main game processing goes here
    } 
     
    GameShutDown();                                            // Shutdown game and release all resources
     
    return(WindowsMessage.wParam);                             // Return to Windows like this
    }                                                          // End WinMain
     
    // WinX Game Programming Console Functions ---------------------------------------------------
    int GameInit(void *Params)
    {
    // This function is where you do all the initialization for your game.
    //
    // Your code goes here
    //
    return(1);                                                 // Return success
     
    } // end GameInit
     
    //--------------------------------------------------------------------------------------------
    int GameShutDown(void *Params)
    {
    // This function is where you shutdown your game and release all resources that you allocated.
    //
    // Your code goes here
    //
    return(1);                                                 // Return success
    //
    } // End GameShutdown
     
    //--------------------------------------------------------------------------------------------
    int GameMain(void *Params)
    {
    // This is the workhorse of your game it will be called continuously in real-time,
    // this is like main() in C, all the calls for you game go here!
    //
    // Your code goes here
    //
    return(1);                                                 // Return success
    //
    } // End GameMain

    Je n'ai recopier ici que la partie interessante pour la boucle du gameloop

    Pourriez vous m'aidez a creer un code similaire avec Delphi-VCL ?
    Je sais comment la faire en Delphi POO (sans la VCL si vous preferer) mais moi j'ai besoin de connaitre comment la faire sous VCL

    J(ai effectuer de longue et infructueuse recherche sur internet et gamedev.com mais sans resultat.

    Comment vous faite vous, dans vos jeux ?

  2. #2
    Membre Expert
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Par défaut
    personnellement je fait comme ça :

    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
    program FASTWINDOW;
     
    uses
      Windows,
      Messages,
      SysUtils;
     
     
    function WndProc(Wnd : HWND; message : UINT; wParam : Integer; lParam: Integer) : Integer; stdcall;
    var
      Handle: HDC;
      ps    : PAINTSTRUCT;
    begin
      case message of
        WM_PAINT:
          begin
            Handle := BeginPaint(Wnd, ps);
            // paint start code : Handle = HDC
     
            // paint end code
            EndPaint(Wnd, ps);
            result := 0;
          end;
     
     
        // others message
     
     
        WM_DESTROY:
          begin
            PostQuitMessage(0);
            result := 0;
          end;
     
       else
          result := DefWindowProc(Wnd, message, wParam, lParam);
       end;
    end;
     
    var
      hWnd     : THandle;
      Msg      : TMsg;
      wndClass : TWndClass;
    begin
      wndClass.style          := CS_HREDRAW or CS_VREDRAW;
      wndClass.lpfnWndProc    := @WndProc;
      wndClass.cbClsExtra     := 0;
      wndClass.cbWndExtra     := 0;
      wndClass.hInstance      := hInstance;
      wndClass.hIcon          := LoadIcon(0, IDI_APPLICATION);
      wndClass.hCursor        := LoadCursor(0, IDC_ARROW);
      wndClass.hbrBackground  := HBRUSH(GetStockObject(WHITE_BRUSH));
      wndClass.lpszMenuName   := nil;
      wndClass.lpszClassName  := 'FastWin';
     
      RegisterClass(wndClass);
     
      hWnd := CreateWindow(
        'FastWin',     
        'Title caption',
        WS_OVERLAPPEDWINDOW, 
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, Instance, nil);        
     
      ShowWindow(hWnd, SW_SHOW);
      UpdateWindow(hWnd);
     
      while GetMessage(msg, 0, 0, 0) do
      begin
        TranslateMessage(msg);
        DispatchMessage(msg);
      end;
    end.
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    bonsoir,

    ce qui s'en approche le plus dans la VCL c'est TApplication.OnIdle

    mais tu peux très bien placer la boucle dont tu parles dans une méthode de la fiche principale...

    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
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
      Msg: TMsg;
    begin
      repeat
         Show;
        if PeekMessage(Msg,0,0,0,PM_REMOVE) then
        begin
          if Msg.message = WM_QUIT then                // Test if this is a quit
            Break;
          TranslateMessage(Msg);                     // Translate any accelerator keys
          DispatchMessage(Msg);                      // Send the message to the window proc
        end;
        //gameloop
      until Application.Terminated;
      Halt;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Application.Terminate;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 45
    Par défaut
    Merci de ta reponse Dr.Who

    Mais ca, je connait pour l'avoir utiliser longtemps, il y a quelques annees, lors de mes programmation en pure 'windows, et lors de mes traductions des demos de jeux de directx7 en c++ vers Delphi POO.
    D'ailleurs voici un squelette de base que j'utilisai alors, tres similaire au tiens.

    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
    program Project1;
     
    { Standard Windows API application written in Object Pascal. 
    No VCL code included. This is all done on the Windows API level. 
    Note that you need to include both Windows and Messages!} 
     
    uses Windows,
      Messages; 
     
    const AppName = 'Window1'; 
     
    function WindowProc(Window: HWnd; AMessage, WParam, 
    LParam: Longint): Longint; stdcall; export;
     
    begin 
       WindowProc := 0; 
       case AMessage of wm_Destroy:
       begin
          PostQuitMessage(0);
          Exit;
       end;
    end;
     
    WindowProc := DefWindowProc(Window, AMessage, WParam, LParam);
    end;
     
    { Register the Window Class }
    function WinRegister: Boolean;
    var WindowClass: TWndClass;
     
    begin
       WindowClass.Style := cs_hRedraw or cs_vRedraw;
       WindowClass.lpfnWndProc := @WindowProc;
       WindowClass.cbClsExtra := 0;
       WindowClass.cbWndExtra := 0;
       WindowClass.hInstance := HInstance;
       WindowClass.hIcon := LoadIcon(0, idi_Application);
       WindowClass.hCursor := LoadCursor(0, idc_Arrow);
       WindowClass.hbrBackground := HBrush(Color_Window);
       WindowClass.lpszMenuName := nil;
       WindowClass.lpszClassName := AppName;
       Result := RegisterClass(WindowClass) <> 0;
    end;
     
    { Create the Window Class }
    function WinCreate: HWnd;
    var hWindow: HWnd;
     
    begin
       hWindow := CreateWindow(AppName, 'Object Pascal Window',
       ws_OverlappedWindow, cw_UseDefault, cw_UseDefault,
       cw_UseDefault, cw_UseDefault, 0, 0, HInstance, nil);
       if hWindow <> 0 then
       begin
          ShowWindow(hWindow, CmdShow);
          UpdateWindow(hWindow);
       end;
       Result := hWindow;
    end;
     
    var AMessage: TMsg;
    hWindow: HWnd;
    begin
       if not WinRegister then
       begin
          MessageBox(0, 'Register failed', nil, mb_Ok);
          Exit;
       end;
     
       hWindow := WinCreate;
       if hWindow = 0 then
       begin
          MessageBox(0, 'WinCreate failed', nil, mb_Ok);
          Exit;
       end;
     
       while GetMessage(AMessage, 0, 0, 0) do
       begin
          TranslateMessage(AMessage);
          DispatchMessage(AMessage);
       end;
     
       Halt(AMessage.wParam);
    end.
    Je connait la programmation en turbo-pascal pour l'avoir longtemps pratiquer, ainsi que le Delphi POO. mais j'utilise de plus en plus Delphi-VCL.
    J'ai abandonnee le c++ a cause de son incompatibilite entre compilateurs, son manque de rigueur et de clarete du code, ainsi que des valeurs/taille possibbles donnee au variables (byte/shorts, double,...) qui peuvent changer dans un meme compilateur grace a quelques headers.
    Examine le code source d'allegro pour voir la totale incomprehensible et impossible a traduire en Delphi

    Ce dont j'ai besoin, c'est un gameloop pour creer des jeux sous directx avec l'utilisation de la VCL dont j'aurai besoin plus tard pour un autre projet de jeu necessitant une interface GUI importante (jeu de strategie) ainsi que de ses outils.

    Mais malgree mes recherche sur internet, dans la doc Delphi, et le livre "Delphi 7 studio", je n'ai pas trouve la reponse

    Merci Paul TOTH,
    Je connaissais OnIddle.
    Et dans ton livre, je n'avait trouver aucune explication pour des boucles en temps reel.

    Dans ta solution, est-ce que la boucle sera-t-elle suffisament rapide et reguliere pour creer des animation de sprites en temps reel ?

    Dans ton exemple de code, un peu equivalent a celle utilisee pour les programmes windows 'pure' sans VCL, ce code ne va t-il pas remplacer le traitement des messages windows et VCL de Delphi (cachee et inaccessible) par celui-ci rendant la VCL instable ou buggee ?
    Est-ce que je peut la placer dans une autre unite/form que la TForm1 ou bien il est obligatoire d'utiliser la TForm1 ?
    Est-ce que je vais obtenir une vitesse equivalente a celle de la version c++ windows pure ?

    Merci de ton aide et bravo pour ton livre qui est SUPER BIEN FAIT

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    le seul pb quand tu invoques Application.ProcessMessages en boucle c'est que ton code est bloqué...ainsi TForm1.OnCreate ne se termine jamais, donc tout ce qui se passe après n'est pas exécuté (si le .DPR crée un autre fiche par exemple)...et si tu ne termines pas la procédure par un Halt, tout ce code ignoré jusqu'alors s'exécutera justement et notamment le Application.Run. Du coup l'application est relancée

    donc ceci mis à part, il n'y a pas de différence entre ce traitement et celui de la VCL car Application.ProcessMessages fait exactement la même chose (PeekMessage, Translate...) rien de plus ! Le lien avec la VCL se fait par les WndProc (comme expliqué dans LE livre )

    Il serait d'ailleurs peut-être plus propre de remplacer le Application.Run du .DPR par une boucle sur Application.HandleMessage (car ProcessMessage est privé)...mais attention, si OnIdle est à nil ou qu'il retourne Done ) True, alors tu tombes sur un WaitMessage.

    Question performances, je ne pense pas que la différence soit sensible sur ce point en particulier...mais après tout dépend du code de ta gameloop justement

    J'utilise parfois une autre approche qui est d'invalider ma fiche lors du Paint...du coup WM_PAINT est appelé en boucle (parmi les autres messages)
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 115
    Par défaut
    Pourquoi ne pas redéfinir un objet TApplication, dans le dpr au lieu de mettre Forms dans les uses, voir ce sujet ou ce sujet, toute l'idée vient du TServiceApplication ou du TISAPIApplication

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    program Jeu;
     
    uses
      DirectXApp,
     
    {$R *.res}
     
    begin
      Application.Initialize; // l'objet Application est un TDirectXApplication qui hérite de TApplication mais ayant déclaré sa propre Run ...
      Application.CreateForm(TMainForm, MainForm);
      Application.Run;
    end.
    Avec OnPaint ou OnIdle, il y a un moyen avec un Thread et un Pool de Buffer de faire une belle Uzine a Gaz, bien fun à coder mais pas forcément plus efficace que les méthodes déjà proposées par Paul Toth ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/11/2013, 23h03
  2. PB avec multi frames - comment faire une multiframe dans URL
    Par guillaumeIOB dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 08/11/2005, 14h34
  3. Comment faire un chronomètre en Delphi ou ASM ?
    Par PoOky dans le forum Langage
    Réponses: 8
    Dernier message: 15/06/2005, 20h49
  4. Comment faire une insertion dans un fichier texte ?
    Par Isa31 dans le forum Langage
    Réponses: 10
    Dernier message: 28/12/2004, 09h06

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