Space invaders ---------------
Url : http://codes-sources.commentcamarche.net/source/42599-space-invadersAuteur : Shakan972Date : 05/09/2013
Licence :
=========
Ce document intitulé « Space invaders » issu de CommentCaMarche
(codes-sources.commentcamarche.net) est mis à disposition sous les termes de
la licence Creative Commons. Vous pouvez copier, modifier des copies de cette
source, dans les conditions fixées par la licence, tant que cette note
apparaît clairement.
Description :
=============
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 inv
aders
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'entrai
ner et non de
retranscrire une pale copie dans ses moindres détail
s. ( Je parle pour les fans du jeu là )
Donc rien de nouve
au 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 enne
mis qui est je vous l'avoue très spécial :)
Bref po
ur 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 commentaire
s afin que mon code soit compréhensible par tous.
LES COMM
ANDES :
Tirer ==> Barre d'espacement
Diriger le canon m
obile ==> Touches fléchées
Faire une pause ==> Touche
P
Source / Exemple :
# -*- coding: cp1252 -*-
#################
##################
# #
# Programme : Space in
vaders #
# Auteur : Shakan972 #
# Date de creation : 13/04/0
7 #
# #
###################################
##########################################
#
#
# Importations des fonctions nécessaires #
#
#
##########################################
from Tkinter i
mport *
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 INVADER
S",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 Shakan9
72",fill='red')
fen.after(3000,LoadMeilleurScore)
# Cette fonct
ion va permettre d'enregistrer
# le meilleur score
def SaveMeilleurScore(res
ultat):
FichierScore=open('HighScore','r')
lecture=pickle.load(Fichier
Score)
# 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 l
e nouveau score record
if resultat>lecture:
FichierScore=
open('HighScore','w')
pickle.dump(resultat,FichierScore)
Fichi
erScore.close()
fen.after(2000,MessageRecord)
else:
fen.a
fter(15000,EcranDePresentation)
FichierScore.close()
# Cette fonction af
fiche un message
# lui indiquant qu'il a établit un
# nouveau record :D
def
MessageRecord():
can.delete(ALL)
can.create_text(320,240,font=('Georg
ia',18),text="Vous avez établi un nouveau record !!",fill='red')
fen.after(3000,LoadMeilleurScore)
# Quant à cette fonction elle va pe
rmettre
# de lire le meilleur score afin de l'afficher
def LoadMeilleurScore
():
global DebutJeu
if DebutJeu!=1:
FichierScore=open('HighSc
ore','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(lect
ure),fill='blue')
FichierScore.close()
fen.after(3000,EcranDeP
resentation)
# 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éi
nitialiser le jeu
# selon la volonté du joueur de recommencer une partie
def
new_game():
global xe,ye,xe2,ye2,xe3,ye3,LimiteAvancement,dx,ListeCoordEnn
emis,ListeEnnemis,ObusEnnemi,flag,photo,NbreEnnemis,Score,ViesJoueur
global
ListeAbri,CoordonneesBriques,projectile,feu,feuEnnemi,PasAvancement
global
dyobus,dyobusEnnemi,DebutJeu,BonusActif,dxeb,EnnemiBonus,Mort,photo,PasMax,Nbre
EnRangees
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.cre
ate_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.dele
te(ObusEnnemi[0])
dx=1
# Pas d'avancement d'un obus
# tiré par
le joueur
dyobus=20
# Pas d'avancement d'un obus
# tiré p
ar 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]
NbreEn
nemis1=6
NbreEnnemis2=6
NbreEnnemis3=6
PasAvancement=0
NbreE
nnemis=[NbreEnnemis1,NbreEnnemis2,NbreEnnemis3]
v=0
BonusActif
=0
dxeb=5
EnnemiBonus=[]
Creation_Abris()
Creation_CanonMo
bile()
# On détermine de manière aléatoire
# le nombre de temps avan
t qu'apparaisse
# le premier ennemi bonus du jeu :)
fen.after(ra
ndrange(60000,100000,100),CreationEnnemiBonus)
AffichageScore.configure(t
ext="Score : "+str(Score),font=('Fixedsys',16))
AffichageVie.conf
igure(text="Lives : "+str(ViesJoueur),font=('Fixedsys',16))
# Appel des fonctions de création des ennemis
# pour recréer un bataillo
n 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
# Cet
te 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:
ListeAbri
s.append(can.create_rectangle(x,y,x+20,y+20,fill='grey'))
Coord
onneesBriques.append([x,y])
x+=20
x=departx
y+=20
i+=1
x+=220
y-=60
# Cette fonction pe
rmet 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(x
c1,yc1,xc1+20,yc1+20,fill='green'))
xc2=xc1-20
yc2=yc1+20
# C
ré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 von
t permettre de créer les ennemis du jeu
# Création de la 1er catégorie d'enne
mis du jeu
def Ennemi_Categorie1():
global ListeEnnemis,ListeCoordEnnemi
s,xe,ye
ListeCoordEnnemis[0].append([xe,ye])
Ennemis=[]
Ennemis.a
ppend(can.create_rectangle(xe,ye,xe+60,ye+20,fill='blue'))
Ennemis.append(c
an.create_rectangle(xe,ye,xe+20,ye+40,fill='blue'))
Ennemis.append(can.crea
te_rectangle(xe+40,ye,xe+60,ye+40,fill='blue'))
ListeEnnemis[0].append(Enne
mis)
xe=xe+80
# Création de la 2e catégorie d'ennemis du jeu
def Enne
mi_Categorie2():
global ListeEnnemis,ListeCoordEnnemis,xe2,ye2
ListeCo
ordEnnemis[1].append([xe2,ye2])
Ennemis=[]
Ennemis.append(can.create_r
ectangle(xe2,ye2,xe2+20,ye2+40,fill='violet'))
Ennemis.append(can.create_re
ctangle(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].appen
d(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].a
ppend(Ennemis)
xe3=xe3+80
# Cette fonction va permettre de créer
# l'en
nemi bonus du jeu
def CreationEnnemiBonus():
global EnnemiBonus,xeb,yeb,
BonusActif,DebutJeu,CoordEnnemiBonus,dxeb,flag
if flag!=0:
if Bo
nusActif!=1:
BonusActif=1
dxeb=5
hasard=r
andrange(0,10,1)
if hasard>=5:
xeb=0
dxeb=dxeb
else:
xeb=630
dx
eb=-dxeb
yeb=randrange(80,400,10)
EnnemiBonus.append(c
an.create_oval(xeb,yeb,xeb+35,yeb+15,fill='red'))
EnnemiBonus.appen
d(can.create_oval(xeb+5,yeb+5,xeb+10,yeb+10,fill='yellow'))
EnnemiB
onus.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,dxe
b,xtir,ytir,DebutJeu,BonusActif,projectile,flag,feu,Score
if flag!=0 and
DebutJeu!=0 and BonusActif!=0 :
# Si l'ennemi bonus atteint l'autre b
out de l'écran
# il s'auto-détruit !! XD
if dxeb>0:
if xeb>=640:
BonusActif=0
can.delet
e(EnnemiBonus[0])
can.delete(EnnemiBonus[1])
c
an.delete(EnnemiBonus[2])
can.delete(EnnemiBonus[3])
xeb=0
yeb=0
EnnemiBonus=[]
# Détermination aléatoire du temps d'appel
# de la fonct
ion qui va permettre de procéder
# à la création d'un nouvel en
nemi bonus
fen.after(randrange(60000,100000,1
00),CreationEnnemiBonus)
else:
if xeb<=20:
BonusActif=0
can.delete(EnnemiBonus[0])
c
an.delete(EnnemiBonus[1])
can.delete(EnnemiBonus[2])
can.delete(EnnemiBonus[3])
xeb=0
yeb=0
EnnemiBonus=[]
fen.after(randrange(60000,10000
0,100),CreationEnnemiBonus)
# On fait l'ennemi bonu
s 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(Enn
emiBonus[2],xeb+15,yeb+5,xeb+20,yeb+10)
can.coords(EnnemiBonus[3],x
eb+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:
Bon
usActif=0
# On efface l'ennemi bonus
# ainsi que l'obus qui l'a touché
if len(projectile)!=0:
can.delete(projectile[0])
can.del
ete(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="Sco
re : "+str(Score),font=('Fixedsys',16))
# On remet l
es coordonnées de l'ennemi
# bonus à zéro pour n'engendrer
aucune
# erreur
xeb,yeb=0,0
xtir,ytir=0,0
# On désac
tive l'animation de l'obus
# tiré par le joueur
feu=0
EnnemiBonus=[]
f
en.after(randrange(15000,25000,100),CreationEnnemiBonus)
# On reboucle le tout
fen.after(50,AnimationEnnemiBonus)
else:
fen.after(50,AnimationEnnemiBonus)
# Cette fonction perme
t 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
afficherSc
ore.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'eff
acer
# le nombre de point gagnés et affichés
# suite à la destruction d'un enn
emi
def EffacerScore():
global afficherScore
i=0
while i<le
n(afficherScore):
can.delete(afficherScore[i])
i+=1
# La fo
nction ci-dessous permet
# d'animer le canon mobile selon
# la direction chois
ie 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 retrou
ve 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 fo
nction 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,NbreEnnemi
s,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 act
ive 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 ListeCoordEnn
emis[i][t][1]>=420:
can.delete(ALL)
image()
flag=0
can.cr
eate_text(320,240,font=('Fixedsys',18),text="Game Over !!",fill='red')
feu=0
ArretAnimation=0
can.delete(canon[0])
can.delete(cano
n[1])
DebutJeu=0
SaveMeilleurS
core(Score)
xc1,yc1=0,0
xc2,yc
2=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'inve
rsion 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(L
isteCoordEnnemis[1])!=0:
if ListeCoordEnnemis[1][len(ListeC
oordEnnemis[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(List
eCoordEnnemis[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]):
Liste
CoordEnnemis[i][t][0]=ListeCoordEnnemis[i][t][0]+dx
ListeCo
ordEnnemis[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],ListeCoordEnne
mis[0][i][0],ListeCoordEnnemis[0][i][1],ListeCoordEnnemis[0][i][0]+60,ListeCoord
Ennemis[0][i][1]+20)
can.coords(ListeEnnemis[0][i][1],ListeCoor
dEnnemis[0][i][0],ListeCoordEnnemis[0][i][1],ListeCoordEnnemis[0][i][0]+20,Liste
CoordEnnemis[0][i][1]+40)
can.coords(ListeEnnemis[0][i][2],List
eCoordEnnemis[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],ListeCoordEnne
mis[1][i][0]+60,ListeCoordEnnemis[1][i][1]+40)
can.coords(Liste
Ennemis[1][i][2],ListeCoordEnnemis[1][i][0]+20,ListeCoordEnnemis[1][i][1]+20,Lis
teCoordEnnemis[1][i][0]+40,ListeCoordEnnemis[1][i][1]+60)
i+=1
i=0
while i<NbreEnnemis[2]:
can.co
ords(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 at
teint le canon
# mobile du joueur
def tir_ennemi():
global feuEnnemi,Xo
bus,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 Ennem
iChoisi[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 v
ont
# canarder le joueur et ses défenses
CanonChoisi=randrange(0,3,1)
ChoixTireur=[]
ChoixTi
reur.append([ListeCoordEnnemis[0][randrange(0,NbreEnnemis[0],1)][0],ListeCoordEn
nemis[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,Xo
bus+2,Yobus+40,fill='orange'))
else:
Xobus=Xobus+40
ObusEnnemi.ap
pend(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=ChoixT
ireur[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,NbreEnnem
is[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,Yobu
s,Xobus+2,Yobus+40,fill='orange'))
# On démarre l'animati
on de l'obus
# tiré par un des ennemis
AnimationObusEnnemi()
# Cette fonction pe
rmet d'animer l'obus tiré
# par un ennemi
def AnimationObusEnnemi():
gl
obal xe,ye,dyobusEnnemi,Yobus,Xobus,ObusEnnemi,feuEnnemi,xc1,xc2,yc1,yc2,feu,Vie
sJoueur
global PartieFinie,flag,projectile,DebutJeu,Score,Mort,ArretAnimati
on,canon
if flag!=0:
if feuEnnemi==1:
Yobus=Yobus+dyo
busEnnemi
abri()
if
Yobus>=480:
if len(ObusEnnemi)==1:
can.delete(ObusEnnemi[0])
feuEnnemi=0
# Si un ti
r ennemi parvient à son objectif en
# touchant le canon mobile du j
oueur ben il crève ==> partie terminée !! :p
e
lif Xobus>=xc2 and Xobus<=xc2+60 and Yobus>=yc2 or Xobus>=xc1 and Xo
bus<=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 aff
iche 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 Ov
er !!",fill='red')
feu=0
ArretAni
mation=0
can.delete(canon[0])
can.dele
te(canon[1])
DebutJeu=0
# On vérifie
le score
SaveMeilleurScore(Score)
xc1,yc1=0,0
xc2,yc
2=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_ima
ge(320,240,image=photo)
# Cette fonction permet de ressuciter
# le déf
unt joueur \o/ Amen !! XD
def Ressurection_joueur():
global canon,xc1,xc
2,yc1,yc2,feu,flag,ArretAnimation,projectile,Mort
if flag!=0:
if l
en(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.cre
ate_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 d
u 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éracti
on 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'e
ffet de ses tirs maladroits :p
def abri():
global CoordonneesBriques,Lis
teAbris,xtir,ytir,feu,Xobus,Yobus,feuEnnemi,CoordEnnemis,ObusEnnemi,projectile
i=0
t=0
while i<len(CoordonneesBriques):
x=Coordonnee
sBriques[i][t]
y=CoordonneesBriques[i][t+1]
# Si le joueur t
ire 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 Coo
rdonneesBriques[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
# comp
osant les abris celle-ci est
# également détruite
if Xobus>=x and Xobus<=x+20 and Yobus>=y:
ca
n.delete(ListeAbris[i])
if len(ObusEnnemi)==1:
can.delete(ObusEnnemi[0])
ObusEnnemi=[]
f
euEnnemi=0
del CoordonneesBriques[i]
del Liste
Abris[i]
t=0
i+=1
# Cette fonction va permettre d'
animer l'obus tiré par
# le canon mobile
def AnimationObus():
global pr
ojectile,xtir,ytir,dxobus,feu,ycible,xcible,xe,ye,xe2,ye2,xe3,ye3,PasAvancement,
dx,ListeAbris,BonusActif
global VieEnnemi,feuEnnemi,NbreEnnemis,ListeCoordE
nnemis,Score,NbreEnnemis,ListeEnnemis,flag,LimiteAvancement
global xeb,yeb,
EnnemiBonus,ArretAnimation
if flag!=0 and len(projectile)==1 and ArretAni
mation!=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 e
nnemi, 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 p
as d'erreur au cas où
# La liste des coordonnées des ennemis es
t vide
# on execute le bloc d'instructions suivant
# uniquement quand la liste des coordonnées n'est
# pas vi
de
if len(ListeCoordEnnemis)>=1:
if len(ListeCoordEnnemis[i])>=1:
while t
<len(ListeCoordEnnemis[i]):
if xtir+5>=ListeC
oordEnnemis[i][t][0] and xtir-5<=ListeCoordEnnemis[i][t][0]+60 :
if ytir<=ListeCoordEnnemis[i][t][1]+5 and ytir>=Liste
CoordEnnemis[i][t][1]-60 :
Score=Score+50
feu=0
A
ffichageScore.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])
de
l ListeEnnemis[i][t]
del ListeCoordEnne
mis[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 ListeCoordEnnem
is[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 ListeCoordE
nnemis[i][t]
t+=1
t=0
i+=1
# Quand il n'y a plus d'ennemis ben on recomm
ence
# 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 re
créer
can.delete(canon[0])
can.delete(canon[
1])
Creation_CanonMobile()
# On reprend to
us les paramètres de départ
# afin qu'il n'y ai aucune erreur
xe,ye=20,20
xe2,ye2=20,80
xe
3,ye3=20,160
# On efface l'ennemi bonus
if
len(EnnemiBonus)!=0:
can.delete(EnnemiBonus[0])
can.delete(EnnemiBonus[1])
can.delete(EnnemiBonu
s[2])
can.delete(EnnemiBonus[3])
xeb,yeb
=0,0
# Avant de passer au niveau suivant
# i
l faut effacer les briques restantes
# à l'écran
if len(ListeAbris)!=0:
i=0
while i<len(ListeAbris):
can.delete(ListeA
bris[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=[]
Ennemi
s3=[]
ListeEnnemis=[Ennemis1,Ennemis2,Ennemis3]
Ennemis=[]
CoordEnnemis1=
[]
CoordEnnemis2=[]
CoordEnnemis3=[]
ListeCoordEnnemis=[CoordEnnemis1,CoordEnnemis2,CoordEn
nemis3]
NbreEnnemis1=6
NbreE
nnemis2=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 diri
ger le canon mobile de gauche à droite
def right(event):
global flag,Deb
utJeu
if DebutJeu!=0:
if flag!=0:
move(20)
def lef
t(event):
global flag,DebutJeu
if DebutJeu!=0:
if flag!=0:
move(-20)
# Cette fonction permet d'effectuer une pause en cours d
e partie
def pause(event):
global flag,pause,feu,DebutJeu,feu,Mort,Bonus
Actif,feuEnnemi,ArretAnimation
# Si le jeu n'a pas commencé
# la fon
ction 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")
f
lag=0
elif flag==0:
flag=1
can.delete(pause)
AnimationObusEnnemi()
if feu==1:
Arre
tAnimation=0
AnimationObus()
#
######################
# #
# Programme principal #
#
#
#######################
# Création de la fenêtre principal
e
fen=Tk()
# Titre de la fenêtre
fen.title('Space invaders')
# Défin
ition du canevas ( Ecran de jeu )
can=Canvas(fen,width=640,height=480,bg='bla
ck')
# Définition des touches qui vont permettre
# de diriger le canon mobil
e
can.bind_all("<Right>",right)
can.bind_all("<Left&
gt;",left)
can.bind_all("<space>",tir_joueur)
can.bind_al
l("<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_gam
e).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_re
ctangle(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=[]
# Ce
tte liste contiendra les coordonnées
# de position des ennemis dans le canevas
CoordEnnemis1=[]
CoordEnnemis2=[]
CoordEnnemis3=[]
ListeCoordEnnemis=[Co
ordEnnemis1,CoordEnnemis2,CoordEnnemis3]
NbreEnnemis1=6
NbreEnnemis2=6
Nbre
Ennemis3=6
NbreEnnemis=[NbreEnnemis1,NbreEnnemis2,NbreEnnemis3]
# Définiti
on des coordonnées de départ
# de chacune des rangées d'ennemis
xe,ye=0,0
x
e2,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()
E
nnemi_Categorie3()
i+=1
# Détermination aléatoire de l'ennemi
# qui tir
a en premier et ainsi de suite
RangEnnemiChoisi=randrange(0,3,1)
Ennemi1Ch
oisi=randrange(0,NbreEnnemis[0],1)
Ennemi2Choisi=randrange(0,NbreEnnemis[1],1)
Ennemi3Choisi=randrange(0,NbreEnnemis[2],1)
EnnemiChoisi=[Ennemi1Choisi,Enne
mi2Choisi,Ennemi3Choisi]
# Définition de l'ennemi bonus
EnnemiBonus=[]
Co
ordEnnemiBonus=[]
# Coordonnées de l'ennemi bonus
xeb=-20
yeb=80
# Ind
icateur 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
ChoixTir
eur=[]
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
# L
e 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
LimiteAvancem
ent=0
projectile=[]
PasAvancement=0
flag=0
# On affiche les indications co
ncernant
# le score et les vies restantes du joueur
AffichageScore=Label(fen
,font=('Fixedsys',16))
AffichageVie=Label(fen,font=('Fixedsys',16))
AffichageS
core.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'aff
ichage de l'écran de présentation
DebutJeu=0
# Cette variable indique
# s
i le joueur est mort ==> Canon mobile détruit
# de plus si cette variable va
ut 1 certaines fonctions
# seront par conséquent désactivées
Mort=0
Arret
Animation=0
# Si le fichier contenant les scores n'existe pas
# on le crée a
vec comme valeur de départ ==> 0
if existe('HighScore')==0:
FichierS
core=open('HighScore','w')
pickle.dump(0,FichierScore)
FichierScore.cl
ose()
# Cette liste va permettre d'afficher
# les scores suite à la destruct
ion d'un ennemi
afficherScore=[]
# On démarre la danse en mettant les enne
mis en scène !!
ennemis()
AnimationEnnemiBonus()
# On affiche l'écran d
e présentation du jeu
EcranDePresentation()
# On met le gestionnaire d'évé
nements en route
fen.mainloop()
Conclusion :
Le zip contient 3 fichier :
==> 1 f
ichier dans lequel est stocké le score du joueur
==> 1 fichier
qui contient le code source du jeu :p
==> 2 fichier images pour agr&ea
cute;menter le jeu ( rien d'incroyable !! Mais bon... )