Astre3.0 : casse briques

Description

Une nouvelle version du casse-briques que j'avais posté il y a quelques années.
L'aspect reste inchangé, les modifications interviennent surtout sur le petit moteur de jeu qui se voit grandement allégé par l'utilisation de la POO qui facilite l'interaction entre objets.

Source / Exemple :


# -*- coding: cp1252 -*-
################################################################################
#                                                                              #
#                             Astres 3.0                                       #
#                                                                              #
#                         Genre : Casse-briques                                #   
#                         Langage : Python 2.6                                 #
#                       Auteur : Guillaume Michon                              #
#                           Date 22/04/2013                                    #
#                                                                              #
################################################################################
from ressources2 import Ressources
from module_scores import *
from module_edition import *
from classeSprite5c import *

from Tkinter import *

from math import cos,sin,radians,sqrt,fabs,atan2
from random import randrange

import pickle
import tkFileDialog
import os
import glob

#-----------------  Chargement des tableaux -------------------#
def tableaux_de_base(event):
    """Appel le chargement des tableaux de base par défaut."""

    chargement("tableau.cb")

def tableaux_personnels(event):
    """Ouverture d'une fenêtre de dialogue contenant toutes les
        séries de taleaux.(touche 3)"""
     
    cheminFichier = tkFileDialog.askopenfilename(filetypes = [("Liste de Tableaux","*.cb")])
    (filepath, nomFichier) = os.path.split(cheminFichier)
    if nomFichier != "":
        chargement(nomFichier)

def chargement(nomFichier):
    """Chargement du fichier contenant une serie de tableaux et
        les scores correspondants à cette série."""
    global nomTableau,listeTableaux,scoresEtTableaux

    nomTableau = nomFichier

    fichier = open(nomFichier,'r')
    scoresEtTableaux = pickle.load(fichier)
    listeTableaux = scoresEtTableaux[1]
    fichier.close
    nouvelle_partie()

