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

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Création d'un jeu en 3D avec Delphi et FireMonkey
Un tutoriel de Grégory Bersegeay

Le , par Alcatîz

60PARTAGES

8  0 
Apprendre à créer un jeu en 3D avec Delphi et FireMonkey
Un projet compilable pour Windows, Mac OS X, Android et iOS, réalisé avec Delphi 10 Seattle

À l'occasion de sa première approche du développement avec FireMonkey, le framework multiplate-forme de Delphi, Grégory Bersegeay a décidé de reprendre un jeu vidéo mythique : Pong. Cela nous permet de voir des rudiments de 3D et d'intelligence artificielle, le tout dans un projet relativement simple d'environ 420 lignes de code.


Les étapes les plus importantes de la création du projet sont détaillées. Sans toucher au code mais simplement en recompilant, nous pourrons faire tourner l'application sous Windows et OS X. Si l'on dispose du plugin Mobile ou d'une version Enterprise de Delphi, on peut le compiler aussi pour iOS et Android.

http://gbegreg.developpez.com/tutori...eation-jeu-3d/

Et vous ?
Que pensez-vous de ce tutoriel ?
Avez-vous déjà testé Delphi XE ?
Connaissez-vous le framework FireMonkey ?

Retrouvez les meilleurs cours et tutoriels pour apprendre la programmation Delphi
Retrouvez les meilleurs cours et tutoriels pour apprendre la programmation des jeux

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de gbegreg
Membre expert https://www.developpez.com
Le 30/10/2016 à 0:39
Bonsoir,

Je vous remercie et je suis flatté de vos retours positifs sur le tutoriel. J'ai uploadé une autre version des sources : la raquette du joueur peut évoluer dans une zone (avant/arrière (axe Y) en plus du droite/gauche (axe X) déjà implémenté). Vous pouvez télécharger cette nouvelle version à cette adresse :
http://gbegreg.developpez.com/tutoriels/delphi/firemonkey/Pong3D/src/FMXPongBis_src.zip

A noter : il ne sera toutefois pas possible de donner plus de vitesse au palet ou de faire des amorties

Techniquement, j'ai ajouté :
    un TPLane pour matérialiser la limite de la zone dans laquelle la raquette du joueur peut évoluer. J'ai associé à ce TPlane un nouveau TLightMaterialSource avec une couleur "Diffuse" Chocolate (pour rester dans le ton de la table de jeu). Le TPlane est cloné (tout comme la raquette) dans la procédure initialiserPlateau afin de matérialiser la zone de jeu de l'adversaire. Attention, l'IA n'est pas modifiée et la raquette gérée par l'ordinateur se déplacera toujours uniquement sur l'axe X).

    Dans l'événement OnMouseDown de la raquette du joueur, lors de la récupération de la position de la raquette, on prend en compte en plus la position sur l'axe Y (Point3D(1,0,0) remplacé par Point3D(1,1,0))

    Dans l'événement OnMouseMove de la raquette du joueur, même chose que précédemment, on prend en compte en plus la position sur l'axe Y (Point3D(1,0,0) remplacé par Point3D(1,1,0)) et on ajoute les contrôles de la nouvelle position par rapport à la limite de zone qui s'étend maintenant aussi sur l'axe Y :
    Code : Sélectionner tout
    1
    2
    3
    if Point.y > 19 then Point := Point3D(point.x,19,point.z);
    if Point.y < 12 then Point := Point3D(point.x,12,point.z);

    Enfin, dans l'événement OnMouseUp, on repositionnait la raquette au centre sur l'axe X et bien là, en plus, on la remet à sa position initiale sur l'axe Y :
    Code : Sélectionner tout
    raquetteJoueur.AnimateFloat('Position.Y',19);

Avec ces petites modifications, le jeu ressemble un peu plus à un jeu auquel j'ai joué enfant sur Atari ST : Shufflepuck Cafe... nostalgie Ça me donne peut être une idée pour un prochain tutoriel : un petit jeu de type "The Light Corridor" (qui était aussi sur ST et Amiga si ça parle à certains...).

