Oui oui, aprés tant d'attente, je met se code à votre disposition, en faite je l'avais fini il y a quelque temps, mais je n'ai pas eu le temps de le poster.
Avec ce type de map, on gere trois couches pour une carte, je m'explique :
Une couche pour le sol
Une couche pour les objets du sol utilisant une couleur transparente (colorkey)
Une couche pour les surfaces au dessus du personnage (feuilles d'arbre,...)
Pour se qui est du code, je ne commenterais pas tout car une majorité du code est la même que le tuto des map indirectes, d'animation (pour un perso), et de map de taille inifinie.
Donc le code principal, le chargement du fichier map et la création de la surface à afficher :
Source / Exemple :
'Le type qu'on utilise pour la map, ça permet d'avoir toutes les variables sous la main
Public Type map
Matrice() As String 'Le sol
MatriceB() As String 'Le sol avec transparence
MatriceH() As String 'Par dessus le hero
MatCol() As String 'Non utilisez dans le zip, sert pour la collision
MapSource As DirectDrawSurface7 'Une image contenant tout les tiles
ddsdMapSource As DDSURFACEDESC2 'Sont descripteurs
MapName As String 'Le nom de la carte qu'on charge, inclu dans le fichier map
PathCol As String 'Le chemin de la matrice de collision
TileSize As String 'La taille d'un tile (en pixel), on peut utiliser diverse taille pour chaque map et ainsi faire des jeux de zoom....
SplitSize As String 'Le nombre de caractere définissant un tile dans la matrice (ex : SplitSize = 4 alors 0000 0000 0000)
End Type 'Fin du type :D
Public MapTest As map 'On défini une variable qui utilisera se type
Public Function LoadMap(MapPath As String) 'La fonction magique !!
'**********Chargement de la matrice *************
'Déclaration des variables
Dim TempString As String 'Variable temporaire de type string
Dim i As Long, size As Integer, state As String
Dim File As Byte
'Ouverture du fichier
File = FreeFile 'On cree un reference libre pour un fichier
Open MapPath For Input As #File 'On ouvre le fichier map que pour la lecture (input)
Line Input #File, MapTest.MapName 'On lit la premiere ligne : Le nom de la carte
Line Input #File, MapTest.TileSize 'On lit la deuxieme ligne : La taille d'un tile
Line Input #File, MapTest.SplitSize 'On lit la troisieme ligne : La taille de la chaine de caractere definissant un tile dans les matrices d'affichages (powaaaa la phrase !)
Do Until EOF(File) 'Tant qu'on est pas a la fin du fichier on recommence (avant j'utiliser Do While Not EOF c'est pareil)
'Lecture d'une ligne
Line Input #File, TempString
If TempString <> "bas" And TempString <> "haut" And state = vbNullString Then 'On verifie que c'est la premiere couche, le sol
'Decoupage matrice du sol
If TempString <> vbNullString Then 'Si TempString n'est pas vide
ReDim Preserve MapTest.Matrice((Len(TempString) \ MapTest.SplitSize) - 1, size) 'On dimensionne la matrice
End If
i = 0 'On initialise i
Do While Len(TempString) >= MapTest.SplitSize 'Tant que TempSttring et superieur à SplitSize
DoEvents 'On laisse calculer le processeur (evite les freeze)
MapTest.Matrice(i, size) = Left$(TempString, MapTest.SplitSize) 'On met le nombre de caractere correspondant à 1 tile dans la matrice
i = i + 1
TempString = Mid$(TempString, MapTest.SplitSize + 1) 'On enleve les caracteres deja pris (ci dessus)
Loop 'On recommence
size = UBound(MapTest.Matrice, 2) + 1 'On incremente size pour le redimensionnement plus haut
ElseIf state = "bas" And TempString <> "haut" Then 'Meme chose mais pour la couche du sol avec transparence
'If TempString <> "haut" Then
'Decoupage matrice du bas
If TempString <> vbNullString Then
ReDim Preserve MapTest.MatriceB((Len(TempString) \ MapTest.SplitSize) - 1, size)
End If
i = 0
Do While Len(TempString) >= MapTest.SplitSize
DoEvents
MapTest.MatriceB(i, size) = Left$(TempString, MapTest.SplitSize)
i = i + 1
TempString = Mid$(TempString, MapTest.SplitSize + 1)
Loop
size = UBound(MapTest.MatriceB, 2) + 1
'End If
ElseIf state = "haut" Then 'Meme chose met pour la couche au dessus du hero
'If TempString <> "bas" Then
'Decoupage matrice du haut
If TempString <> vbNullString Then
ReDim Preserve MapTest.MatriceH((Len(TempString) \ MapTest.SplitSize) - 1, size)
End If
i = 0
Do While Len(TempString) >= MapTest.SplitSize
DoEvents
MapTest.MatriceH(i, size) = Left$(TempString, MapTest.SplitSize)
i = i + 1
TempString = Mid$(TempString, MapTest.SplitSize + 1)
Loop
size = UBound(MapTest.MatriceH, 2) + 1
'End If
Else
state = TempString
size = 0
End If
Loop
Close #File
'*************************************************************************************************
'Ici on a lu entierement le fichier, il faut creer la surface à afficher à partir de notre matrice
'MapSource est la surface contenant les tiles
Set MapTest.MapSource = dd.CreateSurfaceFromFile(App.Path & "\" & MapTest.MapName, MapTest.ddsdMapSource) 'On assigne a la surface le fichier correspondant.
'Creation de 3 surfaces vierges de la taille maximales
ddsdCSol.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT
ddsdCSol.ddscaps.lCaps = DDSCAPS_VIDEOMEMORY
ddsdCTransparent.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT
ddsdCTransparent.ddscaps.lCaps = DDSCAPS_VIDEOMEMORY
ddsdCDessus.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT
ddsdCDessus.ddscaps.lCaps = DDSCAPS_VIDEOMEMORY
'On donne les dimensions a la surface
'**************************************************************************************
'Dans mes tuto precedent il me semble qu'il y a une erreur sur la taille d'une map, dans le code ci present l'erreur est rectifier
'**************************************************************************************
'On test pour verifier que notre carte n'est pas defini sur un tile horizontale ou un tile vertical seulement
'Il y a trois surface vierge car il y a trois couches
If (UBound(MapTest.Matrice, 2) + 1) * MapTest.TileSize <> 0 Then
ddsdCSol.lHeight = (UBound(MapTest.Matrice, 2) + 1) * MapTest.TileSize
ddsdCTransparent.lHeight = (UBound(MapTest.Matrice, 2) + 1) * MapTest.TileSize
ddsdCDessus.lHeight = (UBound(MapTest.Matrice, 2) + 1) * MapTest.TileSize
Else
ddsdCSol.lHeight = MapTest.TileSize
ddsdCTransparent.lHeight = MapTest.TileSize
ddsdCDessus.lHeight = MapTest.TileSize
End If
If (UBound(MapTest.Matrice, 1)) * MapTest.TileSize <> 0 Then
ddsdCSol.lWidth = (UBound(MapTest.Matrice, 1)) * MapTest.TileSize + MapTest.TileSize
ddsdCTransparent.lWidth = (UBound(MapTest.Matrice, 2) + 1) * MapTest.TileSize + MapTest.TileSize
ddsdCDessus.lWidth = (UBound(MapTest.Matrice, 2) + 1) * MapTest.TileSize + MapTest.TileSize
Else
ddsdCSol.lWidth = MapTest.TileSize
ddsdCTransparent.lHeight = MapTest.TileSize
ddsdCDessus.lHeight = MapTest.TileSize
End If
'On assigne les descripteurs au surface correspondantes
Set CSol = dd.CreateSurface(ddsdCSol)
Set CTransparent = dd.CreateSurface(ddsdCTransparent)
Set CDessus = dd.CreateSurface(ddsdCDessus)
'On rempli les surface de noir pour eviter les bug d'affichage
CTransparent.BltColorFill ddRect(0, 0, 0, 0), RGB(255, 0, 255) 'Couche du sol avec element transparent
CDessus.BltColorFill ddRect(0, 0, 0, 0), RGB(255, 0, 255) 'Couche au dessus du hero
'Les variables utilisé dans les calcules suivant
Dim x As Integer, y As Integer
Dim sX1 As Long, sX2 As Long, sY1 As Long, sY2 As Long
Dim dX1 As Long, dX2 As Long, dY1 As Long, dY2 As Long
Dim temp As Long, Largeur As Long
's signifie source et d destination
'Si on a plusieurs Tiles on utilise un procédé un peu complexe de calcul de position correspondant a la position d'un tile sur l'image source et sur la destination (destination = notre map finale)
If ((UBound(MapTest.Matrice, 1)) * MapTest.TileSize <> 0) And (UBound(MapTest.Matrice, 2) + 1) * MapTest.TileSize <> 0 Then
'On defini la largeur de la map
Largeur = (MapTest.ddsdMapSource.lWidth \ MapTest.TileSize) * MapTest.TileSize
'Pour chaque tile
For x = 0 To UBound(MapTest.Matrice, 1)
For y = 0 To UBound(MapTest.Matrice, 2)
'On calcul les dimentsion de destination
dX1 = x * MapTest.TileSize
dX2 = dX1 + MapTest.TileSize
dY1 = y * MapTest.TileSize
dY2 = dY1 + MapTest.TileSize
'Et les dimension de la source pour le sol
sX1 = MapTest.Matrice(x, y) * MapTest.TileSize
sX2 = sX1 + MapTest.TileSize
If sX1 > Largeur Then
sY1 = (sX1 \ Largeur)
sX1 = sX1 - (Largeur * sY1)
sX2 = sX1 + MapTest.TileSize
sY1 = sY1 * MapTest.TileSize
sY2 = sY1 + MapTest.TileSize
Else
sX1 = MapTest.Matrice(x, y) * MapTest.TileSize
sX2 = sX1 + MapTest.TileSize
sY1 = 0
sY2 = sY1 + MapTest.TileSize
End If
'Avec les dimension calculé on blit le tile correspondant à la bonne position sur notre matrice du sol
CSol.Blt ddRect(dX1, dY1, dX2, dY2), MapTest.MapSource, ddRect(sX1, sY1, sX2, sY2), DDBLT_WAIT
'On recommence pour la couche du sol avec des elements transparents
If MapTest.MatriceB(x, y) <> "----" Then
sX1 = MapTest.MatriceB(x, y) * MapTest.TileSize
sX2 = sX1 + MapTest.TileSize
If sX1 > Largeur Then
sY1 = (sX1 \ Largeur)
sX1 = sX1 - (Largeur * sY1)
sX2 = sX1 + MapTest.TileSize
sY1 = sY1 * MapTest.TileSize
sY2 = sY1 + MapTest.TileSize
Else
sX1 = MapTest.MatriceB(x, y) * MapTest.TileSize
sX2 = sX1 + MapTest.TileSize
sY1 = 0
sY2 = sY1 + MapTest.TileSize
End If
CTransparent.Blt ddRect(dX1, dY1, dX2, dY2), MapTest.MapSource, ddRect(sX1, sY1, sX2, sY2), DDBLT_WAIT
End If
'Enfin pour la matrice au dessus du hero et des perso (feuille d'arbres, tunnel,...)
If MapTest.MatriceH(x, y) <> "----" Then
sX1 = MapTest.MatriceH(x, y) * MapTest.TileSize
sX2 = sX1 + MapTest.TileSize
If sX1 > Largeur Then
sY1 = (sX1 \ Largeur)
sX1 = sX1 - (Largeur * sY1)
sX2 = sX1 + MapTest.TileSize
sY1 = sY1 * MapTest.TileSize
sY2 = sY1 + MapTest.TileSize
Else
sX1 = MapTest.MatriceH(x, y) * MapTest.TileSize
sX2 = sX1 + MapTest.TileSize
sY1 = 0
sY2 = sY1 + MapTest.TileSize
End If
CDessus.Blt ddRect(dX1, dY1, dX2, dY2), MapTest.MapSource, ddRect(sX1, sY1, sX2, sY2), DDBLT_WAIT
End If
Next y
Next x
'Si il n'y a qu'un Tile c'est plus simple, les coordonnées sont logiques
Else
sY1 = Round((MapTest.Matrice(x, y) * MapTest.TileSize) / MapTest.ddsdMapSource.lWidth, 0)
sY1 = sY1 * MapTest.TileSize
sY2 = sY1 + MapTest.TileSize
sX1 = MapTest.Matrice(x, y) * MapTest.TileSize
sX1 = sX1 - (MapTest.ddsdMapSource.lWidth * Round(((MapTest.Matrice(x, y) * MapTest.TileSize) / MapTest.ddsdMapSource.lWidth), 0))
sX2 = sX1 + MapTest.TileSize
dX1 = 0
dX2 = 16
dY1 = 0
dY2 = 16
CSol.Blt ddRect(dX1, dY1, dX2, dY2), MapTest.MapSource, ddRect(sX1, sY1, sX2, sY2), DDBLT_WAIT
End If
End Function
'Voila nos surfaces sont pretes a etre affiche :
'On distingue deux cas, ccelui ou la carte est inferieur à la taille de l'ecran (800*600 dans l'exemple), et celui ou c'est superieur
If ddsdCSol.lWidth <= 800 And ddsdCSol.lHeight <= 600 Then
'Dans le cas inferieur, on fait un simple BltFast
Backbuffer.BltFast 0, 0, CSol, ddRect(0, 0, 0, 0), DDBLTFAST_WAIT
Backbuffer.BltFast 0, 0, CTransparent, ddRect(0, 0, 0, 0), DDBLTFAST_SRCCOLORKEY
Else
'Dans l'autre cas on fait un Blt en utilisant des coordonnée de source et de destination
Backbuffer.Blt ddRect(0, 0, 800, 600), CSol, ddRect(X1Map, Y1Map, X2Map, Y2Map), DDBLT_WAIT
Backbuffer.Blt ddRect(0, 0, 800, 600), CTransparent, ddRect(X1Map, Y1Map, X2Map, Y2Map), DDBLT_KEYSRC Or DDBLT_WAIT
End If
'On met le perso dessus les couches de sols mais avant la couche de dessus
Backbuffer.Blt ddRect(PersoX, PersoY, PersoX + 32, PersoY + 48), SPerso, ddRect(PersoSX1, PersoSY1, PersoSX2, PersoSY2), DDBLT_KEYSRC
'Meme raisonnement en deux cas :
If ddsdCSol.lWidth <= 800 And ddsdCSol.lHeight <= 600 Then
Backbuffer.BltFast 0, 0, CDessus, ddRect(0, 0, 0, 0), DDBLTFAST_SRCCOLORKEY
Else
Backbuffer.Blt ddRect(0, 0, 800, 600), CDessus, ddRect(X1Map, Y1Map, X2Map, Y2Map), DDBLT_KEYSRC Or DDBLT_WAIT
End If
Conclusion :
Voila, c'est à peu pret la totalité du code qui permet d'afficher des supermap.
Pour un exemple concret regarder dans le zip, le code du zip n'est pas commenté.
Pour faire cette map j'ai utilisé un editeur de tile supermap, cependant il est blindé de bug donc je ne pense pas le publié sur ce site si il n'y a pas de demande.
J'ai encadré le personnage dans la capture d'ecran.
J'ai failli oublié, la méthode qui permet le deplacement de personnage est un peu different de celle présenté dans mon tuto précédent, en faite j'utilise une image au lieu de plusieurs et je change les coordonnees de source.
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.