#------- Création des briques en fonction du tableau courant ------#
def creation_tableau():
    """L'espace de jeu est redessiné en fonction du tableau courant"""

    #--- on efface tout
    can.delete(ALL)

    #--- on reaffiche les indications en jeu 
    can.create_image(319,329,image=ressources.imageFond)    
    raquette.textePoints = can.create_text(10,5,text="SCORE : "+str(raquette.nombrePoints),anchor=NW,font="Century 10 normal bold",fill='white')    
    can.create_text(200,5,text="Menu : M",anchor=NW,font="Century 10 normal bold",fill='white')    
    can.create_text(350,5,text="Pause : P",anchor=NW,font="Century 10 normal bold",fill='white')
    raquette.texteVie = can.create_text(590,5,text=" X "+str(raquette.nombreVie),anchor=NW,font="Century 10 normal bold",fill='white')
    can.create_image(550,8,anchor=NW,image=ressources.image_raquetteVie)    
    can.create_text(10,640,text="ASTRE 3.0",anchor=NW,font="Century 10 normal bold",fill='white')
    Bonus.textBonus = can.create_text(638,640,text='',anchor=NE,font="Century 10 normal bold",fill='white')
    
    #--- on remet la raquette à son état initial
    raquette.imageSprite = Raquette.imageNormale
    raquette.caneva.itemconfigure(raquette.imageID,image=raquette.imageSprite)
    raquette.set_dimension()
    raquette.place()
    raquette.tableauCibles = []

    #--- on reitinialise les variables de classes
    Sprite.matriceJeu = listeTableaux[tableauCourant]

    Sprite.tableauSpritesMobiles = []
    Sprite.tableauSpritesMobiles.append(raquette)

    Brique.tableauObjetsIdentiques = []    
    Brique.tableauCibles = []
    Brique.tableauBriquesCassables = []
    
    Obus.tableauObjetsIdentiques = []
    Obus.tableauCibles = []
    
    Bonus.tableauObjetsIdentiques = []
    Bonus.tableauCibles = []

    #------------------------------------------------------------------------------------------------------------------------
    # la matrice des briques de chaque tableau est remplie de :
    #           - (chiffre,sens de déplacement) : pour une brique de soliditée 'chiffre' et de mouvement 'sens de déplacement'
    #   ou de   - [] : si il n'y a pas de brique

    for indiceLigne in range(0,len(listeTableaux[tableauCourant])):
        for indiceColonne in range(0,len(listeTableaux[tableauCourant][0])):
            briqueCourante = listeTableaux[tableauCourant][indiceLigne][indiceColonne]
            if briqueCourante:
                # chaque objet 'Brique' est créé avec l'image d'indice 'chiffre' dans le tableau : 'tableauImagesBriques'
                brique = Brique(Brique.tableauImagesBriques[briqueCourante[0]])
                # sa soliditée est égale à ce 'chiffre'
                brique.durabilitee = briqueCourante[0]
                # si il est nul c'est une brique incassable, donc on ne l'ajoute pas au tableau 'tableauBriquesCassables'
                # qui permet au moteur de jeu de déterminer quand le tableau est terminé
                if brique.durabilitee != 0:
                    Brique.tableauBriquesCassables.append(brique)
                # le nombre de points attribués quand la brique disparraît
                brique.pointsAttribues = 50
                # positionnement de la brique dans le canvas
                brique.indiceLigne = indiceLigne
                brique.indiceColonne = indiceColonne
                brique.set_position(indiceColonne*(brique.largeur+2),indiceLigne*(brique.hauteur+2))
                # comportement de la brique vis-à-vis des bords
                brique.reaction_bord_droit = "rebond"
                brique.reaction_bord_gauche = "rebond"
                brique.reaction_bord_haut = "rebond"
                brique.reaction_bord_bas = "rebond"
                Brique.tableauObjetsIdentiques.append(brique)
                # si c'est une brique en mouvement on lui imprime une vitesse et on l'ajoute au tableau des sprites mobiles
                if briqueCourante[1] == 'horizontal':
                    brique.vitesseHorizontale = 4
                    brique.vitesse_X = brique.vitesseHorizontale
                    brique.sensDeplacementH = True
                    Sprite.tableauSpritesMobiles.append(brique)
                elif briqueCourante[1] == 'vertical':
                    brique.vitesseVerticale = 4
                    brique.vitesse_Y = brique.vitesseVerticale
                    brique.sensDeplacementV = True
                    brique.rebord_bas = brique.rebord_bas - (2*brique.hauteur)
                    Sprite.tableauSpritesMobiles.append(brique)
                # les objets 'Obus' l'auront pour cible
                Obus.tableauCibles.append(brique)
                # On détermine par un jet de 100,si la brique fera pop un bonus quand elle sera détruite 
                hazard = randrange(0,100)
                if hazard <= 15:
                    brique.briqueBonus = True

                # on positionne succesivement les objets 'brique' dans une matrice pour résoudre certain cas de collision (cf. méthodes de collision de l'objet brique)
                Sprite.matriceJeu[brique.indiceLigne][brique.indiceColonne] = brique

                brique.place()

    determination_briques_cibles()
    creation_balle()

def determination_briques_cibles():
    """Fonction qui met dans le tableau des cibles de chaque objets 'Brique' en mouvement créé, toutes les objets 'Brique' sur sa trajectoire."""

    for brique in Brique.tableauObjetsIdentiques:
        if brique.sensDeplacementH :
            for briqueCible in Brique.tableauObjetsIdentiques:
                if briqueCible.indiceLigne == brique.indiceLigne and briqueCible != brique:
                    brique.tableauCibles.append(briqueCible)
        if brique.sensDeplacementV :
            for briqueCible in Brique.tableauObjetsIdentiques:
                if briqueCible.indiceColonne == brique.indiceColonne and briqueCible != brique:
                    brique.tableauCibles.append(briqueCible)
                    
#----- Création de la 1ère balle pour le tableau courant ------#
def creation_balle():
    """Fonction qui crée la 1ère balle lors d'un nouveau tableau ou après la perte d'une vie."""
    global balle,pause

    balle = Balle(Balle.imageNormale)

    # pour la variable 'pourcentageRaquette' voir la classe Raquette
    # on considère la balle au centre à sa création donc son angle de renvoie vaut 90 degrés
    balle.pourcentageRaquette = 0.5
    balle.angleRenvoie = radians(balle.pourcentageRaquette * 180)
    balle.set_position((raquette.coord_x+(balle.pourcentageRaquette*raquette.largeur))-(balle.largeur/2),(raquette.coord_y-balle.hauteur))

    # les différentes réactions 
    balle.reaction = 'stop' # pour maintenir la balle sur la raquette (cf:mouvement())
    balle.reaction_bord_droit = "rebond"
    balle.reaction_bord_gauche = "rebond"
    balle.reaction_bord_haut = "rebond"
    balle.reaction_bord_bas = "destruction"

    # la vitesse de la balle (module et composantes)
    balle.vitesseDeBase = 10
    balle.vitesse_X = balle.vitesseDeBase * cos(balle.angleRenvoie)
    balle.vitesse_Y = -(balle.vitesseDeBase* sin(balle.angleRenvoie))

    raquette.reaction = 'rebond'
    raquette.fenetre.bind('<Button-1>',raquette.decolle_balle)
    raquette.fenetre.bind('<n>',raquette.decolle_balle)

    # variable de classe permettant d'avoir accès à toutes les balles
    Balle.tableauObjetsIdentiques = []
    Balle.tableauObjetsIdentiques.append(balle)
    # variable de classe contenant toutes les cibles de la ou des balles
    Balle.tableauCibles = []
    balle.tableauCibles.append(raquette)
    for brique in Brique.tableauObjetsIdentiques:
        balle.tableauCibles.append(brique)

    Brique.tableauCibles.append(balle)
    for brique in Brique.tableauObjetsIdentiques:
        brique.tableauCibles.append(balle)    
    Sprite.tableauSpritesMobiles.append(balle)
    balle.place()

    pause = False

    fenetre.after(250,mouvement)

#------ Mise en mouvement des sprites mobiles ------#
def mouvement():
    """Fonction principale du moteur qui déplace chaque objet contenu dans la variable de classe
       'Sprite' : 'tableauSpritesMobiles' suivant les composantes de leur vitesse."""

    global pause,tableauCourant

    for mobile in Sprite.tableauSpritesMobiles:
        mobile.oldCoord = mobile.get_position() # on sauvegarde l'ancienne position du sprite

        # si le sprite sort de l'écran et qu'aucune alternative (rebond,wrap,stop) n'est définie, sa méthode 'deplacement' renverra 'False'
        if not mobile.deplacement():
            can.delete(mobile.imageID) # alors on l'efface
            if mobile in mobile.__class__.tableauObjetsIdentiques:
                mobile.__class__.tableauObjetsIdentiques.remove(mobile) # on le retire de son groupe de classe
            Sprite.tableauSpritesMobiles.remove(mobile) # il n'est plus concerné par les déplacements
            # si c'est une balle on le retire des cibles des briques
            if isinstance(mobile,Balle):
                Brique.tableauCibles.remove(mobile)
                if not Balle.tableauObjetsIdentiques: # si c'etait la dernière balle on perd une vie
                    pause = True # on arrete tout 
                    vie_perdue() # si c'est possible une balle sera remise et on relancera cette boucle
            # si c'est un bonus on le retire des cibles de la raquette
            if isinstance(mobile,Bonus):
                Raquette.tableauObjetsIdentiques[0].tableauCibles.remove(mobile)

        mobile.newCoord = mobile.get_position() # on sauvegarde sa nouvelle position

        # on effectue alors un test de collision avec chacun des sprites cibles
        for sprite in mobile.tableauCibles:
            #if sprite.coord_y <= mobile.coord_y+mobile.hauteur or sprite.coord_y+sprite.hauteur >= mobile.coord_y:
            if mobile.test_collision(sprite) :
                mobile.set_position(mobile.oldCoord[0],mobile.oldCoord[1]) # si collision on remet le sprite à sa position avant collision

            # on détermibe alors de quel côté elle a eu lieu
            # on positionne le sprite juste au bord de celui percuté
            # et on invoque la méthode correspondant à ce côté
                # Collision par la droite"
                if mobile.coord_x + mobile.largeur <= sprite.coord_x:
                    mobile.coord_x = sprite.coord_x - mobile.largeur
                    mobile.oldCoord2 = mobile.get_position()
                    mobile.collision_droite(sprite)
                    break
                # Collision par la gauche"
                elif mobile.coord_x >= sprite.coord_x + sprite.largeur:
                    mobile.coord_x = sprite.coord_x + sprite.largeur
                    mobile.oldCoord2 = mobile.get_position()                    
                    mobile.collision_gauche(sprite)
                    break
                # Collision par le Haut"                
                elif mobile.coord_y >= sprite.coord_y + sprite.hauteur:
                    mobile.coord_y = sprite.coord_y + sprite.hauteur
                    mobile.oldCoord2 = mobile.get_position()                    
                    mobile.collision_haut(sprite)
                    break
                # Collision par le bas"
                elif mobile.coord_y + mobile.hauteur <= sprite.coord_y:
                    mobile.coord_y = sprite.coord_y - mobile.hauteur
                    mobile.oldCoord2 = mobile.get_position()                    
                    mobile.collision_bas(sprite)
                    break                    
                # il peut arriver qu'avant la collision les sprites se chevauchaient déja
                # il est alors nécessaire de prévoir une méthode gérant ce cas de figure
                else:
                    mobile.collision_deja_engagee(sprite)

    # en debut de partie ou quand le bonus 'raquette collante' est actif
    # la ou les balles sont en mode 'stop' quand elle sont au contact de la raquette,
    # elle doivent donc rester à cette position jusqu'à ce qu'elle soit libérée
    for mobile in Balle.tableauObjetsIdentiques:
        if mobile.reaction == 'stop':
            mobile.set_position((raquette.coord_x+(mobile.pourcentageRaquette*raquette.largeur))-(mobile.largeur/2),(raquette.coord_y-mobile.hauteur))        

    # si le tableau des briques cassables est vide on change de tableau ou la partie est terminée
    if not Brique.tableauBriquesCassables:
        pause = True
        if tableauCourant == len(listeTableaux)-1:
            partie_terminee()
        else:
            tableauCourant += 1
            fenetre.after(500,creation_tableau)

    # après avoir déplacer tous les sprites mobiles on les redessine
    redessine_mobiles()

    if not pause:
        fenetre.after(30,mouvement)

def redessine_mobiles():
    """Fonction qui redessine chaque sprite mobile à sa nouvelle position."""

    for mobile in Sprite.tableauSpritesMobiles:
        mobile.dessine_sprite()

def mise_en_pause(event):
    """Fonction permettant de mettre le jeu en pause"""
    global pause,textPause

    if pause:
        pause = False
        can.delete(textPause)
        fenetre.after(250,mouvement)
    else:
        textPause = can.create_text(270,250,text="PAUSE",anchor=NW,font="Century 15 normal bold",fill='white')
        pause = True

#------ Vie perdue -----------------------------#
def vie_perdue():
    """Fonction invoquée lorqu'une vie est perdue."""
    
    raquette.nombreVie -= 1

    # on reinitialise les tableaux d'objets identiques des 'Bonus' et des 'Obus' et sprites mobiles
    Bonus.tableauObjetsIdentiques = []
    Obus.tableauObjetsIdentiques = []
    Sprite.tableauSpritesMobiles = []

    # on redessine l'air de jeu 
    can.delete(ALL)
    can.create_image(319,329,image=ressources.imageFond)    
    can.itemconfigure(raquette.textePoints,state='normal')
    raquette.textePoints = can.create_text(10,5,text="SCORE : "+str(raquette.nombrePoints),anchor=NW,font="Century 10 normal bold",fill='white')    
    can.create_text(200,5,text="Menu : M",anchor=NW,font="Century 10 normal bold",fill='white')    
    can.create_text(350,5,text="Pause : P",anchor=NW,font="Century 10 normal bold",fill='white')
    can.create_image(550,8,anchor=NW,image=ressources.image_raquetteVie)
    raquette.texteVie = can.create_text(590,5,text=" X "+str(raquette.nombreVie),anchor=NW,font="Century 10 normal bold",fill='white')
    can.create_text(10,640,text="ASTRE 3.0",anchor=NW,font="Century 10 normal bold",fill='white')
    texteBonus = can.create_text(638,640,text="",anchor=NE,font="Century 10 normal bold",fill='white')
    Bonus.textBonus = can.create_text(638,640,text='',anchor=NE,font="Century 10 normal bold",fill='white')
    
    # on remet la raquette dans son état normal
    Raquette.tableauObjetsIdentiques[0].imageSprite = Raquette.imageNormale
    raquette.caneva.itemconfigure(Raquette.tableauObjetsIdentiques[0].imageID,image=Raquette.imageNormale)
    Raquette.tableauObjetsIdentiques[0].set_dimension()
    raquette.reaction = 'rebond'
    Raquette.tableauObjetsIdentiques[0].fenetre.unbind('<Button-1>')
    Raquette.tableauObjetsIdentiques[0].fenetre.unbind('n')    
    raquette.place()
    raquette.tableauCibles = []
    Sprite.tableauSpritesMobiles.append(raquette)
    
    # on réaffiche toutes les briques
    for brique in Brique.tableauObjetsIdentiques:
        brique.place()
        if brique.vitesse_X != 0 or brique.vitesse_Y != 0:
            Sprite.tableauSpritesMobiles.append(brique)

    if raquette.nombreVie == 0:
        partie_terminee()
    else:
        fenetre.after(250,creation_balle)

#--- Partie terminee ou game over -----#
def partie_terminee():
    """Verifie si le score actuel fait parti des 5 premiers"""
    global pause,nom

    pause = True
    fenetre.unbind('<Right>')
    fenetre.unbind('<Left>')
    fenetre.unbind('<KeyRelease-Right>')
    fenetre.unbind('<KeyRelease-Left>')
    fenetre.unbind('<Motion>')
    fenetre.unbind('<n>')
    fenetre.unbind('<Button-1>')
    if raquette.nombrePoints > scoresEtTableaux[0][-1][1]:
        nom = ""
        ecart = 0
        message_top()
    else:
        fenetre.after(1000,menu_principal,'m')

def message_top():
    """Ecrit le texte ammenant l'utilisateur à entrer son pseudo"""

    can.delete(ALL)
    can.create_image(319,329,image=ressources.imageFond)
    can.create_text(80,180,text="Votre score fait parti du top 5 !\n(pour cette liste de tableau)",anchor=NW,font="Century 15 normal bold",fill='white')
    can.create_text(80,240,text="Veuillez saisir votre nom (10 lettres max) :",anchor=NW,font="Century 15 normal bold",fill='white')
    fenetre.bind('<Key>',recup_nom)
    fenetre.bind('<Return>',valide_nom)
    fenetre.bind('<BackSpace>',efface_lettre)
        
    can.create_text(180,280,text=nom+"_",anchor=NW,font="Century 15 normal bold",fill='white')

def efface_lettre(event):
    """Efface une lettre de la variable nom"""
    global nom

    nom = nom[:-1]
    message_top()
    
def recup_nom(event):
    """Récupère la lettre tappée et l'ajoute à la variable 'nom'"""
    global nom

    c = event.char
    if len(nom) < 10:
        nom += c
    message_top()

def valide_nom(event):
    """Le nom est ajouté a la liste des scores.Celle-ci est triée par
        scores croissants.Le dernier score est retiré de la liste."""
    
    scoresEtTableaux[0].append((nom[:10],raquette.nombrePoints))
    tab_score = scoresEtTableaux[0]
    tab_scores_range = sorted(tab_score, key=lambda tab_score: tab_score[1],reverse=True)
    scoresEtTableaux[0] = tab_scores_range[:]
    del scoresEtTableaux[0][-1]
    fichier = open(nomTableau,'w')
    pickle.dump(scoresEtTableaux,fichier)
    fichier.close
    fenetre.unbind('<Key>')
    fenetre.unbind('<Return>')
    fenetre.unbind('<Left>')
    can.after(1000,option_scores,'4')

#------- Menu principal ----------------#
def menu_principal(event):
    """Création de l'interface de menu."""
    global pause
    
    pause = True
    fenetre.unbind('<Key>')
    fenetre.unbind('<Return>')
    fenetre.unbind('<Button-1>')
    fenetre.unbind("<Button1-Motion>")
    fenetre.unbind('<Right>')
    fenetre.unbind('<Left>')
    fenetre.unbind('7')
    fenetre.unbind('8')
    fenetre.unbind('1')
    fenetre.unbind('2')
    fenetre.unbind('3')
    fenetre.unbind('4')
    fenetre.unbind('s')
    fenetre.unbind('0')
    fenetre.unbind('g')
    fenetre.unbind('c')
    fenetre.unbind('+')
    fenetre.unbind('-')
    fenetre.unbind('h')
    fenetre.unbind('v')
    fenetre.unbind('f')
    can.delete(ALL)
    can.create_image(319,329,image=ressources.imageFond)
    can.create_text(180,200,text="A S T R E 3.0",anchor=NW,font="Century 28 normal bold",fill='white')
    can.create_text(180,250,text="1 - Nouvelle Partie",anchor=NW,font="Century 18 normal bold",fill='white')
    can.create_text(180,280,text="2 - Mode Edition",anchor=NW,font="Century 18 normal bold",fill='white')
    can.create_text(180,310,text="3 - Charger Des Tableaux",anchor=NW,font="Century 18 normal bold",fill='white')
    can.create_text(180,340,text="4 - Scores",anchor=NW,font="Century 18 normal bold",fill='white')
    can.create_text(180,370,text="5 - Quitter",anchor=NW,font="Century 18 normal bold",fill='white')
    can.create_text(440,640,text="Auteur - Guillaume Michon",anchor=NW,font="Century 10 normal bold",fill='white')
    fenetre.bind('1',tableaux_de_base)
    fenetre.bind('2',option_edition)
    fenetre.bind('3',tableaux_personnels)
    fenetre.bind('4',option_scores)
    fenetre.bind('5',quitter)

def nouvelle_partie():
    """Fonction invoquée lors d'une nouvelle partie."""
    global tableauCourant,raquette
    
    fenetre.unbind('1')
    fenetre.unbind('2')
    fenetre.unbind('3')
    fenetre.unbind('4')
    fenetre.unbind('5')
    fenetre.bind('<m>',menu_principal)
    fenetre.bind('<p>',mise_en_pause)

    # un objet raquette est créé et initialisé à chaque nouvelle partie
    raquette =  Raquette(Raquette.imageNormale)
    raquette.set_position(260,638)
    raquette.place()
    raquette.vitesseHorizontale = 20
    raquette.reaction = 'rebond'
    raquette.souris_deplacement_vertical = False
    raquette.fenetre.bind('<Right>',raquette.touche_droite)
    raquette.fenetre.bind('<Left>',raquette.touche_gauche)
    raquette.fenetre.bind('<KeyRelease-Right>',raquette.touche_droite_relache)
    raquette.fenetre.bind('<KeyRelease-Left>',raquette.touche_gauche_relache)
    raquette.fenetre.bind('<Motion>',raquette.souris)

    raquette.nombrePoints = 0
    raquette.nombreVie = 3
    raquette.seuilVieSupp = 10000
    raquette.pasSeuilVieSupp = 10000
    
    Raquette.tableauObjetsIdentiques = []
    Raquette.tableauObjetsIdentiques.append(raquette)

    # on invoque la fonction de création du premier tableau ( ou celui désiré pour un test)
    tableauCourant = 0
    creation_tableau()

def option_scores(event):
    """Fonction qui invoque la méthode d'affichage des scores."""

    fenetre.bind('<m>',menu_principal)    
    nomTableau = "tableau.cb"
    # 'scores' est définie dans le module 'module_scores'
    scores(fenetre,can,nomTableau)

def option_edition(event):
    """Fonction qui invoque le mode édition."""

    fenetre.bind('<m>',menu_principal)
    # 'edition' est définie dans le module 'module_edition'
    edition(fenetre,can)
    
def quitter(event):
    """Quitte l'application."""

    fenetre.quit()       
    fenetre.destroy()

if __name__ == '__main__':
    #--- Fenêtre Principale ---
    fenetre = Tk()
    fenetre.title("Astre 3.0")
    fenetre.iconbitmap("Fond2.ico")
    fenetre.resizable(0,0)
    hauteurEcran = fenetre.winfo_height()
    largeurEcran = fenetre.winfo_width()
    fenetre.winfo_screenwidth()
    pos_x = str(((fenetre.winfo_screenwidth()-largeurEcran)/2)-300)
    pos_y = str(((fenetre.winfo_screenheight()-hauteurEcran)/2)-300)
    pos = '+' + pos_x + '+' + pos_y
    fenetre.geometry(pos)

    #--- Canevas Principal ---
    can = Canvas(fenetre,bg='black',width=638,height=658)
    can.pack()

    #--- Création d'un objet 'ressources' contenant les images et sons ---
    ressources = Ressources()

    Sprite.fenetre = fenetre
    Sprite.caneva = can

    Raquette.imagePetite = ressources.image_raquettePetite
    Raquette.imageNormale = ressources.image_raquette
    Raquette.imageGrande = ressources.image_raquetteGrande
    Raquette.imageGun = ressources.image_raquetteGun
    Raquette.imageCollante = ressources.image_raquetteCollante

    Balle.imageNormale = ressources.image_balle
    Balle.imageTueuse = ressources.image_balleTueuse

    Brique.imageIncassable = ressources.image_briqueIncassable
    Brique.imageUnCoup = ressources.image_brique1coups
    Brique.imageDeuxCoups = ressources.image_brique2coups
    Brique.imageTroisCoups = ressources.image_brique3coups
    Brique.tableauImagesBriques = [Brique.imageIncassable,Brique.imageUnCoup,Brique.imageDeuxCoups,Brique.imageTroisCoups]
    
    Bonus.tableauBonus = []
    Bonus.tableauBonus.append((ressources.image_bonusMultiball,'multi balle'))    
    Bonus.tableauBonus.append((ressources.image_bonusBalleTueuse,'balle tueuse'))
    Bonus.tableauBonus.append((ressources.image_bonusGun,'raquette gun'))    
    Bonus.tableauBonus.append((ressources.image_bonusRaquettePetite,'petite raquette'))
    Bonus.tableauBonus.append((ressources.image_bonusRaquetteNormale,'raquette normale'))
    Bonus.tableauBonus.append((ressources.image_bonusRaquetteGrande,'grande raquette'))
    Bonus.tableauBonus.append((ressources.image_bonusColle,'raquette collante'))
    Bonus.tableauBonus.append((ressources.image_bonusPoints,'bonus points'))
    Bonus.tableauBonus.append((ressources.image_bonusVie,'bonus vie'))
    Bonus.tableauBonus.append((ressources.image_bonusBallelente,'balle lente'))
    Bonus.tableauBonus.append((ressources.image_bonusBalleNormale,'balle normale'))    
    Bonus.tableauBonus.append((ressources.image_bonusBallerapide,'balle rapide'))
    
    Obus.imageObus = ressources.image_obus
    menu_principal('m')    
    fenetre.mainloop()

Codes Sources

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.