- JE CONSIDÈRE QUE VOUS POSSÉDER LES CONNAISSANCES PRESSENTE DANS MES PRÉCÉDENTS TUTORIAUX ******
Lors de la création d'un menu, je me suis retrouvé confronté à différents problèmes :
- Passer de mon jeu au menu sans faire bugger DirectX
- Faire différent bouton, le problème n'est pas de les afficher, mais d'accéder au bouton l'un après l'autre avec DirectInput.
Donc se sont les 2 gros problèmes qui se posent, pour la création d'un menu, et au quel je vais répondre.
Source / Exemple :
'Je pars en me disant que votre code comporte déjà cela :
'Dans un module :
'- Une sub d'initialisation avec DirectDraw et DirectInput au minimum.
'- Une sub affichant votre écran principal.
'- Une sub qui gère le clavier
'Et BRunning qui permet l'affichage de votre boucle Do .... Loop Until BRunning =
'False
'Vous allez mettre un nouveau module, appelé le MenuEchap par exemple.
'Et déclaré :
'Public EchapRunning as Boolean
'Ce qui sera notre variable d'affichage du menu echap.
'Puis mettez une sub appeler MEchap.
'Ensuite dans votre sub du clavier vous allez appeler la sub MEchap lorsqu'on
'appuis sur la touche echap :
If (DIstate.Key(DIK_ESCAPE) And &H80) Then Call MEchap
'&H80 étant un cache pour dire que la touche est appuyée.
'Dans la sub MEchap vous mettez en tout premier
BRunning = False
'puis
EchapRunning = True
'Ces deux lignes permettent d'arrêter l'affichage de votre première boucle, et
'd'accorder l'affichage de votre seconde.
'Vous déclarez une image pour le fond de votre menu, et ce qui change est que
'vous avez un bouton pour quand c'est pas sélectionné et un pour quand sest
'sélectionné.
'Donc, on va faire la déclaration de nos différents boutons.
'Il y en aura 3 :
Retour
Option
Quitter
'Donc les déclarations :
'Pour le bouton Retour :
Dim Retour(2) As DirectDrawSurface7
'Comme vous pouvez le voir notre variable est un tableau, ce qui change des
'déclarations normales, ceci peut être utile pour les sprites (animations).
Dim ddsdRetour(2) As DDSURFACEDESC2
' De même pour le ddsd
For i = 1 To 2
' En faisant une boucle ça nous permet de réduire la longueur du code
Set Retour(i) = CreateSurfaceFromFile(DD, App.Path & "\image\retour" & i & ".bmp", ddsdRetour(i))
'Donc Retour(1) sera retour1.bmp, et Retour(2) sera retour2.bmp
Retour(i).SetColorKey DDCKEY_SRCBLT, cke
' Nous définissons une couleur de transparence par la même occasion
Next
'Comme vous pouvez le voir, ceci nous fait gagner des lignes de codes et facilite la suite du code
'Maintenant nous faisons de mémé pour Option et pour Quitter :
Dim BOption(2) As DirectDrawSurface7
'Comme vous pouvez le voir j'ai mis BOption car Option existe déjà en vb
Dim ddsdOption(2) As DDSURFACEDESC2
For i = 1 To 2
Set BOption(i) = CreateSurfaceFromFile(DD, App.Path & "\image\option" & i & ".bmp", ddsdOption(i))
BOption(i).SetColorKey DDCKEY_SRCBLT, cke
Next
' Meme schema que pour Retour.
Dim Quitter(2) As DirectDrawSurface7
Dim ddsdQuitter(2) As DDSURFACEDESC2
For i = 1 To 2
Set Quitter(i) = CreateSurfaceFromFile(DD, App.Path & "\image\quitter" & i & ".bmp", ddsdQuitter(i))
Quitter(i).SetColorKey DDCKEY_SRCBLT, cke
Next
'Ici nous avons défini nos boutons.
'Maintenant si on réfléchit un peu il va nous falloir une variable qui changera
'suivant si c'est Retour(1) ou Retour(2).
Donc en dessous Public EchapRunning as Boolean
Vous mettez :
Public nbrQuitter As Integer ' Integer car on se servira que de 1 et 2 donc pas la
'peine de mettre long.
Public nbrRetour As Integer
Public nbrOption As Integer
'À la place de nbr vous auriez pu mettre State.
'Maintenant, passons à l'affichage :
'Alors comme d'habitude :
Do
Backbuffer.BltFast 0, 0, FondEchap, ddRect(0, 0, 0, 0), DDBLTFAST_WAIT
' Ici nous affichons le fond du menu
Backbuffer.BltFast 20, 30, Retour(nbrRetour), ddRect(0, 0, 116, 55), DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY
Backbuffer.BltFast 10, 100, BOption(nbrOption), ddRect(0, 0, 116, 55), DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY
Backbuffer.BltFast 10, 150, Quitter(nbrQuitter), ddRect(0, 0, 116, 55), DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY
' Et la nos boutons, les positions changes suivant votre menu et la taille de vos
'boutons.
'N oubliez pas de préciser la taille dans ddRect sinon il se pourrait que ça bug
ClavierEchap
' Nous appelons une sub pour le clavier, mais spécifique au menu
Primary.Flip Nothing, DDFLIP_WAIT
' Et on affiche à l ecran, c'est très important, car autrement le menu buggera
Loop Until EchapRunning = False
' Notre boucle dure tant que EchapRunning = True
' Maintenant notre sub principal du menu échap et fini, nous avons réglé le
' problème du passage d'une boucle à une autre.
( BRunning = False
EchapRunning = True
Primary.Flip Nothing, DDFLIP_WAIT
)
'Il faut régler le problème de DirectInput, je vous propose une solution que j'ai
'élaborée et que je trouve plutôt pas mal.
'Nous disons que chaque Bouton possède un statut sélectionner ou non.
'Et nous disons que chaque bouton possède un statut dans tout le menu.
'Donc il faut ajouter une variable qui sera la position de la sélection, moi j'ai tout
'simplement mis :
Public EchapState as Integer
'Donc maintenant dans une nouvelle fonction :
Function ClavierEchap()
'nous mettons l'acquisition du clavier :
DIdevice.GetDeviceStateKeyboard DIstate
'Ensuite il nous faut faire un "événement" pour si la flèche de bas est appuyée :
If (DIstate.Key(DIK_DOWN) And &H80) Then
'Puis nous allons incrémenter notre variable
If EchapState < 3 Then EchapState = EchapState + 1
'Que si Echapstate est inférieur à 3 car nous avons 3 boutons
' Puis nous allons changer la couleur de notre bouton pour le mettre sélectionnée
If EchapState = 1 Then
nbrRetour = 2
End If
' Donc si EchapState = 1 alors nbrRetour = 2 se qui veux dire que notre bouton
' retour sera sélectionné
'Seulement la fonction ClavierEchap est appelée un grand nombre de fois si l'on
'considère qu'il y a environ 60Fps donc appelé 60 fois par seconde, se qui veux
' dire quen un seul appui nous aurons EchapState qui sera égal à 3, donc
' on ne verra pas le bouton du milieu.
'Pour arranger cela on va créé un système de timer
'Comme sa il faudra qu'un certain temps sest écoulé pour que le bouton suivant
'puisse être activé.
' Donc vous ajoutez :
Public TimerFirst As Long
Public TimerSecond As Long
Public TimerSecondState As Long
' Pour pouvoir faire un système de timer il faut 2 relever de temps TimerFirst et
' TimerSecond, puis dans notre code il faudra le statut de TimerSecond.
'Avant :
If EchapState < 3 Then EchapState = EchapState + 1
vous ajoutez :
TimerSecondState = 0
' 0 se qui veux dire (dans l'exemple) que le deuxième ' timer n'a pas eu de relevé dans le temps donc qu'il va falloir en faire un
TimerFirst = DX.TickCount
'Dx.TickCount relève le temps passé sur le système en ms
'Ensuite vous ajoutez à la fin de la fonction aprés le end if
If TimerSecondState = 0 Then
' Si il faut faire un relevé (après un appui sur la fléche du bas)
TimerSecond = DX.TickCount
' on fait un relevé
TimerSecondState = 1
' on dit que le relevé a eu lieu pour pas qu'il soit refait
End If
'Maintenant il ne reste plus qu'as finir le code à l'intérieur du if
If TimerFirst - TimerSecond > 100 Then
'Donc si le temps entre le relevé de TimerFirst et le relevé de TimerSecond est
' supérieurs à 100
If EchapState = 1 Then
nbrRetour = 2
End If
End If
If TimerFirst - TimerSecond > 100 Then
If EchapState = 2 Then
nbrRetour = 1
' Le bouton Retour n'est plus sélectionné, par contre le bouton Option l'est.
nbrOption = 2
End If
End If
If TimerFirst - TimerSecond > 100 Then
If EchapState = 3 Then
nbrOption = 1
Le bouton Option n'est plus sélectionné, par contre le bouton Quitter l'est.
nbrQuitter = 2
End If
End If
'Nous avons fait le système pour descendre dans les boutons de notre menu,
'maintenant il faut remonter, le système est le meme :
If (DIstate.Key(DIK_UP) And &H80) Then
TimerSecondState = 0
' On dit qu'il faut faire un relevé sur TimerSecond
TimerFirst = DX.TickCount
' On fait un relevé sur TimerFirst
If EchapState > 0 Then EchapState = EchapState - 1
' On décremente EchapState seulement sil est supérieur à 0 car le bouton -1
' n'existe pas.
'Puis de même que pour Dik_Down
sauf que EchapState = 3 n'y est pas vu qu'il n'y a pas 4 boutons
If TimerFirst - TimerSecond > 100 Then
If EchapState = 1 Then
nbrRetour = 2
nbrOption = 1
End If
End If
If TimerFirst - TimerSecond > 100 Then
If EchapState = 2 Then
nbrOption = 2
nbrQuitter = 1
End If
End If
End If
'Maintenant nous allons rajouter une précision pour que le code fonctionne
'parfaitement :
If nbrRetour = 2 Then EchapState = 1
If nbrOption = 2 Then EchapState = 2
If nbrQuitter = 2 Then EchapState = 3
'Comme ça, il n'y aura pas d'erreur d'incrémentation ou de decrementation
'Maintenant si on appuis sur Retour :
If (DIstate.Key(DIK_RETURN) And &H80) And EchapState = 1 Then
EchapRunning = False
Call StartGame
End If
'Le bouton Retour étant au state 1 il faut que les deux conditions soit réunis, state 1 et appuis sur Entrée
'Pour Quitter :
If (DIstate.Key(DIK_ESCAPE) And &H80) Then Call UnloadDD
'UnloadDD étant une sub qui ferme proprement le jeu.
Pour UnloadDD je vous la donne sa peut toujours vous servir :
Public Sub UnloadDD()
EchapRunning = False ' On arrete la boucle du menu echap
ShowCursor (True) ' Api qui permet de cacher le curseur de la souris
DD.RestoreDisplayMode 'On repace a l'écran normal
Set Primary = Nothing ' La surface primaire est nul
Set Backbuffer = Nothing ' Le buffer est nul
Set DD = Nothing 'dd est nul
Set DX = Nothing 'dx est nul
DIdevice.Unacquire ' On libere l'acquisition du clavier
End ' on quitte
End Sub
'Voila vous avez un menu qui marche et qui peut faire bonne impression, et
'surtout il y a peut de code, moins de 150 lignes dans l'exemple.
Conclusion :
Alors pour petite précision j'avais trouver un système sur le site de c2i qui permet de faire un Key Down, mais après avoir testé la méthode, j'ai pu constater qu'elle fonctionner très mal, donc je créé cette méthode.
Donc, pour voir bien à quoi ressemble ce tuto regarder l'exemple, par contre il n'est pas commenté, je pense pas que sest nessecaire, vus la taille du tuto ci-dessus.
Si vous voulez des commentaires n'hésité pas je le ferais.
Et si vous avez envie d'un tuto sur un point particulier de DirectX (attention pas 3d) dites le moi .....
Bon code
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.