Je n'ai pas eu l'occasion encore d'utiliser les fonctionnalités de "Tethering". Est ce que ces dernières permettraient d'ajouter la possibilité de jouer à deux humains sur deux machines distinctes (PC/PC, PC/Mac, PC/Android...) ? Je pense que ça pourrait être un bon complément au tutoriel...
4  0 
Avatar de gbegreg
Membre expert https://www.developpez.com
Le 13/02/2017 à 8:22
Bonjour,

Pour celles et ceux qui souhaiteraient tester ce que donne le jeu sous Android et qui ne disposent pas de la partie mobile de Delphi, je viens de le mettre sur le Play Store de Google : https://play.google.com/store/apps/details?id=fr.gbesoft.FMXPong.

Le jeu ne nécessite aucune autorisation, aucune donnée n'est collectée, il est gratuit et sans pub
3  0 
Avatar de gvasseur58
Responsable Lazarus & Pascal https://www.developpez.com
Le 27/10/2016 à 10:59
Merci pour ce tutoriel bien fait et instructif qui rend un grand service à la communauté .

J'espère qu'il incitera d'autres à écrire pour FMX, car ce framework puissant manque de tutoriels adaptés aux débutants, surtout dans le domaine de la 3D.
Ce bravo s'accompagne par conséquent d'une invitation pressante aux contributeurs...
Encore merci .
2  0 
Avatar de ShaiLeTroll
Expert éminent sénior https://www.developpez.com
Le 27/10/2016 à 11:10
Intéressant !
Merci pour ce Tutoriel !

Sinon
Sur Delphi 10.1 Berlin Version 24.0.22858.6822 (la version gratuite), tout est rouge, pourtant, dans l'inspecteur on voit bien White, Aquamarine, Coral
Sur Delphi XE7, cela provoque des erreurs à l'ouverture, mais tout est rouge aussi

En fait, en supprimant, les "Materiel" c'est les TCube qui sont Rouge pourtant pas de trace de propriété Color
La texture est appliqué malgré le tout Rouge
J'ai ajouté d'autres TCube, TSpehre, ils sont Rouge par défaut et ignore les "Materiel" que l'on peut leur affecter
Dans XFM, je n'ai rien trouvé pouvant mettre du Rouge

Suffit de modifier "Lumiere" de Directional en Point pour que tout soit Vert et en Spot pour que tout soit Bleu !
2  0 
Avatar de Cirec
Membre éprouvé https://www.developpez.com
Le 28/10/2016 à 15:25
Bonjour à tous,

j'ai téléchargé et compilé le projet sous Delphi Berlin 10.1 Starter ...
le tout sans aucun soucis de couleur ou autre problème décrit par ShaiLeTroll.
le jeux fonctionne bien ... Merci à l'auteur pour cet excellent exemple

Matériel: Windows Seven 32-Bit avec un vieux AMD 64 3800+ 2.40 GHz et une GeForce GT 230 !!!
2  0 
Avatar de Thierry Laborde
Membre émérite https://www.developpez.com
Le 07/12/2016 à 10:35
Bonjour,

Avez-vous fait le test avec :

Code : Sélectionner tout
FMX.Types.GlobalUseGPUCanvas:= True;
ATTENTION, cette variable (Comme le GlobalUseDXSoftware d'ailleurs) est à mettre à jour dans le source du projet avant le : Application.Initialize
2  0 
Avatar de Paul TOTH
Expert éminent sénior https://www.developpez.com
Le 07/12/2016 à 11:04
Bonjour,

Rien à voir avec le problème de couleur, mais dans cet exemple, on a 3 objets identiques (ou presque) : base, bordDroit et bordGauche...et bien il est tout à fait possible d'en remplacer deux par un TProxyObject

le projet est facile à modifier pour ce faire:
1) ouvrir le DFM en mode texte (Alt + F12)
2) remplacer TCube par TProxyObject sur les objets bordDroit et bordGauche
3) ouvrir le DFM comme une fiche (Alt + F12)
4) valider les deux erreurs sur la propriété Material inexistante
5) renseigner la propriété SourceObject des deux bords pour pointer sur Base

on obtient exactement le même résultat, mais les deux bords sont dessinés par via l'objet "base" dont les dimensions et la position sont surchargées dynamiquement au moment du rendu.

