Methode supermap, tuto tiles 6 !

Description

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.

Codes Sources

A voir également

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.