Commits vergleichen

...

Keine gemeinsamen Commits. 'master' and 'ch3-start' haben vollständig unterschiedliche Historien.

6 geänderte Dateien mit 110 neuen und 156 gelöschten Zeilen
  1. +1
    -0
      .gitignore
  2. +86
    -95
      README.md
  3. +23
    -15
      birdie.py
  4. BIN
     
  5. BIN
     
  6. +0
    -46
      titi_grominet.py

+ 1
- 0
.gitignore Datei anzeigen

@@ -4,6 +4,7 @@ __pycache__/
*.py[cod]
*$py.class
.vscode/

# C extensions
*.so



+ 86
- 95
README.md Datei anzeigen

@@ -1,155 +1,146 @@
# Partie 1
## Pour commencer
# Partie 3

Pour réaliser votre programme, vous allez devoir vous servir des modules fournis par **Pygame Zero** que vous avez installés durant l'introduction.
## Retour à la case départ

La manière d'utiliser la bibliothèque est la suivante :
- À la première ligne de votre script, il faut inporter le module **pgzrun**
- À la dernière ligne, il faut appeler la méthode **go()** de ce module, qui est comme une fonction attachée au module, et que l'on invoque avec la *notation pointée*.
Que se passe-t-il lorsque Titi tombe du bas de l'écran ? En ce moment, vous le perdez probablement pour toujours. Essayons de faire quelque chose de mieux.

Voici donc à quoi devrait ressembler le squelette de tout programme de jeu basé sur *pgzrun*.
> Ajoutez cette nouvelle fonction après la fonction on_mouse_down :

```python
import pgzrun

# Le corps du programme devrait se trouver ici...

pgzrun.go()
def reset():
print("Retour au départ...")
titi.speed = 1
titi.center = (75, 350)
tube_superieur.center = (300, 0)
tube_inferieur.center = (300, tube_superieur.height + ecart)
```

L'exécution d'un tel programme devrait d'ailleur faire apparaître une fenêtre au fond noir et dont le titre est *Pygame Zero Game*
> - Modifiez maintenant le script `birdie.py`, selon le squelette décrit ci-dessus.
> - Entre la première et la dernière ligne (corps du programme), rédigez le code suivant :
Chaque ligne de cette fonction attribue une valeur. D'abord, elle ramène la vitesse de Titi à ce qu'elle était au départ, puis place son centre à une position **(x,y)**. Elle ramène également les tuyaux à leur point de départ. Si vous essayez le jeu maintenant, vous verrez que rien n'a changé. N'oubliez pas qu'une fonction ne fait rien tant que vous ne l'avez pas appelée. Appelons-la à partir de la fonction de mise à jour si Titi quitte l'écran.
> Ajoutez ceci à la fin de la fonction de mise à jour :

```python
TITLE = "Paf l'oiseau"
WIDTH = 400
HEIGHT = 708
if titi.y > HEIGHT :
reset()
```

> - Enregistrez votre fichier,
> - Exécutez-le pour voir le résultat.
Attention à bien respecter les *indentations* à l'intérieur de la fonction *update()*.

Vous devriez voir une fenêtre vide apparaître. Pouvez-vous comprendre ce que fait chaque ligne de code ?
> Vérifiez que tout se réinitialise si Titi tombe du bas de l'écran.
> Il faut aussi réinitialiser le jeu si Titi sort du haut de l'écran.

> - Quittez la fenêtre,
> - Effectuez quelques modifications sur les lignes de votre programme et exécutez à nouveau celui-ci, pour vérifier l'effet attendu.
> - N'oubliez pas de quitter la fenêtre de jeu entre chaque tentative.
> Modifiez votre code pour que cela fonctionne. Astuce : vous aurez besoin du mot-clé **or**.

## Afficher un arrière-plan

> Ajoutez ces lignes à la fin de votre programme. Assurez-vous de bien respecter l'indentation.
## Voler correctement !
En ce moment, Titi l'oiseau semble se téléporter vers le haut lorsque vous cliquez sur l'écran. Il faudrait idéalement qu'il se déplace un peu plus doucement. La raison pour laquelle il semble se déplacer instantanément est cette ligne :

```python
def draw():
screen.blit('cascade', (0, 0))
titi.y -= 50
```

Le mot clef **`def`** crée une fonction. Pour rappel, une fonction est une manière de grouper plusieurs instructions. La fonction que nous créons ici s'appelle **`draw`** (dessiner). Il s'agit d'un nom prédéfini, et il faut une fonction nommée de cette manière si vous voulez que **pgzero** puisse dessiner quoi que ce soit.
La première et unique instruction de la fonction commence par **`screen.blit`**. Elle dit à Pygame Zero de dessiner quelque chose sur l'écran.

> Exécutez le programme tel quel pour voir le résultat. Vous devriez voir l'image d'une cascade à l'intérieur de votre fenêtre. Comme précédemment, essayez de
> modifier les valeurs utilisées entre les parenthèses pour comprendre le rôle de chacune d'elles.
Cela lui fait déplacer un ensemble de 50 pixels d'un seul coup, ce qui n'est pas très fluide ! Lorsqu'un vrai oiseau bat des ailes, cela modifie sa vitesse et non sa position. Le changement de position n'est qu'un effet secondaire de la vitesse.

Vous pouvez télécharger vos propres images, et essayer de les utiliser en tenant compte de leurs tailles.

*NOTE : pgzero cherche après les éléments graphiques dont il a besoin à l'intérieur d'un dossier qui **doit** s'appeler **images***

## Ajouter l'oiseau

> Après la définition de la fonction *`draw`*, ajoutez la ligne suivante :
> Changez votre fonction `on_mouse_down` pour ceci :

```python
bird = Actor('bird1', (75, 350))
def on_mouse_down() :
titi.speed = -6.5
```

Cette ligne ne doit pas être indentée, elle est *hors* de la fonction. Son instruction ne sera exécutée qu'une seule fois, au lancement initial du programme, et définit un **`Actor`**, nommé **bird**. **`Actor`** est un élément de *Pygame Zero*, mais bird est une variable pour désigner l'object *Actor* créé. On peut choisir n'importe quel nom celle-ci. Par exemple, modifions 'bird' en 'titi'.
Essayez et vous verrez que lorsque vous cliquez maintenant, il va juste monter et frapper le haut de l'écran.

***ATTENTION*** : il faut cependant respecter les règles de nommage des variables python : pas d'espace, de caractères accentués, etc.
Nous avons besoin d'un peu de *gravité* pour le faire redescendre après chaque envolée.

> Exécutez à nouveau votre programme. Que se passe-t-il ?
> Créez une variable appelée **gravite** à la fin de votre fichier :

En fait, il ne devrait rien se passer de différent. Nous avons défini un **objet** de type **Actor**, et c'est tout. Si nous voulons voir apparaître cet objet, il faut appeler sa méthode **`draw`** au bon endroit, dans la fonction **`draw`** principale. Cela peut paraître un peu confus, mais voyez les choses comme ceci :
pendant l'on dessine (*draw*) la fenêtre principale du jeu, on demande à dessiner l'objet de type **Actor** en appelant la méthode draw de celui-ci de la manière suivante : `titi.draw()`.
`gravite = 0.3`

> Mettez à jour votre fonction **`draw`** pour refléter ces explications. Vous devriez obtenir quelque chose comme ceci :
Nous utiliserons cette variable pour modifier la vitesse de l'oiseau à chaque image.

> Utilisez cette variable au début de la fonction de mise à jour :

```python
def draw():
screen.blit('background', (0, 0))
titi.draw()
titi.speed += gravite
```

> Une fois que cela fonctionne, expérimentez à nouveau avec les différentes valeurs entre parenthèse (bird1, 75, 350) pour parfaitement comprendre leurs rôles.
> Essayez de placer l'oiseau dans chacun des coins de la fenêtre
> Que se passe-t-il si l'on intervertit les deux lignes à l'intérieur de la fonction `**draw**` ? Pourquoi ?
> Essayez de changer la valeur de la gravité pour voir l'effet qu'elle a.

<img alt="Titi dans son décor" src="https://i.imgur.com/oyjY2HY.png" width=250 />
Maintenant, cet oiseau est plus réaliste et le contrôler demande maintenant un peu plus d'habileté. Vous pouvez essayer de voler entre les tubes, mais nous n'avons toujours rien fait pour vous empêcher de voler droit dans les tuyaux. Nous allons bientôt corriger cela.

## Faisons se déplacer l'oiseau
## Rationnalisation du code
Vous avez peut-être remarqué qu'il y a des portions de code que nous avons dû écrire plusieurs fois à des endroits différents. Par exemple, `titi.speed = 1`. Nous l'avons une fois dans le code de configuration du jeu, puis une autre fois dans la fonction reset(), qui est appelée lorsque Titi meurt et que le jeu redémarre. Il serait peut-être judicieux de n'utiliser la fonction reset() qu'au début du jeu également ! On n'aurait alors besoin du code qu'à un seul endroit.

Pour déplacer l'oiseau, nous allons nous servir de la souris. Ajoutons une nouvelle fonction. Les fonctions peuvent-être placées dans n'importe quel ordre, mais conventionnellement, avant la fonction **`draw`** convient bien.
Ajoutez un appel à la fonction `reset()` à la toute fin du fichier.
Maintenant, nous pouvons supprimer l'appel `titi.speed = 1` qui se produit dans le code de configuration du jeu.
Essayez de suivre la même logique pour ne spécifier les positions de départ des éléments qu'une seule fois dans votre code.

> Écrivez le code suivant à l'endroit suggéré :
Indice : vous devriez pouvoir supprimer 3 valeurs de position. L'une d'entre elles par exemple : `(75, 350)`.

```python
def on_mouse_down():
print('Clic souris !')
titi.y -= 50 # équivalent à titi.y = titi.y - 50
```
Vérifiez que tout fonctionne toujours comme avant.

Tous les objets de type **Actor** ont une position **x** et **y**. Comme nous avons créé titi avec `titi = Actor(...`, il est un **Actor**. La valeur **x** correspond à la position horizontale de l'acteur (gauche/droite), alors que la valeur **y** correspond à la position verticale (haut/base).
### Une longueur d'avance pour Titi.

> Lancez le jeu et cliquez dans la fenêtre pour faire bouger l'oiseau. Que se passe-t-il en si l'on remplace 50 par une autre valeur ?
> Arrivez-vous à faire se déplacer l'oiseau horizontalement ? En sens inverse ?
> L'instruction print est censée afficher 'Clic souris !'. Pouvez-vous voir cela ?
Laissons au joueur un peu plus de temps pour s'envoler avant qu'il ne tombe de l'écran. Nous pouvons déplacer le point de départ à seulement 50 pixels du haut de l'écran. Trouvez cette ligne dans la fonction de réinitialisation :

La fonction **`on_mouse_down`** est *appelée* à chaque fois que l'on clique. Lorsqu'une fonction est appelée, l'ensemble des instructions qu'elle contient sont exécutées. Si l'on veut donner l'impression que l'oiseau se déplace de manière fluide, il faut utiliser de petites valeurs de décalage, et cliquer rapidement à de nombreuses reprises...
`titi.center = (75, 350)`

> Essayez de faire se déplacer l'oiseau de manière fluide...
Remplacez les 350 par quelque chose de beaucoup plus petit (50 par exemple) Essayez et trouvez une valeur qui vous semble juste.
Si vous avez bien rationnalisé votre code, vous remarquerez qu'il n'est nécessaire de changer cette valeur qu'à un seul endroit du code, ce qui évite les erreurs éventuelles.

De même que la fonction **`on_mouse_down`** est appelée lorsque l'on clique, la fonction **`update`**, si elle est définie, est appelée *automatiquement* ne nombreuses fois par seconde (60x normalement).
## Collisions
Dans PyGameZero, rien ne vous empêche de dessiner plusieurs sprites (images) les uns sur les autres. Donc, si nous voulons avoir un certain comportement lorsque les choses se heurtent, nous devons nous en occuper nous-mêmes. Ajoutez ce code à la fin de la fonction de mise à jour :

> Définissez votre propre fonction **`update`** comme suit :
```python
if (titi.colliderect(tube_superieur)) :
heurte_tube()
```

La fonction de collision vérifie si deux objets se touchent. Comme cette fonction se trouve à l'intérieur de la fonction de mise à jour, elle est vérifiée à chaque image. Cela ne fonctionnera à ce stade parce que nous n'avons pas créé la fonction **heurte_tube()**. Créons-la après la fonction de réinitialisation...

```python
def update():
titi.y += 1
def heurte_tube() :
print ("Paf !")
titi.image = "birddead" # (oiseau mort)
```
Maintenant, Titi devrait devenir un fantôme quand vous frappez le tuyau supérieur, mais il semble qu'il y ait encore trois problèmes :

1. Titi reste un fantôme même lorsque le jeu se réinitialise.
2. Titi peut toujours voler à travers le tuyau du bas !
3. Vous pouvez toujours voler, même en tant que fantôme.

> ***AVANT*** de lancer votre programme, essayez de deviner comment il va se comporter...
Essayez de résoudre vous-même les problèmes 1 et 2. Nous allons examiner le 3 ci-dessous.

De nouveau, que se passe-t-il si vous modifier la valeur 1 par une valeur plus grande ? Pour contrôler plus efficacement la vitesse de chute de notre oiseau, nous allons lui *attacher* une variable **`speed`**, de la même manière que pour **x** et **y**. Cette variable est comme un curseur dont on pourra augmenter ou diminuer la valeur pour contrôler la vitesse de chute.
Note : c'est peut-être le bon moment pour essayer de changer la taille de l'espace pour régler la difficulté du jeu. Vous pourriez par exemple le rendre très grand pendant les essais, afin de pouvoir vous concentrer sur les essais et non sur le vol !

> Ajoutez cette ligne en fin de fichier, mais toujours avant **`pgzrun.go()`** bien sûr :
Maintenant, nous aimerions empêcher Titi de continuer à voler lorsqu'il est un fantôme. Le code qui le fait voler a besoin d'un moyen de savoir s'il est toujours vivant. Nous pourrions utiliser la variable `titi.image`, car elle change quand il meurt. Mais il est préférable d'ajouter une nouvelle variable pour rendre notre code plus propre et moins susceptible de se casser si nous faisons des changements plus tard.

Ajoutez cette ligne à la fonction de réinitialisation :

```python
titi.speed = 1
titi.vivant = True
```

On a choisi le nom **speed** car il reflète l'idée de vitesse, mais comme c'est une variable, on aurait pu choisir n'importe quel autre nom respectant les règles habituelles.
Nous créons la nouvelle variable et nous la mettons en place. Maintenant, nous devons nous assurer que Titi ne battra que lorsqu'il sera vivant.

Il ne vous reste plus qu'à modifier la fonction **`update`** pour qu'elle utilise cette variable à la place que la valeur fixe '1'.
Ajoutez cette ligne au début de la fonction **on_mouse_down** :

```python
def update():
titi.y += titi.speed
if (titi.vivant) :
```
N'oubliez pas d'adapter les indentations de la ligne qui change la vitesse, de sorte qu'elle fasse partie de l'instruction if. Nous ne voulons changer la vitesse (en d'autres termes l'envol) que si l'oiseau est vivant !

En utilisant la variable `titi.speed` dans la fonction, on utilise la valeur attribuée à cette variable. Ainsi, chaque fois que la fonction **`update`** est appelée (60x par secondes), la position **y** de l'oiseau est modifié selon la valeur de **speed**, quelle que soit celle-ci.
Cela veut dire que **speed** peut changer pendant que le jeu est en train de tourner !

> Expérimentez avec les différentes valeur pour équilibrer le valeurs de jeu (effet du clic, vitesse de chute, ...)
La prochaine chose à faire est de changer Titi pour qu'il meurre quand il frappe un tuyau.

![L'oiseau qui bouge](https://i.imgur.com/Jx9EDww.gif)
Ajoutez une ligne pour changer la variable "vivant" de Titi en "False" lorsqu'il frappe un tuyau.

## Challenges
> Il vous est conseillé de développer ces différents challenges dans des branches autonomes, par exemple chapitre-1-challenge-1, etc.
> Ainsi, vous garder votre travail de base tel quel et pouvez travailler chaque challenge individuellement.
Voilà pour la partie 3. Dans la partie suivante, nous allons examiner quelques touches finales telles que l'ajout d'une animation de battement, la randomisation des positions du tuyau et le comptage des points

- Modifiez tout le jeu pour le faire fonctionner de manière horizontale.
- Arrangez-vous pour que l'oiseau stoppe tout mouvement si l'on clique dans la fenêtre.
- Arrangez-vous pour que quand vous gardez le bouton de la souris enfoncé, l'oiseau arrête de bouger, mais que quand vous relâchez le bouton, il recommence à bouger. (Indice : vous aurez besoin d'une nouvelle fonction : **`on_mouse_up`**)
- Ajoutez un autre oiseau, se déplacant à une autre vitesse,
- Arrangez-vous pour que quand un oiseau dépasse les limites de l'écran, il réapparaisse de l'autre côté. (Indice : vous allez devoir vous servir de l'instruction **`if`**)
- Arangez-vous pour qu'à chaque clic, l'oiseau accélère...
### Challenges
- Mettez la physique à l'envers ! Faites en sorte que la gravité tire Titi vers le haut, et que les battements d'ailes le poussent vers le bas
- Ajouter une clé de triche qui rend le joueur invincible.
Indice : essayez d'ajouter cette fonction et voyez ce qui se passe lorsque vous appuyez sur une touche :
```python
def on_key_down(key) :
print(key)
```
- Ajouter un petit battement d'aile moins ample et secret que le joueur peut faire en utilisant le bouton droit de la souris. Conseil : vous devrez ajouter un paramètre à votre fonction **on_mouse_down**, pour qu'elle devienne **on_mouse_down(button)**. Essayez d'utiliser la fonction d'impression comme vous l'avez fait dans le dernier défi pour voir quelles sont les valeurs du bouton.

+ 23
- 15
birdie.py Datei anzeigen

@@ -1,26 +1,34 @@
import pgzrun


TITLE = "Paf l'oiseau"
WIDTH = 400
HEIGHT = 762
HEIGHT = 708

def on_mouse_down():
print('Clic souris !')
titi.y -= 50 # deplacement horizontal
titi.x += 25 # deplacement latéral
# cela correspond au deplacement de titi du bas vers le haut
def draw():
screen.blit('cascade', (0, 0))
titi.draw()
#titi = Actor('bird1', (70, 40))
titi = Actor('bird1', (70, 40))
print('Clic souris !!!!')
titi.y -= 50

#(70, 350) le premier chiffre position de depart sur axe x
# le deuxieme chiffre position axe y
def update():
titi.y += titi.speed
#titi.x += tit.speed fera deplacer lateralement
#si on modifie le 1 on augmente la vitesse de la chute
tube_superieur.x -= vitesse_defilement
tube_inferieur.x -= vitesse_defilement
if tube_superieur.right < 0 :
tube_superieur.left = WIDTH
tube_inferieur.left = WIDTH

def draw():
screen.blit('background', (0, 0))
titi.draw()
tube_superieur.draw()
tube_inferieur.draw()

titi = Actor('bird1', (75, 350))
titi.speed = 1
ecart = 140
tube_superieur = Actor('top', (300, 0))
tube_inferieur = Actor('bottom', (300, tube_superieur.height + ecart))
vitesse_defilement = 1

# print(tube_superieur.width, tube_superieur.height)

pgzrun.go()



+ 0
- 46
titi_grominet.py Datei anzeigen

@@ -1,46 +0,0 @@
import pgzrun


TITLE = "Paf l'oiseau"
WIDTH = 400
HEIGHT = 762

# deplacement latéral
# def on_mouse_down():
# print('Clic souris !')
# titi.y -= 50 # deplacement horizontal
# titi.x += 25 # deplacement latéral
# grominet.y -= 50 # deplacement horizontal
# grominet.x += 40 # deplacement latéral
# cela correspond au deplacement de titi du bas vers le haut

# deplacement stoppé
def on_mouse_down():
print('Clic souris !')
titi.y -= 0 # deplacement horizontal
titi.x += 0 # deplacement latéral
grominet.y -= 0 # deplacement horizontal
grominet.x += 0 # deplacement latéral
titi.speed = 0
grominet.speed = 0
# cela correspond a stopper deplacement des perso

def draw():
screen.blit('cascade', (0, 0))
titi.draw()
grominet.draw()
#titi = Actor('bird1', (70, 40))
titi = Actor('titi', (200, 60))
grominet = Actor('grominet', (70, 40))
#(70, 350) le premier chiffre position de depart sur axe x
# le deuxieme chiffre position axe y

def update():
titi.y += titi.speed
grominet.y += grominet.speed
#titi.x += tit.speed fera deplacer lateralement
#si on modifie le 1 on augmente la vitesse de la chute

titi.speed = 1
grominet.speed = 1
pgzrun.go()

Laden…
Abbrechen
Speichern