Bon ok, ça ne va pas révolutionner le projet vu que l'objet de base est des plus simple, mais cette technique est utilisable aussi avec des objets plus complexes (Mesh, Path, Model) qui gagnent à ne pas être copier/coller dans une scène.
2  0 
Avatar de Thierry Laborde
Membre émérite https://www.developpez.com
Le 07/12/2016 à 14:49
Citation Envoyé par chantal04 Voir le message
Du coup questions subsidiaires

Comment puis-je savoir si il faut mettre cette variable à True ?
Sur certains postes l'appli fonctionne très bien sans cette ligne. Si je la mets tout le temps à True, est-ce que cela va dégrader les performances ?
Est ce que des problèmes similaires ont été rencontrés sur d'autre plateformes (Android ou IOS) ?

Chantal
En fait :

Mettre
  • Mettre FMX.Types.GlobalUseDirect2D à False va forcer l'utilisation de GDI+
  • Mettre FMX.Types.GlobalUseDX10Software à True va utiliser L’accélération logiciel (au lieu de Hardware) pour Direct2D (Et Direct3D)
  • Mettre FMX.Types.GlobalUseGPUCanvas à True va forcer l'utilisation du processeur graphique (GPU)


Et en fait selon les choix des Canvas différents seront créés quand on fera du graphisme sur Firemonkey :

  • TCanvasGDIPlus > Unité : FMX.Canvas.GDIP
  • TCanvasD2D > Unité : FMX.Canvas.D2D
  • TCanvasGpu > Unité : FMX.Canvas.GPU


Après si on regarde l'unité FMX.Canvas.D2D et la classe TCustomCanvasD2D on se rend compte qu'on a des propriétés :

  • Direct3DHardware
  • Direct3DSupport
  • Direct3DLevel


Donc je me pencherai là dessus pour en savoir plus sur la config graphique dispo et donc pour déterminer quelles variables mettre à jour ou non.

Attention cela concerne seulement Windows car sur Mac on utilise un Canvas Quartz : TCanvasQuartz, unité : FMX.Canvas.Mac
2  0 
Avatar de Fab4v
Membre à l'essai https://www.developpez.com
Le 08/12/2016 à 14:11
Bonjour à toutes et à tous,

J'ai le même problème que Chantal (normal, on travaille dans le même bureau, et on a la même config )

Après lecture de cet article (Source), on a voulu réécrire/mettre à jour la code présent dans la page avec la dll DX11, puisque c'est maintenant le minimum requis pour Firemonkey.
Les premiers retours de la fonction D3D11CreateDevice étaient bon, que ce soit avec le paramètre D3D_DRIVER_TYPE_HARDWARE ou D3D_DRIVER_TYPE_WARP.
J'avais une seule différence, c'était au niveau du FeatureLevel : celui du Warp était plus élevé qu'en Hardware.

on a donc essayé d'implémenter le code suivant afin de solutionner le problème, par contre, on ne sais pas si c'est vraiment la bonne méthode à appliquer :

Code : Sélectionner tout
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
program FMXPong;

uses
  System.StartUpCopy,
  FMX.Forms,
  FMX.Types,

{$IFDEF MSWINDOWS}
  System.Math,
  Winapi.Windows,
  Winapi.D3D11,
  Winapi.D3DCommon,
  FMX.Context.DX11,
{$ENDIF}

  principale in 'principale.pas' {fPrincipale};

var
  PrevFPUState: TArithmeticExceptionMask;

{$R *.res}

{$IFDEF MSWINDOWS}

// *****************************************************************************
// Copiée de la fonction du même nom dans FMX.Context.DX11. ***

procedure SaveClearFPUState; inline;
begin
  PrevFPUState:= GetExceptionMask;
  SetExceptionMask(exAllArithmeticExceptions);
end;

// *****************************************************************************
// Copiée de la fonction du même nom dans FMX.Context.DX11. ***

procedure RestoreFPUState; inline;
begin
  SetExceptionMask(PrevFPUState);
end;

// *****************************************************************************

procedure TryUseWARPCanvas;
const
  FeatureLevels : array [0 .. 8] of D3D_FEATURE_LEVEL = (
    D3D_FEATURE_LEVEL_12_1,
    D3D_FEATURE_LEVEL_12_0,
    D3D_FEATURE_LEVEL_11_1,
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
    D3D_FEATURE_LEVEL_9_3,
    D3D_FEATURE_LEVEL_9_2,
    D3D_FEATURE_LEVEL_9_1
  );

var
  DX11Library : THandle;
  vResultHardware, vResultWarp: Integer;
  // Variables output de la fonction D3D11CreateDevice. ***
  TestDevice : ID3D11Device;
  LD3DDeviceContext : ID3D11DeviceContext;
  vFeatureLevelHardware, vFeatureLevelWarp: D3D_FEATURE_LEVEL;

begin
  // J'essaye de charger la dll de directX 11. ***
  DX11Library := LoadLibrary(winapi.D3D11.D3D11dll);
  if DX11Library <> 0 then
  begin
    try
      SaveClearFPUState; // copié de la fonction du même nom dans FMX.Context.DX11. ***
      try
        // Est-ce que la procédure "D3D11CreateDevice" est dispo dans la Dll ? ***
        if GetProcAddress(DX11Library, 'D3D11CreateDevice') <> nil then
        begin
          // Test sur le hardware. ***
          vResultHardware := D3D11CreateDevice(
            nil,
            D3D_DRIVER_TYPE_HARDWARE,
            0,
            D3D11_CREATE_DEVICE_BGRA_SUPPORT,
            @FeatureLevels,
            Length(FeatureLevels),
            D3D11_SDK_VERSION,
            TestDevice,
            vFeatureLevelHardware,
            LD3DDeviceContext
          );
          if (Succeeded(vResultHardware)) and (vFeatureLevelHardware < D3D_FEATURE_LEVEL_11_0) then
          begin
            // Test du "high-performance software rasterizer" (cf. msdn "D3D_DRIVER_TYPE enumeration"). ***
            vResultWarp := D3D11CreateDevice(
              nil,
              D3D_DRIVER_TYPE_WARP,
              0,
              D3D11_CREATE_DEVICE_BGRA_SUPPORT,
              @FeatureLevels,
              Length(FeatureLevels),
              D3D11_SDK_VERSION,
              TestDevice,
              vFeatureLevelWarp,
              LD3DDeviceContext
            );
            // Je regarde sur la FeatureLevel est plus élevée en Warp. ***
            if Succeeded(vResultWarp) and (vFeatureLevelWarp >= D3D_FEATURE_LEVEL_11_0) then
            begin
              // C'est le cas, je force le flag "GlobalUseDXSoftware". ***
              GlobalUseDXSoftware := True ;
            end;
          end;
        end;
      finally
        TestDevice := nil;
        RestoreFPUState; // copié de la fonction du même nom dans FMX.Context.DX11. ***
      end;
    finally
      FreeLibrary(DX11Library);
    end;
  end;
end;

// *****************************************************************************

{$ENDIF}

begin

{$IFDEF MSWINDOWS}
  TryUseWARPCanvas;
{$ENDIF}

  Application.Initialize;
  Application.CreateForm(TfPrincipale, fPrincipale);
  Application.Run;
end.
Est-ce qu'on a le droit de faire ça ?

D'avance, un grand merci pour votre aide.
Cordialement.

Edit1:
J'ai modifié le code en testant le FeatureLevel pour le 11.0 (c'est celui qui prend en charge le shader model 5, étant maintenant le minimum requis pour Firemonkey)
Dans mes tests sur ma config, le hardware était en shader model 4 alors que le Warp était en 5.
2  0 
Avatar de gbegreg
Membre expert https://www.developpez.com
Le 27/10/2016 à 11:23
Bonjour ShaiLeTroll,

Le tutoriel a été fait sous Delphi 10 Seattle Pro. Depuis je suis passé à Berlin et tout récemment à l'update 1 de Berlin (toujours la version Pro). Je n'ai pas les erreurs que tu indiques. Il est vrai que je n'ai pas testé avec des versions antérieures de Delphi.

Tu as la version gratuite de Delphi Berlin ? C'est la starter edition non ? Elle intègre FMX ?
1  0