- Vous devez avoir au minimum les connaissances présentes dans mes précédents tutoriaux !! ******
Souvent quand on programme en direct draw on veut faire des jeux, et là plusieurs problèmes se posent !!!
Tout d'abord, dans un jeu (ici jeux de plateforme) il faut quoi ???
1 - Un niveau de jeu
2 - Un personnage qui se déplace dans le niveau
3 - Un décor en interaction avec le personnage
Donc pas beaucoup de chose si on regarde dans cette optique, donc maintenant on va regarder se qu'il faut pour faire un moteur !!
Source / Exemple :
Si nous nous basons sur l'ordre précédemment montré, notre code sera composé de plusieurs fonctions :
1 - Affichage des décors et des personnages
2 - Déplacement du personnage
3 - Interaction avec le personnage
Soit 3 fonctions, mais si nous ne mettons que c'est 3 fonctions, nous n'arriverons à rien.
Donc, je vais vous présenter un ordre différent :
1 - Gestion du clavier
2 - Gestion de la fermeture du jeu
3 - Fonction relative à l'affichage
4 - Affichage du décor
Seulement, le décor doit se déplacer en fonction que le personnage avance ou recule
donc : 4 - Affichage du décor et gestion des déplacements
5- Une fonction d'ouverture des fichiers compressés (GIF et JPEG)
Quoi de plus, le personnage doit pouvoir sauter
6 - Saut du personnage
7 - Fonction relative au saut
Si nous faisons comme cela tous paraît correcte sauf que la ça ne fonctionne toujours pas, car à aucun moment nous ne savons à quel en droit se trouve le personnage...
8 - Position personnage
Maintenant nous avons un plan plutôt correct sur la gestion de notre moteur, il ne reste plus qu'a codé cela.
'**** 1 - Gestion du clavier * ***
Disons que notre personnage doit pouvoir aller à gauche à droite, de plus il faut que la touche echap fasse quitter le jeu et que la touche espace fasse sauter le personnage. Donc, 4 touches à configuré, dans votre module vous mettez une fonction qui sera pour le clavier :
Public Function Clavier()
Il faut ensuite acquérir le statut des touches
DIdevice.GetDeviceStateKeyboard DIstate
et après il faut géré les différentes touches :
If (DIstate.Key(DIK_ESCAPE) And &H80) Then
unloadDD
end if
Ici on regarde avec DIstate si la touche echap est enfoncée si oui alors on appelle unloadDD qui sera la fonction pour quitter le jeu.
Ensuite pour les touches flèche de droite et flèche de gauche :
ScrolD et ScrolG seront les variables de vérification si on appuis sur la touche.
(D pour droite, G pour gauche lol)
Flèche de gauche
ScrolG = IIf(DIstate.Key(DIK_LEFT) And &H80, 1, 0)
Si on appuis sur la fléche de gauche ScrolG = 1 autrement ScrolG = 0
De même pour la flèche de droite sauf que DIK_LEFT devient DIK_RIGHT
ScrolD = IIf(DIstate.Key(DIK_RIGHT) And &H80, 1, 0)
Si on appuis sur la fléche de droite ScrolD = 1 autrement ScrolD = 0
donc en résumer, on fera cela :
Public Function Clavier()
DIdevice.GetDeviceStateKeyboard DIstate 'on rentre les valeurs des touches activées dans 'DIstate
If (DIstate.Key(DIK_LEFT) And &H80) then
End If
If (DIstate.Key(DIK_RIGHT) And &H80) then
End If
If (DIstate.Key(DIK_SPACE) And &H80) Then
End If
If (DIstate.Key(DIK_ESCAPE) And &H80) Then unloadDD
End Function
Ainsi, nous avons donc fait une gestion du clavier, certes il faut encore remplir après Then mais ce n'est pas bien compliqué.Pour les différents codes des touches, je les mettrai dans les explications finales.
'**** 2 - Gestion de la fermeture du jeu ****
Pour gérer la fermeture du jeu, il suffit de quelques lignes.
D'abord comme dit ci-dessus la fonction s'appelle unloadDD :
Public Function unloadDD()
Ensuite il faut arrêter l'affichage à l'écran et vider les caches tout en retournant dans le mode vidéo qui était présent avant l'ouverture du jeu.
Public Function unloadDD()
bRunning = False ' Arrête l'affichage à l'écran
DD.RestoreDisplayMode ' Retourne à l'affichage précédent
Set Primary = Nothing ' Vide les différents caches
Set Backbuffer = Nothing '
Set DD = Nothing '
Set DX = Nothing '
End ' Ferme le jeu
End Function
Voila la fermeture du jeu est paramétrée !!!
' **** 3 - Fonction relative à l'affichage ****
Comme vous savez tous on utilise ddRect donc on la met dans le module :
Public Function ddRect(ByVal X1 As Long, _
ByVal Y1 As Long, _
ByVal X2 As Long, _
ByVal Y2 As Long) _
As RECT
With ddRect
.Left = X1
.Right = X2
.Top = Y1
.Bottom = Y2
End With
End Function
' **** 4 - Affichage du décor et gestion des déplacements ****
Pour afficher une image à l'écran, normalement nous utilisons la commande :
Backbuffer.BltFast dx, dy ,votre_image, ddRect(0, 0, 0, 0), DDBLTFAST_WAIT
donc on part sur cette base.
Il faut que notre fonction affiche l'image à l'écran, mais en la déplacent si le personnage bouge, je l'appel ainsi :
DrawScrolledSurf
D'où :
Public Function DrawScrolledSurf(Surf As DirectDrawSurface7, _
ByVal X, ByVal Y, _
ByVal X1, ByVal X2, _
ByVal Y1, ByVal Y2)
Explication :
Surf est l'image à affiché correspond à dds de Backbuffer.Bltfast
X correspond à dx, Y à Dy, X1, X2, Y1,Y2 correspondent au ddRect
'Ici, on gère l'affichage il faut que l'image apparaisse en partie losrqu'elle arrive sur les bords de l'écran pendant les déplacements.
If X < 0 Then ' si X < 0 donc à gauche de l'écran alors
X1 = X1 - X ' X1 sera diminué de la différence de ce qui sort de l'écran.
X = 0
End If
' De même si le personnage saute
If Y < 0 Then
Y1 = Y1 - Y
Y = 0
End If
If X + X2 > 640 Then X2 = X2 - ((X + X2) - 640) ' Quand X2 atteint une valeur ici 640 alors X2 est remit à sa valeur première
If Y + Y2 > 480 Then Y2 = Y2 - ((Y + Y2) - 640) ' De même pour Y2
Backbuffer.BltFast X, Y, Surf, ddRect(X1, Y1, X2, Y2), DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY
' On à plus qu'à affiché le tous à l'écran avec la gestion des ColorKey.
End Function
5- Une fonction d'ouverture des fichiers compressés (GIF et JPEG)
La même fonction que donné dans les tutoriaux précédents :
'Pour ouvrir des fichiers gif et jpeg
Public Function CreateSurfaceFromFile(DirectDraw As DirectDraw7, ByVal FileName As String, SurfaceDesc As DDSURFACEDESC2) As DirectDrawSurface7
Dim Picture As StdPicture
Dim Width As Long
Dim Height As Long
Dim Surface As DirectDrawSurface7
Dim hdcPicture As Long
Dim hdcSurface As Long
'On Charge l'image
Set Picture = LoadPicture(FileName)
'On convertit les dimensions
'de vbHimetric vers vbPixel
Width = CLng((Picture.Width * 0.001) * 567 / Screen.TwipsPerPixelX)
Height = CLng((Picture.Height * 0.001) * 567 / Screen.TwipsPerPixelY)
'On définit les propriété de la description
With SurfaceDesc
If .lFlags = 0 Then .lFlags = DDSD_CAPS
.lFlags = .lFlags Or DDSD_WIDTH Or DDSD_HEIGHT
If .ddscaps.lCaps = 0 Then .ddscaps.lCaps = DDSCAPS_OFFSCREENPLAIN
If .lWidth = 0 Then .lWidth = Width
If .lHeight = 0 Then .lHeight = Height
End With
'On crée la surface DirectDraw
Set Surface = DirectDraw.CreateSurface(SurfaceDesc)
'On crée de la Mémoire (pour charger l'image)
hdcPicture = CreateCompatibleDC(0)
'On sélectionne le Picture et on le copie
'vers la mémoire crée
SelectObject hdcPicture, Picture.Handle
'Handle de la surface
hdcSurface = Surface.GetDC
'On copie l'image contenue dans hdcSurface vers la surface
StretchBlt hdcSurface, 0, 0, SurfaceDesc.lWidth, SurfaceDesc.lHeight, hdcPicture, 0, 0, Width, Height, vbSrcCopy
'On libère l'espace mémoire contenue dans hdcSurface
Surface.ReleaseDC hdcSurface
DeleteDC hdcPicture
'On transfère la Surface
Set CreateSurfaceFromFile = Surface
'On vide Tout !
Set Picture = Nothing
Set Surface = Nothing
End Function
'**** 6 - Saut du personnage ****
J'utilise le saut avec la méthode des sinus, donc je vais vous expliquez celle-ci.
Public Function SautPerso()
If Not bJumping Then
CheckH LeftPerso
' Une fonction qui sera présente dans la form.
If TopPerso < Hsol Then TopPerso = Hsol
' Pour si notre personnage est trop bas par rapport au sol.
Exit Function
End If
lAngleSaut = lAngleSaut + 5 'L'angle du saut
CheckH LeftPerso
CheckTopPos TopPerso 'Expliqué plus bas
If lAngleSaut > 180 Or Hsol < TopPerso Then ' Si le personnage saute
CheckH LeftPerso ' et qu'il saute trop longtemps
TopPerso = Hsol
HImpulse = 0
lAngleSaut = 0 'alors il y réinitialisation
bJumping = False 'et on ne saute plus
Exit Function
End If
TopPerso = HImpulse - Sin(lAngleSaut / 180 * Pi) * hSaut
'Ici le personnage saute avec la Hauteur de l'impulsion - le sinus (d'où méthode des sinus) de l'angle / 180 pour pouvoir avoir une valeur supérieur a 0 multiplié par Pi qui sera définit plus bas et le tout multiplié par la hauteur du saut.
End Function
Donc il suffit de recréé la position du personnage par rapport au sol pour le faire sauté.
Cette fonction évite de faire :
Topperso = Topperso +0,5 (0,5 en exemple)
puis de faire
Topperso = Topperso - 0,5 (0,5 toujours en exemple)
et bien sur le tous comprenant des if ...
'**** 7 - Fonction relative au saut ****
Tout simplement Pi !!
Public Function Pi() As Double
'Atn(1) = 45° = Pi/4 radians
'donc Pi = Atn(1) × 4
Pi = Atn(1) * 4
End Function
Assez explicite je crois !!!
'**** 8 - Position personnage ****
Il nous faut la position du personnage pour pouvoir faire différente manipulation, tel que la mort du personnage s'il tombe dans un trou.
Function CheckTopPos(TopPos)
If TopPos = Hsol And Hsol > 220 Then
' Si le personnage et en dessous du sol donc dans un trou ben vous mettez se que
'vous voullez vu que j'ai pas mit :P
End If
End Function
Voila le moteur est enfin terminé seulement pour que tout fonctionne correctement il faut une ou 2 peut entre même 3 fonctions dans la form même ou votre code est placé :
'**** Donc d'abord les mouvements vers la droite :
Public Function MoveRight()
if ScrolD = 0 then Exit Function
'si on appuis pas sur la fléche de droite ben c pas sa lol
CheckH LeftPerso + OffSetX
' On récupère la nouvelle positon du personnage ' OffsetX une variable concernant le déplacement.
CheckTopPos TopPerso
' On récupére la position du personnage en hauteur
If TopPerso > Hsol Then Exit Function
'Si le personnage et plus haut que le sol ben on laisse tombé ...
'Scrolling des objets
LeftTonneau = LeftTonneau - OffSetX 'Tous simplement on enlève OffsetX a la position de l'objet, et vu qu'on la défini avec notre fonction d'affichage tout le reste se fait seul !
End Function
'***** Pour les mouvements vers la gauche c'est pareil :
Public Function MoveLeft()
if ScrolG = 0 then Exit Function
'si on appuis pas sur la fléche de gauche ben c pas sa lol
CheckH LeftPerso - OffSetX
' on récupère la nouvelle positon du personnage
' OffsetX une variable concernant le déplacement.
CheckTopPos TopPerso
' on récupère la position du personnage en hauteur
If TopPerso > Hsol Then Exit Function
'Si le personnage et plus haut que le sol ben on laisse tombé ...
'Scrolling des objets
LeftTonneau = LeftTonneau + OffSetX
End Function
'****** Maintenant la position du personnage par rapport au objet celle qui vous manquez !!!!
Public Function CheckH(NewPos)
' Pour exemple :
If NewPos + 80 > LeftCaisse And NewPos < LeftCaisse + 108 Then
Hsol = 220 - 100
'Donc si le personnage et sur la caisse ben la hauteur du sol augmente comme
'sa le personnage ne traverse pas la caisse !!!
Else
'pour mettre une autre objet :
If NewPos + 5 > LeftMur And NewPos < LeftMur + 55 Then
Hsol = -220
Else
If NewPos > LeftGrandTrou And NewPos < LeftGrandTrou + 80 Then
Hsol = 220 + 100
Else
End if
End if
End if
Remarque : Les if sont les un dans les autres et pas les un à la suite des autres !!!
'**************************
Voila il ne reste plus que deux choses à faire :
MoveRight
MoveLeft
SautPerso
Fire
Clavier
mettre tous sa dans la boucle d'affichage !!
Exemple pour l'affichage d'un objet :
DrawScrolledSurf Tonneau, LeftTonneau, TopTonneau, TonneauX1, TonneauX2, 0, 139
Comme vous pouvez le voir toute les données X, Y, X1,X2, Y1, Y2 sont sous forme de variable de type Long !!
'************************
Et derniére chose toutes les variables et autre référence utilisé pour ce module (à placé en haut du modul !!)
Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Public Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Public Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Public DX As New DirectX7
Public DD As DirectDraw7
Public DI As DirectInput
Public DIdevice As DirectInputDevice
Public DImouse As DirectInputDevice
Public Publicouse As DirectInputDevice
Public DIstate As DIKEYBOARDSTATE
Public Primary As DirectDrawSurface7
Public Backbuffer As DirectDrawSurface7
Public bRunning As Boolean
Public lAngleSaut As Long 'Avancement dans le saut
Public HImpulse As Long 'Hauteur d'où l'on saute
Public Hsol As Long
Public OffSetX
pour une meilleur utilisation mettez l'initialisation de vos variables dans une fonction ou une sub exterieur à celle utilisée pour l'affichage.
Maintenant vous avez un jolie petit moteur qui fonctionne bien.
Conclusion :
Un petit conseil, pour le fond si vous voulez que se soit une image qui se répéte n'utilisez pas la fonction qu'on a écrit met bltfast et mettez dans Move_Right et Move_left ceci :
Pour Move_Left :
LeftFond = LeftFond + OffSetX
X2FondScroll = X2FondScroll - OffSetX
If LeftFond >= ScreenWidth Then
LeftFond = 0
X2FondScroll = FondWidth
End If
Pour Move_Right
LeftFond = LeftFond - OffSetX
X2FondScroll = X2FondScroll + OffSetX
If LeftFond < 0 Then
LeftFond = LeftFond + ScreenWidth
X2FondScroll = LeftFond + FondWidth
End If
If X2FondScroll + LeftFond > ScreenWidth Then X2FondScroll = ScreenWidth - LeftFond
Assez explicite je pense, mais il vous faut les variables :
Public LeftFond As Long
Public X2FondScroll As Long
Public X1FondScroll As Long
Public FondHeight As Long
Public FondWidth As Long
Public ScreenWidth As Long
J'allais oublié les codes des touches avec directx :
Touche classique :
DIK_x touche x (x=0..9,A..Z).
DIK_Fx touche de fonction Fx (x=1..15)
DIK_NUMPADx touche x du pavé num (x=0..9)
Modificateurs :
DIK_LSHIFT Shift gauche
DIK_RSHIFT Shift droit
DIK_LCONTROL Ctrl gauche
DIK_RCONTROL Ctrl droit
DIK_LMENU Alt gauche
DIK_RMENU Alt droit
DIK_CAPITAL verrou capitale
Touches spécials :
DIK_SPACE espace
DIK_PRIOR page précédente
DIK_NEXT page suivante
DIK_HOME début
DIK_END fin
DIK_LEFT flèche gauche
DIK_RIGHT flèche droite
DIK_UP flèche haut
DIK_DOWN flèche bas
DIK_INS insérer
DIK_DEL efface à droite
DIK_RETURN entrée
DIK_TAB tabulation
DIK_BACK efface à gauche
Je crois qu'elles sont présentes sur un autre de mes tuto.
Je pense que ce moteur peut être largement améliorer mais il a le mérite de fonctionner.
Des que je peux je met un zip.
Tout les commentaires sont les bienvenues à part les critiques qui n'ont rien avoir avec le sujet :DD
D'aprés Vlad2i c'est le systeme utilisé dans les jeux worms .....
Je remercie Vlad2i qui m'a vraiment beaucoup appris et aider en direct x !!
Bon allé bonne programmation.
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.