Facebook
From martim araujo, 10 Months ago, written in Python.
Embed
Download Paste or View Raw
Hits: 100
  1. import pygame
  2. import sys
  3. import random
  4. import math
  5.  
  6. class CUtils:
  7.     """
  8.        A função GetRandomCoordinate(min_x, max_x, min_y, max_y) recebe quatro argumentos: min_x, max_x, min_y e max_y, que
  9.        representam as faixas de valores para as coordenadas x e y.
  10.        A função retorna um tuple de números inteiros aleatórios.
  11.    """
  12.     @staticmethod
  13.     def GetRandomCoordinate(min_x, max_x, min_y, max_y):
  14.         return (
  15.             random.randint(min_x, max_x),
  16.             random.randint(min_y, max_y),
  17.         )
  18.  
  19.     """
  20.        A função GetRandomFloatNumber(min, max) retorna um número aleatório de ponto flutuante dentro de uma faixa específica.
  21.        Os argumentos min e max definem a faixa de valores para o número aleatório.
  22.        O método retorna um número de ponto flutuante aleatório.
  23.    """
  24.     @staticmethod
  25.     def GetRandomFloatNumber(min, max):
  26.         return random.uniform(float(min), float(max))
  27.  
  28.     """
  29.        A função GetRandomIntegerNumber(min, max) retorna um número inteiro aleatório dentro de uma faixa específica.
  30.        Os argumentos min e max definem a faixa de valores para o número aleatório.
  31.        A função retorna um número inteiro aleatório.
  32.    """
  33.     @staticmethod
  34.     def GetRandomIntegerNumber(min, max):
  35.         return random.randint(int(min), int(max))
  36.  
  37. class CElasticCollision:
  38.     _BACKGROUND_COLOR = (255, 255, 255)
  39.     _BORDER_PX_LENGHT = 10
  40.     _BORDER_COLOR = (0, 0, 0)
  41.     _RED_COLOR = (255, 0, 0)
  42.     _BLUE_COLOR = (0, 0, 255)
  43.     _WHITE_COLOR = (255, 255, 255)
  44.    
  45.     # CElasticCollision Construtor
  46.     def __init__(self, *args):
  47.         self.__Initialize(*args)
  48.  
  49.         # Inicializa a biblioteca Pygame e configura a janela da simulação.
  50.         self.__InitializePyGame()
  51.  
  52.         # Inicializa os objetos de círculo da simulação.
  53.         self.__InitializeCirclesObjects()
  54.  
  55.         # Inicializa a simulação
  56.         self.__RunSimulation()
  57.    
  58.     # CElasticCollision Destrutor
  59.     def __del__(self):
  60.         self.__Initialize('', 0, 0, 0, 0, 0)
  61.    
  62.     ##################
  63.     #@ Private Methods
  64.     ##################
  65.  
  66.     """
  67.        A função __Initialize() é chamada para inicializar as variáveis necessárias para o funcionamento da simulação.
  68.  
  69.        Esta recebe os seguintes argumentos:
  70.            -> args[0]: Título da janela da simulação (convertido para uma string).
  71.            -> args[1]: Largura da janela da simulação (convertida para um número inteiro).
  72.            -> args[2]: Altura da janela da simulação (convertida para um número inteiro).
  73.            -> args[3]: Raio dos círculos da simulação (convertido para um número inteiro).
  74.            -> args[4]: Número de círculos na simulação (convertido para um número inteiro).
  75.            -> args[5]: Velocidade máxima dos círculos (convertida para um número inteiro).
  76.  
  77.        Dentro da função, são inicializadas as seguintes variáveis:
  78.            -> self.window_pygame: Inicializada como None. Será preenchida posteriormente com a janela da simulação criada pelo Pygame.
  79.            -> self.window_title: Armazena o título da janela da simulação.
  80.            -> self.window_width: Armazena a largura da janela da simulação.
  81.            -> self.window_height: Armazena a altura da janela da simulação.
  82.            -> self.circle_objects: Lista vazia que armazenará os objetos dos círculos da simulação.
  83.            -> self.circle_radius: Armazena o raio dos círculos da simulação.
  84.            -> self.circles_count: Armazena o número de círculos na simulação.
  85.            -> self.circles_max_velocity: Armazena a velocidade máxima dos círculos.
  86.  
  87.        Esta função é responsável por preparar e inicializar todas as variáveis necessárias para a simulação
  88.        antes de começar a executá-la.
  89.    """
  90.     def __Initialize(self, *args):
  91.         self.window_pygame = None
  92.         self.window_title = str(args[0])
  93.         self.window_width = int(args[1])
  94.         self.window_height = int(args[2])
  95.        
  96.         self.circle_objects = []
  97.         self.circle_radius = int(args[3])
  98.         self.circles_count = int(args[4])
  99.         self.circles_max_velocity = int(args[5])
  100.    
  101.     """
  102.        A função __InitializePyGame() é responsável por inicializar a biblioteca Pygame e configurar a janela da simulação.
  103.  
  104.        A primeira verificação self.IsPyGameInitialized() verifica se o Pygame já foi inicializado anteriormente.
  105.        Se sim, a função retorna imediatamente sem fazer nada.
  106.  
  107.        Caso o Pygame não tenha sido inicializado, a função chama pygame.init() para inicializar a biblioteca.
  108.        Em seguida, ela cria uma janela com as dimensões especificadas em self.window_width e self.window_height usando pygame.display.set_mode().
  109.        O título da janela é definido usando pygame.display.set_caption() com o valor armazenado em self.window_title.
  110.  
  111.        Desta forma, esta função garante que o Pygame seja inicializado apenas uma vez e que
  112.        a janela de simulação seja configurada corretamente.
  113.    """
  114.     def __InitializePyGame(self):
  115.         if self.IsPyGameInitialized():
  116.             return
  117.        
  118.         pygame.init()
  119.         self.window_pygame = pygame.display.set_mode((self.window_width, self.window_height))
  120.         pygame.display.set_caption(self.window_title)
  121.  
  122.     """
  123.        A função __InitializeCirclesObjects(self) é responsável por inicializar os círculos na simulação.
  124.        Ela verifica se os objetos de círculo já foram inicializados anteriormente e, se sim, retorna imediatamente.
  125.  
  126.        A função possui uma função interna __IsPositionUnique(new_circle_position) que verifica se uma nova posição do círculo é única,
  127.        ou seja, se não há sobreposição com outros círculos já existentes. Essa verificação é feita calculando a distância entre a nova
  128.        posição e as posições dos círculos existentes. Se a distância for menor ou igual ao raio do círculo, significa que há sobreposição.
  129.  
  130.        Dentro de um loop for circle_index in range(self.circles_count), são inicializados os círculos um por um. Para cada círculo, é gerada
  131.        uma posição aleatória dentro dos limites da janela da simulação, garantindo que o círculo não fique muito próximo das bordas.
  132.        A função CUtils.GetRandomCoordinate() é usada para gerar uma posição aleatória dentro desses limites.
  133.  
  134.        Em seguida, é verificado se a posição gerada é única usando a função __IsPositionUnique(). Se a posição não for única
  135.        (ou seja, houver sobreposição), um novo conjunto de coordenadas é gerado até que uma posição única seja encontrada.
  136.  
  137.        Depois de uma posição única ser encontrada, um objeto de círculo é adicionado à lista self.circle_objects.
  138.        Esse objeto contém informações como posição, velocidade, cor e uma lista de círculos com os quais ele já colidiu.
  139.  
  140.        O loop continua até que todos os círculos sejam inicializados e adicionados à lista self.circle_objects.
  141.    """
  142.     def __InitializeCirclesObjects(self):
  143.         if self.IsCircleObjectsInitialized():
  144.             return
  145.  
  146.         """
  147.            A função __IsPositionUnique(new_circle_position) verifica se uma nova posição de círculo é única, ou seja, se não há
  148.            sobreposição com outros círculos já existentes.
  149.  
  150.            A função itera sobre cada objeto de círculo na lista self.circle_objects. Para cada círculo, calcula a distância entre a posição
  151.            do círculo existente e a nova posição do círculo utilizando o Teorema de Pitágoras. A fórmula utilizada é a distância euclidiana
  152.            entre dois pontos no plano:
  153.            distance = math.sqrt((circle['position'][0] - new_circle_position[0]) ** 2 + (circle['position'][1] - new_circle_position[1]) ** 2)
  154.  
  155.            Se a distância calculada for menor ou igual ao raio do círculo (self.circle_radius), significa que há uma sobreposição entre
  156.            os círculos e a função retorna False.
  157.  
  158.            Se a função percorrer todos os círculos existentes e não encontrar nenhuma sobreposição, ela retorna True, indicando que
  159.            a nova posição é única e não há sobreposição com outros círculos.
  160.  
  161.            Esta função é usada na inicialização dos objetos de círculo para garantir que cada novo círculo seja posicionado
  162.            em uma localização única, evitando colisões imediatas entre os círculos.
  163.        """
  164.         def __IsPositionUnique(new_circle_position):
  165.             for circle in self.circle_objects:
  166.                 distance = math.sqrt(
  167.                     (circle['position'][0] - new_circle_position[0]) ** 2 +
  168.                     (circle['position'][1] - new_circle_position[1]) ** 2
  169.                 )
  170.  
  171.                 if distance <= self.circle_radius:
  172.                     return False
  173.  
  174.             return True
  175.  
  176.         for circle_index in range(self.circles_count):
  177.             while True:
  178.                  positi
  179.                     self._BORDER_PX_LENGHT + self.circle_radius,
  180.                     self.window_width - self._BORDER_PX_LENGHT - self.circle_radius,
  181.  
  182.                     self._BORDER_PX_LENGHT + self.circle_radius,
  183.                     self.window_height - self._BORDER_PX_LENGHT - self.circle_radius
  184.                 )
  185.  
  186.                 if __IsPositionUnique(position):
  187.                     break
  188.            
  189.             self.circle_objects.append({
  190.                 'position' : position,
  191.                 'velocity' : [
  192.                     CUtils.GetRandomFloatNumber(1, self.circles_max_velocity),
  193.                     CUtils.GetRandomFloatNumber(1, self.circles_max_velocity)
  194.                 ],
  195.                 'color' : self._RED_COLOR if circle_index < int(self.circles_count * 0.1) else self._BLUE_COLOR,
  196.                 'collided_balls' : []
  197.             })
  198.    
  199.     def __RunSimulation(self):
  200.         # Verifica se o PyGame foi inicializado corretamente
  201.         if not self.IsPyGameInitialized():
  202.             return
  203.  
  204.         """
  205.            A função __CalculateDistance(pt1, pt2) é usada para calcular a distância entre dois
  206.            pontos no plano implementando a fórmula da distância euclidiana.
  207.  
  208.            As coordenadas dos pontos pt1 e pt2 são extraídas, representadas como (x1, y1) e (x2, y2) respectivamente.
  209.  
  210.            A diferença entre as coordenadas x (dx = pt1[0] - pt2[0]) e y (dy = pt1[1] - pt2[1]) é calculada.
  211.  
  212.            A linha return (dx ** 2 + dy ** 2) ** 0.5 calcula a distância euclidiana entre os pontos usando a fórmula
  213.            matemática d = sqrt(dx^2 + dy^2). O resultado é retornado como a distância entre os pontos pt1 e pt2.
  214.  
  215.            Esta função é utilizada em outros lugares do código para calcular a distância entre os centros dos
  216.            círculos e determinar se eles colidiram com base nessa distância.
  217.        """
  218.         def __CalculateDistance(pt1, pt2):
  219.             dx = pt1[0] - pt2[0]
  220.             dy = pt1[1] - pt2[1]
  221.  
  222.             return (dx ** 2 + dy ** 2) ** 0.5
  223.  
  224.         """
  225.            A função __CheckCollision(circle, other_circle) é responsável por verificar se dois círculos colidiram com base nas suas posições e raios.
  226.  
  227.            As variáveis (x1, y1) e (x2, y2) são extraídas das informações dos círculos circle e other_circle, representando suas posições.
  228.  
  229.            A função __CalculateDistance((x1, y1), (x2, y2)) é chamada para calcular a distância entre os centros dos dois círculos.
  230.            Essa função deve estar definida em algum lugar no código e não foi fornecida.
  231.  
  232.            A linha return __CalculateDistance((x1, y1), (x2, y2)) <= (2 * self.circle_radius) verifica se a distância entre os
  233.            centros dos círculos é menor ou igual à soma dos raios dos círculos. Se isso for verdadeiro, significa que os círculos
  234.            estão se sobrepondo e, portanto, ocorreu uma colisão.
  235.  
  236.            Em resumo, esta função verifica se dois círculos colidiram verificando se a distância entre os seus centros é menor
  237.            ou igual à soma de seus raios.
  238.        """
  239.         def __CheckCollision(circle, other_circle):
  240.             (x1, y1) = circle['position']
  241.             (x2, y2) = other_circle['position']
  242.            
  243.             return __CalculateDistance((x1, y1), (x2, y2)) <= (2 * self.circle_radius)          
  244.  
  245.         """
  246.            A função __CalculateNewVelocities(velocity1, velocity2, mass1=1, mass2=1) é responsável por
  247.            calcular as novas velocidades dos círculos após uma colisão.
  248.  
  249.            As variáveis multi1 e multi2 são calculadas para determinar as proporções das massas dos círculos na colisão.
  250.            Essas proporções são usadas para calcular a contribuição relativa de cada círculo na nova velocidade resultante.
  251.  
  252.            A linha delta_v2 = (multi1 * velocity1[0] - multi2 * velocity2[0], multi1 * velocity1[1] - multi2 * velocity2[1])
  253.            calcula a diferença nas velocidades nos eixos x e y entre os círculos, com base nas proporções das massas.
  254.            Essa diferença é o quanto a velocidade de cada círculo será alterada após a colisão.
  255.  
  256.            A linha delta_v1 = (multi2 * velocity2[0] - multi1 * velocity1[0], multi2 * velocity2[1] - multi1 * velocity1[1])
  257.            calcula a diferença nas velocidades nos eixos x e y, mas com a ordem dos círculos invertida.
  258.            Isso é necessário para atualizar corretamente as velocidades de ambos os círculos.
  259.  
  260.            A função retorna a soma das diferenças nas velocidades (delta_v1 + delta_v2), que são as novas velocidades
  261.            para cada círculo após a colisão.
  262.  
  263.            Em resumo, esta função utiliza as massas e as velocidades dos círculos envolvidos em uma colisão para
  264.            calcular as novas velocidades deles após a colisão.
  265.        """
  266.         def __CalculateNewVelocities(velocity1, velocity2, mass1 = 1, mass2 = 1):
  267.             multi1 = mass1 / (mass1 + mass2)
  268.             multi2 = mass2 / (mass1 + mass2)
  269.  
  270.             delta_v2 = (multi1 * velocity1[0] - multi2 * velocity2[0], multi1 * velocity1[1] - multi2 * velocity2[1])
  271.             delta_v1 = (multi2 * velocity2[0] - multi1 * velocity1[0], multi2 * velocity2[1] - multi1 * velocity1[1])
  272.  
  273.             return delta_v1 + delta_v2
  274.  
  275.         """
  276.            A função __UpdateCircles() é responsável por atualizar a posição dos círculos na simulação e lidar com as colisões entre eles.
  277.  
  278.            O primeiro loop for circle in self.circle_objects: itera sobre todos os círculos presentes em self.circle_objects e atualiza
  279.            as posições com base na sua velocidades. Ele também verifica se os círculos atingiram as bordas da janela da simulação e
  280.            inverte a direção da velocidade caso tenham atingido alguma das bordas.
  281.  
  282.            O segundo loop for circle in self.circle_objects: é usado para verificar as colisões entre os círculos.
  283.            Ele itera sobre todos os círculos presentes na lista self.circle_objects e verifica se houve uma colisão com qualquer outro círculo.
  284.  
  285.            Dentro do segundo loop, a função __CheckCollision(circle, other_circle) é chamada para verificar se ocorreu uma colisão
  286.            entre circle e other_circle. Se ocorrer uma colisão e other_circle não estiver na lista collided_balls de circle, as velocidades dos
  287.            círculos são atualizadas usando a função __CalculateNewVelocities((x_vel, y_vel), (other_x_vel, other_y_vel)). Os círculos também
  288.            são adicionados às listas collided_balls um do outro para evitar colisões repetidas.
  289.  
  290.            Se não houver uma colisão entre circle e other_circle, e circle estiver na lista collided_balls de other_circle, as listas
  291.            collided_balls são atualizadas para remover a referência ao outro círculo. Isso garante que a lista collided_balls
  292.            esteja sempre atualizada com as colisões atuais.
  293.  
  294.            Em resumo, esta função atualiza as posições dos círculos, trata colisões entre eles e atualiza as velocidades com base nas colisões ocorridas.
  295.        """
  296.         def __UpdateCircles():
  297.             for circle in self.circle_objects:
  298.                 (x, y) = circle['position']
  299.                 (x_vel, y_vel) = circle['velocity']
  300.  
  301.                 if (x + self.circle_radius <= (self.window_width - self._BORDER_PX_LENGHT)) and (x - self.circle_radius) >= self._BORDER_PX_LENGHT:
  302.                     x += x_vel
  303.                 else:
  304.                     x_vel *= -1
  305.                     x += x_vel
  306.                 if (y + self.circle_radius <= (self.window_height - self._BORDER_PX_LENGHT)) and (y - self.circle_radius) >= self._BORDER_PX_LENGHT:
  307.                     y += y_vel
  308.                 else:
  309.                     y_vel *= -1
  310.                     y += y_vel
  311.                
  312.                 circle['position'] = [x, y]
  313.                 circle['velocity'] = [x_vel, y_vel]
  314.  
  315.             for circle in self.circle_objects:
  316.                 for other_circle in self.circle_objects:
  317.                     exist_collision = __CheckCollision(circle, other_circle)
  318.  
  319.                     if other_circle not in circle['collided_balls'] and circle != other_circle and exist_collision:
  320.                         (x_vel, y_vel) = circle['velocity']
  321.                         (other_x_vel, other_y_vel) = other_circle['velocity']
  322.                        
  323.                         new_velocities = __CalculateNewVelocities((x_vel, y_vel), (other_x_vel, other_y_vel))
  324.  
  325.                         circle['velocity'] = [new_velocities[0], new_velocities[1]]
  326.                         circle['collided_balls'].append(other_circle)
  327.                         other_circle['velocity'] = [new_velocities[2], new_velocities[3]]
  328.                         other_circle['collided_balls'].append(circle)
  329.                     elif not exist_collision:
  330.                         if circle in other_circle['collided_balls']:
  331.                             other_circle['collided_balls'].remove(circle)
  332.                             circle['collided_balls'].remove(other_circle)
  333.        
  334.         """
  335.            A função __DrawWindow() é responsável por desenhar a janela da simulação com o fundo preenchido e as bordas retangulares.
  336.  
  337.            self.window_pygame.fill(self._BACKGROUND_COLOR): Preenche a janela da simulação com a cor de fundo definida em
  338.            _BACKGROUND_COLOR. Essa linha garante que a janela seja limpa e preenchida com a cor correta antes de
  339.            desenhar os retângulos das bordas.
  340.  
  341.            pygame.draw.rect(self.window_pygame, self._BORDER_COLOR, (0, 0, self.window_width, self._BORDER_PX_LENGHT)):
  342.            Desenha um retângulo na parte superior da janela da simulação. O retângulo tem a cor definida em _BORDER_COLOR e
  343.            as coordenadas (0, 0, self.window_width, self._BORDER_PX_LENGHT) especificam a posição e as dimensões do retângulo.
  344.            Nesse caso, o retângulo é desenhado na parte superior da janela com a largura da janela (self.window_width)
  345.            e a espessura das bordas (self._BORDER_PX_LENGHT).
  346.  
  347.            pygame.draw.rect(self.window_pygame, self._BORDER_COLOR, (0, self.window_height - self._BORDER_PX_LENGHT, self.window_width, self._BORDER_PX_LENGHT)):
  348.            Desenha um retângulo na parte inferior da janela da simulação. O retângulo tem a cor definida em _BORDER_COLOR e
  349.            as coordenadas (0, self.window_height - self._BORDER_PX_LENGHT, self.window_width, self._BORDER_PX_LENGHT) especificam
  350.            a posição e as dimensões do retângulo. Nesse caso, o retângulo é desenhado na parte inferior da janela com a largura
  351.            da janela (self.window_width) e a espessura das bordas (self._BORDER_PX_LENGHT).
  352.  
  353.            pygame.draw.rect(self.window_pygame, self._BORDER_COLOR, (0, 0, self._BORDER_PX_LENGHT, self.window_height)):
  354.            Desenha um retângulo na parte esquerda da janela da simulação. O retângulo tem a cor definida em _BORDER_COLOR e
  355.            as coordenadas (0, 0, self._BORDER_PX_LENGHT, self.window_height) especificam a posição e as dimensões do retângulo.
  356.            Nesse caso, o retângulo é desenhado na parte esquerda da janela com a altura da janela (self.window_height)
  357.            e a espessura das bordas (self._BORDER_PX_LENGHT).
  358.  
  359.            pygame.draw.rect(self.window_pygame, self._BORDER_COLOR, (self.window_width - self._BORDER_PX_LENGHT, 0, self._BORDER_PX_LENGHT, self.window_height)):
  360.            Desenha um retângulo na parte direita da janela da simulação. O retângulo tem a cor definida em _BORDER_COLOR e as coordenadas
  361.            (self.window_width - self._BORDER_PX_LENGHT, 0, self._BORDER_PX_LENGHT, self.window_height) especificam a posição e as
  362.            dimensões do retângulo. Nesse caso, o retângulo é desenhado na parte direita
  363.        """
  364.         def __DrawWindow():
  365.             self.window_pygame.fill(self._BACKGROUND_COLOR)
  366.            
  367.             pygame.draw.rect(self.window_pygame, self._BORDER_COLOR, (0, 0, self.window_width, self._BORDER_PX_LENGHT))
  368.             pygame.draw.rect(self.window_pygame, self._BORDER_COLOR, (0, self.window_height - self._BORDER_PX_LENGHT, self.window_width, self._BORDER_PX_LENGHT))
  369.             pygame.draw.rect(self.window_pygame, self._BORDER_COLOR, (0, 0, self._BORDER_PX_LENGHT, self.window_height))
  370.             pygame.draw.rect(self.window_pygame, self._BORDER_COLOR, (self.window_width - self._BORDER_PX_LENGHT, 0, self._BORDER_PX_LENGHT, self.window_height))
  371.  
  372.         """
  373.            A função __DrawCircles() é responsável por desenhar os círculos na janela da simulação. Ela percorre a lista de objetos
  374.            dos círculos (circle_objects) e desenha cada círculo utilizando a função pygame.draw.circle().
  375.  
  376.            Dentro do loop, para cada objeto de círculo, a função pygame.draw.circle() é chamada com os seguintes parâmetros:
  377.                self.window_pygame: A janela da simulação onde o círculo será desenhado.
  378.                
  379.                circle_information.get('color', self._WHITE_COLOR): A cor do círculo. É obtida a partir do dicionário circle_information,
  380.                onde o valor correspondente à chave 'color' é retornado. Se a chave 'color' não existir no dicionário,
  381.                o valor padrão self._WHITE_COLOR (branco) é utilizado.
  382.  
  383.                circle_information.get('position', (0, 0)): A posição do centro do círculo. É obtida do dicionário circle_information,
  384.                onde o valor correspondente à chave 'position' é retornado. Se a chave 'position' não existir no dicionário,
  385.                o valor padrão (0, 0) é utilizado.
  386.                
  387.                self.circle_radius: O raio do círculo.
  388.  
  389.            Desta forma, a função percorre todos os círculos e os desenha na janela da simulação com as cores e posições corretas.
  390.        """
  391.         def __DrawCircles():
  392.             for circle_information in self.circle_objects:
  393.                 pygame.draw.circle(
  394.                     self.window_pygame,
  395.                     circle_information.get('color', self._WHITE_COLOR),
  396.                     circle_information.get('position', (0, 0)),
  397.                     self.circle_radius
  398.                 )
  399.        
  400.         """
  401.            A função __Refresh() é responsável por atualizar a janela da simulação e adicionar um
  402.            pequeno atraso de 10 milissegundos antes de atualizar novamente.
  403.  
  404.            pygame.display.update() atualiza a janela da simulação, mostrando as alterações feitas nos objetos.
  405.            
  406.            pygame.time.delay(10) adiciona um atraso de 10 milissegundos, permitindo controlar a taxa de
  407.            atualização da janela. Isso evita que a janela seja atualizada muito rapidamente, tornando a
  408.            simulação mais suave e reduzindo o consumo de recursos do sistema.
  409.        """
  410.         def __Refresh():
  411.             pygame.display.update()
  412.             pygame.time.delay(10)
  413.  
  414.         while True:
  415.             """
  416.                O loop for event in pygame.event.get() captura todos os eventos que ocorrem na simulação.
  417.                Ele percorre a lista de eventos retornada pela função pygame.event.get().
  418.  
  419.                Para cada evento capturado, é verificado se o tipo de evento é pygame.QUIT, que indica que o usuário
  420.                solicitou o fecho da janela da simulação. Neste caso, as funções pygame.quit() e sys.exit() são chamadas
  421.                para encerrar a simulação corretamente.
  422.            """
  423.             for event in pygame.event.get():
  424.                 if event.type == pygame.QUIT:
  425.                     pygame.quit()
  426.                     sys.exit()
  427.            
  428.             # Atualiza a posição e velocidade dos círculos.
  429.             __UpdateCircles()
  430.  
  431.             # Desenha a janela da simulação, preenchendo o fundo com a cor de fundo definida e desenhando os retângulos que representam as bordas da janela.
  432.             __DrawWindow()
  433.  
  434.             # Desenhar os círculos na janela da simulação.
  435.             __DrawCircles()
  436.  
  437.             # Atualiza a exibição da janela da simulação, mostrando todas as alterações feitas nos passos anteriores.
  438.             __Refresh()
  439.    
  440.     ##################
  441.     #@ Public Methods
  442.     ##################
  443.  
  444.     def IsPyGameInitialized(self):
  445.         # Verifica se o Pygame foi inicializado
  446.         return self.window_pygame != None
  447.  
  448.     def IsCircleObjectsInitialized(self):
  449.         # Verifica se os objetos de circulo foram inicializados
  450.         return len(self.circle_objects) != 0
  451.  
  452.     def GetPyGameWindowWidth(self):
  453.         # Retorna a largura da janela do Pygame
  454.         return self.window_width
  455.  
  456.     def GetPyGameWindowHeight(self):
  457.         # Retorna a altura da janela do Pygame
  458.         return self.window_height
  459.  
  460. if __name__ == '__main__':
  461.     # Cria uma instância do gerenciador da simulação
  462.     collision_manager = CElasticCollision(
  463.         "Colisao Elastica", # Título da janela
  464.         800, # Largura da janela
  465.         600, # Altura da janela
  466.         15, # Raio do círculo
  467.         20, # Quantidade de círculos
  468.         5.0 # Velocidade inicial maxima dos círculos
  469.     )
  470.