begin process at 2010 07 29 15:56:35
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Jeux

 > SPACE INVADERS

SPACE INVADERS


 Information sur la source

Note :
10 / 10 - par 2 personnes
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Jeux Classé sous :shoot, spaceinvaders Niveau :Débutant Date de création :07/05/2007 Date de mise à jour :07/05/2007 11:19:23 Vu / téléchargé :3 705 / 241

Auteur : Shakan972

Ecrire un message privé
Site perso
Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
C'est donc un jeu que je vous propose qui tente de vous faire redécouvrir un classique des jeux vidéos j'ai nommé :
==> Space invaders

Bien entendu je n'ai pas repris toutes les idées de ce jeu et je n'ai réalisé ce programme que dans le but de m'entrainer et non de
retranscrire une pale copie dans ses moindres détails. ( Je parle pour les fans du jeu là )

Donc rien de nouveau dans ce shoot classique que j'ai réadapté à mon goût, si ce n'est qu'il était très intéressant comme support de programmation.
Sinon vous m'excuserez d'avance pour le design des ennemis qui est je vous l'avoue très spécial :)

Bref pour ceux qui aimeront amusez vous bien pour les autres, j'espère que vous prendrez plaisir à comprendre la structure de mon programme.

Sinon sachez justement que j'ai apporté un grand nombre de commentaires afin que mon code soit compréhensible par tous.

LES COMMANDES :

Tirer ==> Barre d'espacement
Diriger le canon mobile ==> Touches fléchées
Faire une pause ==> Touche P

Source

  • # -*- 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()
# -*- 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()


 Conclusion

Le zip contient 3 fichier :

