X. Création de la boucle principale dans l'objet Jeu▲
On a à ce stade du projet tous les modules objets nécessaires à la création de l'objet Jeu.
Cet objet est programmé dans la classe clGame qui est pour l'instant vide.
On a déterminé précédemment dans le schéma des objets que l'objet Jeu (clGame) contenait :
- un objet de type clSharedData pour le partage des données entre les écrans ;
- un objet de type clScreen qui contient une instance de l'écran courant ;
- un objet de type clCommand pour la gestion des commandes.
Déclaration ces objets en en-tête du module clGame.
' Objet Ecran
Private oScreen As ClScreen
' Objet pour commandes
Private oCommand As ClCommand
' Objet pour données partagées entre les écrans
Private oSharedData As ClSharedDataL'algorithme de déroulement du jeu à été écrit sommairement lors de la création de la classe d'interface clScreen.
Réécrivont l'agorithme complet de cette classe Jeu en « pseudocode ».
Initialisation de l'objet Jeu
oCommand = Nouvel objet de commandes clCommand
oSharedData = Nouvel objet de données clSharedData
Changement d'écran vers écran de menu
Fin d'initialisation
Procédure de début de jeu
Mettre <demande de sortie> à Faux
Début boucle de jeu
Exécute mise à jour des commandes dans oScreen
Exécute mise à jour de l'écran dans oScreen
Exécute mise à jour de l'affichage dans oScreen
Exécute la fonction d'attente dans oScreen
Si oScreen demande un changement d'écran
oScreen = Nouvel écran fonction de l'écran suivant dans oScreen
Affecte oCommand et oSharedData à oScreen
Fin Si
Si <demande de sortie> = Vrai Alors Sortie de la boucle de jeu
Fin boucle de jeu
Fin procédure de début de jeu
Procédure de fin de jeu
Mettre <demande de sortie> à Vrai
Fin procédure de fin de jeu
Procédure de changement d'écran (paramètre = nom de l'écran)
oScreen = Nouvel écran fonction du pramètre
Affecte oCommand et oSharedData à oScreen
Fin procédure de changement d'écranNotez qu'on défini deux procédures, une pour lancer le jeu et une autre pour l'arrêter.
Il est nécessaire de pouvoir sortir de la boucle de jeu (qui est sans fin) afin de libérer le programme avant de détruire l'objet jeu.
Traduisons ce « pseudocode » en VBA :
'***************************************************************************************
'* OBJET JEU
'***************************************************************************************
Option Explicit
' Objet Ecran
Private oScreen As ClScreen
' Objet pour commandes
Private oCommand As ClCommand
' Objet pour données partagées entre les écrans
Private oSharedData As ClSharedData
' Flag pour arrêt de la boucle de jeu
Private StopLoop As Boolean
'------------------------------------------------------------------------
' Initialisation de l'objet de Jeu
'------------------------------------------------------------------------
Private Sub Class_Initialize()
' Objet pour commandes
Set oCommand = New ClCommand
' Objet pour données partagées
Set oSharedData = New ClSharedData
' Premier écran = menu
GameChangeScreen "menu"
End Sub
'------------------------------------------------------------------------
' Procédure de début de jeu
'------------------------------------------------------------------------
Public Sub RunGame()
' Pas de sortie de boucle demandée au lancement du jeu
StopLoop = False
Do
' Mise à jour des commandes
oScreen.UpdateCommand
' Mise à jour de l'écran
oScreen.UpdateScreen
' Affichage de l'écran
oScreen.DisplayScreen
' Minuterie
oScreen.ScreenWait
' Test si changement d'écran demandé
If oScreen.ChangeScreen Then
' Change l'écran
If GameChangeScreen(oScreen.NextScreen) = False Then
' Si pas d'écran suivant => quitte le jeu
Exit Do
End If
End If
' Si sortie de boucle demandée => sort de la boucle
If StopLoop Then Exit Do
Loop
End Sub
'------------------------------------------------------------------------
' Procédure de fin de jeu
'------------------------------------------------------------------------
Public Sub StopGame()
' Sortie de boucle demandée pour l'arrêt du jeu
StopLoop = True
End Sub
'------------------------------------------------------------------------
' Procédure de changement d'écran
'------------------------------------------------------------------------
Private Function GameChangeScreen(pScreenName) As Boolean
' Renvoit Vrai par défaut
GameChangeScreen = True
' Changement d'écran en fonction du nom d'écran en pramètre
Select Case pScreenName
' Changement pour le menu
Case "menu"
Set oScreen = Nothing
Set oScreen = New ClScreenMenu
' Autre changement
Case Else
' Si pas d'écran suivant connu => renvoit Faux pour arrêter le jeu
GameChangeScreen = False
End Select
' Réaffecte les objets de commande et de données partagées au nouvel écran courant
Set oScreen.Command = oCommand
Set oScreen.SharedData = oSharedData
End FunctionL'objet Jeu est prêt !
On commence à voir l'intérêt de la programmation orientée objet.
Pour ajouter un nouvel écran il suffira de rajouter son enchainement dans la fonction GameChangeScreen.
XI. Lancement du jeu dans le formulaire▲
On a défini dans le schéma des objets que le formulaire contenait un objet de type clGame.
On déclare donc en en-tête de module un objet oGame que l'on instanciera au lancement du jeu.
Justement, parlons du lancement du jeu :
Si on souhaite lancer le jeu à l'ouverture du formulaire, on doit placer le code de lancement dans l'événement Initialize du formulaire.
On a alors un problème car le lancement du jeu fait entrer le programme dans une boucle sans fin.
C'est la boucle de la procédure RunGame.
Or la procédure Initialize du formulaire doit être menée à son terme afin que le formulaire soit totalementinitialisé et affiché.
Nous allons donc faire exécuter notre procédure de démarrage en différé par une minuterie, à l'aide de l'instruction OnTime de l'objet Application.
Cette instruction OnTime nécessite une fonction publique dans un module standard (donc pas dans le module du formulaire qui est un module de classe).
Voici en pseudocode le formulaire et la fonction différée dans un nouveau module ModFunctions.
Initialisation du formulaire
Appel différé d'une fonction StartGame d'un module nommé ModFunctions
Fin d'initialisation du formulaire
Fonction Principale Main
Crée l'objet Jeu
Lance le jeu (procédure RunGame de l'objet Jeu) => entre dans une boucle sans fin
Ferme le formulaire
Fin de la fonction Main
Evénément Demande de fermeture du formulaire
Arrête le jeu (procédure StopGame de l'objet Jeu) => sort de la boucle sans fin
Fin d'Evénément Demande de fermetureFunction StartGame
Exécute la fonction principale du formulaire
Fin function StartGameTraduisons en VBA :
'***************************************************************************************
'* FORMULAIRE DE JEU
'***************************************************************************************
Option Explicit
' objet Jeu
Private oGame As ClGame
'------------------------------------------------------------------------
' Initialisation du formulaire
'------------------------------------------------------------------------
Private Sub UserForm_Initialize()
' Délais d'une seconde avant excution de la fonction principal
' La procédure UserForm_Initialize doit arriver à son terme
Application.OnTime DateAdd("s", 1, Now), "StartGame"
End Sub
'------------------------------------------------------------------------
' Fonction principal
'------------------------------------------------------------------------
Public Function Main()
' Instancie l'objet Jeu
Set oGame = New ClGame
' Lance le jeu
oGame.RunGame
' Une fois le jeu terminé, décharge le formulaire
Unload Me
End Function
'------------------------------------------------------------------------
' Demande de fermeture du formulaire
'------------------------------------------------------------------------
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
' Arrête le jeu si on demande la fermeture du formulaire
oGame.StopGame
End Sub'***************************************************************************************
'* FUNCTIONS DIVERSES
'***************************************************************************************
Option Explicit
'------------------------------------------------------------------------
' Fonction de lancement du jeu
' Cette fonction est appelée depuis le formulaire par Application.OnTime
'------------------------------------------------------------------------
Public Function StartGame()
FormGame.Main
End FunctionL'affichage du formulaire va donc demander l'exécution différée de la fonction StartGame qui à sont tour demandera l'exécution de la fonction Main du formulaire afin de lancer le jeu.
Il est important d'arrêter le jeu à la demande de fermeture du formulaire.
Sans ça, la boucle sans fin ne s'arrêterait pas.
Attention : la procédure ClScreen_ScreenWait n'a pas été programmée.
Pour tester à ce stade, il faudrait ajouter un DoEvents dans cette procédure.


