Découpeur de sprites (pour jeux rpg)

Description

Voici une petite source toute simple qui permet de découper des sprites de manière industrielle, efficace ...

Avant : A l'époque ...
Imaginons un petit RPG avec des sprites de bonhommes... Il faut les mettre dans une grille de 32x32, grille visible ou pas, peu importe, puis faire une boucle qui les découpe avec un pas prédéfini.

Avantage : Rapide
Inconvénients : Les sprites ont toujours la même taille, la préparation de la plaquette de sprites est plutôt longue.

Maintenant : Avec ma source ...
Vous créez une surface, vous collez vos sprites, là ou il y a de la place, vous pouvez par exemple, mettre votre petite épée juste entre les jambes du boss, pourquoi pas ...

Le programme va simplement extraire les pixels du sprite vers un nouveau bitmap, sans prendre des bouts d'autres sprites qui seraient dans la zone de découpage.

Source / Exemple :


Public Class Form1

    Public Liste_Pixels_EnCours_Traitement As New List(Of Point)
    Public Matrice_Pixels_Déjà_Traités(,) As Boolean
    Public Couleur_Transparente As Color

    Structure Sprite_Pixel_Information
        Public Position As Point
        Public Couleur As Color
    End Structure
    Public Liste_Pixels_Composant_Le_Sprite As New List(Of Sprite_Pixel_Information)

    Public Sub SPLIT_IMAGES_FROM_SURFACE(ByVal Id_Debut_Image As Integer, ByVal Index_Image_Src As Integer)

        ' Crée le bitmap contenant la planche de sprite
        Dim BitmapSrc As Bitmap = PictureBox1.Image
        ' Récupere la couleur transparente, dans le coin du bitmap
        Couleur_Transparente = BitmapSrc.GetPixel(0, 0)

        ' Redimension la matrice des pixels traités
        ReDim Matrice_Pixels_Déjà_Traités(BitmapSrc.Width - 1, BitmapSrc.Height - 1)

        ' Initialise la matrice comme une zone non traitée
        For Ny = 0 To BitmapSrc.Height - 1
            For Nx = 0 To BitmapSrc.Width - 1
                Matrice_Pixels_Déjà_Traités(Nx, Ny) = False
            Next
        Next

        ' Boucle principal qui parcours la zone complete en recherchant un debut de sprite.
        Dim X As Integer = 0, Y As Integer = 0
        For Pos As Integer = 0 To (BitmapSrc.Width * BitmapSrc.Height) - 1

            ' Ignore les pixels déjà traités
            If Matrice_Pixels_Déjà_Traités(X, Y) = False Then

                ' Recherche d'un nouveau sprite grace a une couleur non-transparente
                If Not (BitmapSrc.GetPixel(X, Y) = Couleur_Transparente) Then
                    ' Pixel trouvé, indique sur la matrice que le pixel a été traité
                    Matrice_Pixels_Déjà_Traités(X, Y) = True

                    ' Initialise la liste des pixels en cours et ajoute le pixel précédemment trouvé.
                    Liste_Pixels_EnCours_Traitement.Clear()
                    Liste_Pixels_EnCours_Traitement.Add(New Point(X, Y))

                    ' Initialise la zone de découpage du sprite au coordonnée du premier pixel
                    SpriteEnCours.X = X : SpriteEnCours.Y = Y
                    SpriteEnCours.Width = X : SpriteEnCours.Height = Y

                    ' Lance le traitement, en cherchant tout les pixels composant le sprite
                    zSPLIT_Voisin(BitmapSrc)

                    ' Verifie la validité du sprite grace a ses dimensions >0
                    If SpriteEnCours.Width - SpriteEnCours.X > 0 And SpriteEnCours.Height - SpriteEnCours.Y > 0 Then

                        ' Crée un bitmap de destination
                        Dim BitmapDSt As New Bitmap(SpriteEnCours.Width - SpriteEnCours.X + 1, SpriteEnCours.Height - SpriteEnCours.Y + 1)
                        ' Parcours la liste des pixels composants le sprite et reconstruit le sprite tout seul
                        For N = 0 To Liste_Pixels_Composant_Le_Sprite.Count - 1
                            BitmapDSt.SetPixel(Liste_Pixels_Composant_Le_Sprite(N).Position.X - SpriteEnCours.X, Liste_Pixels_Composant_Le_Sprite(N).Position.Y - SpriteEnCours.Y, Liste_Pixels_Composant_Le_Sprite(N).Couleur)
                        Next

                        ' Affiche le resultat dans le deuxieme picturebox
                        PictureBox2.Image = BitmapDSt
                        PictureBox2.Update()

                        ' Dodo 0.1 s
                        Threading.Thread.Sleep(100)

                    End If

                End If
            End If

            ' Incrémente la position de recherche de la boucle principal
            If X >= BitmapSrc.Width - 1 Then X = 0 : Y += 1 Else X += 1

        Next

    End Sub

    Public SpriteEnCours As New Rectangle
    Sub zSPLIT_Voisin(ByRef BitmapSrc As Bitmap)
        ' Vide la liste des pixels qui composent le sprite.
        Liste_Pixels_Composant_Le_Sprite.Clear()

        Do
            ' Si plus de pixel à traiter, sortir de la boucle, le sprite est terminé.
            If Liste_Pixels_EnCours_Traitement.Count = 0 Then Exit Do

            ' Récupére les coordonnées du premier pixel à traiter.
            Dim X As Integer = Liste_Pixels_EnCours_Traitement(0).X
            Dim Y As Integer = Liste_Pixels_EnCours_Traitement(0).Y

            ' Supprime le pixel de la liste des pixels à traiter
            Liste_Pixels_EnCours_Traitement.RemoveAt(0)

            ' Ajoute les informations du pixel dans la liste des pixels qui compose le sprite
            Dim Pixel As New Sprite_Pixel_Information
            Pixel.Position = New Point(X, Y)
            Pixel.Couleur = BitmapSrc.GetPixel(X, Y)
            Liste_Pixels_Composant_Le_Sprite.Add(Pixel)

            ' Réajuste en temps réél la zone de découpage du sprite
            If SpriteEnCours.X > X Then SpriteEnCours.X = X
            If SpriteEnCours.Y > Y Then SpriteEnCours.Y = Y
            If SpriteEnCours.Width < X Then SpriteEnCours.Width = X
            If SpriteEnCours.Height < Y Then SpriteEnCours.Height = Y

            ' Controle les voisins Gauche, Droite, Bas, Haut
            If X - 1 >= 0 Then ZVoisinRoutine(BitmapSrc, X - 1, Y)
            If X + 1 < BitmapSrc.Width Then ZVoisinRoutine(BitmapSrc, X + 1, Y)
            If Y - 1 >= 0 Then ZVoisinRoutine(BitmapSrc, X, Y - 1)
            If Y + 1 < BitmapSrc.Height Then ZVoisinRoutine(BitmapSrc, X, Y + 1)

        Loop

    End Sub

Conclusion :


L'utilisation de SET PIXEL et GET PIXEL sont ici utilisés dans un but éducatif.
Je conseille de stocker le bitmap dans un tableau et de traiter le tout ! Class MARSHALL par exemple !

Le fait de placer les sprites n'importe où à l'inconvénient d'être difficile a exploiter lors d'une animation.
Je conseille de joindre un fichier qui fera une correspondance entre l'index du sprite découpé et son ordre dans une animation, ou indiquer des caractèristiques sûpplémentaires, tel offset ou autres ...

J'espère que cette première source vous servira ...

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.