Compare commits

...

No commits in common. 'master' and 'ch-2-start' have entirely different histories.

5 changed files with 112 additions and 136 deletions
Split View
  1. +1
    -0
      .gitignore
  2. +54
    -103
      README.md
  3. +24
    -15
      birdie.py
  4. BIN
     
  5. +33
    -18
      titi_grominet.py

+ 1
- 0
.gitignore View File

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

# C extensions
*.so



+ 54
- 103
README.md View File

@@ -1,155 +1,106 @@
# Partie 1
## Pour commencer
# Partie 2
Maintenant que nous avons un arrière-plan et un oiseau qui vole de haut en bas, ajoutons les tuyaux aux travers desquels l'oiseau va devoir passer.

Pour réaliser votre programme, vous allez devoir vous servir des modules fournis par **Pygame Zero** que vous avez installés durant l'introduction.
## Ajouter les tuyaux

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*.
Vous avez déjà vu que nous pouvons créer des objets `Actor` et comment les déplacer sur l'écran. Au besoin, retournez voir dans la section précédente comment vous avez procédé avec l'oiseau.

Voici donc à quoi devrait ressembler le squelette de tout programme de jeu basé sur *pgzrun*.
Nous devons donc ajouter deux tuyaux, et si vous regardez dans le répertoire images, vous verrez que nous avons deux fichiers nommés `top.png` et `bottom.png`. Comment les ajouter au jeu ?

```python
import pgzrun

# Le corps du programme devrait se trouver ici...
> Créons deux nouveaux acteurs en ajoutant à la fin de votre code :

pgzrun.go()
```python
tube_superieur = Actor('top', (300,0))
tube_inferieur = Actor('bottom', (300,500))
```

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 :
Pour voir apparaître les tuyaux, il ne faut pas oublier de demander leur dessin. À vous de déterminer où placer ces deux lignes :

```python
TITLE = "Paf l'oiseau"
WIDTH = 400
HEIGHT = 708
tube_superieur.draw()
tube_inferieur.draw()
```

> - Enregistrez votre fichier,
> - Exécutez-le pour voir le résultat.
> Testez le résultat

Vous devriez voir une fenêtre vide apparaître. Pouvez-vous comprendre ce que fait chaque ligne de code ?
Bien, nous avons des tuyaux ! Mais ils sont juste là, sur la page, et il n'y a pas d'espace entre eux.

> - 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.
*Pouvez-vous deviner ce que les `(300, 0)` et `(300, 500)` signifient ? Modifiez-les pour vérifier.*

## Afficher un arrière-plan
## Attention à l'écart

> Ajoutez ces lignes à la fin de votre programme. Assurez-vous de bien respecter l'indentation.
Comment faire un trou pour que notre oiseau puisse voler ? Nous devons nous assurer que nous positionnons les tuyaux au bon endroit sur l'écran, et pour ce faire, nous devons connaître la taille de chaque image.

> Voyons ce que nous pouvons découvrir d'un acteur, en ajoutant ce code à la fin de votre programme :

```python
def draw():
screen.blit('cascade', (0, 0))
print(tube_superieur.width, tube_superieur.height)
```

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.

Vous pouvez télécharger vos propres images, et essayer de les utiliser en tenant compte de leurs tailles.
> Exécutez le programme et regardez quels nombres apparaissent dans la console.

*NOTE : pgzero cherche après les éléments graphiques dont il a besoin à l'intérieur d'un dossier qui **doit** s'appeler **images***
Vous devriez voir apparaître deux chiffres (normalement 100 500), c'est la largeur et la hauteur du tube supérieur en pixels.

## Ajouter l'oiseau

> Après la définition de la fonction *`draw`*, ajoutez la ligne suivante :
Grâce à ces informations, nous pouvons modifier la construction des tuyaux supérieurs et inférieurs en conséquence :

```python
bird = Actor('bird1', (75, 350))
ecart = 140
tube_superieur = Actor('top', (300, 0))
tube_inferieur = Actor('bottom', (300, tube_superieur.height + ecart))
```

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'.

***ATTENTION*** : il faut cependant respecter les règles de nommage des variables python : pas d'espace, de caractères accentués, etc.

> Exécutez à nouveau votre programme. Que se passe-t-il ?
Les deux valeurs séparées par une virgule à la fin de chaque ligne Actor contrôlent la position **x** (de gauche à droite), et **y** (de haut en bas) de l'Actor. Ainsi `(300,0)` place le tuyau à 300 pixels du bord gauche, et 0 pixel en bas du haut de la fenêtre.

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()`.
D'où viennent ces calculs ? Eh bien, l'écart est une nouvelle variable que nous créons, et nous disons que la hauteur du tuyau supérieur plus l'écart doit être la valeur **y** du tuyau inférieur. Essayez de changer la valeur de l'écart et voyez ce qui se passe.

> Mettez à jour votre fonction **`draw`** pour refléter ces explications. Vous devriez obtenir quelque chose comme ceci :

```python
def draw():
screen.blit('background', (0, 0))
titi.draw()
```
> Exécutez pour vérifier que nous avons créé un écart

> 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 ?
*Quel est le plus grand écart que vous pouvez faire tout en voyant le tuyau de fond ?*

<img alt="Titi dans son décor" src="https://i.imgur.com/oyjY2HY.png" width=250 />

## Faisons se déplacer l'oiseau
## Allons de l'avant

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.
Pour donner l'impression que l'oiseau vole vers l'avant, et bien que cela paraissent paradoxal, il va falloir faire se déplacer les tubes. C'est une technique classique dans les jeux vidéos : le joueur reste immobile, c'est tout le reste qui se déplace.

> Écrivez le code suivant à l'endroit suggéré :
Faisons donc bouger ces tuyaux. Tout comme nous l'avons fait avec notre oiseau, nous pouvons créer une variable de vitesse pour les tuyaux et l'utiliser pour les faire bouger. Nous voulons que la ligne de code suivante s'exécute une fois lorsque nous lançons le programme, elle doit donc se trouver à la fin de votre code :

```python
def on_mouse_down():
print('Clic souris !')
titi.y -= 50 # équivalent à titi.y = titi.y - 50
vitesse_defilement = 1
```

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).
Et ils doivent se déplacer continuellement, donc ce code va dans la fonction de mise à jour :

> 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 ?
```python
tube_superieur.x += vitesse_defilement
tube_inferieur.x += vitesse_defilement
```

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...
Testez. Tout se passe-t-il comme prévu ? Si ce n'est pas le cas, relisez votre code et essayez de le corriger.

> Essayez de faire se déplacer l'oiseau de manière fluide...

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).
## Plus de tuyaux

> Définissez votre propre fonction **`update`** comme suit :
Nous avons besoin de plus de tuyaux, une seule paire ne suffit pas. En fait, nous en avons déjà assez, nous pouvons simplement les faire tourner en boucle lorsqu'ils sortent de l'écran.

```python
def update():
titi.y += 1
```
Pour ce faire, nous allons utiliser l'instruction `if` ainsi que les tests conditinnels `<` et `>`.

> ***AVANT*** de lancer votre programme, essayez de deviner comment il va se comporter...
Il y a trois choses délicates avec les énoncés `if` :

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.
- Que testez-vous exactement ? Que se passe-t-il après le "si" ?
- Il ne faut pas oublier les deux points à la fin du test conditionnel.
- Il faut que l'indentation soit correcte - combien d'espaces au début de la ligne ? - pour que le bon code soit exécuté.

> Ajoutez cette ligne en fin de fichier, mais toujours avant **`pgzrun.go()`** bien sûr :

```python
titi.speed = 1
```
## Boucles sur les tuyaux

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.
Mettons-nous au travail dans la fonction de mise à jour, car c'est là que nous déplaçons les tuyaux.

Il ne vous reste plus qu'à modifier la fonction **`update`** pour qu'elle utilise cette variable à la place que la valeur fixe '1'.
> Ajoutez ce code à la fin de la fonction, et assurez-vous que vous l'indentez pour qu'il soit vraiment à l'intérieur de la fonction.
> Efforcez-vous de *réellement* comprendre le sens des lignes de code.

```python
def update():
titi.y += titi.speed
if tube_superieur.x < 0 :
tube_superieur.x = WIDTH
```

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, ...)

![L'oiseau qui bouge](https://i.imgur.com/Jx9EDww.gif)

## 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.

- 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...
Il devrait toutefois subsister certains soucis... À vous de les corriger 😁

+ 24
- 15
birdie.py View File

@@ -1,26 +1,35 @@
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
#titi.x += 10

#(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.x < 0 :
tube_superieur.x = WIDTH = 400
if tube_inferieur.x < 0 :
tube_inferieur.x = WIDTH = 400

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

pgzrun.go()

BIN
View File


+ 33
- 18
titi_grominet.py View File

@@ -3,30 +3,28 @@ import pgzrun

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

# 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
def on_mouse_down(button):
print('Clic souris !')
print (button)
if mouse.LEFT is button :
titi.y -= 0 # deplacement horizontal
titi.x += 25 # deplacement latéral
grominet.y -= 0 # deplacement horizontal
grominet.x += 40 # deplacement latéral
if mouse.RIGHT is button :
titi.y += 0 # deplacement horizontal
titi.x -= 25 # deplacement latéral
grominet.y += 0 # 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))
screen.blit('meme', (0, 0))
titi.draw()
grominet.draw()
#titi = Actor('bird1', (70, 40))
@@ -41,6 +39,23 @@ def update():
#titi.x += tit.speed fera deplacer lateralement
#si on modifie le 1 on augmente la vitesse de la chute

# modif si tombe en bas, doit reapparaitre en haut
if titi.top > HEIGHT :
titi.bottom = 0
if titi.bottom > HEIGHT :
titi.top = 400
if grominet.top > HEIGHT :
grominet.bottom = 0
if grominet.bottom > HEIGHT :
grominet.top = 400
if grominet.left > WIDTH :
grominet.right = 0
if grominet.right > WIDTH :
grominet.left = 700
if titi.left > WIDTH :
titi.right = 0
if titi.right > WIDTH :
titi.left = 0
titi.speed = 1
grominet.speed = 1
pgzrun.go()

Loading…
Cancel
Save