==> 1 fichier dans lequel est stocké le score du joueur
==> 1 fichier qui contient le code source du jeu :p
==> 2 fichier images pour agrémenter le jeu ( rien d'incroyable !! Mais bon... )

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

07 mai 2007 11:18:01 :
J'avais oublié de préciser les commandes du jeu ;)
07 mai 2007 11:19:23 :
Faute d'orthographe

 Sources du même auteur

Source avec Zip Source avec une capture SNAKE
Source avec Zip Source avec une capture DÉTERMINATION APPROXIMATIVE DE PI À L'AIDE DE LA MÉTHODE DE ...
Source avec une capture ANALYSE FRÉQUENTIELLE D'UNE PHRASE
Source avec Zip Source avec une capture ATTRACTION ÉLECTROSTATIQUE ENTRE CHARGES ÉLECTRIQUES (LOI DE...
Source avec Zip Source avec une capture RÉSOLUTION D'ÉQUATIONS DU SECOND DEGRÉS

 Sources de la même categorie

Source avec Zip Source avec une capture CASSE BRIQUE par elnabo
Source avec Zip COMPTEBON.PY par ACONNES
Source avec Zip Source avec une capture JEU DU SERPENT ////\\\\ SNAKE par elnabo
Source avec Zip Source avec une capture LES CONTES DE MONTE CRYPTO par amaury74
Source avec Zip Source avec une capture UN CLASSIC SOKOBAN par blackgrimly

Commentaires et avis

Commentaire de aera group le 08/05/2007 12:00:08

Très bonne source bravo, il n'y a rien à dire je met 10 sans aucune ésitation !!!
Bonne continuation et encore bravo
______
Aéra

Commentaire de TMONOD le 12/05/2007 12:22:37

Bonjour,
Même si le résultat fonctionne bien, (même si c'est un peu lent ;)) il y a beaucoup à dire sur l'optimisation du code et les mauvaises habitudes de programmation :
- Pas de programmation objet, rien que des methodes
- pas de séparation de la logique du jeu et de l'interface (comment faire si on veux adapter le jeu en wx, qt ou gtk ?)
- des instructions comme celle ci :
can.delete(EnnemiBonus[0])
                can.delete(EnnemiBonus[1])
                can.delete(EnnemiBonus[2])
                can.delete(EnnemiBonus[3])
ne peuvent-elles pas être mises dans une boucle ?

- même genre de remarque pour :
        Ennemi_Categorie1()
        Ennemi_Categorie2()
        Ennemi_Categorie3()
imagine le boulot quand on voudra ajouter un Ennemi_categorie4...;

Les points positifs :
- Source trés bien commentée
- noms des variables explicites
- Design tout à fait correct

Si ca amuses quelqu'un je propose un mini concours d'optimisation du code de ce jeu sans qu'il n'y ait aucune modification de l'aspect visuel et de la logique du jeu !!
...allez ! je me lance de mon côté ! à bientôt

Commentaire de Shakan972 le 12/05/2007 15:54:02

La vérité c'est que je savais très bien que ce programme méritait une optimisation poussée d'où le fait de l'avoir commenté au maximum déjà j'avais pensé qu'il aurait fallut utiliser les classes car ce genre de procédé que sont les classes semble ma foi bien plus adapté et plus correcte d'utilisation dans ce genre de projet.
Le problème étant que je n'ai pas encore abordé les classes qui plus est je ne connais aucune bibliothèques graphiques pour python omis Tkinter, c'est un fait donc je sais très bien que mon code est un foutoir notable j'en suis conscient à 100% mais j'ai tout de même limité la casse en commentant au maximum et cela il faut bien l'admettre.
La notion de fonction est donc la notion qui m'a le plus aidé dans ce projet bien entendu le code mérite d'être raccourci mais n'ayant pas encore une fois les notions suffisantes pour répondre à ce problème j'ai donc présenté le programme tel quel.
Certes il est long mais comme tu dis il fonctionnes mais comme tu dis il y a des défauts apparents j'en prends note et j'y réfléchirai.
Mais saches que j'ai réalisé ce programme avec les notions acquises au cours des 9 premiers chapitres du livre de Gérard Swinnen donc voilà.
Ce n'est pas une excuse valable pour expliquer mes erreurs mais il y a une part de la raison qui fait que le code soit présenté comme il t'est présenté actuellement donc en espérant qu'il puisse néanmmoins servir de source d'inspiration je suis tout de même content d'avoir posté cette source ici.

@+ et bon coding !!  :)

Commentaire de aera group le 12/05/2007 16:35:12

Tu peut être un peut brutale TMONOD quand tu parles des "mauvaises habitude de programmation" : ici, l'utilisation de classes n'est pas indispensable, bien qu'elle accéléreraient le jeu. On peut discuter longtemps sur le fait d'utiliser des classes ou plutôt les fonctions, mais sache que pour ce genre de jeu, je n'utiliserais pas non plus de classes (trop de travail :) il faut savoir rester simple parfois !). Pareil, je pense qu'il ne faut pas séparer la logique du jeu et l'interface, ça n'a aucun sens, même pour le passage sous WxPython ou autre : c'est complettement différent de Tkinter (au passage, si tu pouvez nous expliquer comment tu fais parce que la je vois pas comment on peut le faire). Par contre tu a raison quand tu parles des fonctions que l'on pourrait répété, l'a, je doit dire que c'est tout de même dommage, on pouvait faire quelque chose de bien. Très bonne idée que celle du "mini concours d'optimisation du code". Bon courrage à tous et j'espère que certaine personne présenterons des programmes interressants !
_____
Aéra

Commentaire de aera group le 12/05/2007 16:37:26

Au faite, Shakan972 je voullais te felliciter pour ce travail : en être arrivé à faire ce jeu en étant au chapitre 9 du cour de Gérard Swinnen, c'est remarcable. J'ai fini le livre et je suis long de savoir faire un tel jeu aussi bien.

Commentaire de Shakan972 le 12/05/2007 16:47:51

Merçi de tes félicitations ça fait toujours plaisir ;)

Faut dire que j'ai la sale habitude de ne pas finir un chapitre sans avoir fini tous les exercices qui vont avec d'où le fait que je n'ai pas terminé le livre et puis si en plus je me rajoute des épreuves comme ce jeu ben je suis pas prêt de voir le bout :D

Bref merçi !!

Commentaire de TMONOD le 13/05/2007 16:40:03

Hello tout le monde,
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...

Commentaire de TMONOD le 16/05/2007 21:33:49

Bonsoir,
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

Commentaire de Shakan972 le 17/05/2007 04:38:40

J'en suis vraiment navré à l'avenir je ferais en sorte de coder de manière plus claire et plus explicite sur ce j'espère ne pas t'avoir trop dégouté de la programmation ;)

Commentaire de TMONOD le 21/05/2007 21:58:53

En fait pour tout te dire, c'est mon métier et j'en vis plutôt bien. Même s'il est vrai que je ne suis pas du tout dans la branche "jeux" et interfaces graphiques mais dans des trucs moins drôles comme la compta et le contrôle de gestion.

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.

Commentaire de Shakan972 le 22/05/2007 03:49:06

Je te remerçie de tes encouragements et je tacherai dans tirer un certain enseignement pour avancer dans ce domaine que j'aime et je veux bien sûr parler de la programmation.
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 ;)

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Juillet 2010
LMMJVSD
   1234
567891011
12131415161718
19202122232425
262728293031 

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,905 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales