Search code examples
pythonpython-3.xpygameparticles

"Particle Object Not Defined" Error Message


I am currently trying to write a program that creates 20 random dots on the screen and times how long it takes you to click them in succession (they shouldn't appear all at once). Clearly, my code isn't finished but I keep getting an error message saying that "Particle object isn't iterable." Could anyone help me out? Thanks! (I know my particle list is a bit ridiculous too, but what can you do? :-))

import pygame
import random
import math
import sys

background_colour = (255,255,255)
(width, height) = 600,500

screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('DBS Test')

circle1 = (pygame.draw.circle(screen, (255, 255, 255), (300, 250), 25, 25))


def addVectors(angle1, length1, angle2, length2):
    x  = math.sin(angle1) * length1 + math.sin(angle2) * length2
    y  = math.cos(angle1) * length1 + math.cos(angle2) * length2

    angle = 0.5 * math.pi - math.atan2(y, x)
    length  = math.hypot(x, y)

    return (angle, length)

def findParticle(particles, x, y):
    for p in particles:
        if math.hypot(p.x-x, p.y-y) <= p.size:
            return p
    return None

class Particle:
    def __init__(self, position, size):
        self.x, self.y = position
        self.size = size
        self.colour = (255, 0, 0)
        self.thickness = 20
    def display(self):
        pygame.draw.circle(screen, self.colour, (self.x, self.y), self.size, self.thickness)

particle_one = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_two = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_three = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_four = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_five = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_six = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_seven = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_eight = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_nine = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_ten = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_eleven = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_twelve = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_thirteen = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_fourteen = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_fifteen = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_sixteen = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_seventeen = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_eighteen = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_nineteen = Particle((random.randint(0,600), random.randint(0,500)), 20)
particle_twenty = Particle((random.randint(0,600), random.randint(0,500)), 20)

particle_one.display()

selected_particle = None
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            (mouseX, mouseY) = pygame.mouse.get_pos()
            selected_particle = findParticle(particle_one, mouseX, mouseY)
        elif event.type == pygame.MOUSEBUTTONUP:
            selected_particle = None

    if selected_particle:
        (mouseX, mouseY) = pygame.mouse.get_pos()
        dx = mouseX - selected_particle.x
        dy = mouseY - selected_particle.y
        particle_two.display()


pygame.display.flip()


def main():
pass

if __name__ == '__main__':
main()

Solution

  • The problem is that you pass a single particle instance, but the findParticle function expects an iterable (for example a list). You can create a list of particles when the program starts and then pass this list to the function.

    import pygame
    import random
    import math
    
    
    pygame.init()  # Initialize all pygame modules.
    background_colour = (255,255,255)
    screen = pygame.display.set_mode((600, 500))
    clock = pygame.time.Clock()
    
    
    def findParticle(particles, x, y):
        for p in particles:
            if math.hypot(p.x-x, p.y-y) <= p.size:
                return p
        return None
    
    
    class Particle:
    
        def __init__(self, position, size):
            self.x, self.y = position
            self.size = size
            self.colour = (255, 0, 0)
    
        def display(self):
            pygame.draw.circle(screen, self.colour, (self.x, self.y), self.size)
    
    
    # Create a list for the particles.
    particles = []
    for _ in range(20):
        particle = Particle((random.randint(0,600), random.randint(0,500)), 20)
        particles.append(particle)  # Append the new particle.
    
    # Or use a list comprehension:
    # particles = [Particle((random.randint(0,600), random.randint(0,500)), 20) for _ in range(20)]
    
    selected_particle = None
    running = True
    
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                (mouseX, mouseY) = pygame.mouse.get_pos()
                # Now pass the particles list instead of a single particle.
                selected_particle = findParticle(particles, mouseX, mouseY)
            elif event.type == pygame.MOUSEBUTTONUP:
                selected_particle = None
    
        if selected_particle:
            # Set the x and y-position of the particle at the same time.
            selected_particle.x, selected_particle.y = pygame.mouse.get_pos()
    
        # Clear the screen, then draw the particles.
        screen.fill(background_colour)
        for particle in particles:
            particle.display()
    
        pygame.display.flip()
        clock.tick(30)  # Limits the frame rate to 30 fps.
    
    pygame.quit()