IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation multimédia/Jeux Python Discussion :

PyGame, quelques questions sans réponses


Sujet :

Programmation multimédia/Jeux Python

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut PyGame, quelques questions sans réponses
    Bonjour à tous,
    Pour la petite histoire, je développe en Python depuis maintenant 2 ans au taff (je suis DBA avec beaucoup d'administration de bases en Python !). Je suis aussi un très gros joueur de jeux vidéo (6 à 8h par jours en semaine). Du coup je me suis dis, mais pourquoi ne pas joindre deux choses qui me passionnent, le développement (en python pour le coup) et le jeu vidéo. Alors je suis tombé sur Pygame et je tente de faire quelques animations toutes bêtes avant de tenter quoi que ce soit, classique en somme.

    J'essaye de faire une animation avec des "balles" qui rebondissent non-stop dans la fenêtre (exemple pris sur un wiki et que je complique au fur et à mesure). Elles rebondissent sur les bords, et entre elles (sans me casser la tête avec les angles de collision etc ...). En gros si une balle touche un bord ou une autre balle alors elle repart d'où elle vient.
    J'ai de temps en temps une balle qui va se mettre à "bugguer" sur un bord ou bien pendant qu'elle en croise une autre : la balle "tremble" et fini par repartir. De temps en temps, les balles se traversent aussi. J'ai beau chercher, je ne trouve pas la faille dans mon code qui est pourtant simple.
    Auriez vous un oeil avisé afin de me donner une piste de l'endroit où ca pourrait foirer ?

    Voici le code complet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
     
    import sys, pygame, random, time
     
    #Initialisation de la fenetre
    pygame.init()
    nb_ball=5
    size = width, height = 800, 600
    black = 0, 0, 0
    screen = pygame.display.set_mode(size)
     
    class Ball():
            def __init__(self):
                    self.image = pygame.image.load('ball.png')
                    self.rect = self.newRandomPosition()
                    self.moveSpeed = self.newRandomSpeed()
                    return
     
            def newRandomPosition(self):
                    # Generation d'une position de depart aleatoire
                    rect = self.image.get_rect()
                    xpos = random.randint(rect.width, width - rect.width)
                    ypos = random.randint(rect.height, height - rect.height)
                    rect = rect.move([xpos, ypos])
                    return rect
     
            def newRandomSpeed(self):
                    # Generation d'une vitesse aleatoire
                    random_speed=[random.randint(-10,10), random.randint(-10,10)]
                    while 0 in random_speed:
                            random_speed=[random.randint(-10,10), random.randint(-10,10)]
                    return random_speed
     
            def move(self):
                    self.rect = self.rect.move(self.moveSpeed)
                    # On rebondit sur les bords de la fenetre
                    if self.rect.left < 0 or self.rect.right > width:
                            self.reverseHorizontal()
                    if self.rect.top < 0 or self.rect.bottom > height:
                            self.reverseVertical()
                    return
     
            def reverseHorizontal(self):
                    self.moveSpeed[0] = -self.moveSpeed[0]
                    return
     
            def reverseVertical(self):
                    self.moveSpeed[1] = -self.moveSpeed[1]
                    return
     
            def displayBall(self):
                    screen.blit(self.image, self.rect)
                    return
     
            def detectCollisions(self, ballList, exceptions=[]):
                    allRect=[]
                    for j in range(len(ballList)):
                            if ballList[j] != self and j not in exceptions:
                                    allRect.append(ballList[j].rect)
                            listCollisions=self.rect.collidelistall(allRect)
                    return listCollisions
     
     
     
    ball_list=[]
    for i in range(nb_ball):
            ball_list.append(Ball())
     
    while 1:
            # Timer pour avoir un déplacement pas trop lent/rapide pour mes yeux :)
            time.sleep(0.01)
     
            # Capture d'event pour quitter
            for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                            pygame.display.quit()
                            sys.exit()
     
            # Nettoyage de la fenetre
            screen.fill(black)
     
            # Deplacement basique des balles
            for ball in ball_list:
                    ball.move()
                    ball.displayBall()
     
            # On detecte les collisions entre balles
            already_moved=[]
            for i in range(len(ball_list)):
                    listCollisions=ball_list[i].detectCollisions(ball_list)
                    if listCollisions != []:
                            already_moved.append(i)
                            ball_list[i].reverseHorizontal()
                            ball_list[i].reverseVertical()
                            for collision in listCollisions:
                                    ball_list[collision].reverseHorizontal()
                                    ball_list[collision].reverseVertical
                    ball_list[i].displayBall()
            pygame.display.flip()

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    beaucoup de mal à suivre la logique du code ....

    pitié ... créées une class Ball.

    voilà un exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    from pygame import *
    import random
     
    scrrect = Rect(0,0,800,600) # rectangle de la fenetre
    screen = display.set_mode(scrrect.size) # creation de a fenetre
     
    class Ball(Rect):
        ballimage = image.load('ball.png') # charge l'image de la balle
        ballrect = ballimage.get_rect() # rectangle de la balle
     
        def __init__(self):
            x = random.randint(0,scrrect.w - Ball.ballrect.w) # positionne la balle au hasard
            y = random.randint(0,scrrect.h - Ball.ballrect.h) # positionne la balle au hasard
            Rect.__init__(self,Ball.ballrect.move(x,y)) # cree et positionne le rectangle 
            self.speedx = random.randint(-2,2) # vitesse de deplacement et angle
            self.speedy = random.choice((-2,2)) # vitesse de deplacement et angle
            self.clock = time.Clock() # temporisation
            self.ticks = 0 # temporisation
            self.laps = random.randint(5,10) # temporisation
     
        def update(self):
            self.ticks += self.clock.tick() # temporisation
            if self.ticks >= self.laps: # temporisation
                temp_list = balls[:] # liste des objects "collisionables"
                temp_list.remove(self) # excepte l'objet en question
                r = self.move(self.speedx,self.speedy).collidelist(temp_list)
                if not scrrect.contains(self.move(self.speedx,0)): self.speedx *= -1
                if not scrrect.contains(self.move(0,self.speedy)): self.speedy *= -1
                if r > -1:
                    r = temp_list[r]
                    if not self.move(self.speedx,0).colliderect(r):
                        self.speedy *= -1 # inverse la vitesse
                    elif not self.move(0,self.speedy).colliderect(r):
                        self.speedx *= -1 # inverse la vitesse
                    else:
                        self.speedy *= -1 
                        self.speedx *= -1
                else:
                    self.x += self.speedx # deplace la balle
                    self.y += self.speedy # deplace la balle
                self.ticks -= self.laps # temporisation
     
    nballs = 10
    balls = []
     
    for i in range(nballs): # cree la liste de balles
        b = Ball()
        while b.collidelist(balls) != -1: b = Ball() # si emplacement deja occupe, recree une balle
        balls.append(b)
     
    clock = time.Clock() # temporisation de l'affichage
    ticks = 0 # temporisation de l'affichage
    laps = 20 # temporisation de l'affichage
     
    while event.poll().type != QUIT: # temps qu'on quitte pas
        for b in balls: b.update() # deplace les balles
        ticks += clock.tick()
        if ticks >= laps:
            screen.fill(0)
            for b in balls: screen.blit(Ball.ballimage,b) # affichage
            display.flip()
            ticks -= laps

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut
    Milles excuses ! J'ai édité le code du premier post.

    Pour ma défense, je dirais que j'ai commencé mes 20 000 premières lignes de code sur des scripts (plugins pour diverses appli) donc du code plutôt court en général et vu que personne d'autre que moi ne fait du python dans ma boîte ...

    Bref, j'ai pris bien 45min pour tenter de faire quelque chose de propre pour que vous puissiez m'aider. En espérant que ce soit plus clair cette fois-ci.

    Encore une fois, j'ai fais ce que je pensais bien alors ne m'en veuillez pas trop si certaines règles du developpement Python ne sont pas respectées

    EDIT : Nouveauté ... j'ai même une des balles qui vient de totalement sortir de la fenêtre par un des bords ... Je ne comprends pas vraiment le pourquoi du comment

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    bien,
    je ne connais pas la taille de la balle, mais si elle se déplace plus vite (en distance) que sa largeur, il y a des change qu'elle ne détecte pas la collision avec les autres.
    il est plus facile, du moins je trouve, de gérer une collision avant qu'elle n'arrive ...
    je vous ai mis un code dans ma réponse précédente; peut être pourra-t-il vous aider.

    les balles qui vibrent ou qui traversent ... hum ... souvent la vitesse de déplacement à changée, vu que vous n'utilisez pas de float() dans votre code, je soupçonne que la vitesse ne reverse pas comme elle devrait.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut
    J'avoue ne pas très bien voir de différence, à part que je vérifie s'il y a collision, et non pas s'il va y avoir collision.
    Le fait que les Rect se chevauchent n'est pas un soucis en soit pour Python. Donc je me dis que mon code ferait chevaucher deux Rect juste le temps d'un tour de boucle. Et que ensuite chacun retrouverait sa place.
    Je vais tout de même garder ta façon de procéder, qui je dois bien l'avouer est plus logique.

    Par contre, je découvre totalement pygame.Clock et pour être honnête j'ai beau relire la doc (http://www.pygame.org/docs/ref/time.html) et ton code sur tout ce qui concerne la temporisation ... je suis perdu ... surtout avec les "laps".

    Bref, je me dis que c'est l'heure qui fait ca. Je verrais demain si je trouve quelques liens sur le fonctionnement du clock et du coup comprendre comment fonctionne ta temporisation.

    Merci beaucoup josmiley de m'avoir mis sur la voie et d'avoir pris de ton temps pour mon problème !

  6. #6
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    j'ai éditer mon précédent code pour que les balles aient des angles différents.


    J'avoue ne pas très bien voir de différence, à part que je vérifie s'il y a collision, et non pas s'il va y avoir collision.
    imaginons 2 balles qui vont à la rencontre l'une de l'autre. elles avancent de 2 pixels par cycle.
    la 1ere overlap la seconde de 2 pixels, pas grave, au 2eme cycle elle sortira ....
    sauf que la second (dans le même 1er cycle) overlap la 1er à son tour; les 2 balles s'overlap donc de 4 pixels ...
    au second cycle, selon comment est construit le code, aucune des 2 ne pourra s'extirper, ou bien une vibrera ou restera fixe temps que l'autre ne sera pas sortie se son rectangle.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut
    Hm ... c'est vrai qu'en y réfléchissant bien (ou mieux c'est comme on veut), je comprends mieux et suis finalement totalement d'accord avec toi.

    Sujet Clos, merci à toi josmiley.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Jeu de labyrinthe, plusieurs questions sans réponse.
    Par Hedg-Hop dans le forum Débuter
    Réponses: 20
    Dernier message: 12/08/2012, 16h47
  2. Plusieurs questions sans réponses
    Par laposte dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 11/06/2010, 16h40
  3. questions sans réponses
    Par miroush dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 08/03/2010, 13h54
  4. [Débutant] Quelques questions sans réponses...
    Par fifou91 dans le forum LabVIEW
    Réponses: 1
    Dernier message: 11/08/2007, 11h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo