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

Contribuez Python Discussion :

[JEU] [Python 2 et 3] Terrain miné - ne pas confondre avec "Mines" !


Sujet :

Contribuez Python

  1. #1
    Invité
    Invité(e)
    Par défaut [JEU] [Python 2 et 3] Terrain miné - ne pas confondre avec "Mines" !
    Bonjour,

    Voici le jeu Terrain miné - fait maison - à ne pas confondre avec le jeu "Mines".

    Nom : exemple-jeu-terrain-mine.png
Affichages : 380
Taille : 8,7 Ko

    But du jeu :

    Vous devez déplacer une grosse boule vers un carré placé en bas de l'écran.
    Malheureusement pour vous, le terrain est miné !
    Saurez-vous atteindre votre but sans vous faire exploser ?
    Bien entendu, vous êtes libres de reprendre ce code pour faire vos propres forks.

    Version Python2 : python2-jeu-tkinter-terrain-mine.py (fichier à télécharger)

    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
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    # logiciel pour Python2
     
    # (c) 2014 Raphaël SEBAN (tarball69)
    # publié sous licence GNU General Public License GPLv3
    # cf http://www.gnu.org/licenses/gpl.html
     
    # on demande en premier lieu
    # la librairie graphique Tkinter
    from Tkinter import *
     
    # on veut aussi utiliser
    # les nombres aléatoires
    import random
     
    # ------------------- DEBUT DU PROGRAMME -------------------------------
     
    def debut_jeu ():
        "le programme commence ici"
        # init variables globales
        global fenetre, canvas, bouton_jouer
        global c_width, c_height, center_x, center_y
        # on crée la fenêtre principale
        fenetre = Tk()
        fenetre.title("Mon super jeu !")
        fenetre.resizable(width=False, height=False)
        # on ajoute des composants graphiques
        canvas = Canvas(fenetre, bg="black", width=400, height=300)
        canvas.pack(padx=5, pady=5)
        # on met des données courantes en globales
        c_width = canvas.winfo_reqwidth()
        c_height = canvas.winfo_reqheight()
        center_x = c_width // 2
        center_y = c_height // 2
        # bouton 'jouer'
        bouton_jouer = Button(fenetre)
        bouton_jouer.pack(side=LEFT, padx=50, pady=5)
        # bouton 'quitter'
        Button(
            fenetre, text="Quitter", command=fenetre.destroy
        ).pack(side=RIGHT, padx=5, pady=5)
        # on affiche une présentation du jeu
        presenter_jeu()
        # et on lance la
        # boucle événementielle principale
        fenetre.mainloop()
    # end def
     
    def presenter_jeu ():
        "on affiche ici une présentation du jeu"
        # on commence toujours par effacer le canevas graphique
        # qui nous fait office d'écran de jeu
        canvas.delete(ALL)
        # on affiche un titre
        # par rapport au centre de l'écran de jeu
        canvas.create_text(
            center_x, center_y - 100,
            text="Terrain miné",
            font="sans 16 bold",
            fill="navajowhite2",        # couleur du texte
        )
        # on affiche des règles du jeu succinctes
        canvas.create_text(
            center_x, center_y + 30,
            text="""\
    Règles du jeu:
     
    Vous devez déplacer une grosse boule vers un carré placé en bas de l'écran.
    Malheureusement pour vous, le terrain est miné !
    Saurez-vous atteindre votre but sans vous faire exploser ?
    Utilisez les flèches du clavier pour vous déplacer.
            """,
            justify=LEFT,
            font="sans 10 bold italic",
            fill="Pale Goldenrod",
            width=0.8 * c_width,        # 80% de la largeur totale
        )
        # on s'assure que le joueur pourra (re)jouer
        bouton_jouer.configure(
            text="Jouer !", command=nouvelle_partie, state=NORMAL
        )
    # end def
     
    def nouvelle_partie ():
        "on réinitialise une nouvelle partie ici"
        # init variables globales
        global tid_joueur, tid_mines
        # on autorise le joueur à arrêter la partie quand il le souhaite
        bouton_jouer.configure(
            text="Stop !", command=arreter_partie, state=NORMAL
        )
        # on efface le canevas graphique
        canvas.delete(ALL)
        # on crée l'avatar du joueur (boule)
        creer_joueur()
        # on crée le carré d'arrivée
        creer_carre_final()
        # on mine le terrain
        miner_terrain()
        # on associe les touches fléchées du clavier
        # à nos propres fonctions de gestion du mouvement
        fenetre.bind_all("<Up>", deplacer_haut)
        fenetre.bind_all("<Down>", deplacer_bas)
        fenetre.bind_all("<Left>", deplacer_gauche)
        fenetre.bind_all("<Right>", deplacer_droite)
        # c'est ici qu'on lance les boucles inscrites dans le temps
        tid_joueur = fenetre.after(100, boucle_joueur)
        # les mines aussi vont avoir leur propre cycle de vie
        tid_mines = fenetre.after(1000, boucle_mines)
    # end def
     
    def creer_joueur ():
        """
            on crée l'avatar du joueur;
            ici le joueur est représenté par une grosse boule;
            on conserve l'identifiant de l'objet sur le canevas;
            ça nous servira plus tard;
            on prend des coordonnées au hasard;
        """
        # init variables globales
        global diametre_boule, rayon
        global boule_x, boule_y
        global sens_x, sens_y, pas
        global boule_joueur
        # inits
        diametre_boule = 20         # diamètre de la boule
        rayon = diametre_boule // 2
        boule_x = diametre_boule + random.randint(0, c_width - diametre_boule)
        boule_y = diametre_boule + random.randint(0, 10)
        sens_x, sens_y = (0, 0)     # sens de déplacement initial
        pas = random.randint(2, 5)  # quantité de déplacement (pixels)
        # on dessine l'avatar joueur (boule)
        boule_joueur = canvas.create_oval(
            boule_x - rayon, boule_y - rayon,
            boule_x + rayon, boule_y + rayon,
            outline="ivory2",       # couleur du contour
            width=1,                # épaisseur du trait de contour (pixels)
            fill="light sky blue",  # couleur du remplissage
        )
    # end def
     
    def creer_carre_final ():
        """
            on crée le carré final (carré d'arrivée);
            on conserve l'identifiant de l'objet sur le canevas;
            ça nous servira plus tard;
            on prend des coordonnées au hasard;
        """
        # init variables globales
        global taille_carre, demi_carre
        global carre_x, carre_y
        global carre_final
        # on crée le carré d'arrivée
        taille_carre = diametre_boule + 6
        demi_carre = taille_carre // 2
        carre_x = 10 + random.randint(0, c_width - taille_carre - 10)
        carre_y = c_height - taille_carre - random.randint(5, 20)
        # on dessine le carré final (arrivée)
        carre_final = canvas.create_rectangle(
            carre_x - demi_carre, carre_y - demi_carre,
            carre_x + demi_carre, carre_y + demi_carre,
            outline="ivory",        # couleur du contour
            width=1,                # épaisseur du trait de contour (pixels)
            fill="palegreen1",      # couleur du remplissage
        )
    # end def
     
    def miner_terrain ():
        "on mine le terrain au début d'une partie"
        # on choisit un nombre au hasard
        nombre_mines = random.randint(10, 20)
        # on boucle pour poser autant de mines
        for i in range(nombre_mines):
            # on pose une mine au hasard
            poser_mine()
        # end for
    # end def
     
    def poser_mine ():
        """
            on pose une mine au hasard, mais jamais dans le voisinage
            immédiat du joueur;
        """
        # init variables locales
        tailles = [8, 10, 12]
        couleurs = ["sandy brown", "peru", "sienna1", "coral1"]
        couleur_contour = "burlywood1"
        # on boucle tant que ce n'est pas bon
        # ici, on bouclera cent fois (par précaution)
        # et on abandonnera si on n'y arrive pas
        for i in range(100):
            # on choisit de nouvelles coordonnées au hasard
            mine_x = random.randint(0, c_width)
            mine_y = random.randint(0, c_height)
            # les mines ont une taille variable;
            taille_mine = random.choice(tailles)
            # on recherche les collisions avec d'autres objets
            collisions = canvas.find_overlapping(
                *b_rect(mine_x, mine_y, taille_mine)
            )
            # aucun objet dans le voisinage ?
            if not collisions:
                # on choisit une couleur parmi une palette
                color = random.choice(couleurs)
                # on peut poser notre mine !
                canvas.create_oval(
                    b_rect(mine_x, mine_y, taille_mine//2),
                    outline=couleur_contour,
                    width=1,        # épaisseur de trait de contour (pixels)
                    fill=color,     # couleur du remplissage
                )
                # on remonte la boule joueur
                # au premier plan d'affichage
                canvas.tag_raise(boule_joueur, ALL)
                # c'est bon, on a posé notre mine
                # on peut quitter la boucle
                break
            # end if
        # end for
    # end def
     
    def b_rect (x, y, size):
        """
            retourne les coordonnées (top, left, bottom, right) d'un
            rectangle de délimitation autour d'un point P(x, y);
        """
        # rectangle d'influence (bounding rectangle)
        return (x - size, y - size, x + size, y + size)
    # end def
     
    def boucle_joueur ():
        "boucle temporelle qui gère les mouvements du joueur"
        # init variables globales
        global boule_x, boule_y
        global tid_joueur
        # le joueur a atteint le carré final ?
        if carre_x - demi_carre < boule_x < carre_x + demi_carre and \
                carre_y - demi_carre < boule_y < carre_y + demi_carre:
            # bravo ! c'est gagné !
            return bravo()
        # end if
        # on recherche des collisions
        collisions = canvas.find_overlapping(*canvas.bbox(boule_joueur))
        # le joueur a heurté autre chose que le carré final ?
        if len(collisions) > 1 and carre_final not in collisions:
            # aïe ! dommage !
            return game_over()
        # end if
        # tout est OK on déplace le joueur
        boule_x = (boule_x + sens_x * pas) % c_width
        boule_y = (boule_y + sens_y * pas) % c_height
        canvas.coords(
            boule_joueur,
            boule_x - rayon, boule_y - rayon,
            boule_x + rayon, boule_y + rayon,
        )
        # on boucle à nouveau dans le temps
        tid_joueur = fenetre.after(50, boucle_joueur)
    # end def
     
    def boucle_mines ():
        "boucle temporelle qui gère la vie des mines"
        # init variables globales
        global tid_mines
        # on pose une mine de temps en temps
        poser_mine()
        # prochaine mine dans... (millisecondes)
        delai = random.randint(1000, 2000)
        # on relance la boucle après ce délai
        tid_mines = fenetre.after(delai, boucle_mines)
    # end def
     
    def bravo ():
        "super ! le joueur a réussi !"
        # on affiche l'écran final
        ecran_final(
            titre="BRAVO",
            sous_titre="C'est gagné !",
            couleur_titre="lemon chiffon",
            couleur_sous_titre="pale green",
        )
    # end def
     
    def game_over ():
        "c'est ballot ! le joueur a perdu !"
        # on affiche l'écran final
        ecran_final(
            titre="GAME OVER",
            sous_titre="C'est perdu !",
            couleur_titre="firebrick1",
            couleur_sous_titre="floral white",
        )
    # end def
     
    def arreter_partie ():
        "le joueur souhaite arrêter la partie"
        # on affiche l'écran final
        ecran_final(
            titre="ABANDON",
            sous_titre="Partie annulée !",
            couleur_titre="gold",
            couleur_sous_titre="light grey",
        )
    # end def
     
    def ecran_final (**kw):
        "on effectue ici des opérations communes à tous les écrans finaux"
        # on bloque les clics intempestifs sur le bouton 'jouer'
        bouton_jouer.configure(state=DISABLED)
        # on stoppe les boucles temporelles qui pourraient
        # éventuellement être encore en cours d'exécution
        arreter_boucles()
        # on efface le canevas graphique
        canvas.delete(ALL)
        # on récupère le titre et sa couleur
        titre = kw.get("titre") or ""
        couleur = kw.get("couleur_titre") or "white"
        # on affiche le titre
        canvas.create_text(
            center_x, center_y - 40,
            text=titre,
            font="sans 36 bold",
            fill=couleur,
        )
        # on récupère le sous-titre et sa couleur
        sous_titre = kw.get("sous_titre") or ""
        couleur = kw.get("couleur_sous_titre") or "white"
        # on affiche le sous-titre
        canvas.create_text(
            center_x, center_y,
            text=sous_titre,
            font="sans 16 bold italic",
            fill=couleur,
        )
        # on relance presenter_jeu() après @delai
        # avec toutefois un minimum de 1 seconde
        delai = kw.get("delai") or 2000     # valeur par défaut
        fenetre.after(max(1000, delai), presenter_jeu)
    # end def
     
    def arreter_boucles ():
        "on arrête les boucles temporelles susceptibles de tourner encore"
        # init variables globales
        global tid_joueur, tid_mines
        # stooop !
        fenetre.after_cancel(tid_joueur)
        fenetre.after_cancel(tid_mines)
        # RAZ thread ids
        tid_joueur = tid_mines = 0
    # end def
     
    def deplacer_haut (event=None):
        "on déplace l'avatar du joueur vers le haut"
        # init variables globales
        global sens_x, sens_y
        # grâce à la boucle du jeu,
        # nous n'avons pas besoin de plus que ça
        sens_x, sens_y = (0, -1)
    # end def
     
    def deplacer_bas (event=None):
        "on déplace l'avatar du joueur vers le bas"
        # init variables globales
        global sens_x, sens_y
        # grâce à la boucle du jeu,
        # nous n'avons pas besoin de plus que ça
        sens_x, sens_y = (0, 1)
    # end def
     
    def deplacer_gauche (event=None):
        "on déplace l'avatar du joueur vers la gauche"
        # init variables globales
        global sens_x, sens_y
        # grâce à la boucle du jeu,
        # nous n'avons pas besoin de plus que ça
        sens_x, sens_y = (-1, 0)
    # end def
     
    def deplacer_droite (event=None):
        "on déplace l'avatar du joueur vers la droite"
        # init variables globales
        global sens_x, sens_y
        # grâce à la boucle du jeu,
        # nous n'avons pas besoin de plus que ça
        sens_x, sens_y = (1, 0)
    # end def
     
    # ------------------- FIN DU PROGRAMME ---------------------------------
     
    # ce script est automatiquement lancé grâce à ceci :
     
    # /!\ à connaître par coeur /!\
    if __name__ == "__main__":
        # lancer le programme
        debut_jeu()
    # end if
    Version Python3 : python3-jeu-tkinter-terrain-mine.py (fichier à télécharger)

    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
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
     
    # logiciel pour Python3
     
    # (c) 2014 Raphaël SEBAN (tarball69)
    # publié sous licence GNU General Public License GPLv3
    # cf http://www.gnu.org/licenses/gpl.html
     
    # on demande en premier lieu
    # la librairie graphique Tkinter
    from tkinter import *
     
    # on veut aussi utiliser
    # les nombres aléatoires
    import random
     
    # ------------------- DEBUT DU PROGRAMME -------------------------------
     
    def debut_jeu ():
        "le programme commence ici"
        # init variables globales
        global fenetre, canvas, bouton_jouer
        global c_width, c_height, center_x, center_y
        # on crée la fenêtre principale
        fenetre = Tk()
        fenetre.title("Mon super jeu !")
        fenetre.resizable(width=False, height=False)
        # on ajoute des composants graphiques
        canvas = Canvas(fenetre, bg="black", width=400, height=300)
        canvas.pack(padx=5, pady=5)
        # on met des données courantes en globales
        c_width = canvas.winfo_reqwidth()
        c_height = canvas.winfo_reqheight()
        center_x = c_width // 2
        center_y = c_height // 2
        # bouton 'jouer'
        bouton_jouer = Button(fenetre)
        bouton_jouer.pack(side=LEFT, padx=50, pady=5)
        # bouton 'quitter'
        Button(
            fenetre, text="Quitter", command=fenetre.destroy
        ).pack(side=RIGHT, padx=5, pady=5)
        # on affiche une présentation du jeu
        presenter_jeu()
        # et on lance la
        # boucle événementielle principale
        fenetre.mainloop()
    # end def
     
    def presenter_jeu ():
        "on affiche ici une présentation du jeu"
        # on commence toujours par effacer le canevas graphique
        # qui nous fait office d'écran de jeu
        canvas.delete(ALL)
        # on affiche un titre
        # par rapport au centre de l'écran de jeu
        canvas.create_text(
            center_x, center_y - 100,
            text="Terrain miné",
            font="sans 16 bold",
            fill="navajowhite2",        # couleur du texte
        )
        # on affiche des règles du jeu succinctes
        canvas.create_text(
            center_x, center_y + 30,
            text="""\
    Règles du jeu:
     
    Vous devez déplacer une grosse boule vers un carré placé en bas de l'écran.
    Malheureusement pour vous, le terrain est miné !
    Saurez-vous atteindre votre but sans vous faire exploser ?
    Utilisez les flèches du clavier pour vous déplacer.
            """,
            justify=LEFT,
            font="sans 10 bold italic",
            fill="Pale Goldenrod",
            width=0.8 * c_width,        # 80% de la largeur totale
        )
        # on s'assure que le joueur pourra (re)jouer
        bouton_jouer.configure(
            text="Jouer !", command=nouvelle_partie, state=NORMAL
        )
    # end def
     
    def nouvelle_partie ():
        "on réinitialise une nouvelle partie ici"
        # init variables globales
        global tid_joueur, tid_mines
        # on autorise le joueur à arrêter la partie quand il le souhaite
        bouton_jouer.configure(
            text="Stop !", command=arreter_partie, state=NORMAL
        )
        # on efface le canevas graphique
        canvas.delete(ALL)
        # on crée l'avatar du joueur (boule)
        creer_joueur()
        # on crée le carré d'arrivée
        creer_carre_final()
        # on mine le terrain
        miner_terrain()
        # on associe les touches fléchées du clavier
        # à nos propres fonctions de gestion du mouvement
        fenetre.bind_all("<Up>", deplacer_haut)
        fenetre.bind_all("<Down>", deplacer_bas)
        fenetre.bind_all("<Left>", deplacer_gauche)
        fenetre.bind_all("<Right>", deplacer_droite)
        # c'est ici qu'on lance les boucles inscrites dans le temps
        tid_joueur = fenetre.after(100, boucle_joueur)
        # les mines aussi vont avoir leur propre cycle de vie
        tid_mines = fenetre.after(1000, boucle_mines)
    # end def
     
    def creer_joueur ():
        """
            on crée l'avatar du joueur;
            ici le joueur est représenté par une grosse boule;
            on conserve l'identifiant de l'objet sur le canevas;
            ça nous servira plus tard;
            on prend des coordonnées au hasard;
        """
        # init variables globales
        global diametre_boule, rayon
        global boule_x, boule_y
        global sens_x, sens_y, pas
        global boule_joueur
        # inits
        diametre_boule = 20         # diamètre de la boule
        rayon = diametre_boule // 2
        boule_x = diametre_boule + random.randint(0, c_width - diametre_boule)
        boule_y = diametre_boule + random.randint(0, 10)
        sens_x, sens_y = (0, 0)     # sens de déplacement initial
        pas = random.randint(2, 5)  # quantité de déplacement (pixels)
        # on dessine l'avatar joueur (boule)
        boule_joueur = canvas.create_oval(
            boule_x - rayon, boule_y - rayon,
            boule_x + rayon, boule_y + rayon,
            outline="ivory2",       # couleur du contour
            width=1,                # épaisseur du trait de contour (pixels)
            fill="light sky blue",  # couleur du remplissage
        )
    # end def
     
    def creer_carre_final ():
        """
            on crée le carré final (carré d'arrivée);
            on conserve l'identifiant de l'objet sur le canevas;
            ça nous servira plus tard;
            on prend des coordonnées au hasard;
        """
        # init variables globales
        global taille_carre, demi_carre
        global carre_x, carre_y
        global carre_final
        # on crée le carré d'arrivée
        taille_carre = diametre_boule + 6
        demi_carre = taille_carre // 2
        carre_x = 10 + random.randint(0, c_width - taille_carre - 10)
        carre_y = c_height - taille_carre - random.randint(5, 20)
        # on dessine le carré final (arrivée)
        carre_final = canvas.create_rectangle(
            carre_x - demi_carre, carre_y - demi_carre,
            carre_x + demi_carre, carre_y + demi_carre,
            outline="ivory",        # couleur du contour
            width=1,                # épaisseur du trait de contour (pixels)
            fill="palegreen1",      # couleur du remplissage
        )
    # end def
     
    def miner_terrain ():
        "on mine le terrain au début d'une partie"
        # on choisit un nombre au hasard
        nombre_mines = random.randint(10, 20)
        # on boucle pour poser autant de mines
        for i in range(nombre_mines):
            # on pose une mine au hasard
            poser_mine()
        # end for
    # end def
     
    def poser_mine ():
        """
            on pose une mine au hasard, mais jamais dans le voisinage
            immédiat du joueur;
        """
        # init variables locales
        tailles = [8, 10, 12]
        couleurs = ["sandy brown", "peru", "sienna1", "coral1"]
        couleur_contour = "burlywood1"
        # on boucle tant que ce n'est pas bon
        # ici, on bouclera cent fois (par précaution)
        # et on abandonnera si on n'y arrive pas
        for i in range(100):
            # on choisit de nouvelles coordonnées au hasard
            mine_x = random.randint(0, c_width)
            mine_y = random.randint(0, c_height)
            # les mines ont une taille variable;
            taille_mine = random.choice(tailles)
            # on recherche les collisions avec d'autres objets
            collisions = canvas.find_overlapping(
                *b_rect(mine_x, mine_y, taille_mine)
            )
            # aucun objet dans le voisinage ?
            if not collisions:
                # on choisit une couleur parmi une palette
                color = random.choice(couleurs)
                # on peut poser notre mine !
                canvas.create_oval(
                    b_rect(mine_x, mine_y, taille_mine//2),
                    outline=couleur_contour,
                    width=1,        # épaisseur de trait de contour (pixels)
                    fill=color,     # couleur du remplissage
                )
                # on remonte la boule joueur
                # au premier plan d'affichage
                canvas.tag_raise(boule_joueur, ALL)
                # c'est bon, on a posé notre mine
                # on peut quitter la boucle
                break
            # end if
        # end for
    # end def
     
    def b_rect (x, y, size):
        """
            retourne les coordonnées (top, left, bottom, right) d'un
            rectangle de délimitation autour d'un point P(x, y);
        """
        # rectangle d'influence (bounding rectangle)
        return (x - size, y - size, x + size, y + size)
    # end def
     
    def boucle_joueur ():
        "boucle temporelle qui gère les mouvements du joueur"
        # init variables globales
        global boule_x, boule_y
        global tid_joueur
        # le joueur a atteint le carré final ?
        if carre_x - demi_carre < boule_x < carre_x + demi_carre and \
                carre_y - demi_carre < boule_y < carre_y + demi_carre:
            # bravo ! c'est gagné !
            return bravo()
        # end if
        # on recherche des collisions
        collisions = canvas.find_overlapping(*canvas.bbox(boule_joueur))
        # le joueur a heurté autre chose que le carré final ?
        if len(collisions) > 1 and carre_final not in collisions:
            # aïe ! dommage !
            return game_over()
        # end if
        # tout est OK on déplace le joueur
        boule_x = (boule_x + sens_x * pas) % c_width
        boule_y = (boule_y + sens_y * pas) % c_height
        canvas.coords(
            boule_joueur,
            boule_x - rayon, boule_y - rayon,
            boule_x + rayon, boule_y + rayon,
        )
        # on boucle à nouveau dans le temps
        tid_joueur = fenetre.after(50, boucle_joueur)
    # end def
     
    def boucle_mines ():
        "boucle temporelle qui gère la vie des mines"
        # init variables globales
        global tid_mines
        # on pose une mine de temps en temps
        poser_mine()
        # prochaine mine dans... (millisecondes)
        delai = random.randint(1000, 2000)
        # on relance la boucle après ce délai
        tid_mines = fenetre.after(delai, boucle_mines)
    # end def
     
    def bravo ():
        "super ! le joueur a réussi !"
        # on affiche l'écran final
        ecran_final(
            titre="BRAVO",
            sous_titre="C'est gagné !",
            couleur_titre="lemon chiffon",
            couleur_sous_titre="pale green",
        )
    # end def
     
    def game_over ():
        "c'est ballot ! le joueur a perdu !"
        # on affiche l'écran final
        ecran_final(
            titre="GAME OVER",
            sous_titre="C'est perdu !",
            couleur_titre="firebrick1",
            couleur_sous_titre="floral white",
        )
    # end def
     
    def arreter_partie ():
        "le joueur souhaite arrêter la partie"
        # on affiche l'écran final
        ecran_final(
            titre="ABANDON",
            sous_titre="Partie annulée !",
            couleur_titre="gold",
            couleur_sous_titre="light grey",
        )
    # end def
     
    def ecran_final (**kw):
        "on effectue ici des opérations communes à tous les écrans finaux"
        # on bloque les clics intempestifs sur le bouton 'jouer'
        bouton_jouer.configure(state=DISABLED)
        # on stoppe les boucles temporelles qui pourraient
        # éventuellement être encore en cours d'exécution
        arreter_boucles()
        # on efface le canevas graphique
        canvas.delete(ALL)
        # on récupère le titre et sa couleur
        titre = kw.get("titre") or ""
        couleur = kw.get("couleur_titre") or "white"
        # on affiche le titre
        canvas.create_text(
            center_x, center_y - 40,
            text=titre,
            font="sans 36 bold",
            fill=couleur,
        )
        # on récupère le sous-titre et sa couleur
        sous_titre = kw.get("sous_titre") or ""
        couleur = kw.get("couleur_sous_titre") or "white"
        # on affiche le sous-titre
        canvas.create_text(
            center_x, center_y,
            text=sous_titre,
            font="sans 16 bold italic",
            fill=couleur,
        )
        # on relance presenter_jeu() après @delai
        # avec toutefois un minimum de 1 seconde
        delai = kw.get("delai") or 2000     # valeur par défaut
        fenetre.after(max(1000, delai), presenter_jeu)
    # end def
     
    def arreter_boucles ():
        "on arrête les boucles temporelles susceptibles de tourner encore"
        # init variables globales
        global tid_joueur, tid_mines
        # stooop !
        fenetre.after_cancel(tid_joueur)
        fenetre.after_cancel(tid_mines)
        # RAZ thread ids
        tid_joueur = tid_mines = 0
    # end def
     
    def deplacer_haut (event=None):
        "on déplace l'avatar du joueur vers le haut"
        # init variables globales
        global sens_x, sens_y
        # grâce à la boucle du jeu,
        # nous n'avons pas besoin de plus que ça
        sens_x, sens_y = (0, -1)
    # end def
     
    def deplacer_bas (event=None):
        "on déplace l'avatar du joueur vers le bas"
        # init variables globales
        global sens_x, sens_y
        # grâce à la boucle du jeu,
        # nous n'avons pas besoin de plus que ça
        sens_x, sens_y = (0, 1)
    # end def
     
    def deplacer_gauche (event=None):
        "on déplace l'avatar du joueur vers la gauche"
        # init variables globales
        global sens_x, sens_y
        # grâce à la boucle du jeu,
        # nous n'avons pas besoin de plus que ça
        sens_x, sens_y = (-1, 0)
    # end def
     
    def deplacer_droite (event=None):
        "on déplace l'avatar du joueur vers la droite"
        # init variables globales
        global sens_x, sens_y
        # grâce à la boucle du jeu,
        # nous n'avons pas besoin de plus que ça
        sens_x, sens_y = (1, 0)
    # end def
     
    # ------------------- FIN DU PROGRAMME ---------------------------------
     
    # ce script est automatiquement lancé grâce à ceci :
     
    # /!\ à connaître par coeur /!\
    if __name__ == "__main__":
        # lancer le programme
        debut_jeu()
    # end if
    Amusez-vous bien !

    @+.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 059
    Points : 1 396
    Points
    1 396
    Par défaut
    je serai tenté de recoder avec pygame.
    je vais réfléchir sur un algo pour placer les mines.

  3. #3
    Membre actif Avatar de Kurodiam
    Inscrit en
    Décembre 2013
    Messages
    208
    Détails du profil
    Informations forums :
    Inscription : Décembre 2013
    Messages : 208
    Points : 215
    Points
    215
    Par défaut
    Python est le plus cool

  4. #4
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par josmiley Voir le message
    je serai tenté de recoder avec pygame.
    Pourquoi pas ? Ca peut faire un chouette défi.

    est-ce que le code vérifie la faisabilité du parcours ?
    Non, seule la dépose de mines vérifie qu'on ne pose pas dans le voisinage immédiat d'autres objets, y compris du joueur.

    Jetez un oeil au code : non seulement il est court, mais de plus il est abondamment commenté et codé de façon scolaire (je l'ai écrit ce matin pour illustrer un tutoriel Python à l'attention des élèves ISN).

    L'idée du jeu m'est venue tout naturellement : il fallait que le code soit (très) court et qu'il synthétise bien l'ensemble des questions posées l'année dernière par les élèves.

    Algorithmiquement parlant, ce jeu est simpliste :

    1. On place une boule représentant le joueur à une position de départ aléatoire.
    2. On place de même le carré d'arrivée à une position aléatoire
    3. On mine le terrain avec un nb aléatoire de mines allant de 10 à 20 mines au départ
    4. On lance la boucle de jeu : une boucle de gestion des mouvements du joueur et une boucle de cycle de vie des mines
    5. Dans la boucle joueur on vérifie si la boule est arrivée dans le carré final si oui bravo() sinon on vérifie les collisions avec les mines si oui game_over() sinon on calcule les nouvelles positions de la boule et on boucle sur soi-méme dans le temps
    6. Dans la boucle des mines, on pose une mine au hasard puis on attend un délai aléatoire avant de recommencer, de sorte que plus le temps passe et plus le terrain est miné

    Rien de bien compliqué, en somme.

    A la base, ce jeu sert d'exemple pour mon tutoriel, mais j'ai pensé qu'en le publiant ici, ça donnerait une occasion à qui veut de s'en donner à coeur joie et de laisser libre cours à son imagination la plus débridée qui soit.

    Je suis sûr qu'en se basant sur le concept, on peut inventer des variantes absolument délirantes.

    A vous de jouer.

    @+.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 059
    Points : 1 396
    Points
    1 396
    Par défaut
    Citation Envoyé par tarball69 Voir le message
    6. Dans la boucle des mines, on pose une mine au hasard...
    pas vraiment au hasard puisqu'il n'y a pas de chevauchement des mines, c'est justement sur cet algo que je vais me pencher: Ne pas placer une mine au hasard, mais à un emplacement libre.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par josmiley Voir le message
    pas vraiment au hasard puisqu'il n'y a pas de chevauchement des mines, c'est justement sur cet algo que je vais me pencher: Ne pas placer une mine au hasard, mais à un emplacement libre.
    Je résumais => les positions des mines sont aléatoires puis il y a vérification de collisions éventuelles, si collision on cherche une nouvelle position au hasard sinon on mine.

    Maintenant, en pygame, je ne sais pas. Il y a probablement une fonctionnalité qui gère les collisions, enfin, je crois, je ne connais pas pygame.

    @+.

  7. #7
    Membre actif Avatar de Kurodiam
    Inscrit en
    Décembre 2013
    Messages
    208
    Détails du profil
    Informations forums :
    Inscription : Décembre 2013
    Messages : 208
    Points : 215
    Points
    215
    Par défaut
    euh .... j’espère que Jamie va quand même revenir

  8. #8
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Kurodiam Voir le message
    euh .... j’espère que Jamie va quand même revenir
    ??? Jamie ???

  9. #9
    Membre actif Avatar de Kurodiam
    Inscrit en
    Décembre 2013
    Messages
    208
    Détails du profil
    Informations forums :
    Inscription : Décembre 2013
    Messages : 208
    Points : 215
    Points
    215
    Par défaut
    Je parle de celui qui est doué en anglais

  10. #10
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Kurodiam Voir le message
    Je parle de celui qui est doué en anglais
    Quel rapport avec le jeu ici présent ?

    @+.

  11. #11
    Membre actif Avatar de Kurodiam
    Inscrit en
    Décembre 2013
    Messages
    208
    Détails du profil
    Informations forums :
    Inscription : Décembre 2013
    Messages : 208
    Points : 215
    Points
    215
    Par défaut
    Désolé , aucun ^^

Discussions similaires

  1. Python => Aide sur les fonctions min() et max() de Python
    Par PythonNovices dans le forum Général Python
    Réponses: 2
    Dernier message: 30/12/2014, 16h28
  2. [Jeu python] Solutions à mes problémes
    Par moithibault dans le forum Général Python
    Réponses: 1
    Dernier message: 12/06/2010, 12h09
  3. Réponses: 2
    Dernier message: 02/11/2009, 15h25
  4. Créer un jeu.. Python est le bon ?
    Par Miksimus dans le forum Programmation multimédia/Jeux
    Réponses: 11
    Dernier message: 06/02/2009, 22h31
  5. Réponses: 2
    Dernier message: 27/05/2008, 13h56

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