IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation multimédia/Jeux Python Discussion :

algorithme de placement de tile isométrique sur carte procédural


Sujet :

Programmation multimédia/Jeux Python

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 28
    Points
    28
    Par défaut algorithme de placement de tile isométrique sur carte procédural
    Bonjour a tous,

    J'essaie depuis quelques temps d'afficher des cartes aléatoires en isométrique. Pour ce qui est de la génération de la carte je n'ai pas de problème, mais la ou je bloque, c'est lorsqu'il me faut choisir la bonne image de tile a afficher selon les autres tiles qui l'entour.

    En gros, j'essaie de faire quelque chose qui ressemble a une carte de simcity2000. Voir image:

    Nom : images.jpg
Affichages : 792
Taille : 12,2 Ko

    Vous voyer les reliefs des montagnes sur l'image, et bien je cherche a faire parreil.

    Comme je disais, générer la carte dans un tableau ça va, afficher des tiles en iso ça va aussi, mon problème c'est vraiment de faire un algorithme qui va décider si je dois mettre le dessin 0 ou le 1 ou le 2... qui correspondent a une tile plate, ou bien un angle au nord, ou au sud, ou bien un coin...

    voici mon code (test) que je trafique dans tout les senses depuis longtemps (désolé, c'est un peu le bordel, je suis un amateur et le code est pas optimisé):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
     
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
     
    #Importation des modules
    try:
        import os, pygame, random
    except ImportError as err:
        print("Impossible de charger le module: ", err)
        print("Sortie forcé du systeme")
     
    #Constante de la fenêtre
    PLACE = "center" #emplacement de la fenetre dans l'écran
    TITLE = "TestIso"
     
    #Constantes du jeu
    FPS = 90 #nombre d'image par seconde
    SCROLLING = 5 #vitesse du scrolling
    TILESIZE = (112,83,27)
     
    #Fonction
    def loadImage(name, color=None):
        """Charge les images et retourne un object image, si color = -1
        la fonction prend le pixel à l'adresse (0,0) comme référence à
        la couleur de transparence. L'image doit être dans le dossier
        "images" """
        cheminImage = os.path.join("images", name)
        try:
            image = pygame.image.load(cheminImage).convert_alpha()
     
            if color == -1:
                color = image.get_at((0,0))
     
            if color != None:
                image.set_colorkey(color)
     
            return image
     
        except pygame.error:
            print ("Impossible de charger l'image:", name)
     
            return None
     
    def decoupe(image, size):
        """Découpe un tile-set en bloque selon la taille (en pixels) des tuiles
        et retourne toutes les images dans une liste"""
        lImage = []
        for b in range(0, image.get_height(), size[1]):
            for a in range(0, image.get_width(), size[0]):
                lImage.append(image.subsurface(a, b, size[0], size[1]))
     
        return lImage
     
    def builtMap(size, relief, erosion):
        """Générateur de carte"""
     
        #Crée une carte plate de niveau 0
        liste = []
        for y in range(size[1]):
            l1 = []
            for x in range(size[0]):
                l1.append(0)
            liste.append(l1)
     
        #Déplace un curseur de niveau 255 dans la map aléatoirement en prennent
        #en compte les collision avec les bords de la map ce qui crée un relief
     
        #position et direction de départ aléatoire
        x,y = random.randrange(0, int(size[0])), random.randrange(0, int(size[1]))
        direction = random.choice([(-1,0),(1,0),(0,-1),(0,1),(-1,1),(1,1),(1,-1)])
     
        for i in range(relief):
     
            #change la couleur de la case   
            liste[y][x] = 100
     
            x += direction[0]
            y += direction[1]
     
            #change de direction en cas de sortie des limites
            dx, dy = direction
            if x < 0 or x > len(liste[0])-1:
                x -= direction[0]
                dx = -dx
            if y < 0 or y > len(liste)-1:
                y -= direction[1]
                dy = -dy
            direction = (dx,dy)
     
            #change la direction en cour de route (1 chance sur 10)
            choix = random.randrange(0,10)
            if choix == 0:
                direction = random.choice([(-1,0),(1,0),(0,-1),(0,1),(-1,1),(1,1),(1,-1)])
     
     
        #Crée un contour de niveau 0 sur la carte pour donné une effet
        #d'ile
        a = 0
        for ligne in liste:
            b = 0
            for data in ligne:
                if a <= 5:
                    liste[a][b] = 0
                elif a >= len(liste)-6:
                    liste[a][b] = 0
                elif b <= 5:
                    liste[a][b] = 0
                elif b >= len(liste[0])-6:
                    liste[a][b] = 0
     
                b += 1
            a += 1
     
     
        #Affine la carte en lissant les arrêtes des niveaux de la map, prend chaque
        #case autour de la case concerné et fais une moyenne des niveaux que l'on attribue
        #ensuite à la case concerné
        for i in range(erosion):
            y = 0
            for ligne in liste:
                x = 0
                for value in ligne:
                    try:
                        #Vérifie si la case est l'une des quatres coin ou non, puis calcul
                        #la moyenne des niveaux des cases autour de la case, le bloc try
                        #est pour éviter un dépassement de liste
                        if x == 0 and y == 0:
                            newValue = int((liste[y][x+1]+liste[y+1][x]+liste[y+1][x+1])/3)
                        elif x == len(liste[0])-1 and y == len(liste)-1:
                            newValue = int((liste[y-1][x-1]+liste[y-1][x]+liste[y][x-1])/3)
                        elif x == len(liste[0])-1 and y == 0:
                            newValue = int((liste[y][x-1]+liste[y+1][x-1]+liste[y+1][x])/3)
                        elif x == 0 and y == len(liste[0])-1:
                            newValue = int((liste[y-1][x]+liste[y-1][x+1]+liste[y][x+1])/3)
                        elif x == len(liste[0])-1:
                            newValue = int((liste[y-1][x-1]+liste[y-1][x]+liste[y][x-1]+\
                                            liste[y+1][x-1]+liste[y+1][x])/5)
                        elif y == len(liste)-1:
                            newValue = int((liste[y-1][x-1]+liste[y-1][x]+liste[y-1][x+1]+\
                                            liste[y][x-1]+liste[y][x+1])/5)
                        else:
                            newValue = int((liste[y-1][x-1]+liste[y-1][x]+liste[y-1][x+1]+\
                                            liste[y][x-1]+liste[y][x+1]+liste[y+1][x-1]+\
                                            liste[y+1][x]+liste[y+1][x+1])/8)
                    except:
                        pass
     
                    #donne la valeur calculé à la case
                    liste[y][x] = newValue
                    x += 1
                y += 1
     
        return liste
     
    def formatHeight(liste, nbLevel, height):
     
        liste2 = []
        for ligne in liste:
            l = []
            for data in ligne:
     
                data = int(data/nbLevel)
                data *= height
     
                l.append(data)
     
            liste2.append(l)
     
        return liste2
     
    def formatMap(liste):
     
        liste2 = []
        j = 0
        for ligne in liste:
            l = []
            i = 0
            for data in ligne:
     
                data2 = None
     
                try:
                    if liste[j][i-1] > data:
                        data2 = 2
                except:
                    pass
     
                try:
                    if liste[j-1][i] > data:
                        data2 = 1
                except:
                    pass
     
                try:
                    if liste[j][i+1] > data:
                        data2 = 4
                except:
                    pass
     
                try:
                    if liste[j+1][i] > data:
                        data2 = 3
     
                except:
                    pass
     
                try:
                    if liste[j-1][i-1] > data and liste[j-1][i] == data and liste[j][i-1] == data:
                        data2 = 5
                except:
                    pass
     
                try:
                    if liste[j+1][i-1] > data and liste[j+1][i] == data and liste[j][i-1] == data:
                        data2 = 6
                except:
                    pass
     
                try:
                    if liste[j+1][i+1] > data and liste[j+1][i] == data and liste[j][i+1] == data:
                        data2 = 7
                except:
                    pass
     
                try:
                    if liste[j-1][i+1] > data and liste[j-1][i] == data and liste[j][i+1] == data:
                        data2 = 8
                except:
                    pass
     
                if data2 == None:
                    data2 = 0
     
                l.append(data2)
                i += 1
     
            liste2.append(l)
            j += 1
     
        for j in range(0,len(liste2)):
            for i in range(0,len(liste2[0])):
     
                try:
                    if liste2[j+1][i] == 5 and liste2[j][i+1] == 5:
                        liste2[j][i] = 9
                except:
                    pass
     
    ##            try:
    ##                if liste2[j-1][i] == 6 and liste2[j][i+1] == 6:
    ##                    liste2[j][i] = 10
    ##            except:
    ##                pass
     
                try:
                    if liste2[j-1][i] == 7 and liste2[j][i-1] == 7:
                        liste2[j][i] = 11
                except:
                    pass
     
        return liste2
     
    #Classes        
    class Game():
        """Gère tout les éléments du jeu"""
     
        def __init__(self, **kwarg):
            """Constructeur:
            parametre =
            title (str) = Titre de la fenêtre
            screenSize (width, height) = Taille de l'écran
            fullscreen (bool) = Option de plein écran
            sound (bool) = Option du son"""
     
            title = "Game"
            screenSize = (800,600)
            fullScreen = False
     
            for key in kwarg:
                if key == "title": title = kwarg[key]
                elif key == "screenSize": screenSize = kwarg[key]
                elif key == "fullScreen": fullScreen = kwarg[key]
                else: raise ValueError("Invalid Argument :"+key)
     
            pygame.init()
            os.environ['SDL_VIDEO_CENTERED'] = PLACE
     
            if fullScreen:
                self.screen = pygame.display.set_mode(screenSize, pygame.FULLSCREEN)
            else:
                self.screen = pygame.display.set_mode(screenSize)
     
            pygame.mouse.set_visible(True)
            pygame.key.set_repeat(100,30)
            pygame.display.set_caption(title)
     
            self.area = self.screen.get_rect()
            self.run = True
     
            self.loadImage()
            self.createObjet()
            self.loop()
     
     
        def loadImage(self):
     
            mask = loadImage("tileMask.png")
            self.listMask = decoupe(mask, (TILESIZE[0],TILESIZE[1]))
     
        def createObjet(self):
            """Crée tous les objets et/ou les prépares"""
     
            self.pause = False
     
            heightMap = builtMap((50,50), 1000, 5) #carte en niveau de gris
            heightTile = formatHeight(heightMap, 10, TILESIZE[2]) #hauteur des tiles
            numberTile = formatMap(heightTile)
            self.map = Layout(numberTile, heightTile, self.listMask)
     
        def loop(self):
            """Boucle principal"""
            while self.run:
     
                pygame.time.Clock().tick(FPS)
     
                self.event()
                self.scrolling()
     
                if not self.pause:
                    None
     
                self.render()
     
            pygame.quit()
     
        def event(self):
            """Gère tout les évènements concenant la fenêtre (clavier/sourie)"""
            #Gestion clavier
            for ev in pygame.event.get():
     
                if ev.type == pygame.QUIT:
                    self.run = False
     
                #Sortie de programme                    
                if ev.type == pygame.KEYDOWN:
                    if ev.key == pygame.K_ESCAPE:
                        self.run = False
     
                    #reset tout les objets (les recrées)
                    elif ev.key == pygame.K_r:
                        self.createObjet()
     
                    #Set/reset pause
                    elif ev.key == pygame.K_p:
                        if self.pause:
                            self.pause = False
                        else:
                            self.pause = True
     
        def scrolling(self):
     
            self.map.scrolling()
     
        def render(self):
            """Gère l'affichage de tout les objets"""
     
            #background
            self.screen.fill((0,0,0))
     
            #affiche la carte
            self.map.display()
     
            #actualize
            pygame.display.flip()
     
    class Layout():
        """Crée une carte (liste de liste) d'objet Tile, selon un plan
           et dimentionne le tout selon la taille des tile (TILESIZE)
           et leur couleur (COLORWALL, COLORGROUND, COLORSTART et COLOREND)"""
     
        def __init__(self, plan, heightTile, listMask):
            """Constructeur"""
            self.screen = pygame.display.get_surface()
            self.area = self.screen.get_rect()
     
            self.listMask = listMask
     
            self.map = []
            y = 0
            for ligne in plan:
                x = 0
                for data in ligne:
     
                    self.map.append(Tile((x,y), listMask[data], heightTile[y][x]))
     
                    x += 1
                y += 1
     
        def scrolling(self):
     
            if pygame.key.get_pressed()[pygame.K_UP]:
                for element in self.map:
                    element.move((0,SCROLLING))
            if pygame.key.get_pressed()[pygame.K_DOWN]:
                for element in self.map:
                    element.move((0,-SCROLLING))
            if pygame.key.get_pressed()[pygame.K_LEFT]:
                for element in self.map:
                    element.move((SCROLLING,0))
            if pygame.key.get_pressed()[pygame.K_RIGHT]:
                for element in self.map:
                    element.move((-SCROLLING,0))
     
        def get_map(self):
     
            return self.map
     
        def display(self):
            """Affiche tout les elements de la carte"""
            for element in self.map:
                element.display()
     
    class Tile():
        """Crée une tuile carré"""
     
        def __init__(self, adresse, image, height):
            """Constructeur"""
     
            self.screen = pygame.display.get_surface()
            self.area = self.screen.get_rect()
     
            self.image = image
            self.rect = self.image.get_rect()
     
            self.height = height
            self.adresse = adresse
     
            x = adresse[0]*int(self.rect.width/2)-adresse[1]*(self.rect.height-TILESIZE[2])
            y = adresse[0]*int((self.rect.height-TILESIZE[2])/2)+adresse[1]*int((self.rect.height-TILESIZE[2])/2)
            self.rect.topleft = (x,y-self.height)
     
        def move(self, coord):
     
            self.rect = self.rect.move(coord)
     
        def display(self):
     
            if self.area.colliderect(self.rect):
                self.screen.blit(self.image, self.rect)
     
    #Execution
    if __name__ == "__main__":
     
        Game(title=TITLE, fullScreen=False)
    et les images:

    Nom : tileMask.png
Affichages : 1326
Taille : 5,1 Ko

    En gros ce que le code fait, on génère un carte aléatoire (une ile) dans builtmap, ce qui me donne une liste de hauteur de 0 a 100, ensuite je format ces hauteurs (dans une nouvelle liste) selon la hauteur des tiles pour créé des niveaux (des plateaux de montagne), ensuite a partir de cette nouvelle liste je choisi les bonne images a afficher, ensuite et bien c'est comme pour toutes carte en iso, je crée des objets tiles avec l'image et la hauteur de la tiles dans une liste et ensuite j'affiche chaque élément de la liste.

    Comme je disais, je suis très très amateur, donc c'est peu-être juste ma façons de faire qui n'est pas bonne, dans tout les cas, je suis ouvert au critique.

    Merci pour votre aide,

    Pascal

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 28
    Points
    28
    Par défaut
    J'ai oublier de dire qu'il me manque des dessins de tuile et que j'y allais au fur et a mesure qu'il me manquait des images.

    Peut-être aussi que ma question n'est pas clair, en gros je voudrais savoir comment les programmeurs font en général pour créé un algorithme générique qui va placer les bonne tuiles au bonne endroit, car moi a date j'ai pas eu le choix de programmer chaque cas possible et sa devient un bordel monstre en plus c'est extremement long a faire. Pour chaque case j'ai 9 cas possible selon la position des 8 case autour, sa me fais genre quoi 9^8 posibilité , je peux pas tous les coder.

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 858
    Points : 218 577
    Points
    218 577
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Je crois que la technique la plus utilisée c'est simplement de faire des tests pour trouver la tuile qui correspond.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 28
    Points
    28
    Par défaut
    et bien, c'est ce que j'essaye de faire mais ça marche pas super bien... Pour l'instant j'ai presque quelque chose de bien, mais reste certaine tuile qui ne s'affiche pas au bonne place.

    C'est peu-être mon approche qui n'est pas correct. Pour l'instant, je crée une heightMap remplie de valeur entre 0 et 100, ensuite je converti ces valeurs en level selon la hauteur des tuiles (ici c'est 27) et ensuite je reconvertie ces valeurs en numéro de tuiles selon le cas.

    Je pense que je serais peu-être mieux de créé un calque par hauteur de level, les convertirs en numéro de tuile, et ensuite les additionners, tu en pense quoi?

    (Comme tu peux le voir c'est surtout la technique qui me bloque)

  5. #5
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 858
    Points : 218 577
    Points
    218 577
    Billets dans le blog
    120
    Par défaut
    Dans SimCity, je pense que la hauteur de différence pouvant être entre deux case est limité à 1, ou maximum 2. Il ne peux pas y avoir de différence plus grande. Cela réduit énormément les combinaisons.
    De plus, je pense qu'au lieu d'utiliser une telle image :
    vous devriez couper chaque tuile en quatre. Ainsi, vous pouvez faire des assemblages et mieux correspondre aux hauteur du terrain.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 28
    Points
    28
    Par défaut
    Bonne idée, en limitant la hauteur entre chaque étape ça va beaucoup m'aider

    Je ne comprend pas ce que tu veux dire part couper chaque image en 4? Ça va juste me faire encore plus de possibilité à analyser non?

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 28
    Points
    28
    Par défaut
    Sinon, j'ai réusis à le faire en utilisant des rectangles incliner en me servant de la classe polygon de Pygame. Perso, je trouve le résultat assez convianquant, on dirait presque de la 3D . J'ai eu l'idée en prenant ma douche

    utilise : python 3.x et Pygame

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
     
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
     
    #Importation des modules
    try:
        import os, pygame, random
    except ImportError as err:
        print("Impossible de charger le module: ", err)
        print("Sortie forcé du systeme")
     
    #Constante de la fenêtre
    PLACE = "center" #emplacement de la fenetre dans l'écran
    TITLE = "TestIso"
     
    #Constantes du jeu
    FPS = 90 #nombre d'image par seconde
    SCROLLING = 5 #vitesse du scrolling
    TILESIZE = (20,20)
    MAPSIZE = (50,50)
     
    def builtMap(size, relief, erosion):
        """Générateur de carte"""
     
        #Crée une carte plate de niveau 0
        liste = []
        for y in range(size[1]):
            l1 = []
            for x in range(size[0]):
                l1.append(0)
            liste.append(l1)
     
        #Déplace un curseur de niveau 255 dans la map aléatoirement en prennent
        #en compte les collision avec les bords de la map ce qui crée un relief
     
        #position et direction de départ aléatoire
        x,y = random.randrange(0, int(size[0])), random.randrange(0, int(size[1]))
        direction = random.choice([(-1,0),(1,0),(0,-1),(0,1),(-1,1),(1,1),(1,-1)])
     
        for i in range(relief):
     
            #change la couleur de la case   
            liste[y][x] = 200
     
            x += direction[0]
            y += direction[1]
     
            #change de direction en cas de sortie des limites
            dx, dy = direction
            if x < 0 or x > len(liste[0])-1:
                x -= direction[0]
                dx = -dx
            if y < 0 or y > len(liste)-1:
                y -= direction[1]
                dy = -dy
            direction = (dx,dy)
     
            #change la direction en cour de route (1 chance sur 10)
            choix = random.randrange(0,10)
            if choix == 0:
                direction = random.choice([(-1,0),(1,0),(0,-1),(0,1),(-1,1),(1,1),(1,-1)])
     
     
        #Crée un contour de niveau 0 sur la carte pour donné une effet
        #d'ile
        a = 0
        for ligne in liste:
            b = 0
            for data in ligne:
                if a <= 5:
                    liste[a][b] = 0
                elif a >= len(liste)-6:
                    liste[a][b] = 0
                elif b <= 5:
                    liste[a][b] = 0
                elif b >= len(liste[0])-6:
                    liste[a][b] = 0
     
                b += 1
            a += 1
     
     
        #Affine la carte en lissant les arrêtes des niveaux de la map, prend chaque
        #case autour de la case concerné et fais une moyenne des niveaux que l'on attribue
        #ensuite à la case concerné
        for i in range(erosion):
            y = 0
            for ligne in liste:
                x = 0
                for value in ligne:
                    try:
                        #Vérifie si la case est l'une des quatres coin ou non, puis calcul
                        #la moyenne des niveaux des cases autour de la case, le bloc try
                        #est pour éviter un dépassement de liste
                        if x == 0 and y == 0:
                            newValue = int((liste[y][x+1]+liste[y+1][x]+liste[y+1][x+1])/3)
                        elif x == len(liste[0])-1 and y == len(liste)-1:
                            newValue = int((liste[y-1][x-1]+liste[y-1][x]+liste[y][x-1])/3)
                        elif x == len(liste[0])-1 and y == 0:
                            newValue = int((liste[y][x-1]+liste[y+1][x-1]+liste[y+1][x])/3)
                        elif x == 0 and y == len(liste[0])-1:
                            newValue = int((liste[y-1][x]+liste[y-1][x+1]+liste[y][x+1])/3)
                        elif x == len(liste[0])-1:
                            newValue = int((liste[y-1][x-1]+liste[y-1][x]+liste[y][x-1]+\
                                            liste[y+1][x-1]+liste[y+1][x])/5)
                        elif y == len(liste)-1:
                            newValue = int((liste[y-1][x-1]+liste[y-1][x]+liste[y-1][x+1]+\
                                            liste[y][x-1]+liste[y][x+1])/5)
                        else:
                            newValue = int((liste[y-1][x-1]+liste[y-1][x]+liste[y-1][x+1]+\
                                            liste[y][x-1]+liste[y][x+1]+liste[y+1][x-1]+\
                                            liste[y+1][x]+liste[y+1][x+1])/8)
                    except:
                        pass
     
                    #donne la valeur calculé à la case
                    liste[y][x] = newValue
                    x += 1
                y += 1
     
        return liste
     
    #Classes        
    class Game():
        """Gère tout les éléments du jeu"""
     
        def __init__(self, **kwarg):
            """Constructeur:
            parametre =
            title (str) = Titre de la fenêtre
            screenSize (width, height) = Taille de l'écran
            fullscreen (bool) = Option de plein écran
            sound (bool) = Option du son"""
     
            title = "Game"
            screenSize = (800,600)
            fullScreen = False
     
            for key in kwarg:
                if key == "title": title = kwarg[key]
                elif key == "screenSize": screenSize = kwarg[key]
                elif key == "fullScreen": fullScreen = kwarg[key]
                else: raise ValueError("Invalid Argument :"+key)
     
            pygame.init()
            os.environ['SDL_VIDEO_CENTERED'] = PLACE
     
            if fullScreen:
                self.screen = pygame.display.set_mode(screenSize, pygame.FULLSCREEN)
            else:
                self.screen = pygame.display.set_mode(screenSize)
     
            pygame.mouse.set_visible(True)
            pygame.key.set_repeat(100,30)
            pygame.display.set_caption(title)
     
            self.area = self.screen.get_rect()
            self.run = True
     
            self.createObjet()
            self.loop()
     
        def createObjet(self):
            """Crée tous les objets et/ou les prépares"""
     
            self.pause = False
     
            liste = builtMap(MAPSIZE, 3000, 5)
     
            self.layout = []
            j = 0
            for ligne in liste:
                y = j*int(TILESIZE[1]/4)
                x = -j*int(TILESIZE[0]/2)
                i = 0
                for data in ligne:
     
                    pointHeight = []
                    try:
                        pointHeight.append(liste[j-1][i-1])
                    except:
                        pointHeight.append(0)
     
                    try:
                        pointHeight.append(liste[j-1][i])
                    except:
                        pointHeight.append(0)
     
                    try:
                        pointHeight.append(liste[j][i])
                    except:
                        pointHeight.append(0)
     
                    try:
                        pointHeight.append(liste[j][i-1])
                    except:
                        pointHeight.append(0)
     
                    self.layout.append(Tile((x,y), pointHeight, data))
     
                    x += int(TILESIZE[0]/2)
                    y += int(TILESIZE[1]/4)
                    i += 1
     
                j += 1
     
        def loop(self):
            """Boucle principal"""
            while self.run:
     
                pygame.time.Clock().tick(FPS)
     
                self.event()
                self.scrolling()
     
                if not self.pause:
                    None
     
                self.render()
     
            pygame.quit()
     
        def event(self):
            """Gère tout les évènements concenant la fenêtre (clavier/sourie)"""
            #Gestion clavier
            for ev in pygame.event.get():
     
                if ev.type == pygame.QUIT:
                    self.run = False
     
                #Sortie de programme                    
                if ev.type == pygame.KEYDOWN:
                    if ev.key == pygame.K_ESCAPE:
                        self.run = False
     
                    #reset tout les objets (les recrées)
                    elif ev.key == pygame.K_r:
                        self.createObjet()
     
                    #Set/reset pause
                    elif ev.key == pygame.K_p:
                        if self.pause:
                            self.pause = False
                        else:
                            self.pause = True
     
        def scrolling(self):
     
            if pygame.key.get_pressed()[pygame.K_UP]:
                for element in self.layout:
                    element.move((0,SCROLLING))
            if pygame.key.get_pressed()[pygame.K_DOWN]:
                for element in self.layout:
                    element.move((0,-SCROLLING))
            if pygame.key.get_pressed()[pygame.K_LEFT]:
                for element in self.layout:
                    element.move((SCROLLING,0))
            if pygame.key.get_pressed()[pygame.K_RIGHT]:
                for element in self.layout:
                    element.move((-SCROLLING,0))
     
        def render(self):
            """Gère l'affichage de tout les objets"""
     
            #background
            self.screen.fill((0,0,0))
     
            for element in self.layout:
                element.display()
     
            #actualize
            pygame.display.update()
     
    class Tile():
        """Crée une carte (liste de liste) d'objet Tile, selon un plan
           et dimentionne le tout selon la taille des tile (TILESIZE)
           et leur couleur (COLORWALL, COLORGROUND, COLORSTART et COLOREND)"""
     
        def __init__(self, coord, listHeight, color):
            """Constructeur"""
            self.screen = pygame.display.get_surface()
            self.area = self.screen.get_rect()
     
            if color < 10:
                color = 10
            elif color > 255:
                color = 255
     
            self.color = (color,125,color)
     
            x,y = coord
            self.listPoint = []
            self.listPoint.append([x,y-listHeight[0]])
            self.listPoint.append([x+int(TILESIZE[0]/2),y+int(TILESIZE[1]/4)-listHeight[1]])
            self.listPoint.append([x,y+int(TILESIZE[1]/2)-listHeight[2]])
            self.listPoint.append([x-int(TILESIZE[0]/2),y+int(TILESIZE[1]/4)-listHeight[3]])
     
        def move(self, coord):
     
            for point in self.listPoint:
     
                point[0] += coord[0]
                point[1] += coord[1]
     
        def display(self):
            """Affiche tout les elements de la carte"""
     
            pygame.draw.polygon(self.screen, self.color, self.listPoint, 0)
     
    #Execution
    if __name__ == "__main__":
     
        Game(title=TITLE, fullScreen=False)

  8. #8
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 858
    Points : 218 577
    Points
    218 577
    Billets dans le blog
    120
    Par défaut
    J'ai pensé découper en quatre comme cela :

    Mais j'ai un grand grand doute sur ce fonctionnement.
    Images attachées Images attachées  
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 28
    Points
    28
    Par défaut
    ok je vois, mais je comprend ce que ça va changer rendu a l'affichage, ça reviens a diviser la taille des tuiles par 2 finalement non, et j'ai toujours le problème de les placer au bon endroit?

  10. #10
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 858
    Points : 218 577
    Points
    218 577
    Billets dans le blog
    120
    Par défaut
    Le problème de placement est "plus simple" car pour chaque quart, il vous faut plus que trois tests (ou 6, si vous permettez d'avoir des différences de hauteur de 2).
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2013
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 54
    Points : 28
    Points
    28
    Par défaut
    aaaaaa, c'est pas fou ça , j'y avais pas pensé, je vais commencer a mettre ça en application

    merci beaucoup

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Python 3.X] Problème clique sourie sur carte isométrique (Pygame)
    Par PascalStl dans le forum Programmation multimédia/Jeux
    Réponses: 3
    Dernier message: 10/08/2014, 12h27
  2. [Système] navigation sur carte du type mappy
    Par BernardT dans le forum Langage
    Réponses: 2
    Dernier message: 28/10/2005, 09h39
  3. Reset sur carte à puce
    Par stolken dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 05/10/2005, 00h08
  4. [STRUTS][TILES] Problème sur actions génériques
    Par xv-mnt dans le forum Struts 1
    Réponses: 1
    Dernier message: 02/08/2005, 10h15
  5. Comment lire sur Carte/Interface PCI
    Par Philippe299 dans le forum MFC
    Réponses: 4
    Dernier message: 12/07/2005, 10h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo