1/5 (11 avis)
Vue 32 556 fois - Téléchargée 4 582 fois
# -*- coding: cp1252 -*- ################################### # # # Programme : Space invaders # # Auteur : Shakan972 # # Date de creation : 13/04/07 # # # ################################### ########################################## # # # Importations des fonctions nécessaires # # # ########################################## from Tkinter import * from random import * import time import pickle ############################ # # # Définition des fonctions # # # ############################ # Cette fonction affiche l'écran de présentation du jeu def EcranDePresentation(): global DebutJeu if DebutJeu!=1: AffichageScore.configure(text="",font=('Fixedsys',16)) AffichageVie.configure(text="",font=('Fixedsys',16)) can.delete(ALL) fen.after(1500,Titre) # On afficher le nom du jeu à l'écran def Titre(): global DebutJeu if DebutJeu!=1: can.create_text(320,240,font=('Fixedsys',24),text="SPACE INVADERS",fill='blue') fen.after(2000,Titre2) # On affiche le nom de l'auteur ( It's me !! :p ) def Titre2(): global DebutJeu if DebutJeu!=1: can.create_text(320,270,font=('Freshbot',18),text="By Shakan972",fill='red') fen.after(3000,LoadMeilleurScore) # Cette fonction va permettre d'enregistrer # le meilleur score def SaveMeilleurScore(resultat): FichierScore=open('HighScore','r') lecture=pickle.load(FichierScore) # Si le score réalisé à la fin de la partie # est supérieur à celui déjà enregistré dans le fichier # alors on remplace ce dernier par le nouveau score record if resultat>lecture: FichierScore=open('HighScore','w') pickle.dump(resultat,FichierScore) FichierScore.close() fen.after(2000,MessageRecord) else: fen.after(15000,EcranDePresentation) FichierScore.close() # Cette fonction affiche un message # lui indiquant qu'il a établit un # nouveau record :D def MessageRecord(): can.delete(ALL) can.create_text(320,240,font=('Georgia',18),text="Vous avez établi un nouveau record !!",fill='red') fen.after(3000,LoadMeilleurScore) # Quant à cette fonction elle va permettre # de lire le meilleur score afin de l'afficher def LoadMeilleurScore(): global DebutJeu if DebutJeu!=1: FichierScore=open('HighScore','r') lecture=pickle.load(FichierScore) can.delete(ALL) can.create_text(320,240,font=('Fixedsys',24),text="HIGH SCORE",fill='blue') can.create_text(320,270,font=('Fixedsys',24),text=str(lecture),fill='blue') FichierScore.close() fen.after(3000,EcranDePresentation) # Cette fonction permet de vérifier # l'existence d'un fichier def existe(fname): try: f=open(fname,'r') f.close() return 1 except: return 0 # Cette fonction permet de réinitialiser le jeu # selon la volonté du joueur de recommencer une partie def new_game(): global xe,ye,xe2,ye2,xe3,ye3,LimiteAvancement,dx,ListeCoordEnnemis,ListeEnnemis,ObusEnnemi,flag,photo,NbreEnnemis,Score,ViesJoueur global ListeAbri,CoordonneesBriques,projectile,feu,feuEnnemi,PasAvancement global dyobus,dyobusEnnemi,DebutJeu,BonusActif,dxeb,EnnemiBonus,Mort,photo,PasMax,NbreEnRangees DebutJeu=1 # On remet l'image d'origine photo=PhotoImage(file='earth.gif') can.create_image(320,240,image=photo) Mort=0 # On efface tout à l'écran can.delete(ALL) can.create_image(320,240,image=photo) # Coordonnées de départ des ennemis # pour chaque catégorie xe,ye=20,20 xe2,ye2=20,80 xe3,ye3=20,160 LimiteAvancement=1 if len(ObusEnnemi)==1: can.delete(ObusEnnemi[0]) dx=1 # Pas d'avancement d'un obus # tiré par le joueur dyobus=20 # Pas d'avancement d'un obus # tiré par un ennemi dyobusEnnemi=10 feu=0 ViesJoueur=3 Score=0 feuEnnemi=0 Ennemis1=[] Ennemis2=[] Ennemis3=[] ListeEnnemis=[Ennemis1,Ennemis2,Ennemis3] Ennemis=[] projectile=[] CoordEnnemis1=[] CoordEnnemis2=[] CoordEnnemis3=[] ListeCoordEnnemis=[CoordEnnemis1,CoordEnnemis2,CoordEnnemis3] NbreEnnemis1=6 NbreEnnemis2=6 NbreEnnemis3=6 PasAvancement=0 NbreEnnemis=[NbreEnnemis1,NbreEnnemis2,NbreEnnemis3] v=0 BonusActif=0 dxeb=5 EnnemiBonus=[] Creation_Abris() Creation_CanonMobile() # On détermine de manière aléatoire # le nombre de temps avant qu'apparaisse # le premier ennemi bonus du jeu :) fen.after(randrange(60000,100000,100),CreationEnnemiBonus) AffichageScore.configure(text="Score : "+str(Score),font=('Fixedsys',16)) AffichageVie.configure(text="Lives : "+str(ViesJoueur),font=('Fixedsys',16)) # Appel des fonctions de création des ennemis # pour recréer un bataillon de vaisseaux hostiles # prêts à en découdre à nouveau avec le joueur !! while v<6: Ennemi_Categorie1() Ennemi_Categorie2() Ennemi_Categorie3() v+=1 flag=1 # Cette fonction permet de créer les abris # assurant la défense en papier du canon mobile XD def Creation_Abris(): global ListeAbris,CoordonneesBriques ListeAbris=[] CoordonneesBriques=[] i=0 x=40 y=340 while i<3: limX=x+120 limY=y+60 departx=x while y<limY: while x<limX: ListeAbris.append(can.create_rectangle(x,y,x+20,y+20,fill='grey')) CoordonneesBriques.append([x,y]) x+=20 x=departx y+=20 i+=1 x+=220 y-=60 # Cette fonction permet de créer le nerf de la guerre # ==> Le canon mobile \o/ def Creation_CanonMobile(): global canon,xc1,xc2,yc1,yc2 canon=[] xc1=20 yc1=440 # Création du canon canon.append(can.create_rectangle(xc1,yc1,xc1+20,yc1+20,fill='green')) xc2=xc1-20 yc2=yc1+20 # Création de la plate-forme du canon canon.append(can.create_rectangle(xc2,yc2,xc2+60,yc2+20,fill='green')) # Les 3 fonctions ci-dessous vont permettre de créer les ennemis du jeu # Création de la 1er catégorie d'ennemis du jeu def Ennemi_Categorie1(): global ListeEnnemis,ListeCoordEnnemis,xe,ye ListeCoordEnnemis[0].append([xe,ye]) Ennemis=[] Ennemis.append(can.create_rectangle(xe,ye,xe+60,ye+20,fill='blue')) Ennemis.append(can.create_rectangle(xe,ye,xe+20,ye+40,fill='blue')) Ennemis.append(can.create_rectangle(xe+40,ye,xe+60,ye+40,fill='blue')) ListeEnnemis[0].append(Ennemis) xe=xe+80 # Création de la 2e catégorie d'ennemis du jeu def Ennemi_Categorie2(): global ListeEnnemis,ListeCoordEnnemis,xe2,ye2 ListeCoordEnnemis[1].append([xe2,ye2]) Ennemis=[] Ennemis.append(can.create_rectangle(xe2,ye2,xe2+20,ye2+40,fill='violet')) Ennemis.append(can.create_rectangle(xe2+40,ye2,xe2+60,ye2+40,fill='violet')) Ennemis.append(can.create_rectangle(xe2+20,ye2+20,xe2+40,ye2+60,fill='violet')) ListeEnnemis[1].append(Ennemis) xe2=xe2+80 # Création de la 3e catégorie d'ennemis du jeu def Ennemi_Categorie3(): global ListeEnnemis,ListeCoordEnnemis,xe3,ye3 ListeCoordEnnemis[2].append([xe3,ye3]) Ennemis=[] Ennemis.append(can.create_rectangle(xe3+20,ye3,xe3+40,ye3+60,fill='brown')) Ennemis.append(can.create_rectangle(xe3,ye3+20,xe3+60,ye3+40,fill='brown')) ListeEnnemis[2].append(Ennemis) xe3=xe3+80 # Cette fonction va permettre de créer # l'ennemi bonus du jeu def CreationEnnemiBonus(): global EnnemiBonus,xeb,yeb,BonusActif,DebutJeu,CoordEnnemiBonus,dxeb,flag if flag!=0: if BonusActif!=1: BonusActif=1 dxeb=5 hasard=randrange(0,10,1) if hasard>=5: xeb=0 dxeb=dxeb else: xeb=630 dxeb=-dxeb yeb=randrange(80,400,10) EnnemiBonus.append(can.create_oval(xeb,yeb,xeb+35,yeb+15,fill='red')) EnnemiBonus.append(can.create_oval(xeb+5,yeb+5,xeb+10,yeb+10,fill='yellow')) EnnemiBonus.append(can.create_oval(xeb+15,yeb+5,xeb+20,yeb+10,fill='yellow')) EnnemiBonus.append(can.create_oval(xeb+25,yeb+5,xeb+30,yeb+10,fill='yellow')) # Cette fonction va permettre d'animer # le mouvement de l'ennemi bonus def AnimationEnnemiBonus(): global EnnemiBonus,xeb,yeb,dxeb,xtir,ytir,DebutJeu,BonusActif,projectile,flag,feu,Score if flag!=0 and DebutJeu!=0 and BonusActif!=0 : # Si l'ennemi bonus atteint l'autre bout de l'écran # il s'auto-détruit !! XD if dxeb>0: if xeb>=640: BonusActif=0 can.delete(EnnemiBonus[0]) can.delete(EnnemiBonus[1]) can.delete(EnnemiBonus[2]) can.delete(EnnemiBonus[3]) xeb=0 yeb=0 EnnemiBonus=[] # Détermination aléatoire du temps d'appel # de la fonction qui va permettre de procéder # à la création d'un nouvel ennemi bonus fen.after(randrange(60000,100000,100),CreationEnnemiBonus) else: if xeb<=20: BonusActif=0 can.delete(EnnemiBonus[0]) can.delete(EnnemiBonus[1]) can.delete(EnnemiBonus[2]) can.delete(EnnemiBonus[3]) xeb=0 yeb=0 EnnemiBonus=[] fen.after(randrange(60000,100000,100),CreationEnnemiBonus) # On fait l'ennemi bonus avancer xeb=xeb+dxeb if len(EnnemiBonus)!=0: can.coords(EnnemiBonus[0],xeb,yeb,xeb+35,yeb+15) can.coords(EnnemiBonus[1],xeb+5,yeb+5,xeb+10,yeb+10) can.coords(EnnemiBonus[2],xeb+15,yeb+5,xeb+20,yeb+10) can.coords(EnnemiBonus[3],xeb+25,yeb+5,xeb+30,yeb+10) # On vérifie si l'obus tiré par le joueur # touche l'ennemi bonus si tel est le cas # l'ennemi bonus est détruit et on l'efface # de l'ecran pour faire le joueur empocher 300 pts !! if feu!=0: if ytir<=yeb and ytir>=yeb-25: if xtir>=xeb-10 and xtir<=xeb+40: BonusActif=0 # On efface l'ennemi bonus # ainsi que l'obus qui l'a touché if len(projectile)!=0: can.delete(projectile[0]) can.delete(EnnemiBonus[0]) can.delete(EnnemiBonus[1]) can.delete(EnnemiBonus[2]) can.delete(EnnemiBonus[3]) # On utlise la fonction score afin # d'afficher le nombre de points gagnés # à la suite de la destruction de # l'ennemi bonus score(300,xeb,yeb,17.5,7.5) # Gain de points ==> Modification du score du joueur Score+=300 AffichageScore.configure(text="Score : "+str(Score),font=('Fixedsys',16)) # On remet les coordonnées de l'ennemi # bonus à zéro pour n'engendrer aucune # erreur xeb,yeb=0,0 xtir,ytir=0,0 # On désactive l'animation de l'obus # tiré par le joueur feu=0 EnnemiBonus=[] fen.after(randrange(15000,25000,100),CreationEnnemiBonus) # On reboucle le tout fen.after(50,AnimationEnnemiBonus) else: fen.after(50,AnimationEnnemiBonus) # Cette fonction permet d'afficher # le nombre de points gagnés à la suite # de la destruction d'un ennemi def score(donnee,x,y,x2,y2): global afficherScore afficherScore.append(can.create_text(x+x2,y+y2,font=('Fixedsys',8),text=str(donnee)+' pts',fill='red')) fen.after(1500,EffacerScore) # Cette fonction permet d'effacer # le nombre de point gagnés et affichés # suite à la destruction d'un ennemi def EffacerScore(): global afficherScore i=0 while i<len(afficherScore): can.delete(afficherScore[i]) i+=1 # La fonction ci-dessous permet # d'animer le canon mobile selon # la direction choisie par le joueur def move(dx): global xc1,xc2,yc1,yc2,ViesJoueur,flag if ViesJoueur!=0 or flag!=0: xc1=xc1+dx xc2=xc2+dx # Si on arrive au bord de l'écran # le canon mobile se retrouve bloqué # afin de ne pas aller plus loin :p if xc2<=0: xc1=20 xc2=0 can.coords(canon[0],xc1,yc1,xc1+20,yc1+20) can.coords(canon[1],xc2,yc2,xc2+60,yc2+20) elif xc2>=600: xc1=600 xc2=580 can.coords(canon[0],xc1,yc1,xc1+20,yc1+20) can.coords(canon[1],xc2,yc2,xc2+60,yc2+20) else: can.coords(canon[0],xc1,yc1,xc1+20,yc1+20) can.coords(canon[1],xc2,yc2,xc2+60,yc2+20) # Cette fonction va s'occuper de faire les ennemis se déplacer # automatiquement dans le canevas histoire qu'ils puissent esquiver # les tirs du joueur ( un genre d'IA à deux balles quoi !! XD ) def ennemis(): global dx,feuEnnemi,NbreEnnemis,Xobus,Yobus,ListeCoordEnnemis,DebutJeu,NbreEnRangees global ListeEnnemis,PasAvancement,NbreEnnemis,flag,LimiteAvancement,BonusActif,PasMax if flag!=0 and len(NbreEnnemis)>=1 and DebutJeu!=0: # Si tous les ennemis ont été détruits # ce n'est pas la peine d'exécuter l'animation # de quelque chose qui n'existe plus :p if NbreEnnemis!=0: i=0 t=0 PasAvancement+=1 # On active le système de tir des méchants :p # ==> Armement des canons ==> Prêt à détruire l'ennemi ( le joueur ) # Yes sir !! XD tir_ennemi() # Si jamais les ennemis atteignent le bas # de l'écran la partie s'arrête et le joueur # a perdu !! :p while i<len(ListeCoordEnnemis): while t<len(ListeCoordEnnemis[i]): if ListeCoordEnnemis[i][t][1]>=420: can.delete(ALL) image() flag=0 can.create_text(320,240,font=('Fixedsys',18),text="Game Over !!",fill='red') feu=0 ArretAnimation=0 can.delete(canon[0]) can.delete(canon[1]) DebutJeu=0 SaveMeilleurScore(Score) xc1,yc1=0,0 xc2,yc2=0,0 t+=1 t=0 i+=1 i=0 # Si les ennemis arrive au bout de l'écran # leur direction s'inverse et ils vont # dans le sens opposé dy=0 if dx>0: # On va utiliser cette 2e variable afin # de s'assurer de l'inversion de la direction # des ennemis dx2=dx if len(ListeCoordEnnemis[0])!=0: if ListeCoordEnnemis[0][len(ListeCoordEnnemis[0])-1][0]>=560: dx=-dx2 dy=10 if len(ListeCoordEnnemis[1])!=0: if ListeCoordEnnemis[1][len(ListeCoordEnnemis[1])-1][0]>=560: dx=-dx2 dy=10 if len(ListeCoordEnnemis[2])!=0: if ListeCoordEnnemis[2][len(ListeCoordEnnemis[2])-1][0]>=560: dx=-dx2 dy=10 elif dx<0: dx2=dx if len(ListeCoordEnnemis[0])!=0: if ListeCoordEnnemis[0][0][0]<=20: dx=-dx2 dy=10 if len(ListeCoordEnnemis[1])!=0: if ListeCoordEnnemis[1][0][0]<=20: dx=-dx2 dy=10 if len(ListeCoordEnnemis[2])!=0: if ListeCoordEnnemis[2][0][0]<=20: dx=-dx2 dy=10 i=0 t=0 # On fait avancer tous les ennemis # du canevas while i<len(ListeCoordEnnemis): while t<len(ListeCoordEnnemis[i]): ListeCoordEnnemis[i][t][0]=ListeCoordEnnemis[i][t][0]+dx ListeCoordEnnemis[i][t][1]=ListeCoordEnnemis[i][t][1]+dy t+=1 i+=1 t=0 i=0 while i<NbreEnnemis[0]: can.coords(ListeEnnemis[0][i][0],ListeCoordEnnemis[0][i][0],ListeCoordEnnemis[0][i][1],ListeCoordEnnemis[0][i][0]+60,ListeCoordEnnemis[0][i][1]+20) can.coords(ListeEnnemis[0][i][1],ListeCoordEnnemis[0][i][0],ListeCoordEnnemis[0][i][1],ListeCoordEnnemis[0][i][0]+20,ListeCoordEnnemis[0][i][1]+40) can.coords(ListeEnnemis[0][i][2],ListeCoordEnnemis[0][i][0]+40,ListeCoordEnnemis[0][i][1],ListeCoordEnnemis[0][i][0]+60,ListeCoordEnnemis[0][i][1]+40) i+=1 i=0 while i<NbreEnnemis[1]: can.coords(ListeEnnemis[1][i][0],ListeCoordEnnemis[1][i][0],ListeCoordEnnemis[1][i][1],ListeCoordEnnemis[1][i][0]+20,ListeCoordEnnemis[1][i][1]+40) can.coords(ListeEnnemis[1][i][1],ListeCoordEnnemis[1][i][0]+40,ListeCoordEnnemis[1][i][1],ListeCoordEnnemis[1][i][0]+60,ListeCoordEnnemis[1][i][1]+40) can.coords(ListeEnnemis[1][i][2],ListeCoordEnnemis[1][i][0]+20,ListeCoordEnnemis[1][i][1]+20,ListeCoordEnnemis[1][i][0]+40,ListeCoordEnnemis[1][i][1]+60) i+=1 i=0 while i<NbreEnnemis[2]: can.coords(ListeEnnemis[2][i][0],ListeCoordEnnemis[2][i][0]+20,ListeCoordEnnemis[2][i][1],ListeCoordEnnemis[2][i][0]+40,ListeCoordEnnemis[2][i][1]+60) can.coords(ListeEnnemis[2][i][1],ListeCoordEnnemis[2][i][0],ListeCoordEnnemis[2][i][1]+20,ListeCoordEnnemis[2][i][0]+60,ListeCoordEnnemis[2][i][1]+40) i+=1 fen.after(50,ennemis) else: fen.after(50,ennemis) # Cette fonction gère le tir des ennemis # et vérifie si un a atteint le canon # mobile du joueur def tir_ennemi(): global feuEnnemi,Xobus,Yobus,ObusEnnemi,ListeCoordEnnemis,EnnemiChoisi,ChoixTireur,NbreEnnemis,flag,DebutJeu if flag!=0: if DebutJeu!=0: if feuEnnemi!=1 : feuEnnemi=1 ObusEnnemi=[] i=0 while i<len(EnnemiChoisi): if EnnemiChoisi[i]==0: del EnnemiChoisi[i] i+=1 if len(EnnemiChoisi)==1: Choix=0 else: Choix=randrange(0,len(EnnemiChoisi),1) # En fonction de la catégorie d'ennemis choisie # les coordonnées d'un obus tiré ne seront pas # les mêmes pour tout le monde if len(ObusEnnemi)!=1: if Choix==0: if NbreEnnemis[0]!=0: # La portion de code ci-dessous va permettre aux # ennemis de choisir le canon avec lequel ils vont # canarder le joueur et ses défenses CanonChoisi=randrange(0,3,1) ChoixTireur=[] ChoixTireur.append([ListeCoordEnnemis[0][randrange(0,NbreEnnemis[0],1)][0],ListeCoordEnnemis[0][randrange(0,NbreEnnemis[0],1)][1]]) Xobus=ChoixTireur[0][0]+9 Yobus=ChoixTireur[0][1]+40 if CanonChoisi==1: ObusEnnemi.append(can.create_rectangle(Xobus,Yobus,Xobus+2,Yobus+40,fill='orange')) else: Xobus=Xobus+40 ObusEnnemi.append(can.create_rectangle(Xobus,Yobus,Xobus+2,Yobus+40,fill='orange')) elif Choix==1: if NbreEnnemis[1]!=0: ChoixTireur=[] ChoixTireur.append([ListeCoordEnnemis[1][randrange(0,NbreEnnemis[1],1)][0],ListeCoordEnnemis[1][randrange(0,NbreEnnemis[1],1)][1]]) Xobus=ChoixTireur[0][0]+29 Yobus=ChoixTireur[0][1]+60 ObusEnnemi.append(can.create_rectangle(Xobus,Yobus,Xobus+2,Yobus+40,fill='orange')) elif Choix==2: if NbreEnnemis[2]!=0: ChoixTireur=[] ChoixTireur.append([ListeCoordEnnemis[2][randrange(0,NbreEnnemis[2],1)][0],ListeCoordEnnemis[2][randrange(0,NbreEnnemis[2],1)][1]]) Xobus=ChoixTireur[0][0]+29 Yobus=ChoixTireur[0][1]+60 ObusEnnemi.append(can.create_rectangle(Xobus,Yobus,Xobus+2,Yobus+40,fill='orange')) # On démarre l'animation de l'obus # tiré par un des ennemis AnimationObusEnnemi() # Cette fonction permet d'animer l'obus tiré # par un ennemi def AnimationObusEnnemi(): global xe,ye,dyobusEnnemi,Yobus,Xobus,ObusEnnemi,feuEnnemi,xc1,xc2,yc1,yc2,feu,ViesJoueur global PartieFinie,flag,projectile,DebutJeu,Score,Mort,ArretAnimation,canon if flag!=0: if feuEnnemi==1: Yobus=Yobus+dyobusEnnemi abri() if Yobus>=480: if len(ObusEnnemi)==1: can.delete(ObusEnnemi[0]) feuEnnemi=0 # Si un tir ennemi parvient à son objectif en # touchant le canon mobile du joueur ben il crève ==> partie terminée !! :p elif Xobus>=xc2 and Xobus<=xc2+60 and Yobus>=yc2 or Xobus>=xc1 and Xobus<=xc1+20 and Yobus>=yc1: can.delete(canon[0]) can.delete(canon[1]) if len(projectile)!=0: can.delete(projectile[0]) if len(ObusEnnemi)!=0: can.delete(ObusEnnemi[0]) feuEnnemi=0 feu=1 # Diminution du capital de vies # du joueur ViesJoueur=ViesJoueur-1 ArretAnimation=1 Mort=1 # On affiche les vies restantes du joueur if ViesJoueur>=0: AffichageVie.configure(text="Lives : "+str(ViesJoueur),font=('Fixedsys',16)) # Si le nombre de vie est non nul # le joueur ressucite cela va de soi ! if ViesJoueur>0: fen.after(500,Ressurection_joueur) else: # On efface l'écran can.delete(ALL) image() can.create_text(320,240,font=('Fixedsys',18),text="Game Over !!",fill='red') feu=0 ArretAnimation=0 can.delete(canon[0]) can.delete(canon[1]) DebutJeu=0 # On vérifie le score SaveMeilleurScore(Score) xc1,yc1=0,0 xc2,yc2=0,0 # Suspension des animations flag=0 if len(ObusEnnemi)==1: can.coords(ObusEnnemi[0],Xobus,Yobus,Xobus+2,Yobus+40) fen.after(50,AnimationObusEnnemi) # Cette fonction va permettre d'afficher un # paysage post-apocalyptique si le joueur # fait un game over !! :( :( def image(): global photo photo=PhotoImage(file='apocalypse.gif') can.create_image(320,240,image=photo) # Cette fonction permet de ressuciter # le défunt joueur \o/ Amen !! XD def Ressurection_joueur(): global canon,xc1,xc2,yc1,yc2,feu,flag,ArretAnimation,projectile,Mort if flag!=0: if len(projectile)!=0: can.delete(projectile[0]) Mort=0 ArretAnimation=0 xc1=20 yc1=440 can.delete(canon[0]) can.delete(canon[1]) canon=[] canon.append(can.create_rectangle(xc1,yc1,xc1+20,yc1+20,fill='green')) xc2=xc1-20 yc2=yc1+20 canon.append(can.create_rectangle(xc2,yc2,xc2+60,yc2+20,fill='green')) feu=0 # Cette fonction va permettre de gérer le tir du canon # ainsi que les collisions avec les cibles situées en # haut du canevas :) def tir_joueur(event): global xc2,yc2,xtir,ytir,projectile,feu,VieEnnemi,flag,DebutJeu if DebutJeu!=0: if flag!=0: if feu!=1 : feu=1 xtir=xc2+20 ytir=yc2-40 projectile=[(can.create_oval(xtir,ytir,xtir+20,ytir+20,fill='yellow'))] time.sleep(0.09) # On lance l'animation de l'obus # tiré par le joueur AnimationObus() # Cette fonction va gérer l'intéraction d'un obus avec une # brique composant l'un des abris ainsi si le joueur tire sur # l'un des abris qui lui sont offerts ceux-ci se désagrégeront # sous l'effet de ses tirs maladroits :p def abri(): global CoordonneesBriques,ListeAbris,xtir,ytir,feu,Xobus,Yobus,feuEnnemi,CoordEnnemis,ObusEnnemi,projectile i=0 t=0 while i<len(CoordonneesBriques): x=CoordonneesBriques[i][t] y=CoordonneesBriques[i][t+1] # Si le joueur tire sur l'une des briques # composant les abris celle-ci est détruite if xtir==x and ytir==y : can.delete(ListeAbris[i]) can.delete(projectile[0]) feu=0 del CoordonneesBriques[i] del ListeAbris[i] t=0 i+=1 i=0 t=0 if feuEnnemi==1: while i<len(CoordonneesBriques): x=CoordonneesBriques[i][t] y=CoordonneesBriques[i][t+1] # Si l'ennemi tire sur l'une des briques # composant les abris celle-ci est # également détruite if Xobus>=x and Xobus<=x+20 and Yobus>=y: can.delete(ListeAbris[i]) if len(ObusEnnemi)==1: can.delete(ObusEnnemi[0]) ObusEnnemi=[] feuEnnemi=0 del CoordonneesBriques[i] del ListeAbris[i] t=0 i+=1 # Cette fonction va permettre d'animer l'obus tiré par # le canon mobile def AnimationObus(): global projectile,xtir,ytir,dxobus,feu,ycible,xcible,xe,ye,xe2,ye2,xe3,ye3,PasAvancement,dx,ListeAbris,BonusActif global VieEnnemi,feuEnnemi,NbreEnnemis,ListeCoordEnnemis,Score,NbreEnnemis,ListeEnnemis,flag,LimiteAvancement global xeb,yeb,EnnemiBonus,ArretAnimation if flag!=0 and len(projectile)==1 and ArretAnimation!=1: if feu==1: ytir=ytir-dyobus abri() if ytir<=20: feu=0 can.delete(projectile[0]) # Le bloc d'instructions qui suit permet de gérer l'intéraction entre # un tir d'obus provoqué par le joueur et un ennemi, donc si l'obus # touche un ennemi il est logique de dire que celui-ci est détruit i=0 t=0 while i<len(ListeCoordEnnemis): # Pour qu'il n'y ai pas d'erreur au cas où # La liste des coordonnées des ennemis est vide # on execute le bloc d'instructions suivant # uniquement quand la liste des coordonnées n'est # pas vide if len(ListeCoordEnnemis)>=1: if len(ListeCoordEnnemis[i])>=1: while t<len(ListeCoordEnnemis[i]): if xtir+5>=ListeCoordEnnemis[i][t][0] and xtir-5<=ListeCoordEnnemis[i][t][0]+60 : if ytir<=ListeCoordEnnemis[i][t][1]+5 and ytir>=ListeCoordEnnemis[i][t][1]-60 : Score=Score+50 feu=0 AffichageScore.configure(text="Score : "+str(Score),font=('Fixedsys',16)) can.delete(projectile[0]) score(50,ListeCoordEnnemis[i][t][0],ListeCoordEnnemis[i][t][1],30,20) if i==0: NbreEnnemis[0]=NbreEnnemis[0]-1 can.delete(ListeEnnemis[i][t][0]) can.delete(ListeEnnemis[i][t][1]) can.delete(ListeEnnemis[i][t][2]) del ListeEnnemis[i][t] del ListeCoordEnnemis[i][t] elif i==1: NbreEnnemis[1]=NbreEnnemis[1]-1 can.delete(ListeEnnemis[i][t][0]) can.delete(ListeEnnemis[i][t][1]) can.delete(ListeEnnemis[i][t][2]) del ListeEnnemis[i][t] del ListeCoordEnnemis[i][t] elif i==2: NbreEnnemis[2]=NbreEnnemis[2]-1 can.delete(ListeEnnemis[i][t][0]) can.delete(ListeEnnemis[i][t][1]) del ListeEnnemis[i][t] del ListeCoordEnnemis[i][t] t+=1 t=0 i+=1 # Quand il n'y a plus d'ennemis ben on recommence # le carnage mais cette fois en rendant la bataille # plus épicée !! T_T if NbreEnnemis[0]+NbreEnnemis[1]+NbreEnnemis[2]==0: # On efface le canon mobile pour le recréer can.delete(canon[0]) can.delete(canon[1]) Creation_CanonMobile() # On reprend tous les paramètres de départ # afin qu'il n'y ai aucune erreur xe,ye=20,20 xe2,ye2=20,80 xe3,ye3=20,160 # On efface l'ennemi bonus if len(EnnemiBonus)!=0: can.delete(EnnemiBonus[0]) can.delete(EnnemiBonus[1]) can.delete(EnnemiBonus[2]) can.delete(EnnemiBonus[3]) xeb,yeb=0,0 # Avant de passer au niveau suivant # il faut effacer les briques restantes # à l'écran if len(ListeAbris)!=0: i=0 while i<len(ListeAbris): can.delete(ListeAbris[i]) i+=1 # On recrée les abris du joueur Creation_Abris() LimiteAvancement+=1 if len(ObusEnnemi)==1: can.delete(ObusEnnemi[0]) if dx<0: dx=-dx # On accelère la cadence des ennemis !! # Caramba !! XD dx=dx+1 flag=0 # Le joueur et les ennemis pourront # à nouveau tirer !! feu=0 feuEnnemi=0 BonusActif=0 Ennemis1=[] Ennemis2=[] Ennemis3=[] ListeEnnemis=[Ennemis1,Ennemis2,Ennemis3] Ennemis=[] CoordEnnemis1=[] CoordEnnemis2=[] CoordEnnemis3=[] ListeCoordEnnemis=[CoordEnnemis1,CoordEnnemis2,CoordEnnemis3] NbreEnnemis1=6 NbreEnnemis2=6 NbreEnnemis3=6 PasAvancement=0 NbreEnnemis=[NbreEnnemis1,NbreEnnemis2,NbreEnnemis3] v=0 # Appel des fonctions de création des ennemis # pour recréer un bataillon de vaisseaux hostiles # prêts à en découdre à nouveau avec le joueur !! while v<6: Ennemi_Categorie1() Ennemi_Categorie2() Ennemi_Categorie3() v+=1 flag=1 else: can.coords(projectile[0],xtir,ytir,xtir+20,ytir+20) fen.after(50,AnimationObus) # Les deux fonctions ci-dessous permettent # de diriger le canon mobile de gauche à droite def right(event): global flag,DebutJeu if DebutJeu!=0: if flag!=0: move(20) def left(event): global flag,DebutJeu if DebutJeu!=0: if flag!=0: move(-20) # Cette fonction permet d'effectuer une pause en cours de partie def pause(event): global flag,pause,feu,DebutJeu,feu,Mort,BonusActif,feuEnnemi,ArretAnimation # Si le jeu n'a pas commencé # la fonction ne démarre pas # Il en est de même si le joueur # est mort :p if DebutJeu!=0 and Mort!=1: if flag==1: pause=can.create_text(320,240,font=('Fixedsys',18),text="PAUSE") flag=0 elif flag==0: flag=1 can.delete(pause) AnimationObusEnnemi() if feu==1: ArretAnimation=0 AnimationObus() ####################### # # # Programme principal # # # ####################### # Création de la fenêtre principale fen=Tk() # Titre de la fenêtre fen.title('Space invaders') # Définition du canevas ( Ecran de jeu ) can=Canvas(fen,width=640,height=480,bg='black') # Définition des touches qui vont permettre # de diriger le canon mobile can.bind_all("<Right>",right) can.bind_all("<Left>",left) can.bind_all("<space>",tir_joueur) can.bind_all("<p>",pause) can.grid(row=1,column=0,columnspan=2,rowspan=3) # Installation d'une image de fond # pour être plus dans l'ambiance 8) photo=PhotoImage(file='earth.gif') can.create_image(320,240,image=photo) # Définition des boutons # Ce bouton permet de commencer une nouvelle partie Button(fen,text="New game",font=("Fixedsys"),command=new_game).grid(row=2,column=2,sticky=N,padx=5) Button(fen,text="Quit",font=("Fixedsys"),command=fen.destroy).grid(row=3,column=2,sticky=N,padx=5) # On crée les abris ListeAbris=[] CoordonneesBriques=[] i=0 x=40 y=340 while i<3: limX=x+120 limY=y+60 departx=x while y<limY: while x<limX: ListeAbris.append(can.create_rectangle(x,y,x+20,y+20,fill='grey')) CoordonneesBriques.append([x,y]) x+=20 x=departx y+=20 i+=1 x+=220 y-=60 # Coordonnées du canon mobile canon=[] xc1=0 yc1=0 xc2=0 yc2=0 # Création des ennemis situés en haut du canevas Ennemis1=[] Ennemis2=[] Ennemis3=[] ListeEnnemis=[Ennemis1,Ennemis2,Ennemis3] Ennemis=[] # Cette liste contiendra les coordonnées # de position des ennemis dans le canevas CoordEnnemis1=[] CoordEnnemis2=[] CoordEnnemis3=[] ListeCoordEnnemis=[CoordEnnemis1,CoordEnnemis2,CoordEnnemis3] NbreEnnemis1=6 NbreEnnemis2=6 NbreEnnemis3=6 NbreEnnemis=[NbreEnnemis1,NbreEnnemis2,NbreEnnemis3] # Définition des coordonnées de départ # de chacune des rangées d'ennemis xe,ye=0,0 xe2,ye2=0,0 xe3,ye3=0,0 i=0 t=0 # On dessine chacune des catégories # d'ennemis dans le canevas en utilisant # les fonctions qui sont dédiées à leur création while i<6: Ennemi_Categorie1() Ennemi_Categorie2() Ennemi_Categorie3() i+=1 # Détermination aléatoire de l'ennemi # qui tira en premier et ainsi de suite RangEnnemiChoisi=randrange(0,3,1) Ennemi1Choisi=randrange(0,NbreEnnemis[0],1) Ennemi2Choisi=randrange(0,NbreEnnemis[1],1) Ennemi3Choisi=randrange(0,NbreEnnemis[2],1) EnnemiChoisi=[Ennemi1Choisi,Ennemi2Choisi,Ennemi3Choisi] # Définition de l'ennemi bonus EnnemiBonus=[] CoordEnnemiBonus=[] # Coordonnées de l'ennemi bonus xeb=-20 yeb=80 # Indicateur renseignant sur l'activation # et le passage de l'ennemi bonus dans le canevas BonusActif=0 # Pas d'avancement de l'ennemi bonus dxeb=1 # Définition des coordonnées d'un obus xtir=xc2 ytir=yc2-20 ObusEnnemi=[] feu=0 feuEnnemi=0 VieEnnemi=1 dyobus=20 dyobusEnnemi=10 dx=0 ChoixTireur=[] ChoixTireur.append([ListeCoordEnnemis[0][randrange(0,NbreEnnemis[0],1)][0],ListeCoordEnnemis[0][randrange(0,NbreEnnemis[0],1)][1]]) Xobus=ChoixTireur[0][0]+9 Yobus=ChoixTireur[0][1]+40 # Le compteur de score Score=0 # Le nombre de vies du joueur avant de morfler définitivement XD ViesJoueur=3 # Cette variable va nous permettre d'ajuster # le pas d'avancement des ennemis en fonction # de leur vitesse afin qu'il n'y ai pas d'erreurs LimiteAvancement=0 projectile=[] PasAvancement=0 flag=0 # On affiche les indications concernant # le score et les vies restantes du joueur AffichageScore=Label(fen,font=('Fixedsys',16)) AffichageVie=Label(fen,font=('Fixedsys',16)) AffichageScore.grid(row=0,column=0,sticky=W) AffichageVie.grid(row=0,column=1,sticky=E) # Cette variable va permettre de suspendre certaines # fonctions durant l'affichage de l'écran de présentation DebutJeu=0 # Cette variable indique # si le joueur est mort ==> Canon mobile détruit # de plus si cette variable vaut 1 certaines fonctions # seront par conséquent désactivées Mort=0 ArretAnimation=0 # Si le fichier contenant les scores n'existe pas # on le crée avec comme valeur de départ ==> 0 if existe('HighScore')==0: FichierScore=open('HighScore','w') pickle.dump(0,FichierScore) FichierScore.close() # Cette liste va permettre d'afficher # les scores suite à la destruction d'un ennemi afficherScore=[] # On démarre la danse en mettant les ennemis en scène !! ennemis() AnimationEnnemiBonus() # On affiche l'écran de présentation du jeu EcranDePresentation() # On met le gestionnaire d'événements en route fen.mainloop()
22 mai 2007 à 03:49
Sinon sache que si j'ai dit ne pas t'avoir trop dégouté c'est justement parce que je sais que je n'avais respecté aucune règle préalable dans la réalisation de ce projet mais je suis content que tu me l'ai rappelé car il n'y a rien de plus utile qu'une bonne méthode pour réussir quelque chose en l'occurence un bon projet en programmation.
Sinon je te souhaites bonne chance à toi aussi et au plaisir de lire tes messages sur cette partie du site ;)
21 mai 2007 à 21:58
Je connais bien au moins 10 langages de prog et j'ai un "vernis" de connaissance sur au moins une dizaine d'autres...
Même s'il n'est pas du tout (du tout) académique, ton style de programmation démontre une certaine capacité à trouver des solutions à des problèmes abstraits, une opiniatreté à aller jusqu'au bout de ce que tu commences.
...reste plus qu'à prendre quelques cours et à prendre un peu de bouteille et tu ira loin !!!
Bonne chance.
17 mai 2007 à 04:38
16 mai 2007 à 21:33
Bon, je jette l'éponge le code de Shakan972 est vraiment trop penible à analyser :
variables globales re-déclarées 4 fois, mélange entre les fonctions de Tk et la logique du jeu etc...
En fait, pour refaire tout ca dans les règles de l'art, il faut TOUT refaire, donc, pas drôle, donc je jette l'éponge (bis).
Tchuss
13 mai 2007 à 16:40
En fait, j'ai laissé de côté Python depuis quelques temps pour revenir à ruby et samlltalk et la lecture de ce prog m'a fait byzare.
Même si je suis d'accord qu'on n'est pas obligé d'utiliser du c4 pour tuer une mouche, je pense malgré tout que s'avoir décomposer un problème et l'organiser permet de le resoudre à 80%.
Je viens de passer 3 heures sur le code de Shakan972 à essayer de mettre à plat une approche différente, en expliquant chaque étape, et j'ai pris beaucoup de plaisir à découvrir les "astuces" qu'il a choisis pour faire tourner son appli. L'informatique est aussi riche que la philosophie pour découvrir l'âme humaine et on ne dit jamais assez que c'est un art.
Trève de bavardages, je termine le "reingeneering" de ce trés noble Space Invaders et j'espère que d'autres prendront le temps de plancher dessus, la page python de ce site a besoin d'un peu de "sang neuf" !!
A bientôt donc...
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.