IV-A. Importation et Initialisation▲
Au niveau des importations, en général, on se contente de celles qui suivent:
import
pygame
import
pygame.image
from
pygame.locals import
*
pygame.init
(
)
pygame.font.init
(
)
L'écran du jeu est créé par la fonction pygame.display.set_mode((largeur, hauteur)). On peut aussi changer le titre de la fenêtre par l'instruction pygame.display.set_caption(MonTitre)
screen =
pygame.display.set_mode
((
768
, 544
))
pygame.display.set_caption
(
"Oh Mummy"
)
IV-B. Chargement des images▲
Pour charger une image, il suffit d'appeler la fonction pygame.image.load(imagepath). J'ai décidé pour plus de clareté de charger toutes mes images dans un dictionnaire ImageOhMummy.
- ImageOhMummy['Gargou'] contient les différentes positions que le héros peut prendre
- ImageOhMummy['Mummy'] contient les différentes positions qu'une momie peut prendre
- ImageOhMummy['GuardianMummy'] contient la séquence d'apparition de la momie cachée
- ImageOhMummy['Trace'] contient les différentes traces que peut laisser le héros sur le sol
- ImageOhMummy['Box'] contient les différentes découvertes que le héros peut faire
- ImageOhMummy['Chiffre'] contient les chiffres pour afficher le score
- ImageOhMummy['ChiffreScroll'] contient les chiffres pour afficher le score quand le héros possède le parchemin
ImageOhMummy =
{}
ImageOhMummy['Gargou'
] =
{}
ImageOhMummy['Gargou'
]['Left'
] =
pygame.image.load
(
"./Image/GargouLeft.png"
)
...
ImageOhMummy['Mummy'
] =
{}
ImageOhMummy['Mummy'
]['Left'
] =
pygame.image.load
(
"./Image/MummyLeft.png"
)
...
ImageOhMummy['GuardianMummy'
] =
{}
for
i in
range(
1
, 17
):
ImageOhMummy['GuardianMummy'
][i] =
pygame.image.load
(
"./Image/GuardianMummy"
+
str(
i)+
".png"
)
...
ImageOhMummy['Trace'
] =
{}
ImageOhMummy['Trace'
]['None'
] =
pygame.image.load
(
"./Image/TraceNone.png"
)
ImageOhMummy['Trace'
]['LeftDown'
] =
pygame.image.load
(
"./Image/TraceLeftDown.png"
)
...
ImageOhMummy['Box'
] =
{}
ImageOhMummy['Box'
]['RoyalMummy'
] =
pygame.image.load
(
"./Image/RoyalMummy.png"
)
...
ImageOhMummy['Chiffre'
] =
{}
ImageOhMummy['ChiffreScroll'
] =
{}
ImageOhMummy['Score'
] =
pygame.image.load
(
"./Image/Score.png"
)
ImageOhMummy['Men'
] =
pygame.image.load
(
"./Image/Men.png"
)
ImageOhMummy['EndLife'
] =
pygame.image.load
(
"./Image/EndLife.png"
)
ImageOhMummy['End200'
] =
pygame.image.load
(
"./Image/End200.png"
)
ImageOhMummy['GameOver'
] =
pygame.image.load
(
"./Image/GameOver.png"
)
for
i in
range(
10
):
ImageOhMummy['Chiffre'
][i] =
pygame.image.load
(
'./Image/Chiffre'
+
str(
i)+
".png"
)
ImageOhMummy['ChiffreScroll'
][i] =
pygame.image.load
(
'./Image/ChiffreScroll'
+
str(
i)+
".png"
)
IV-C. Les différentes classes▲
IV-C-1. Base commune des classes▲
Les différentes classes présentées à la suite ont toutes une base commune. Tout d'abord, elles dérivent toutes
de la classe pygame.sprite.Sprite. De ce que j'en ai compris, cette classe permet de définir un objet
visuable à l'écran. La dérivation se fait de la manière suivante:
pygame.sprite.Sprite.__init__(self, self.containers) où self.containers est un tuple contenant
les groupes de sprites (dans notre cas des RenderUpdates (cf la fonction main()))
Dans la création de la classe, il y a ensuite 2 attributs à définir obligatoirement:
L'attribut image contient l'image de votre objet. Il peut par exemple correspondre à une image préalablement chargée
ou bien à une surface vide (pygame.Surface((largeur, hauteur))) que l'on pourra remplir avec la méthode fill(R, G, B) ou
blit(img, (x, y)).
L'attribut rect définit en général le rectangle englobant image. On se contente en général
de le créer de la façon suivante: self.rect = self.image.get_rect().
On pourra ensuite positionner ce rectangle dans la scène en modifiant par exemple les attributs top et left de rect.
Enfin, pour détruire un objet dérivant de la classe pygame.sprite.Sprite, il suffira de lui appliquer la méthode kill().
IV-C-2. Classe Gargou▲
La classe Gargou permet de gérer le héros.
Les attributs x et y donne la position de héros dans le tableau représentant
le plateau (cf la classe Plate). Le personnage prenant 4 cases de ce tableau, les composantes x et y
correspondent à la position en haut à gauche du héros.
L'attribut facing donne le sens dans laquelle se déplace le héros (0: à droite, 1: en haut,
2: à gauche, 3: en bas). L'attribut moving gère les 2 positions possibles pour chaque sens de déplacement.
La fonction move gère le déplacement du personnage en fonction de la flèche sur laquelle vous avez appuyé. La fonction
vérifie tout d'abord la validité du déplacement. Chaque fois que le personnage effectue un déplacement valide, il laisse derrière lui une trace de pas qui va permettre
de dégager les boîtes. Cela sera géré par l'appel à PLATE.Update(...).
A chaque déplacement, en fonction de la valeur des attributs facing et moving, on
met à jour l'attribut image par l'image correspondante.
Enfin, l'attribut level donne le niveau du héros et permet de définir l'algorithme de déplacement
des momies. A chaque fois que le héros finit la série des 5 niveaux d'une pyramide, cet attribut augmente de 1.
Quand le héros a récupéré la clé et les restes de la momie, il peut changer de niveau en remontant à l'entrée initiale
( condition à vérifier: PLATE.Key and PLATE.RoyalMummy and self.x == 15 and self.y == 1 )
Une unique instance de cette classe est créée et est globale au jeu nommée GARGOU
class
Gargou
(
pygame.sprite.Sprite):
def
__init__
(
self):
pygame.sprite.Sprite.__init__
(
self, self.containers)
self.image =
ImageOhMummy['Gargou'
]['MoveDownRight'
]
self.rect =
self.image.get_rect
(
)
self.x =
15
self.y =
1
self.facing =
0
self.moving =
0
self.rect.left =
320
self.rect.top =
94
self.level =
1
def
move
(
self, direction):
try
: direct =
direction.index
(
1
)
except
: return
self.facing =
direct
x =
self.x; y =
self.y
if
direct ==
0
: x =
self.x +
1
elif
direct ==
1
: y =
self.y -
1
elif
direct ==
2
: x =
self.x -
1
elif
direct ==
3
: y =
self.y +
1
if
PLATE.plate[y][x] ==
PLATE.plate[y][x+
1
] ==
PLATE.plate[y+
1
][x] ==
PLATE.plate[y+
1
][x+
1
] ==
1
:
self.x =
x
self.y =
y
else
: return
PLATE.Update
(
self.x, self.y, self.facing, self.moving)
if
PLATE.Key and
PLATE.RoyalMummy and
self.x ==
15
and
self.y ==
1
:
PLATE.Level =
max(
1
, (
PLATE.Level +
1
) %
6
)
PLATE.ChangeLevel =
True
self.moving =
(
self.moving +
1
) %
2
self.image =
ImageOhMummy['Gargou'
]['Face'
][2
*
self.facing +
self.moving]
self.rect.left =
80
+
16
*
self.x
self.rect.top =
78
+
16
*
self.y
IV-C-3. Classe Life▲
La classe Life permet de gérer à la fois le nombre restant de vies du héros et son affichage à l'écran.
La fonction Update permet de réafficher à l'écran les vies restantes du héros quand ce nombre change.
Une seule instance de cette classe sera créée en tant que variable globale et nommée LIFE pour une manipulation
plus aisée.
class
Life
(
pygame.sprite.Sprite):
def
__init__
(
self):
pygame.sprite.Sprite.__init__
(
self, self.containers)
self.life =
5
## Le héros démarre avec 5 vies
self.image =
pygame.Surface
((
320
, 32
))
self.rect =
self.image.get_rect
(
)
self.rect.top =
78
self.rect.left =
416
def
Update
(
self):
self.image.fill
((
255
, 255
, 0
))
self.image.blit
(
ImageOhMummy['Men'
], (
0
, 0
))
for
i in
range(
0
, self.life, 2
):
self.image.blit
(
ImageOhMummy['Gargou'
]['MoveRight'
], (
64
+
32
*
i, 0
))
for
i in
range(
1
, self.life, 2
):
self.image.blit
(
ImageOhMummy['Gargou'
]['Right'
], (
64
+
32
*
i, 0
))
IV-C-4. Classe Score▲
La classe Score permet de gérer le score du héros ainsi que son affichage à l'écran. Il y a de même
une unique fonction Update appelée chaque fois que le score change. Si le héros a découvert le parchemin
et qu'il ne l'a pas encore utilisé, le score est affiché en inversant les couleurs jaune et bleu.
Une seule instance de cette classe sera créée en tant que variable globale et nommée SCORE pour une manipulation
plus aisée.
class
Score
(
pygame.sprite.Sprite):
def
__init__
(
self):
pygame.sprite.Sprite.__init__
(
self, self.containers)
self.score =
0
self.image =
pygame.Surface
((
176
, 16
))
self.image.fill
((
255
, 255
, 0
))
self.rect =
self.image.get_rect
(
)
self.rect.top =
78
self.rect.left =
96
self.image.blit
(
ImageOhMummy['Score'
], (
0
, 0
))
for
i in
range(
5
):
self.image.blit
(
ImageOhMummy['Chiffre'
][0
], (
96
+
16
*
i, 0
))
def
Update
(
self):
scorestr =
str(
self.score).zfill
(
5
) ## Récupération du score sous forme d'une chaînes de caractères de longueur 5
b =
0
for
i in
scorestr:
if
PLATE.Scroll: self.image.blit
(
ImageOhMummy['ChiffreScroll'
][int(
i)], (
96
+
16
*
b, 0
))
else
: self.image.blit
(
ImageOhMummy['Chiffre'
][int(
i)], (
96
+
16
*
b, 0
))
b +=
1
IV-C-5. Classe Mummy▲
La classe Mummy permet de gérer les momies (mouvement et affichage à l'écran). Toutes les momies du jeu sont
contenues dans la liste globale MUMMY. Une instance de Mummy possède les mêmes attributs qu'une
instance de Gargou à savoir x, y, facing et moving et ont la
même signification.
L'attribut supplémentaire movable permet de gérer la vitesse de déplacement de la momie pour que celle-ci ne se déplace pas trop vite.
On distingue ici 3 fonctions movevalable, move et Initialize.
La fonction Initialize permet de repositionner chaque momie encore vivante au changement de niveau.
La fonction movevalable retourne toutes les cases sur laquelle une momie peut se déplacer à partir de sa position.
La fonction move gère le déplacement de la momie. Ce déplacement va dépendre du niveau atteint par le héros. Les momies
seront ainsi de plus en plus "intelligentes" et chercheront à force à se déplacer en direction du héros.
class
Mummy
(
pygame.sprite.Sprite):
def
__init__
(
self, x, y):
pygame.sprite.Sprite.__init__
(
self, self.containers)
self.image =
ImageOhMummy['Mummy'
]['MoveRight'
]
self.rect =
self.image.get_rect
(
)
self.x =
x
self.y =
y
self.facing =
0
self.moving =
0
self.rect.left =
80
+
x *
16
self.rect.top =
78
+
y *
16
self.movable =
0
def
movevalable
(
self):
res =
[]
if
PLATE.plate[self.y][self.x+
2
] ==
1
and
PLATE.plate[self.y+
1
][self.x+
2
] ==
1
: res.append
(
0
)
if
PLATE.plate[self.y-
1
][self.x] ==
1
and
PLATE.plate[self.y-
1
][self.x+
1
] ==
1
: res.append
(
1
)
if
PLATE.plate[self.y][self.x-
1
] ==
1
and
PLATE.plate[self.y+
1
][self.x-
1
] ==
1
: res.append
(
2
)
if
PLATE.plate[self.y+
2
][self.x] ==
1
and
PLATE.plate[self.y+
2
][self.x+
1
] ==
1
: res.append
(
3
)
return
res
def
move
(
self):
self.movable =
(
self.movable +
1
) %
3
if
self.movable ==
0
:
if
GARGOU.level ==
1
: direct =
random.randint
(
0
, 3
)
elif
GARGOU.level ==
2
: direct =
random.choice
(
[0
, 1
, 2
, 3
, self.facing, self.facing])
elif
GARGOU.level ==
3
: direct =
random.choice
(
self.movevalable
(
))
elif
GARGOU.level ==
4
:
m =
self.movevalable
(
)
m.extend
(
[self.facing, self.facing, self.facing])
direct =
random.choice
(
m)
elif
GARGOU.level ==
5
:
m =
[]
if
self.x ==
GARGOU.x:
if
self.y -
GARGOU.y <
0
: direct =
3
elif
self.y -
GARGOU.y >
0
: direct =
1
elif
self.y ==
GARGOU.y:
if
self.x -
GARGOU.x <
0
: direct =
0
elif
self.x -
GARGOU.x >
0
: direct =
2
else
:
m =
self.movevalable
(
)
m.extend
(
[self.facing, self.facing, self.facing])
direct =
random.choice
(
m)
elif
GARGOU.level >=
6
:
m =
[]
if
self.x -
GARGOU.x <
0
: m.append
(
0
)
elif
self.x -
GARGOU.x >
0
: m.append
(
2
)
if
self.y -
GARGOU.y <
0
: m.append
(
3
)
elif
self.y -
GARGOU.y >
0
: m.append
(
1
)
direct =
random.choice
(
m)
self.facing =
direct
x =
self.x; y =
self.y
if
direct ==
0
: x =
self.x +
1
elif
direct ==
1
: y =
self.y -
1
elif
direct ==
2
: x =
self.x -
1
elif
direct ==
3
: y =
self.y +
1
if
PLATE.plate[y][x] ==
PLATE.plate[y][x+
1
] ==
PLATE.plate[y+
1
][x] ==
PLATE.plate[y+
1
][x+
1
] ==
1
:
for
mum in
MUMMY:
if
self !=
mum and
abs(
x-
mum.x) <=
1
and
abs(
y -
mum.y) <=
1
:
return
else
:
self.x =
x
self.y =
y
else
: return
self.moving =
(
self.moving +
1
) %
2
self.image =
ImageOhMummy['Mummy'
]['Face'
][2
*
self.facing +
self.moving]
self.rect.left =
80
+
16
*
self.x
self.rect.top =
78
+
16
*
self.y
def
Initialize
(
self, x, y):
self.x =
x
self.y =
y
self.facing =
0
self.moving =
0
self.rect.left =
80
+
x *
16
self.rect.top =
78
+
y *
16
self.movable =
0
IV-C-6. Classe GuardianMummy▲
La classe GuardianMummy permet de gérer la naissance de la momie cachée dans une des boîtes.
Sa position dans sa boîte va dépendre de la position du héros au moment où celui-ci a dégagé entièrement la boîte de
telle sorte que cette position soit la plus proche de la position du dégagement. Là encore, il n'y a qu'une fonction
utile, la fonction Update. Celle-ci va gérer l'apparition régulière de la momie.
Il y a 16 vues avant que la momie soit entièrement apparue. Une fois ce nombre atteint, on rajoute donc une momie
dans la liste globale MUMMY. la case de naissance de la momie devenant une case sur laquelle le héros et les autres
momies peuvent se déplacer, on met à jour le tableau PLATE.plate. Enfin, on vide la liste globale GUARDIANMUMMY
(qui ne peut contenir au maximum qu'un élément) et on tue l'instance de la classe GuardianMummy.
class
GuardianMummy
(
pygame.sprite.Sprite):
def
__init__
(
self, x, y):
## x et y corresponde au numéro de la boîte sachant que 0<=x<=4 et 0<=y<=3
pygame.sprite.Sprite.__init__
(
self, self.containers)
self.view =
0
self.image =
pygame.Surface
((
0
,0
)) ## On part d'une image vide
self.rect =
self.image.get_rect
(
)
## Définition de la position de naissance de la Momie
if
GARGOU.x <
3
+
7
*
x: self.x =
3
+
7
*
x
elif
GARGOU.x >
6
+
7
*
x: self.x =
6
+
7
*
x
else
: self.x =
GARGOU.x
if
GARGOU.y <
5
+
5
*
y: self.y =
5
+
5
*
y
elif
GARGOU.y >
6
+
5
*
y: self.y =
6
+
5
*
y
else
: self.y =
GARGOU.y
self.movable =
0
def
Update
(
self):
self.movable =
(
self.movable +
1
) %
6
if
self.movable ==
0
:
self.view +=
1
self.image =
ImageOhMummy['GuardianMummy'
][self.view]
self.rect =
self.image.get_rect
(
)
self.rect.top =
110
+
16
*
self.y -
2
*
self.view
self.rect.left =
80
+
16
*
self.x
if
self.view ==
16
:
MUMMY.append
(
Mummy
(
self.x, self.y))
PLATE.plate[self.y][self.x] =
1
PLATE.plate[self.y+
1
][self.x] =
1
PLATE.plate[self.y][self.x+
1
] =
1
PLATE.plate[self.y+
1
][self.x+
1
] =
1
PLATE.image.blit
(
ImageOhMummy['Trace'
]['None'
], (
16
*
self.x -
16
, 16
*
self.y -
16
))
PLATE.image.blit
(
ImageOhMummy['Trace'
]['None'
], (
16
*
(
self.x+
1
) -
16
, 16
*
self.y -
16
))
PLATE.image.blit
(
ImageOhMummy['Trace'
]['None'
], (
16
*
self.x -
16
, 16
*
(
self.y+
1
) -
16
))
PLATE.image.blit
(
ImageOhMummy['Trace'
]['None'
], (
16
*
(
self.x+
1
) -
16
, 16
*
(
self.y+
1
) -
16
))
GUARDIANMUMMY.pop
(
)
self.kill
(
)
IV-C-7. Classe Plate▲
La classe Plate gère le plateau de jeu.
L'attribut plate est un tableau à 2 dimensions représentant les cases possibles de déplacement, 1 étant
une case accessible et 0 une non accesible (bord ou une partie d'une boîte). Comme on le voit sur la figure ci-dessus,
les cases jaunes représentent une partie d'un mur, les cases blanches une partie d'une boîte et les cases noires représentent
le chemin sur lequel peut mouvoir le héros.
L'attribut trace est un tableau à 2 dimensions donnant les cases sur lesquelles le héros s'est déjà déplacé et
permettant de savoir si une boîte à été entièrement dégagée. Il a donc les mêmes dimensions que l'attribut plate.
L'attribut box est un tableau à 2 dimensions donnant l'état des boîtes à découvrir (au départ toutes sont à
NonTested).
L'attribut boxchoice est un tableau à 1 dimension de même taille que box qui contient toutes
les découvertes à faire, chaque découverte étant aléatoirement reliée à une case de box.
L'attribut Key détermine si la clé a été découverte.
L'attribut Scroll détermine si le héros possède le parchemin.
L'attribut RoyalMummy détermine si les restes de la momie ont été découvertes.
L'attribut Level détermine le niveau dans la pyramide dans lequel évolue le héros (1 <= Level <= 5)
L'attribut ChangeLevel indique si le héros doit changer de niveau dans la pyramide.
Une case du plateau de jeu représente une surface de 16x16 à l'écran. Ainsi les personnages prennent 2x2 cases sur le jeu.
Une boîte contient 5x3 cases. On se retrouve ainsi avec un total de 39x26 cases sachant que la bordure du tableau
plate représentent le mur extérieur (d'épaisseur une case). Il y a ainsi tout une gymnastique pour se répérer
à l'intérieur de ce tableau.
Chaque fois qu'on initialise le plateau (c'est à dire qu'on change de niveau), une momie supplémentaire apparaît
(MUMMY.append(Mummy(1, 23))) que l'on place en bas à gauche de l'écran, les momies survivantes sont
repositionnées à côté.
La fonction Update (appelée lors du mouvement du héros) permet de mettre à jour et d'afficher le tableau
des traces de pas puis appelle la fonction UpdateBox pour vérifier si une boîte a été ou non entièrement
dégagée. Celle-ci appelle elle-même la fonction UpdateClose en spécifiant la boîte test.
Si une boîte est dégagée, on effectue le résultat de la boîte (augmentation du score, apparition d'une momie, découverte
d'un objet, ...).
De même que la plupart des autres classes, une seule instance globale est créée et nommée PLATE, ce qui permet
d'y avoir accès facilement dans les autres classes.
class
Plate
(
pygame.sprite.Sprite):
def
__init__
(
self, level):
pygame.sprite.Sprite.__init__
(
self, self.containers)
self.Initialize
(
level)
def
Initialize
(
self, level):
self.plate =
[39
*
[0
] for
i in
range(
26
)]
self.trace =
[39
*
[0
] for
i in
range(
26
)]
self.box =
[5
*
['NonTested'
] for
i in
range(
4
)]
l =
str(
level)
self.boxchoice =
['Treasure'
, 'Treasure'
, 'Treasure'
, 'Treasure'
, 'Treasure'
, 'Treasure'
, 'Treasure'
, 'Treasure'
, 'Treasure'
, 'Treasure'
,
'GuardianMummy'
+
l, 'Key'
, 'RoyalMummy'
, 'Scroll'
, 'Empty'
+
l, 'Empty'
+
l, 'Empty'
+
l, 'Empty'
+
l, 'Empty'
+
l, 'Empty'
+
l]
random.shuffle
(
self.boxchoice)
self.Key =
False
self.Scroll =
False
self.RoyalMummy =
False
self.Level =
level
self.ChangeLevel =
False
for
i in
range(
3
, 24
, 5
):
for
j in
range(
1
, 38
):
self.plate[i][j] =
1
self.plate[i+
1
][j] =
1
for
j in
range(
1
, 37
, 7
):
for
i in
range(
3
, 25
):
self.plate[i][j] =
1
self.plate[i][j+
1
] =
1
self.plate[1
][15
] =
1
self.plate[1
][16
] =
1
self.plate[2
][15
] =
1
self.plate[2
][16
] =
1
self.image =
pygame.Surface
((
592
, 384
))
self.image.fill
((
255
, 255
, 0
))
self.rect =
self.image.get_rect
(
)
self.rect.left =
96
self.rect.top =
94
## Affichage du plateau
for
i in
range(
1
, 25
):
for
j in
range(
1
, 38
):
if
self.plate[i][j] ==
1
:
self.image.blit
(
ImageOhMummy['Trace'
]['None'
], (
16
*
j -
16
, 16
*
i -
16
))
for
i in
range(
4
):
for
j in
range(
5
):
self.image.blit
(
ImageOhMummy['Box'
]['NonTested'
+
l], (
32
+
16
*
7
*
j, 64
+
16
*
5
*
i))
LIFE.Update
(
)
MUMMY.append
(
Mummy
(
1
, 23
))
i =
1
for
mum in
MUMMY:
mum.Initialize
(
1
+
2
*
i, 23
)
i +=
1
def
Update
(
self, x, y, facing, moving):
## Mise à jour des traces
if
facing ==
0
:
self.trace[y][x-
1
] =
1
self.trace[y+
1
][x-
1
] =
1
if
moving ==
0
: self.image.blit
(
ImageOhMummy['Trace'
]['DownRight'
], (
16
*
x -
32
, 16
*
y -
16
))
else
: self.image.blit
(
ImageOhMummy['Trace'
]['UpRight'
], (
16
*
x -
32
, 16
*
y -
16
))
elif
facing ==
1
:
self.trace[y+
2
][x] =
1
self.trace[y+
2
][x+
1
] =
1
if
moving ==
0
: self.image.blit
(
ImageOhMummy['Trace'
]['LeftUp'
], (
16
*
x -
16
, 16
*
y +
16
))
else
: self.image.blit
(
ImageOhMummy['Trace'
]['RightUp'
], (
16
*
x -
16
, 16
*
y +
16
))
elif
facing ==
2
:
self.trace[y][x+
2
] =
1
self.trace[y+
1
][x+
2
] =
1
if
moving ==
0
: self.image.blit
(
ImageOhMummy['Trace'
]['DownLeft'
], (
16
*
x +
16
, 16
*
y -
16
))
else
: self.image.blit
(
ImageOhMummy['Trace'
]['UpLeft'
], (
16
*
x +
16
, 16
*
y -
16
))
elif
facing ==
3
:
self.trace[y-
1
][x] =
1
self.trace[y-
1
][x+
1
] =
1
if
moving ==
0
: self.image.blit
(
ImageOhMummy['Trace'
]['LeftDown'
], (
16
*
x -
16
, 16
*
y -
32
))
else
: self.image.blit
(
ImageOhMummy['Trace'
]['RightDown'
], (
16
*
x -
16
, 16
*
y -
32
))
## Mise à jour des cases
if
y>
2
: self.UpdateBox
(
x, y)
def
UpdateBox
(
self, x, y):
xx1 =
min(
4
, max(
0
, (
x -
3
) //
7
))
yy1 =
min(
3
, max(
0
, (
y -
5
) //
5
))
xx2 =
min(
4
, (
x -
1
)//
7
)
yy2 =
min(
3
, (
y -
3
) //
5
)
if
self.box[yy1][xx1] ==
'NonTested'
: self.UpdateClose
(
xx1, yy1)
if
self.box[yy1][xx2] ==
'NonTested'
: self.UpdateClose
(
xx2, yy1)
if
self.box[yy2][xx1] ==
'NonTested'
: self.UpdateClose
(
xx1, yy2)
if
self.box[yy2][xx2] ==
'NonTested'
: self.UpdateClose
(
xx2, yy2)
def
UpdateClose
(
self, x, y):
for
i in
range(
3
+
5
*
y, 10
+
5
*
y):
for
j in
range(
1
+
7
*
x, 10
+
7
*
x):
if
self.plate[i][j] ==
1
and
self.trace[i][j] ==
0
: return
False
self.box[y][x] =
self.boxchoice[5
*
y +
x]
self.image.blit
(
ImageOhMummy['Box'
][self.box[y][x]], (
32
+
112
*
x, 64
+
80
*
y))
if
self.box[y][x] ==
'Treasure'
: SCORE.score +=
5
elif
self.box[y][x] ==
"RoyalMummy"
:
SCORE.score +=
50
self.RoyalMummy =
True
elif
self.box[y][x] ==
"Scroll"
:
self.Scroll =
True
SCORE.Update
(
)
elif
self.box[y][x] ==
"Key"
:
self.Key =
True
elif
self.box[y][x] ==
"GuardianMummy"
+
str(
self.Level):
GUARDIANMUMMY.append
(
GuardianMummy
(
x, y))
SCORE.Update
(
)
IV-D. Fonction main()▲
La fonction main va nous permettre d'initialiser toutes nos variables et de gérer les évènements
clavier et le rafraîchissement de l'écran.
clock = pygame.time.Clock() permet de créer une horloge qui permettra ensuite de fixer le nombre d'images à la seconde que
générera le jeu. Ce nombre est alors défini par la fonction clock.tick(fps) où fps est le
nombre d'images par seconde.
On définit ensuite les différents groupes de sprite (all, plate, endgame) de type
ici pygame.sprite.RenderUpdates qui géreront l'affichage à l'écran, lesquels sont attribués aux différentes classes
(Plate.containers = plate, Score.containers = all, ...).
Enfin nos différentes variables sont créées et définies de manière globale. Puis on affiche un arrière plan sur l'écran de jeu ( screen.blit(background, (0, 0)))
et on force le rafraîchissement entier de la fenêtre de jeu (pygame.display.flip())
def
main
(
):
clock =
pygame.time.Clock
(
)
background =
pygame.Surface
(
SCREENRECT.size)
background =
background.convert
(
)
background.fill
((
255
,255
,0
))
all =
pygame.sprite.RenderUpdates
(
)
plate =
pygame.sprite.RenderUpdates
(
)
endgame =
pygame.sprite.RenderUpdates
(
)
Plate.containers =
plate
Score.containers =
all
Gargou.containers =
all
Life.containers =
all
Mummy.containers =
all
GuardianMummy.containers =
all
global
PLATE
global
SCORE
global
GARGOU
global
LIFE
global
MUMMY
global
GUARDIANMUMMY
SCORE =
Score
(
)
LIFE =
Life
(
)
MUMMY =
[]
GUARDIANMUMMY =
[]
GARGOU =
Gargou
(
)
GARGOU.level =
1
PLATE =
Plate
(
1
)
screen.blit
(
background, (
0
, 0
))
pygame.display.flip
(
)
On définit enfin une boucle infinie dans laquelle sera contrôlé le jeu.
Cette boucle commence par une condition qui teste les évènements reçus par Pygame (pygame.event.get()).
Si le joueur a appuyé sur la touche Escape (évènement de type KEYDOWN) ou bien qu'un évènement de type QUIT
a été généré, on quitte le jeu.
On effectue alors les actions des différents personnages:
- On récupère les touches sur lesquelles le joueur a appuyé en ne considérant que les flèches et on effectue les
déplacement du héros (GARGOU.move(direction)).
- Si une momie est en train de naître, guardian.Update() met à jour son évolution.
- Pour chaque momie du jeu, on effectue un déplacement (mum.move()). Puis on vérifie qu'une fois
déplacée, elle n'entre pas en collision avec le héros. Si le héros perd sa dernière vie, on affiche l'image GameOver
( screen.blit(ImageOhMummy['GameOver'], (208, 238)) ) et on attend que le joueur quitte le jeu ou recommence
une partie en appuyant sur la touche 'c' ou 'C'.
Si le joueur a fini un tableau (condition PLATE.ChangeLevel à vérifier), on réinitialise le tout.
Enfin, à la fin de la boucle, on réaffiche en dessinant nos groupes de sprite sur la scène (pl = plate.draw(screen) et
dirty = all.draw(screen) ) et en effectuant le raffraîchissement à l'écran ( pygame.display.update(pl) et
pygame.display.update(dirty) ), le tout en forçant le nombre de frames par seconde ( clock.tick(12) )
goon =
True
while
goon:
for
event in
pygame.event.get
(
):
if
event.type ==
QUIT or
(
event.type ==
KEYDOWN and
event.key ==
K_ESCAPE): return
keystate =
pygame.key.get_pressed
(
)
direction =
[keystate[K_RIGHT], keystate[K_UP], keystate[K_LEFT], keystate[K_DOWN]]
GARGOU.move
(
direction)
for
guardian in
GUARDIANMUMMY: guardian.Update
(
)
for
mum in
MUMMY:
mum.move
(
)
if
abs(
mum.x -
GARGOU.x) <=
1
and
abs(
mum.y -
GARGOU.y) <=
1
:
if
not
PLATE.Scroll:
LIFE.life -=
1
LIFE.Update
(
)
if
LIFE.life ==
0
:
goon =
False
screen.blit
(
ImageOhMummy['GameOver'
], (
208
, 238
))
while
True
:
for
event in
pygame.event.get
(
):
if
event.type ==
QUIT or
(
event.type ==
KEYDOWN and
event.key ==
K_ESCAPE): return
keystate =
pygame.key.get_pressed
(
)
if
keystate[ord(
'c'
)] or
keystate[ord(
'C'
)]:
return
main
(
)
pygame.display.flip
(
)
clock.tick
(
10
)
else
:
PLATE.Scroll =
False
SCORE.Update
(
)
mum.kill
(
)
MUMMY.remove
(
mum)
if
PLATE.ChangeLevel:
if
PLATE.Level ==
1
:
if
random.randint
(
0
, 1
) ==
0
and
LIFE.life <
9
:
background.blit
(
ImageOhMummy['EndLife'
], (
0
, 0
))
LIFE.life +=
1
else
:
background.blit
(
ImageOhMummy['End200'
], (
0
, 0
))
SCORE.score +=
200
screen.blit
(
background, (
0
, 0
))
for
mum in
MUMMY: mum.kill
(
)
MUMMY =
[]
GARGOU.level +=
1
while
True
:
for
event in
pygame.event.get
(
):
if
event.type ==
QUIT or
(
event.type ==
KEYDOWN and
event.key ==
K_ESCAPE): return
keystate =
pygame.key.get_pressed
(
)
if
keystate[ord(
'c'
)] or
keystate[ord(
'C'
)]: break
pygame.display.flip
(
)
clock.tick
(
10
)
for
mum in
GUARDIANMUMMY: mum.kill
(
)
GUARDIANMUMMY =
[]
background.fill
((
255
,255
,0
))
screen.blit
(
background, (
0
, 0
))
pygame.display.flip
(
)
PLATE.Initialize
(
PLATE.Level)
SCORE.Update
(
)
#draw the scene
pl =
plate.draw
(
screen)
dirty =
all.draw
(
screen)
pygame.display.update
(
pl)
pygame.display.update
(
dirty)
clock.tick
(
12
)
pygame.time.wait
(
1000
)