2017-09-11 3 views
1

Le comportement souhaité est:Barre de progression à l'intérieur d'un bouton dans Pygame

Lorsque l'utilisateur tient la souris sur le bouton, la barre de progression gris foncé apparaît et commence à s'incrémentée à un rythme constant. Je veux être en mesure de déterminer combien de temps cela prendra pour remplir complètement (comme 2 secondes). Si la souris déplace le bouton AVANT que la barre de progression ait atteint 100%, la barre de progression doit aller directement à 0%. Si la barre atteint 100%, le programme devrait imprimer quelque chose dans le terminal.

Voici le code:

import sys 
import pygame 
import time 
from pygame.locals import * 
from os import path 

pygame.init() 

screen = pygame.display.set_mode((900, int(900 * (16/9)))) 

clock = pygame.time.Clock() 

BLACK = (0, 0, 0) 
GREEN = (0, 255, 0) 
WHITE = (255, 255, 255) 
BACKGROUND_COLOR = (237, 225, 192) 
LIGHT_GRAY = (60, 60, 60) 
GRAY = (30, 30, 30) 

class Button: 

    def __init__(self, screen, x, y, w, h, button_color_active, button_color_inactive, text, font, size = 50, text_color = BLACK): 
     self.screen = screen 

     self.game_folder = path.dirname(__file__) 
     self.font = path.join(self.game_folder, font + '.ttf') 

     self.x, self.y, self.w, self.h = x, y, w, h 
     self.button_color_active = button_color_active 
     self.button_color_inactive = button_color_inactive 

     self.text, self.size = text, size 
     self.text_color = text_color 

     self.button_rect = pygame.Rect(self.x, self.y, self.w, self.h) 
     self.button_font = pygame.font.Font(self.font, self.size) 
     self.label = self.button_font.render(self.text, 1, self.text_color) 

    def draw(self): 
     if self.button_rect.collidepoint(pygame.mouse.get_pos()): 
      #pygame.draw.rect(self.screen, self.button_color_inactive, self.button_rect) 
      for progress in range(42): 
       pygame.draw.rect(screen, LIGHT_GRAY, pygame.Rect(50,600,10*progress,80)) 
       pygame.display.update() 

     else: 
      pygame.draw.rect(self.screen, self.button_color_active, self.button_rect) 
     self.screen.blit(self.label, (self.x + 20, self.y + 5)) 

    def is_clicked(self, mouse_pos): 
     return bool(self.button_rect.collidepoint(mouse_pos)) 

    def set_new_color(self, active_color, inactive_color): 
     self.button_color_active = active_color 
     self.button_color_inactive = inactive_color 

button_start = Button(screen, 50, 600, 400, 80, GRAY, LIGHT_GRAY, 'START', 'roboto-black', 50, WHITE) 
while True: 
    screen.fill(BACKGROUND_COLOR) 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      pygame.quit() 
    #pygame.draw.rect(screen, GRAY, pygame.Rect(50,600,400,80)) 
    #pygame.draw.rect(screen, LIGHT_GRAY, pygame.Rect(50,600,10*progress,80)) 
    button_start.draw() 
    pygame.display.flip() 
    clock.tick(60) 
a = str(input('shomething: ')) 

Répondre

1

Tout d'abord vous avez besoin d'une minuterie. Vous pouvez utiliser le dt (temps delta) que pygame.clock.tick(fps) renvoie pour augmenter une variable time. Ne faites cela que si la souris survole le bouton, sinon réinitialisez la minuterie.

Pour calculer la largeur de la rect vous pouvez le faire (proportionality):

width = time * coefficient 

Voici un exemple minimal:

import pygame as pg 


pg.init() 

screen = pg.display.set_mode((640, 480)) 
clock = pg.time.Clock() 
FONT = pg.font.Font(None, 36) 
BACKGROUND_COLOR = (237, 225, 192) 
LIGHT_GRAY = (120, 120, 120) 
GRAY = (30, 30, 30) 

# Button variables. 
button_rect = pg.Rect(50, 100, 200, 80) 
max_width = 200 # Maximum width of the rect. 
max_time = 4 # Time after which the button should be filled. 
# Coefficient to calculate the width of the rect for a given time. 
coefficient = max_width/max_time 
time = 0 

dt = 0 
done = False 

while not done: 
    for event in pg.event.get(): 
     if event.type == pg.QUIT: 
      done = True 

    mouse_pos = pg.mouse.get_pos() 
    if button_rect.collidepoint(mouse_pos): 
     # If mouse is over the button, increase the timer. 
     if time < max_time: # Stop increasing if max_time is reached. 
      time += dt 
      if time >= max_time: 
       time = max_time 
    else: # If not colliding, reset the time. 
     time = 0 

    width = time * coefficient 

    screen.fill(BACKGROUND_COLOR) 
    pg.draw.rect(screen, LIGHT_GRAY, (51, 100, width, 80)) 
    pg.draw.rect(screen, GRAY, button_rect, 2) 
    txt = FONT.render(str(round(time, 2)), True, GRAY) 
    screen.blit(txt, (20, 20)) 

    pg.display.flip() 
    dt = clock.tick(60)/1000 

pg.quit() 
+0

merci pour la réponse, mais quand j'exécute le code et survolez le bouton le programme ne fait rien. J'utilise python 2.7 – lvvittor

+0

J'ai trouvé l'erreur: vous devez changer le code en dt = clock.tick (60)/float (1000) car sans le float dt est égal à 0 – lvvittor

+0

Oui, en Python 2 l'un des les nombres doivent être un flottant pour obtenir un flottant comme résultat, sinon si les deux nombres sont des entiers, il effectue une division entière. En Python 3, '/' fonctionne comme la division normale en maths. Vous pouvez également utiliser une future importation 'from __future__ import division' en haut du programme et'/'fonctionnera comme dans Python 3. Pourquoi n'utilisez-vous pas 3? 2 ne sera maintenu que pour 2 années supplémentaires (btw votre question est marquée comme "python-3.x"). – skrx