Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#51 Le 11/12/2010, à 23:01

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Je suis ce conseil dans ce nouveau script:

J'utilise maintenant ma classe pour afficher 2 images et leur nom au-dessus.

Walk = miks_walk2.png    miks walk2     Static = miks_static1.png    miks static 

Je les ai placée dans ce que les anglais appellent un dictionnary que je traduis ici par dictionnaire.

N'importe quelle image d'arrière-plan de la bonne taille conviendra (608 x 472px ici), mais vous pouvez le changer dans le code si vous ne voulez pas redimensionner votre image. Ici, j'ai placé texte et image en haut de l'écran.

#!/usr/bin/ env python
# -*- coding: utf-8 -*-

# donne le nom de l'image d'arrière-plan
image_arriere_plan = 'arriereplan.png'

# donne la largeur et la hauteur de l'écran
largeur_ecran = 608
hauteur_ecran = 472

# importe la bibliothèque Pygame
import pygame
from pygame.locals import *
from sys import exit

class Sprite:
    """ Un sprite défini par son nom, son image et la position de son image et on ajoute une police de caractères """
    def __init__(self, nom, image, x, y):

        self.nom = nom
        self.image = image
        self.x = x
        self.y = y
        self.police = pygame.font.SysFont("arial", 50)

    def imprime_nom(self):
        """ affiche le nom du sprite à l'écran avec la police et la couleur choisie """
        surface_texte = self.police.render(self.nom, True, (0,0,0))
        screen.blit(surface_texte, (self.x, 10))

    def affiche_image(self):
        """ affiche l'image du sprite"""
        image_sprite = pygame.image.load(self.image).convert_alpha()
        screen.blit(image_sprite, (self.x, self.y))

#initialise pygame
pygame.init()

# définit la taille de la fenêtre
screen = pygame.display.set_mode((largeur_ecran, hauteur_ecran), 0, 32)
# donne le titre de la fenêtre
pygame.display.set_caption("Miks voudrait bouger")

arriereplan = pygame.image.load(image_arriere_plan).convert()

# les sprites 'S' et 'W' avec leurs noms, le nom de leur image et leur position
dictionnaire_sprites = { 'S':Sprite("Static", 'miks_static1.png', 300, 100), 'W':Sprite("Walk", 'miks_walk2.png', 100, 100) }

while True:
    # pour fermer la fenêtre
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()

    # affiche l'arriere-plan
    screen.blit(arriereplan, (0,0))

    # Pour chaque élément du dictionnaire des sprites
    for item in dictionnaire_sprites:
        # utilise la fonction d'impression du nom du sprite
        dictionnaire_sprites[item].imprime_nom()

        # utilise la fonction d'affichage de l'image du sprite
        dictionnaire_sprites[item].affiche_image()

    # réactualise l'affichage
    pygame.display.update()

Peut-être la police serait à insérer dans une classe plus globale définissant le jeu entier, non ?

Ce qui me pose souci, c'est de récupérer la hauteur ou la largeur du personnage et de le blitter en fonction de cela (par exemple si je voulais les mettre l'un en dessous de l'autre.

Ce qui est fait dans une fonction ne semble pas pouvoir servir dans une autre.

Dernière modification par doudoulolita (Le 11/12/2010, à 23:19)

Hors ligne

#52 Le 12/12/2010, à 00:50

tshirtman

Re : Faire une animation sur la création de jeux vidéo libres

doudoulolita a écrit :

Je les ai placée dans ce que les anglais appellent un dictionnary que je traduis ici par dictionnaire.

t'as raison, les dictionnaires c'est super cool smile (on les appels aussi souvent hashtables, c'est la même chose)

Peut-être la police serait à insérer dans une classe plus globale définissant le jeu entier, non ?

ça peut être pertinent oui, mais dans ce cas, il faut se poser la question de comment le sprite y accède…

si il dispose d'une référence à la classe du jeu, c'est un peu moche, (deux objets qui s'inter référencent) mais bon, dans usf, je fais pas mal ce genre de choses, si on peux éviter, c'est mieux.

Ce qui me pose souci, c'est de récupérer la hauteur ou la largeur du personnage et de le blitter en fonction de cela (par exemple si je voulais les mettre l'un en dessous de l'autre.

Ce qui est fait dans une fonction ne semble pas pouvoir servir dans une autre.

En effet, c'est même l'un des grand intérêts des fonctions (et des classes) le cloisonnement, ce qui est fait dans un scope, ne doit pas sortir de ce scope,

Après, dans ton cas, tu veux probablement laisser le choix de positionnement au niveau du jeu (boucle principale) plutôt qu'au niveau du sprite. Quand à la taille d'un sprite, tu peut l"obtenir avec la fonction get_rect() sur la surface (fait le dans le constructeur aussi, vu que tu n'as qu'une image).

ps: n'hésite pas à installer bpython et l'utiliser comme shell interactif pour tes tests, son autocompletion le rends très agréable pour les découvertes smile

Dernière modification par tshirtman (Le 12/12/2010, à 00:52)

Hors ligne

#53 Le 03/01/2011, à 13:01

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Hello, je devrais lire plus souvent mes posts, je viens de découvrir ta réponse. Merci et bonne année !
J'ai un peu travaillé sur l'autre petit jeu avec les nounours qui changent en fonction de la couleur du background, maintenant, je parviens à inscrire un score sur l'écran ! Encore un an ou deux, et je peux travailler sur le code d'USF ! wink

Hors ligne

#54 Le 03/01/2011, à 16:09

tshirtman

Re : Faire une animation sur la création de jeux vidéo libres

lol

(rire spontané et à ne pas prendre comme une moquerie wink)

Dernière modification par tshirtman (Le 03/01/2011, à 16:10)

Hors ligne

#55 Le 10/01/2011, à 21:23

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Dans la phase suivante de mon jeu où la souris change en fonction de la couleur de l'arrière-plan, voici donc l'ajout de la fonction permettant d'afficher du texte pour les chiffres de la page d'accueil ainsi que pour afficher le score.

Celui-ci s'incrémente quand on passe sur du bleu et diminue quand on passe sur du rouge. Une autre fonction vérifie si le score atteint un minimum ou un maximum et affiche comme auparavant l'image de victoire ou de défaite.

J'ai divisé le score par 100 avant de l'afficher pour que les chiffres soient plus faciles à lire par des enfants de maternelles, mais il faut noter que les chiffres négatifs ne sont pas l'idéal pour eux. Une autre solution serait à trouver, ne serait-ce que mettre les chiffres négatifs en bordeaux, par exemple (on ne peut pas les mettre en rouge, bien sûr)

J'ai essayé de travaillé le plus possible avec les fonctions et de les limiter à des taches précises mais il y a sans doute des erreurs.

A noter qu'il faut changer le chemin des images dans la ligne chemin pour que ça fonctionne chez vous. Vous ne vous appelez pas Doudoulolita, non ? wink

#!/usr/bin/ env python
# -*- coding: utf-8 -*-

# importe la bibliothèque Pygame
import pygame
from pygame.locals import *
from sys import exit
import os.path

# indique le chemin des images
chemin = '/home/doudoulolita/Bureau/donnees/programmation/04_programmes_maternelles/'

# définit les images choisies pour l'arrière-plan  et la souris sans le chemin de leur dossier
nom_image_arriereplan = 'arriereplan.png'
nom_image_arriereplan1 = 'arriereplan1.png'
nom_image_arriereplan2 = 'arriereplan2.png'
nom_image_victoire = 'tux_victoire.png'
nom_image_defaite = 'tux_defaite.png'
nom_image_souris1 = 'miks_static.png'
nom_image_souris2 = 'miks_smackup2.png'
nom_image_souris3 = 'miks_roll2.png'

# définit les images choisies pour l'arrière-plan  et la souris avec le chemin du dossier
image_arriereplan = chemin + nom_image_arriereplan
image_arriereplan1 = chemin + nom_image_arriereplan1
image_arriereplan2 = chemin + nom_image_arriereplan2
image_victoire = chemin + nom_image_victoire
image_defaite = chemin + nom_image_defaite
image_souris1 = chemin + nom_image_souris1
image_souris2 = chemin + nom_image_souris2
image_souris3 = chemin + nom_image_souris3

# appelle la fonction horloge et le temps
clock = pygame.time.Clock()
temps = pygame.time.get_ticks()
temps2 = clock.get_time()

#initialise pygame
pygame.init()

# initialise les variables
i = 0
k = 0
score = 0

# définit la taille de la fenêtre
screen = pygame.display.set_mode((608, 472), 0, 32)
# donne le titre de la fenêtre
pygame.display.set_caption("Miks aime le bleu")

# charge les images
arriereplan = pygame.image.load(image_arriereplan).convert()
arriereplan1 = pygame.image.load(image_arriereplan1).convert()
arriereplan2 = pygame.image.load(image_arriereplan2).convert()
victoire = pygame.image.load(image_victoire).convert()
defaite = pygame.image.load(image_defaite).convert()
souris1 = pygame.image.load(image_souris1).convert_alpha()
souris2 = pygame.image.load(image_souris2).convert_alpha()
souris3 = pygame.image.load(image_souris3).convert_alpha()

# récupère la largeur et la hauteur de l'image d'arrière-plan
largeur_arriereplan = arriereplan.get_width()
hauteur_arriereplan = arriereplan.get_height()

# divise et réduit la largeur et la hauteur d'arrière-plan
width = largeur_arriereplan/2-18
height = hauteur_arriereplan/2-12

# crée les vignettes de la page accueil
arriereplan1p = pygame.transform.scale(arriereplan1, (width, height))
arriereplan2p = pygame.transform.scale(arriereplan2, (width, height))

# définit les couleurs
bleu = (50, 100, 255, 255)
rouge = (255, 0, 0, 255)
vert = (0, 255, 0)

# indique les scores maximums et minimums
score_max = 3000
score_min = -3000

# fonction d'affichage de la souris suivant la couleur de l'arrière-plan
def rendu_miks():  
    """ k est la position dans le tableau initialisée à 0 """
    k = 0
    """ si la couleur est bleue, change k et donc l'image de la souris """
    if couleur_ecran == bleu:
        k = 1    
    """ si la couleur est rouge, change k et donc l'image de la souris """
    elif couleur_ecran == rouge:
        k = 2
    """ affiche l'image de la souris """
    screen.blit(souris_x[k], (x,y))

def imprime_texte(texte,x_texte):
    """ affiche du texte à l'écran avec la police et la couleur choisie """
    ma_police = pygame.font.SysFont("arial", 100)
    surface_texte = ma_police.render(texte, True, vert)
    screen.blit(surface_texte, (x_texte, height+(height/2)))

def accueil_jeu():
    """ Définit les dimensions du rectangle de la page d'accueil """ 
    Rect = (6, 16, largeur_arriereplan-12, height+12) 
    i = 0
    """ remplit l'écran de blanc """
    screen.fill((255,255,255))
    """ crée un rectangle vert """
    pygame.draw.rect(screen, vert, Rect, 0)
    """ affiche successivement la première vignette et la deuxième sur la page d'accueil """ 
    screen.blit(arriereplan1p, (10, 20)) 
    screen.blit(arriereplan2p, ((width+24), 20)) 
    """ affiche l'image de la souris """
    k = 0
    screen.blit(souris_x[k], (x,y))

def verifie_score():
    """ affiche le score puis le temps dans la console """
    print score
    print temps
    """ si le score dépasse le maximum, affiche l'image de la victoire """
    if score > score_max:
        screen.blit(victoire, (0, 0))
    """ si le score est inférieur au minimum, affiche l'image de la défaite """
    if score < score_min:
        screen.blit(defaite, (0, 0))
   
while True:
    # pour fermer la fenêtre
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
    # inscrémente le temps depuis le début du jeu
    temps += 1

    # récupère les touches pressées
    touche_pressee = pygame.key.get_pressed()

    #tableau des images pour l'arrière-plan
    arriereplan_x = [arriereplan, arriereplan1, arriereplan2]

    # choisit l'image d'arrière-plan selon la touche
    if  touche_pressee[K_KP1]:
        i = 1
        
    elif touche_pressee[K_KP2]:
        i = 2
                
    elif touche_pressee[K_KP0]:
        i = 0
    # affiche l'arrière-plan en fonction de la touche pressée, connue grâce à la variable i
    screen.blit(arriereplan_x[i], (0, 0))

    # définit la position de la souris
    x, y = pygame.mouse.get_pos()
    
    # échantillonne la couleur que survole la souris
    couleur_ecran = screen.get_at((x, y))

    # tableau des images utilisées pour la souris
    souris_x = [souris1, souris2, souris3] 

    # Place le curseur de la souris au centre de l'image
    x-= souris_x[k].get_width() / 2
    y-= souris_x[k].get_height() / 2
 
    # Si on presse la touche 0
    if i == 0:
        # appelle la fonction qui affiche la page d'accueil
        accueil_jeu()
        # affiche les chiffres 1 puis 2 grâce à al fonction d'affichage de texte
        imprime_texte("1", width-(width/2))
        imprime_texte("2", width+(width/2))

    # si la touche 1 ou la touche 2 sont pressés
    elif i == 1 or i == 2:
        # si la couleur est bleue, on ajoute 1 au score
        if couleur_ecran == bleu:
            score +=1

        # si la couleur est rouge, on ote 1 au score 
        if couleur_ecran == rouge:
            score -=1
        # appelle la fonction d'affichage l'image de la souris
        rendu_miks()
        # appelle la fonction de vérification du score
        verifie_score()
        # divise le score par 100 pour des chiffres plus petits et un changement moins rapide
        score2 = score/100
        # transforme le chiffre du score en texte à afficher
        texte_score = str(score2)
        # affiche le score sur l'écran grâce à la fonction d'affichage de texte
        imprime_texte(texte_score,(largeur_arriereplan-150))
              
    # réactualise l'affichage
    pygame.display.flip()

Il y a encore du chemin à faire, car lorsque l'on revient à la page d'accueil en appuyant sur 0 (pavé numérique), le score est toujours là où il en était, il ne se remet pas à 0 automatiquement. hmm

D'autre part, je ne suis pas sûre que l'on ait besoin ici de calculer le temps. Je l'ai laissé dans le code car à un moment, je basais le score dessus, mais j'ai changé ça dans cette version du jeu.

Je rappelle qu'étant débutante, je ne prétends pas que mon code soit parfait, loin de là, mais s'il peut aider un tant soit peu quelqu'un d'autre que moi à progresser grâce aux commentaires du code et aux interventions de mon ami Tshirtman, ce serait bien ! De toute façon, moi, je peux progresser grâce à ce forum, donc ça n'est pas inutile ! cool

Si on veut rendre le jeu plus intéressant pour les petits joueurs, on peut leur faire faire des fonds beaucoup plus complexes, que l'on intégrera plus tard dans le jeu (il faut bien sûr les renommer) :
- utiliser de l'herbe avec la baguette magique de Tuxpaint pour cacher un peu les bords des traits rouges et bleus
- ajouter d'autres formes faites avec d'autres couleurs
- ajouter des tampons (ne contenant ni rouge, ni bleu)

Dernière modification par doudoulolita (Le 10/01/2011, à 21:28)

Hors ligne

#56 Le 12/01/2011, à 11:27

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

J'avance cette fois de nouveau sur les Sprites (personnages qui bougent) et les classes, mais ma technique pour faire avancer les personnages tout en changeant de pose n'est pas super car  les images restent affichées les unes sur les autres.
Pour l'instant, les personnages ne peuvent qu'avancer d'une distance horizontale (axe X) nommée improprement "vitesse".  Ici, en fait, la vitesse est utilisée pour séparer l'image 1 de l'image 2.
Il y a 2 frames pour chaque personnage, Miks et Rizzie.

Miks   miks_static1.png   miks_walk2.png   Rizzie   rizzie-static1.png      rizzie-walk1.png

J'utilise la fonction Clock de Pygame pour me donner le temps, mais là encore, je pense que je maîtrise mal les nuances et les possibilités offertes.
t est le nombre de fois qu'on refait la succession de l'image 1 et de l'image 2. Là encore, ce n'est probablement pas comme ça que ça devrait être utilisé mais je ne sais pas encore comment faire autrement...  hmm

#!/usr/bin/ env python
# -*- coding: utf-8 -*-

# donne la largeur et la hauteur de l'écran
largeur_ecran = 608
hauteur_ecran = 472

# importe la bibliothèque Pygame
import pygame
from pygame.locals import *
from sys import exit

class Sprite:
    """ Un sprite défini par son nom, son image et la position de son image et on ajoute une police de caractères """

    def __init__(self, nom, walk1, walk2, x, y, vitesse):

        self.nom = nom
        self.walk1 = walk1
        self.walk2 = walk2
        self.x = x
        self.y = y
        self.police = pygame.font.SysFont("arial", 50)
        self.vitesse = vitesse

    def imprime_nom(self):
        """ affiche le nom du sprite à l'écran avec la police et la couleur choisie """
        surface_texte = self.police.render(self.nom, True, (0,0,0))
        screen.blit(surface_texte, (self.x, (self.y-60)))

    def affiche_image1(self):
        """ affiche l'image du sprite"""
        image1 = pygame.image.load(self.walk1).convert_alpha()
        screen.blit(image1, (t*self.x, self.y))

    def affiche_image2(self):
        """ affiche l'image du sprite"""
        image2 = pygame.image.load(self.walk2).convert_alpha()
        screen.blit(image2, ((t*self.x)+self.vitesse, self.y))
   
#initialise pygame
pygame.init()

# définit la taille de la fenêtre
screen = pygame.display.set_mode((largeur_ecran, hauteur_ecran), 0, 32)
# donne le titre de la fenêtre
pygame.display.set_caption("Miks et rizzie vont-ils bouger ?")

# appelle la fonction horloge et le temps
clock = pygame.time.Clock()
temps = pygame.time.get_ticks()
temps1 = clock.get_time()
t = 1

# les sprites 'S' et 'W' avec leurs noms, le nom de leur image et leur position
dictionnaire_sprites = { 'S':Sprite('Miks', 'miks_static.png', 'miks_walk2.png', 100, 100, 100), 'W':Sprite('Rizzie', 'rizzie-static1.png', 'rizzie-walk1.png', 100, 300, 100) }

while True:
    # pour fermer la fenêtre
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()

    # affiche l'arriere-plan
    screen.fill((255,255,255))

    # Donne le temps dans la console
    print temps1
    temps +=1
    print temps

    # Pour chaque élément du dictionnaire des sprites
    for item in dictionnaire_sprites:
        # utilise la fonction d'impression du nom du sprite
        dictionnaire_sprites[item].imprime_nom()

        # utilise la fonction d'affichage de l'image du sprite et créée une boucle pour le faire avancer
        t +=1
        for t in range(1,10):
            if temps < (t*200):
                dictionnaire_sprites[item].affiche_image1()
            if temps > (t*200) and temps < (t*400):
                dictionnaire_sprites[item].affiche_image2()

    # réactualise l'affichage
    pygame.display.update()

Toute aide sera la bienvenue pour avancer sur ce sujet !

Dernière modification par doudoulolita (Le 12/01/2011, à 11:38)

Hors ligne

#57 Le 12/01/2011, à 11:32

tshirtman

Re : Faire une animation sur la création de jeux vidéo libres

Perso, je préfère utiliser juste get_ticks() et utiliser le temps passé depuis la dernière fois (c'est ce que ça renvoit) pour tous mes calculs d'évolution, si j'ai besoin pour un objet particulier, il va stocker un compteur, auquel il ajoutera cette valeur à chaque mise à jour, si beaucoup d'objet en ont besoin, je peux en faire un global, auquel j'ajouterai la valeur juste après l'avoir eu, ça marche assez bien.

Avant j'avais utilisé la fonction temps de python, mais c'est plus simple d'utiliser le module de pygame, qui est précis quelle que soit la plateforme.

Aussi, quand tu te rends compte que quelque chose est mal nommé, il est urgent de remplacer le nom à tous les endroit ou il est utilisé, immédiatement, sinon ton programme perds du sens, et devient plus difficile à comprendre, y compris pour toi même, ça te force a tordre ta pensée, et ça complique vraiment les choses. (plus l'esprit est clair, plus c'est facile d'avancer).

edit: je viens de voir que tu charge l'image à chaque affichage! c'est très lourd, fait le à l'initialisation, et utilise l'image chargée à chaque affichage…

class Sprite:
    """ Un sprite défini par son nom, son image et la position de son image et on ajoute une police de caractères """

    def __init__(self, nom, walk1, walk2, x, y, vitesse):

        self.nom = nom
        self.walk1 = walk1
        self.walk2 = walk2
        self.x = x
        self.y = y
        self.police = pygame.font.SysFont("arial", 50)
        self.vitesse = vitesse
        self.image1 = pygame.image.load(self.walk1).convert_alpha()
        self.image2 = pygame.image.load(self.walk2).convert_alpha()
        self.surface_texte = self.police.render(self.nom, True, (0,0,0))

    def imprime_nom(self):
        """ affiche le nom du sprite à l'écran avec la police et la couleur choisie """
        screen.blit(self.surface_texte, (self.x, (self.y-60)))

    def affiche_image1(self):
        """ affiche l'image du sprite"""
        screen.blit(self.image1, (t*self.x, self.y))

    def affiche_image2(self):
        """ affiche l'image du sprite"""
        screen.blit(self.image2, ((t*self.x)+self.vitesse, self.y))

j'ai fait la même chose pour le texte, au passage. (puisqu'il ne change pas).

Dernière modification par tshirtman (Le 12/01/2011, à 11:36)

Hors ligne

#58 Le 12/01/2011, à 12:04

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Merci pour tes conseils.

Il me semble aussi plus logique de changer la position x du perso de cette manière car on laisse la position initiale inchangée:

    def affiche_image1(self):
        """ affiche l'image du sprite"""
        screen.blit(self.image1, (self.x+(t*self.vitesse), self.y))

    def affiche_image2(self):
        """ affiche l'image du sprite"""
        screen.blit(self.image2, (self.x+(t*self.vitesse)+self.vitesse, self.y))

De même, pour la boucle qui génère les images successives, c'est plus logique comme ça:

        # utilise la fonction d'affichage de l'image du sprite et créée une boucle pour le faire avancer
        t +=1
        for t in range(1,10):
            if temps < (t*200):
                dictionnaire_sprites[item].affiche_image1()
            if temps > (t*200) and temps < (2*t*200):
                dictionnaire_sprites[item].affiche_image2()

Dernière modification par doudoulolita (Le 09/02/2011, à 22:30)

Hors ligne

#59 Le 12/01/2011, à 13:04

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Au final, je me retrouve avec ce code pour faire bouger mes 2 personnages:

#!/usr/bin/ env python
# -*- coding: utf-8 -*-

# donne la largeur et la hauteur de l'écran
largeur_ecran = 608
hauteur_ecran = 472

# importe la bibliothèque Pygame
import pygame
from pygame.locals import *
from sys import exit

class Sprite:
    """ Un sprite défini par son nom, son image et la position de son image et on ajoute une police de caractères """

    def __init__(self, nom, walk1, walk2, x, y, vitesse):

        self.nom = nom
        self.walk1 = walk1
        self.walk2 = walk2
        self.x = x
        self.y = y
        self.police = pygame.font.SysFont("arial", 50)
        self.vitesse = vitesse
        self.image1 = pygame.image.load(self.walk1).convert_alpha()
        self.image2 = pygame.image.load(self.walk2).convert_alpha()
        self.surface_texte = self.police.render(self.nom, True, (0,0,0))

    def imprime_nom(self):
        """ affiche le nom du sprite à l'écran avec la police et la couleur choisie """
        screen.blit(self.surface_texte, (self.x, (self.y-60)))

    def affiche_image1(self):
        """ affiche l'image du sprite"""
        screen.blit(self.image1, (self.x+(t*self.vitesse), self.y))

    def affiche_image2(self):
        """ affiche l'image du sprite"""
        screen.blit(self.image2, (self.x+(t*self.vitesse)+self.vitesse, self.y))
   
#initialise pygame
pygame.init()

# définit la taille de la fenêtre
screen = pygame.display.set_mode((largeur_ecran, hauteur_ecran), 0, 32)
# donne le titre de la fenêtre
pygame.display.set_caption("Miks et rizzie vont-ils bouger ?")

# appelle la fonction temps puis initialise le nombre de fois qu'on affichera la boucle
temps = pygame.time.get_ticks()
t = 1

# les sprites 'S' et 'W' avec leurs noms, le nom de leur image et leur position
dictionnaire_sprites = { 'S':Sprite('Miks', 'miks_static.png', 'miks_walk2.png', 100, 100, 100), 'W':Sprite('Rizzie', 'rizzie-static1.png', 'rizzie-walk1.png', 100, 300, 100) }

while True:
    # pour fermer la fenêtre
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()

    # affiche l'arriere-plan
    screen.fill((255,255,255))

    # Donne le temps dans la console
    temps +=1
    print temps

    # Pour chaque élément du dictionnaire des sprites
    for item in dictionnaire_sprites:
        # utilise la fonction d'impression du nom du sprite
        dictionnaire_sprites[item].imprime_nom()

        # utilise la fonction d'affichage de l'image du sprite et créée une boucle pour le faire avancer
        t +=1
        for t in range(1,10):
            if temps < (t*200):
                dictionnaire_sprites[item].affiche_image1()
            if temps > (t*200) and temps < (2*t*200):
                dictionnaire_sprites[item].affiche_image2()

    # réactualise l'affichage
    pygame.display.update()

Hors ligne

#60 Le 12/01/2011, à 13:21

tshirtman

Re : Faire une animation sur la création de jeux vidéo libres

aussi, j'aurais tendance à faire une seule fonction 'affiche' par classe, et dessiner ce qu'elle afficher en fonction du temps, soit passé en parametre, soit stocké dans la classe…

Hors ligne

#61 Le 07/02/2011, à 20:56

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

J'ai recopié la classe Vector2 du livre Beginning Game development with Python and Pygame de Will McGugan et je crois que c'est correct.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import math

class Vector2(object):

    def __init__(self, x=0.0, y=0.0):
        self.x = x
        self.y = y

    def __str__(self):
        return "(%s, %s)"%(self.x, self.y)

    @staticmethod
    def from_points(P1, P2):
        return Vector2( P2[0] - P1[0], P2[1] - P1[1] )

        def get_magnitude(self):
            return math.sqrt( self.x**2 + self.y**2 )

        def normalize(self):
            magnitude = self.get_magnitude()
            self.x /= magnitude
            self.y /= magnitude

        # rhs veut dire coté droit
        def __add__(self, rhs):
            return Vector2(self.x + rhs.x, self.y + rhs.y)

        def __sub__(self, rhs):
            return Vector2(self.x - rhs.x, self.y - rhs.y)
 
        def __neg__(self):
            return Vector2(-self.x, -self.y)

Ensuite, le livre dit de télécharger un module nommé gameobject avant de passer à un autre programme mais je voulais faire ce nouveau programme avec ma propre classe Vector2 et bien sûr mes images: Miks et un décor perso.
Voici le programme:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# nom des images
nom_fichier_arriereplan = 'miksplanete.png'
nom_fichier_personnage = 'miks_static.png'

# importation des modules pygame
import pygame
from pygame.locals import *
from sys import exit
from Vector2 import *

# démarrage de pygame
pygame.init()

# creation de l'écran
ecran = pygame.display.set_mode((640, 480), 0, 32)

# charge les images
arriereplan = pygame.image.load(nom_fichier_arriereplan).convert()
personnage = pygame.image.load(nom_fichier_personnage).convert_alpha()

# horloge
horloge = pygame.time.Clock()

# position
position = Vector2(100.0, 100.0)
vitesse = 250.
# appel de la classe Vector2
direction = Vector2()

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
        # changement de position lors du clic
        if event.type == MOUSEBUTTONDOWN:
            destination = Vector2(*event.pos) - Vector2(*personnage.get_size())/2.
            # vecteur du point de départ au point d'arrivée
            direction = Vector2.from_points(position, destination)
            # normalisation du vecteur
            direction.normalize()
    
    # affiche les images
    ecran.blit(arriereplan, (0.0, 0.0))
    ecran.blit(personnage, position)

    # temps passé
    temps_passe = horloge.tick()
    temps_passe_secondes = temps_passe / 1000.0

    # distance
    distance_parcourue = temps_passe_secondes * vitesse
    position += direction * distance_parcourue

    pygame.display.update()

Or, il y a des problèmes avec ma classe Vector2 alors qu'avec Vector2.py + util.py, récupérés dans gameobject.zip (une fois le dossier décompressé) , ça marche.
J'obtiens d'abord ça:

Traceback (most recent call last):
  File "01_programme_vecteur.py", line 47, in <module>
    screen.blit(sprite, position)
TypeError: invalid destination position for blit

Si je remplace position par des coordonnées chiffrées, voilà ce que ça donne:

Traceback (most recent call last):
  File "01_programme_vecteur.py", line 55, in <module>
    position += heading * distance_parcourue
TypeError: unsupported operand type(s) for *: 'Vector2' and 'float'

Comme j'aime bien tout faire moi-même (même s'il s'agit de réinventer la poudre), j'aimerais bien savoir quelle fonction permet de multiplier un vecteur et d'utiliser pour cela des chiffres à virgule. j'aimerais bien que ma classe Vector2 sache faire ça sans devenir trop complexe.

Dernière modification par doudoulolita (Le 08/02/2011, à 01:14)

Hors ligne

#62 Le 07/02/2011, à 22:25

tshirtman

Re : Faire une animation sur la création de jeux vidéo libres

donner a ta classe la capacité d'être utilisé dans des opérations, ça s'appelle la "surcharge d'opérateur" smile en python, ça se fait assez simplement, en définissant les opérations dont tu as besoin, parmis __mul__ __add__ __sub__ et __div__

>>> class test(object):
...     def __init__(self, x, y):
...             self.x, self.y = x, y
...     def __mul__(self, i):
...             if isinstance(i, int):
...                     return test(self.x * i, self.y * i)
... 
>>> test(2,5)
<__main__.test object at 0xb75ae18c>
>>> test(2,5) * 4
<__main__.test object at 0xb75ae22c>
>>> (test(2,5) * 4).x
8

j'ai ici considéré le cas ou i est un int, mais rien ne t'empèche de vérifier qu'il est un float, et de faire un traitement différent, et dans le cas ou tu n'a pas prévus ce que c'est tu peux jeter une Exception TypeError("object can only be multiplied with int and floats)

par exemple (tu peux surcharger __str__ aussi par exemple, pour pouvoir faire un print() de tes classes et les voir s'afficher joliment)

>>> class test(object):
...     def __init__(self, x, y):
...             self.x, self.y = x, y
...     def __mul__(self, i):
...             if isinstance(i, int):
...                     return test(self.x * i, self.y * i)
...     def __str__(self):
...             return str(self.x)+", "+str(self.y)
... 
>>> test(4,4)
<__main__.test object at 0xb75ae3ac>
>>> print test(4,4)
4, 4
>>> print test(4,4)*8
32, 32

Dernière modification par tshirtman (Le 07/02/2011, à 22:27)

Hors ligne

#63 Le 08/02/2011, à 00:44

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Merci, je testerai plus tard dans ma classe Vector2.

En attendant, grâce à gameobject, j'ai pu continuer à travailler. J'ai donc dezippé le dossier et ai copié vector2.py et util.py dans le dossier de mon programme.

J'ai amélioré un peu le dernier script en faisant aller Miks exactement au point défini par la souris et en changeant les images suivant la direction. A noter qu'un des petits nounours n'est pas encore utilisé (miks_staticb.png), mais il servira peut-être un jour !
Il faut donc cliquer pour indiquer à Miks où aller, j'ai oublié de le préciser pour le script précédent. Mais ceux qui savent lire le code auront compris ce qu'est l'event MOUSEBUTTONUP (quand on lâche le clic de la souris).
Le fond est le même.

miks_static.png   miks_walk2.png   miks_staticb.png  miks_walk2b.png

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# nom des images
nom_fichier_arriereplan = 'miksplanete.png'
nom_fichier_personnage1 = 'miks_static.png'
nom_fichier_personnage2 = 'miks_walk2.png'
nom_fichier_personnage1b = 'miks_staticb.png'
nom_fichier_personnage2b = 'miks_walk2b.png'

# importation des modules pygame
import pygame
from pygame.locals import *
from sys import exit
from vector2 import *

# démarrage de pygame
pygame.init()

# creation de l'écran
ecran = pygame.display.set_mode((640, 480), 0, 32)

# charge les images
arriereplan = pygame.image.load(nom_fichier_arriereplan).convert()
personnage1 = pygame.image.load(nom_fichier_personnage1).convert_alpha()
personnage2 = pygame.image.load(nom_fichier_personnage2).convert_alpha()
personnage1b = pygame.image.load(nom_fichier_personnage1b).convert_alpha()
personnage2b = pygame.image.load(nom_fichier_personnage2b).convert_alpha()

# horloge
horloge = pygame.time.Clock()

# Appel de la classe Vector2 pour la position de départ, fixée à 100 en x et 100 en y
position = Vector2(100.0, 100.0)
vitesse = 250.
# appel de la classe Vector2 pour la direction
direction = Vector2()
k = 0

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
    # temps passé
    temps_passe = horloge.tick()
    temps_passe_secondes = temps_passe / 1000.0
    # tableau des images utilisées pour le personnage
    personnage = [personnage1, personnage2, personnage1b, personnage2b]

    # changement de position lors du clic
    if event.type == MOUSEBUTTONUP:
        k = 1
        destination_x = event.pos[0] - personnage[k].get_width()/2.0
        destination_y = event.pos[1] - personnage[k].get_height()
        destination = (destination_x, destination_y)
        # vecteur du point de départ au point d'arrivée
        direction = Vector2.from_points(position, destination)
        # normalisation du vecteur
        direction.normalize()
        # distance puis position suivante
        distance_parcourue = temps_passe_secondes * vitesse
        position += direction * distance_parcourue
        (x, y) = position
        if x > (destination_x - 1.0):
            k = 3

    else:
        k = 0

    # affiche les images
    ecran.blit(arriereplan, (0.0, 0.0))
    ecran.blit(personnage[k], position)

    pygame.display.update()

Miks ne marche pas encore et est encore bien hésitant sur la direction à prendre quand il est arrivé à bon port, mais je progresse encore un peu sur les vecteurs et autres. smile

Dernière modification par doudoulolita (Le 08/02/2011, à 11:03)

Hors ligne

#64 Le 08/02/2011, à 11:38

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

On peut aussi copier cette partie du fichier util.py et l'insérer dans la fichier vector2.py de gameobject:

def format_number(n, accuracy=6):

    """Formats a number in a friendly manner

    (removes trailing zeros and unneccesary point."""



    fs = "%."+str(accuracy)+"f"

    str_n = fs%float(n)

    if '.' in str_n:

        str_n = str_n.rstrip('0').rstrip('.')

    if str_n == "-0":

        str_n = "0"

    #str_n = str_n.replace("-0", "0")

    return str_n

Il ne faut pas oublier de supprimer cette partie dans vector2.py avant de supprimer le fichier util.py:

from util import format_number

On peut sans doute supprimer d'autres fonctions pour l'instant inutiles de la classe vector2, mais je ne sais pas encore lesquelles ! hmm

Hors ligne

#65 Le 09/02/2011, à 22:17

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Cet après-midi, au boulot, mini succès auprès de 2 jeunes qui viennent en accès libre jouer sur nos ordis. smile

Le plus jeune (9-10 ans) aime bien jouer à Ultimate Smash Friends, tape sur toutes les touches et obtient des mouvements sur Rohon et Bearsum que je lui présente comme mes créations. Quand je lui dis que c'est moi qui ai réalisé Rizland, il le choisit immédiatement. Comme quoi, le "fait maison" marche bien ! big_smile

Un autre, de 2-3 ans plus vieux, me demande comment je fais et se lance direct sur une création de décor, tout simplement en jouant avec les formes de bases d'Inkscape. On sauvegarde et on exporte en bitmap.

Il est allé sur Internet chercher une image à rajouter dans son décor (des personnages bizarrement !), alors je lui ai parlé de l'impossibilité d'utiliser certaines images et lui ai dit de juste s'en servir comme source d'inspiration.

Il regrette qu'on ne puisse pas jouer seul à USF, comme le premier petit garçon.  hmm  L'AI est très attendue !

Quand ils sont partis, je reprend son décor, plutôt sympa et dynamique malgré sa simplicité de réalisation, et n'ai qu'à changer légèrement l'emplacement d'une des 3 plateformes (il n'y avait rien au centre et les persos tombaient dès qu'ils arrivaient) puis répartir les formes sur middle, background et foreground pour en faire un niveau jouable. Un petit coup de xml et je l'intègre dans USF sur mon ordi.

J'attends la semaine prochaine pour lui montrer en jeu et lui demanderai s'il veut bien que je vous présente son oeuvre. cool

Dernière modification par doudoulolita (Le 09/02/2011, à 22:33)

Hors ligne

#66 Le 09/02/2011, à 22:27

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

J'ai pas mal fouillé sur Internet aussi en vue de mieux préparer ma prochaine animation sur la programmation et je penche de plus en plus pour Scratch.
Mais mon coeur balance aussi pour une personnalisation d'USF, grâce aux changements du xml, ou à des variations du code python/pygame d'un programme plus simple. smile

Je serais aussi intéressée de savoir comment vous avez appris python ou d'autres langages de programmation (bouquins, cours d'informatique, sites, essais/erreurs, etc...), quelles difficultés vous avez rencontrées, etc.
Je dis "vous" car si Tshirtman et moi sommes un peu seuls ici, j'espère que d'autres m'aideront un jour dans ce topic.

Dernière modification par doudoulolita (Le 09/02/2011, à 22:33)

Hors ligne

#67 Le 11/02/2011, à 23:45

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Petite avancée dans mon code, pour pouvoir changer de personnage grâce à la touche 2 du pavé numérique. Chaque personnage a 4 images de nom identique stockée dans un dossier à son nom. Il suffit de changer le nom du dossier pour uploader l'image du bon personnage, qu'il se tourne vers la droite ou vers la gauche ou encore qu'il soit statique (mais ici, il reste tourné vers la droite, l'autre image statique tournée vers la gauche n'est pas encore utilisée).

miks static1.png   miks walk2.png   miks static1b.png   miks walk2b.png   rizzie static1.png   rizzie walk2.png   rizzie static1b.png   rizzie walk2b.png

J'ai bien du mal à maîtriser les évènements, et en particulier que presser une touche soit conservé en mémoire. J'ai déplacé les lignes de code un peu aléatoirement jusqu'à ce que ça fonctionne.

Image de fond : miksplanete2.png

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# nom des images
nom_fichier_arriereplan = 'miksplanete2.png'
nom_fichier1 = 'static1.png'
nom_fichier2 = 'walk2.png'
nom_fichier3 = 'static1b.png'
nom_fichier4 = 'walk2b.png'

nom_dossier = ['rizzie', 'miks']

# couleurs ecran
R = 12
V = 42
B = 126

# importation des modules pygame
import pygame
from pygame.locals import *
from sys import exit
from Vector2 import *

# démarrage de pygame
pygame.init()

# creation de l'écran
ecran = pygame.display.set_mode((640, 480), 0, 32)

# charge les images
arriereplan = pygame.image.load(nom_fichier_arriereplan).convert_alpha()


# horloge
horloge = pygame.time.Clock()

# Appel de la classe Vector2 pour la position de départ, fixée à 100 en x et 100 en y
position = Vector2(100.0, 100.0)
vitesse = 250.
# appel de la classe Vector2 pour la direction
direction = Vector2()
a = 0
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
    # temps passé
    temps_passe = horloge.tick()
    temps_passe_secondes = temps_passe / 1000.0

    # récupère les touches pressées pour le choix du personnage
    touche_pressee = pygame.key.get_pressed()
    if  touche_pressee[K_KP2]:
        # si la touche 2 du pavé numérique est pressée, l'image du deuxième personnage est uploadée
        a = 1

    personnage1 = pygame.image.load(nom_dossier[a] + '/' + nom_fichier1).convert_alpha()
    personnage2 = pygame.image.load(nom_dossier[a] + '/' + nom_fichier2).convert_alpha()
    personnage3 = pygame.image.load(nom_dossier[a] + '/' + nom_fichier3).convert_alpha()
    personnage4 = pygame.image.load(nom_dossier[a] + '/' + nom_fichier4).convert_alpha()

    # tableau des images utilisées pour le personnage
    personnage = [personnage1, personnage2, personnage3, personnage4]

    # changement de position lors du clic, quand on lève le doigt du bouton
    if event.type == MOUSEBUTTONUP:
        # k est le numero de l'image du personnage, pour qu'il change de pose; si on clique, on met la pose marche vers la droite
        k = 1
        destination_x = event.pos[0] - personnage[k].get_width()/2.0
        destination_y = event.pos[1] - personnage[k].get_height()
        destination = (destination_x, destination_y)
        # vecteur du point de départ au point d'arrivée
        direction = Vector2.from_points(position, destination)
        # normalisation du vecteur
        direction.normalize()
        # distance puis position suivante
        distance_parcourue = temps_passe_secondes * vitesse
        position += direction * distance_parcourue
        (x, y) = position
        # lorsqu'on est à gauche de la position d'arrivée, on met l'image gauche du personnage
        if x > (destination_x - 1.0):
            k = 3
        #  s'il n'y a pas de clic de souris, on on met la pose statique
    else:
        k = 0

    # affiche la couleur de l'écran puis les images
    ecran.fill((R,V,B))
    ecran.blit(arriereplan, (0.0, 0.0))
    ecran.blit(personnage[k], position)

    pygame.display.update()

Je n'avance vraiment pas vite, je crois que je manque de logique et de compréhension des principes essentiels, même si ça s'améliore progressivement.
Il semble que l'essai/erreur un peu à la louche ne soit pas la meilleure technique pour progresser même si ça finit par marcher avant un peu d'opiniatreté. cool

Dernière modification par doudoulolita (Le 12/02/2011, à 00:14)

Hors ligne

#68 Le 11/03/2011, à 13:03

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Lien très utile (en français) : site du zero - pygame smile

Hors ligne

#69 Le 02/04/2011, à 03:18

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Encore des ameliorations pour mon programme en pygame où ce sont les couleurs bleues et rouges de Tuxpaint qui mènent le jeu. cool
Il faudra bien sûr changer le chemin vers vos images dans:

# indique le chemin des images
chemin = '/home/user/programmation/04_programmes_maternelles/'

Une nouvelle image a été ajoutée: "arriereplan_cote.png", simple image blanche, qui mesure 192 * 472 px. Elle sera placée à droite du jeu, et servira de fond pour la partie "score".
arriereplan1.png, arriereplan2.png (comportant les couleurs bleues et rouges définies dans le jeu), tux_victoire.png et tux_defaite.png font toutes 608 * 472 px, comme dans Tuxpaint et ne comportent pas de transparence. Voir les images du programme Miks
La taille de l'écran étant définie par ailleurs dans le code, il faut mieux ne pas changer la taille de ces images.
Les 3 poses du nounours Miks sont les même que lors des essais précédents (ils font environ 50 px de haut, mais leur taille exacte n'a pas d'importance pour le jeu). Bien sûr, vous pouvez remplacer tout ça par votre propres images (faites avec  Tuxpaint + Gimp ou Inkscape) et les placer dans le même dossier que le jeu !
    miks-souris1     miks-souris2   miks-souris3

"arriereplan.png" peut cette fois être une simple image blanche de 608 * 472 px. J'aurais aimé la supprimer (mais je ne peux pas sans revoir beaucoup mon code donc je la laisse) car les chiffres 1 et 2 sont maintenant affichés avec cette fonction.

def imprime_texte(texte,x_texte):
    """ affiche du texte à l'écran avec la police et la couleur choisie """
    ma_police = pygame.font.SysFont("arial", 100)
    surface_texte = ma_police.render(texte, True, vert)
    screen.blit(surface_texte, (x_texte, height+(height/2)))

La position verticale est définie par une hauteur qui se trouve ailleurs dans le code (cherchez un peu !). On appellera ensuite dans la boucle cette fonction imprime_texte. La position horizontale est alors indiquée par une largeur définie également ailleurs dans le code (cherchez encore !). Cela correspond au x_texte de la fonction (est-ce clair ?)

        # affiche les chiffres 1 puis 2 grâce à la fonction d'affichage de texte
        imprime_texte("1", width-(width/2))
        imprime_texte("2", width+(width/2))

Ce nouveau code permet d'afficher le score d'une manière plus visuelle pour les petits, avec des petits nounours qui apparaissent quand le score augmente.
Voir dans le code le détail de la fonction sous la ligne suivante:

def verifie_score():

J'ai volontairement limité le score affiché à 6 car c'est à peu près ce que les enfants apprennent en moyenne section de maternelles, mon public cible... wink

Voici le code entier du jeu au stade où il en est maintenant:

#!/usr/bin/ env python
# -*- coding: utf-8 -*-

# importe la bibliothèque Pygame
import pygame
from pygame.locals import *
from sys import exit
import os.path

# indique le chemin des images
chemin = '/home/user/programmation/04_programmes_maternelles/'

# définit les images choisies pour l'arrière-plan  et la souris sans le chemin de leur dossier
nom_image_arriereplan = 'arriereplan.png'
nom_image_arriereplan_cote = 'arriereplan_cote.png'
nom_image_arriereplan1 = 'arriereplan1.png'
nom_image_arriereplan2 = 'arriereplan2.png'
nom_image_victoire = 'tux_victoire.png'
nom_image_defaite = 'tux_defaite.png'
nom_image_souris1 = 'miks_static.png'
nom_image_souris2 = 'miks_smackup2.png'
nom_image_souris3 = 'miks_roll2.png'

# définit les images choisies pour l'arrière-plan  et la souris avec le chemin du dossier
image_arriereplan = chemin + nom_image_arriereplan
image_arriereplan_cote = chemin + nom_image_arriereplan_cote
image_arriereplan1 = chemin + nom_image_arriereplan1
image_arriereplan2 = chemin + nom_image_arriereplan2
image_victoire = chemin + nom_image_victoire
image_defaite = chemin + nom_image_defaite
image_souris1 = chemin + nom_image_souris1
image_souris2 = chemin + nom_image_souris2
image_souris3 = chemin + nom_image_souris3

# appelle la fonction horloge et le temps
clock = pygame.time.Clock()
temps = pygame.time.get_ticks()
temps2 = clock.get_time()

#initialise pygame
pygame.init()

# initialise les variables
i = 0
k = 0
score = 0

# définit la taille de la fenêtre
screen = pygame.display.set_mode((800, 472), 0, 32)
# donne le titre de la fenêtre
pygame.display.set_caption("Miks aime le bleu")

# charge les images
arriereplan = pygame.image.load(image_arriereplan).convert()
arriereplan_cote = pygame.image.load(image_arriereplan_cote).convert()
arriereplan1 = pygame.image.load(image_arriereplan1).convert()
arriereplan2 = pygame.image.load(image_arriereplan2).convert()
victoire = pygame.image.load(image_victoire).convert()
defaite = pygame.image.load(image_defaite).convert()
souris1 = pygame.image.load(image_souris1).convert_alpha()
souris2 = pygame.image.load(image_souris2).convert_alpha()
souris3 = pygame.image.load(image_souris3).convert_alpha()

# récupère la largeur et la hauteur de l'image d'arrière-plan
largeur_arriereplan = arriereplan.get_width()
hauteur_arriereplan = arriereplan.get_height()

# divise et réduit la largeur et la hauteur d'arrière-plan
width = largeur_arriereplan/2-18
height = hauteur_arriereplan/2-12

# crée les vignettes de la page accueil
arriereplan1p = pygame.transform.scale(arriereplan1, (width, height))
arriereplan2p = pygame.transform.scale(arriereplan2, (width, height))

# définit les couleurs
bleu = (50, 100, 255, 255)
rouge = (255, 0, 0, 255)
vert = (0, 255, 0)

# indique les scores maximums et minimums
score_max = 3000
score_min = -3000

# fonction d'affichage de la souris suivant la couleur de l'arrière-plan
def rendu_miks():  
    """ k est la position dans le tableau initialisée à 0 """
    k = 0
    """ si la couleur est bleue, change k et donc l'image de la souris """
    if couleur_ecran == bleu:
        k = 1    
    """ si la couleur est rouge, change k et donc l'image de la souris """
    elif couleur_ecran == rouge:
        k = 2
    """ affiche l'image de la souris """
    screen.blit(souris_x[k], (x,y))

def imprime_texte(texte,x_texte):
    """ affiche du texte à l'écran avec la police et la couleur choisie """
    ma_police = pygame.font.SysFont("arial", 100)
    surface_texte = ma_police.render(texte, True, vert)
    screen.blit(surface_texte, (x_texte, height+(height/2)))

def accueil_jeu():
    """ Définit les dimensions du rectangle de la page d'accueil """ 
    Rect = (6, 16, largeur_arriereplan-12, height+12) 
    i = 0
    """ remplit l'écran de blanc """
    screen.fill((255,255,255))
    """ crée un rectangle vert """
    pygame.draw.rect(screen, vert, Rect, 0)
    """ affiche successivement la première vignette et la deuxième sur la page d'accueil """ 
    screen.blit(arriereplan1p, (10, 20)) 
    screen.blit(arriereplan2p, ((width+24), 20)) 
    """ affiche l'image de la souris """
    k = 0
    screen.blit(souris_x[k], (x,y))

def verifie_score():
    """ affiche le score réel puis le temps dans la console """
    print score
    print temps
    """ affiche le nombre de nounours correspondant au score affiché """
    if score2 == 0:
        screen.blit(souris_x[0], ((largeur_arriereplan+30), 20))
    if score2 < 0:
        for s in range(0,3):
            if score2 < -s:
                screen.blit(souris_x[2], ((largeur_arriereplan+30), (20+s*80)))      
        for s in range(0,3):
            if score2 < -(s+3):
                screen.blit(souris_x[2], ((largeur_arriereplan+130), (20+s*80))) 
    if score2 > 0:     
        for s in range(0,3):
            if score2 > s:
                screen.blit(souris_x[1], ((largeur_arriereplan+30), (20+s*80)))      
        for s in range(0,3):
            if score2 > (s+3):
                screen.blit(souris_x[1], ((largeur_arriereplan+130), (20+s*80)))

while True:
    # pour fermer la fenêtre
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
    # inscrémente le temps depuis le début du jeu
    temps += 1

    # récupère les touches pressées
    touche_pressee = pygame.key.get_pressed()

    #tableau des images pour l'arrière-plan
    arriereplan_x = [arriereplan, arriereplan1, arriereplan2]

    screen.blit(arriereplan_cote, (608, 0)) 

    # choisit l'image d'arrière-plan selon la touche
    if  touche_pressee[K_KP1]:
        i = 1
        
    elif touche_pressee[K_KP2]:
        i = 2
                
    elif touche_pressee[K_KP0]:
        i = 0
    # affiche l'arrière-plan en fonction de la touche pressée, connue grâce à la variable i
    screen.blit(arriereplan_x[i], (0, 0))

    # définit la position de la souris
    x, y = pygame.mouse.get_pos()
    
    # échantillonne la couleur que survole la souris
    couleur_ecran = screen.get_at((x, y))

    # tableau des images utilisées pour la souris
    souris_x = [souris1, souris2, souris3] 

    # Place le curseur de la souris au centre de l'image
    x-= souris_x[k].get_width() / 2
    y-= souris_x[k].get_height() / 2
 
    # Si on presse la touche 0
    if i == 0:
        # appelle la fonction qui affiche la page d'accueil
        accueil_jeu()
        # affiche les chiffres 1 puis 2 grâce à la fonction d'affichage de texte
        imprime_texte("1", width-(width/2))
        imprime_texte("2", width+(width/2))

    # si la touche 1 ou la touche 2 sont pressés
    elif i == 1 or i == 2:
        # divise le score par 500 pour des chiffres plus petits et un changement moins rapide
        score2 = score/500
        # si la couleur est bleue, on ajoute 1 au score
        if couleur_ecran == bleu and score2 < 6:
            score +=1
        # si la couleur est rouge, on ote 1 au score 
        if couleur_ecran == rouge and score2 > -6:
        score -=1
        # appelle la fonction d'affichage l'image de la souris
        rendu_miks()

        # transforme le chiffre du petit score en texte à afficher
        texte_score = str(score2)
        # affiche le petit score sur l'écran grâce à la fonction d'affichage de texte
        imprime_texte(texte_score,(largeur_arriereplan + 40))

        # appelle la fonction de vérification du score
        verifie_score()
        # si le score dépasse le maximum, affiche l'image de la victoire
        if score2 >= 6:
            screen.blit(victoire, (0, 0))

        # si le score est inférieur au minimum, affiche l'image de la défaite
        if score2 <= -6:
            screen.blit(defaite, (0, 0)) 
              
    # réactualise l'affichage
    pygame.display.flip()

Mon souci reste que le score ne se "bloque" pas à 6: si on bouge la souris quand l'image de la défaite ou de la victoire s'affiche, on peut revenir sur le jeu involontairement. hmm
Continue ou break ne fonctionne pas comme je le voudrais. Break arrête le jeu et la fenêtre se ferme et si je me souviens bien, continue ne change rien au problème.
L'idéal serait de pouvoir revenir automatiquement à la page d'accueil après un petit temps de latence, je pense.

Dernière modification par doudoulolita (Le 02/04/2011, à 03:54)

Hors ligne

#70 Le 02/04/2011, à 13:23

tshirtman

Re : Faire une animation sur la création de jeux vidéo libres

pygame.time.wait(temps_de_latence_en_ms)
accueil_jeu()

?

Hors ligne

#71 Le 15/04/2011, à 14:31

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

Ubuntu en rade suite à une mise à jour, je testerai donc ça plus tard. merci quand même ! cool

Hors ligne

#72 Le 06/05/2011, à 11:10

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

miks_walk2 J'ai enfin réussi à faire marcher Miks et Rizzie.

Pour se faire, j'ai eu besoin d'ajouter dans mon dossier une image nommée rectangle_blanc.png qui a la même taille que miks_walk2.png, soit la plus large des images que j'utilise. J'ai aussi allongé la taille de la fenêtre à 900.

#!/usr/bin/ env python
# -*- coding: utf-8 -*-

# donne la largeur et la hauteur de l'écran
largeur_ecran = 900
hauteur_ecran = 472

# importe la bibliothèque Pygame
import pygame
from pygame.locals import *
from sys import exit

class Sprite:
    """ Un sprite défini par son nom, son image et la position de son image et on ajoute une police de caractères """

    def __init__(self, nom, walk1, walk2, x, y, vitesse):

        self.nom = nom
        self.walk1 = walk1
        self.walk2 = walk2
        self.x = x
        self.y = y
        self.police = pygame.font.SysFont("arial", 50)
        self.vitesse = vitesse
        self.image1 = pygame.image.load(self.walk1).convert_alpha()
        self.image2 = pygame.image.load(self.walk2).convert_alpha()
        self.surface_texte = self.police.render(self.nom, True, (0,0,0))

    def imprime_nom(self):
        """ affiche le nom du sprite à l'écran avec la police et la couleur choisie """
        screen.blit(self.surface_texte, (20, (self.y-60)))

    def affiche_image(self, temps):
        """ affiche l'image du sprite"""
        if temps >= (t*self.vitesse) and temps < (t*self.vitesse)+(self.vitesse/4):
            screen.blit(self.image1, (self.x+(t*self.vitesse), self.y))
        if temps >= (t*self.vitesse)+(self.vitesse/4) and temps < (t*100)+(self.vitesse/2):
            screen.blit(rectangle_blanc, (self.x+(t*self.vitesse), self.y))            
        if temps >= (t*self.vitesse)+(self.vitesse/2) and temps < (temps*100)+(3*self.vitesse/4):
            screen.blit(self.image2, ((2*self.x)+(t*self.vitesse), self.y))  
        if temps >= (t*self.vitesse)+(3*self.vitesse/4) and temps < (temps*100)+self.vitesse:
            screen.blit(rectangle_blanc, ((2*self.x)+(t*self.vitesse), self.y))                                          
   
#initialise pygame
pygame.init()

# définit la taille de la fenêtre
screen = pygame.display.set_mode((largeur_ecran, hauteur_ecran), 0, 32)
# donne le titre de la fenêtre
pygame.display.set_caption("Miks et rizzie vont-ils bouger ?")

# appelle la fonction temps puis initialise le nombre de fois qu'on affichera la boucle
temps = pygame.time.get_ticks()
t = 1

# les sprites 'S' et 'W' avec leurs noms, le nom de leur image et leur position
dictionnaire_sprites = { 'S':Sprite('Miks', 'miks_static1.png', 'miks_walk2.png', 80, 100, 80), 'W':Sprite('Rizzie', 'rizzie-static1.png', 'rizzie-walk1.png', 80, 300, 80) }

rectangle_blanc = pygame.image.load('rectangle_blanc.png').convert_alpha()

while True:
    # pour fermer la fenêtre
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()

    # affiche l'arriere-plan
    screen.fill((255,255,255))

    # Donne le temps dans la console
    temps +=1
    print temps

    # Pour chaque élément du dictionnaire des sprites
    for item in dictionnaire_sprites:
        # utilise la fonction d'impression du nom du sprite
        dictionnaire_sprites[item].imprime_nom()

        # utilise la fonction d'affichage de l'image du sprite et créée une boucle pour le faire avancer
        t +=1
        for t in range(1,40):
                dictionnaire_sprites[item].affiche_image(temps)              

    # réactualise l'affichage
    pygame.display.update()

Ce n'est pas parfait parce que ça clignote pas mal mais je crois que je tiens le principe. Sinon, je ne parviendrai pas à le faire avec un fond qui ne soit pas uni, donc il y a encore un petit souci.

Dernière modification par doudoulolita (Le 06/05/2011, à 11:13)

Hors ligne

#73 Le 06/05/2011, à 11:50

tshirtman

Re : Faire une animation sur la création de jeux vidéo libres

Hum, je pense que tu fait erreur, effacer avec un rectangle blanc n'est pas une approche souple ni efficace…  je ne comprends pas trop pourquoi tu as besoin de ça…

en gros à chaque affichage de l'écran, il faut tout redessiner dans l'ordre:
-le fond (au moins une couleur sur tout l'écran, mais sinon, une image qui couvre tout le fond).
-les décors éventuels
-les personnages et les objets
-les décors plus proches de la caméra que les personnages
-l'éventuel overlay (points de vie, textes, icones, etcs).

de cette façon, pas besoin de carré pour effacer des bouts…

Hors ligne

#74 Le 06/05/2011, à 12:59

doudoulolita

Re : Faire une animation sur la création de jeux vidéo libres

J'avais trouvé cette approche dans un tuto sur les sprites; Sinon, redessiner entièrement l'arrière-plan avec un screen.fill ne semblait pas génial lors de mes tentatives mais je réessaierai.

miks_walk2.pngAutre essai sur le jeu des couleurs, avec les persos qui bougent, il faut ajouter une image de Miks à chercher dans Images du programmes Miks

#!/usr/bin/ env python
# -*- coding: utf-8 -*-

# importe la bibliothèque Pygame
import pygame
from pygame.locals import *
from sys import exit
import os.path

# indique le chemin des images
chemin = '/home/epn13/01-laurence/programmation/04b_programmes_maternelles/'

# définit les images choisies pour l'arrière-plan  et la souris sans le chemin de leur dossier
nom_image_arriereplan = 'arriereplan.png'
nom_image_arriereplan_cote = 'arriereplan_cote.png'
nom_image_arriereplan1 = 'arriereplan1.png'
nom_image_arriereplan2 = 'arriereplan2.png'
nom_image_victoire = 'tux_victoire.png'
nom_image_defaite = 'tux_defaite.png'
nom_image_souris1 = 'miks_static.png'
nom_image_souris2 = 'miks_smackup2.png'
nom_image_souris3 = 'miks_roll2.png'
nom_image_souris1b = 'miks_walk2.png'

# définit les images choisies pour l'arrière-plan  et la souris avec le chemin du dossier
image_arriereplan = chemin + nom_image_arriereplan
image_arriereplan_cote = chemin + nom_image_arriereplan_cote
image_arriereplan1 = chemin + nom_image_arriereplan1
image_arriereplan2 = chemin + nom_image_arriereplan2
image_victoire = chemin + nom_image_victoire
image_defaite = chemin + nom_image_defaite
image_souris1 = chemin + nom_image_souris1
image_souris2 = chemin + nom_image_souris2
image_souris3 = chemin + nom_image_souris3
image_souris1b = chemin + nom_image_souris1b

# appelle la fonction horloge et le temps
clock = pygame.time.Clock()
temps = pygame.time.get_ticks()
temps2 = clock.get_time()

#initialise pygame
pygame.init()

# initialise les variables
i = 0
k = 0
score = 0

# définit la taille de la fenêtre
screen = pygame.display.set_mode((800, 472), 0, 32)
# donne le titre de la fenêtre
pygame.display.set_caption("Miks aime le bleu")

# charge les images
arriereplan = pygame.image.load(image_arriereplan).convert()
arriereplan_cote = pygame.image.load(image_arriereplan_cote).convert()
arriereplan1 = pygame.image.load(image_arriereplan1).convert()
arriereplan2 = pygame.image.load(image_arriereplan2).convert()
victoire = pygame.image.load(image_victoire).convert()
defaite = pygame.image.load(image_defaite).convert()
souris1 = pygame.image.load(image_souris1).convert_alpha()
souris2 = pygame.image.load(image_souris2).convert_alpha()
souris3 = pygame.image.load(image_souris3).convert_alpha()
souris1b = pygame.image.load(image_souris1b).convert_alpha()

# récupère la largeur et la hauteur de l'image d'arrière-plan
largeur_arriereplan = arriereplan.get_width()
hauteur_arriereplan = arriereplan.get_height()

# divise et réduit la largeur et la hauteur d'arrière-plan
width = largeur_arriereplan/2-18
height = hauteur_arriereplan/2-12

# crée les vignettes de la page accueil
arriereplan1p = pygame.transform.scale(arriereplan1, (width, height))
arriereplan2p = pygame.transform.scale(arriereplan2, (width, height))

# définit les couleurs
bleu = (50, 100, 255, 255)
rouge = (255, 0, 0, 255)
vert = (0, 255, 0)
blanc = (255, 255, 255)

# indique les scores maximums et minimums
score_max = 3000
score_min = -3000

# fonction d'affichage de la souris suivant la couleur de l'arrière-plan
def rendu_miks():  
    """ si la couleur est bleue, change k et donc l'image de la souris """
    if couleur_ecran != bleu and couleur_ecran != rouge:
        if temps%2 == 0:   
            k = 0
            pygame.time.wait(100)
        else:
            k = 3
            pygame.time.wait(100)  
    if couleur_ecran == bleu: 
        if temps%2 == 0:     
            k = 0
            pygame.time.wait(100)            
        else:
            k = 1
            pygame.time.wait(200)       
    elif couleur_ecran == rouge:
        if temps%2 == 0:       
            k = 0
            pygame.time.wait(100)            
        else:
            k = 2
            pygame.time.wait(200)
    """ affiche l'image de la souris """
    screen.blit(souris_x[k], (x,y))

def imprime_texte(texte,x_texte):
    """ affiche du texte à l'écran avec la police et la couleur choisie """
    ma_police = pygame.font.SysFont("arial", 100)
    surface_texte = ma_police.render(texte, True, vert)
    screen.blit(surface_texte, (x_texte, height+(height/2)))

def accueil_jeu():
    """ Définit les dimensions du rectangle de la page d'accueil """ 
    Rect = (6, 16, largeur_arriereplan-12, height+12) 
    i = 0
    """ remplit l'écran de blanc """
    screen.fill((255,255,255))
    """ crée un rectangle vert """
    pygame.draw.rect(screen, vert, Rect, 0)
    """ affiche successivement la première vignette et la deuxième sur la page d'accueil """ 
    screen.blit(arriereplan1p, (10, 20)) 
    screen.blit(arriereplan2p, ((width+24), 20)) 
    """ affiche l'image de la souris """
    k = 0
    screen.blit(souris_x[k], (x,y))

def verifie_score():
    """ affiche le score réel puis le temps dans la console """
    print score
    print temps
    """ affiche le nombre de nounours correspondant au score affiché """
    if score2 == 0:
        screen.blit(souris_x[0], ((largeur_arriereplan+30), 20))
    if score2 < 0:
        for s in range(0,3):
            if score2 < -s:
                screen.blit(souris_x[2], ((largeur_arriereplan+30), (20+s*80)))      
        for s in range(0,3):
            if score2 < -(s+3):
                screen.blit(souris_x[2], ((largeur_arriereplan+130), (20+s*80))) 
    if score2 > 0:     
        for s in range(0,3):
            if score2 > s:
                screen.blit(souris_x[1], ((largeur_arriereplan+30), (20+s*80)))      
        for s in range(0,3):
            if score2 > (s+3):
                screen.blit(souris_x[1], ((largeur_arriereplan+130), (20+s*80)))

while True:
    # pour fermer la fenêtre
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
    # inscrémente le temps depuis le début du jeu
    temps += 1

    # récupère les touches pressées
    touche_pressee = pygame.key.get_pressed()

    #tableau des images pour l'arrière-plan
    arriereplan_x = [arriereplan, arriereplan1, arriereplan2]

    screen.blit(arriereplan_cote, (608, 0)) 

    # choisit l'image d'arrière-plan selon la touche
    if  touche_pressee[K_KP1]:
        i = 1
        
    elif touche_pressee[K_KP2]:
        i = 2
                
    elif touche_pressee[K_KP0]:
        i = 0
    # affiche l'arrière-plan en fonction de la touche pressée, connue grâce à la variable i
    screen.blit(arriereplan_x[i], (0, 0))

    # définit la position de la souris
    x, y = pygame.mouse.get_pos()
    
    # échantillonne la couleur que survole la souris
    couleur_ecran = screen.get_at((x, y))

    # tableau des images utilisées pour la souris
    souris_x = [souris1, souris2, souris3, souris1b] 

    # Place le curseur de la souris au centre de l'image
    x-= souris_x[k].get_width() / 2
    y-= souris_x[k].get_height() / 2
 
    # Si on presse la touche 0
    if i == 0:
        # appelle la fonction qui affiche la page d'accueil
        accueil_jeu()
        # affiche les chiffres 1 puis 2 grâce à al fonction d'affichage de texte
        imprime_texte("1", width-(width/2))
        imprime_texte("2", width+(width/2))

    # si la touche 1 ou la touche 2 sont pressés
    elif i == 1 or i == 2:
        # divise le score par 500 pour des chiffres plus petits et un changement moins rapide
        score2 = score/10
        # si la couleur est bleue, on ajoute 1 au score
        if couleur_ecran == bleu and score2 < 6:
            score +=1
        # si la couleur est rouge, on ote 1 au score 
        if couleur_ecran == rouge and score2 > -6:
        score -=1
        # appelle la fonction d'affichage l'image de la souris
        rendu_miks()

        # transforme le chiffre du petit score en texte à afficher
        texte_score = str(score2)
        # affiche le petit score sur l'écran grâce à la fonction d'affichage de texte
        imprime_texte(texte_score,(largeur_arriereplan + 40))

        # appelle la fonction de vérification du score
        verifie_score()
        # si le score dépasse le maximum, affiche l'image de la victoire
        if score2 >= 6:
            screen.blit(victoire, (0, 0))

        # si le score est inférieur au minimum, affiche l'image de la défaite
        if score2 <= -6:
            screen.blit(defaite, (0, 0)) 
              
    # réactualise l'affichage
    pygame.display.flip()

Hors ligne

#75 Le 06/05/2011, à 13:29

tshirtman

Re : Faire une animation sur la création de jeux vidéo libres

Si tu as un soucis avec le screen.fill() on peut voir ce que c'est, mais c'est en effet la bonne approche wink

Hors ligne