Circle collision, pop-up error "CreaCir' object has no attribute 'radio'"

Question:

I make a program where I generate circles of random size and position, by means of classes in python, I have managed to generate the circles as I wish but all collide with each other, so I have created a method so that this does not happen but it generates an error that I can not identify "’CreaCir’ object has no attribute ‘radio’", so I do not know what I’m doing wrong, the terminal tells me that the error is in the circle class in the collision method in the return, if someone could mark my error and give me advice to fix it I would appreciate it.

my code is as follows. first my circle class where I contain the collision method:

class Circulo(PosGeo):
    def __init__(self, x, y, r):
        self.x = x
        self.y = y
        self.radio = r
        self.cx = x+r
        self.cy = y+r

    def dibujar(self, ventana):
        pg.draw.circle(ventana, "white", (self.x, self.y), self.radio, 1)

    def update(self):
        pass

    def colisionC(self, c2):
        return self.radio + c2.radio > sqrt(pow(self.cx - c2.cx, 2) + pow(self.cy - c2.cy, 2))#where I get the error

now a part of my main code:

class CreaCir:
    def __init__(self, figs):
        self.i = 1
        
        self.r = randint(5, 104)
        self.x = randint(0, 500 + self.r)
        self.y = randint(0, 300 + self.r)
        self.creOne = Circulo(self.x, self.y, self.r) 
        self.figs.append(self.creOne)
        

    def update(self):
        if self.i <100:
            choca = False
            self.r = randint(5, 104)
            self.x = randint(0, 500 + self.r)
            self.y = randint(0, 300 + self.r) 
            self.creOne = Circulo(self.x, self.y, self.r)
            for  j in range (self.i):
                choca = self.creOne.colisionC(self.figs[j])#here is where I use the collision method to my object
                if choca == True:
                    break
            if choca == False:
                self.figs.append(self.creOne)
                self.i+=1

    def dibujar(self, ventana):
        pass

called:

class Ventana:
    def __init__(self, Ven_Tam= (700, 500)):
        
        pg.init()
        self.ven_tam = Ven_Tam

        self.ven = pg.display.set_caption("Linea")
        self.ven = pg.display.set_mode(self.ven_tam)
        self.ven.fill(pg.Color('#404040'))
        self.figs = []
        self.figs.append(CreaCir(self.figs))
        self.reloj = pg.time.Clock()
        
    def check_events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
                quit()
        pg.display.flip()

    def run(self):
        while True:
            self.check_events()

            for fig in self.figs:
                fig.update()

            for fig in self.figs:
                fig.dibujar(self.ven)

            self.reloj.tick(30)
                 

if __name__ == '__main__':
    ven = Ventana()
    ven.run()
Asked By: Moy

||

Answers:

The cause of the error is that you have put a CreaCir object in the figs list. So the first item in figs (self.creOne.colisionC(self.figs[j])) is a CreaCir object and this object has no radio.

Just remove that line of code, it is absolutely unnecessary.

self.figs.append(CreaCir(self.figs))

Create the CreaCir in run, but don’t put it in the list:

class Ventana:
    def __init__(self, Ven_Tam= (700, 500)):
        
        pg.init()
        self.ven_tam = Ven_Tam

        self.ven = pg.display.set_caption("Linea")
        self.ven = pg.display.set_mode(self.ven_tam)
        self.ven.fill(pg.Color('#404040'))
        self.figs = []
        self.reloj = pg.time.Clock()
        
    def check_events(self):
        # [...]

    def run(self):

        cirCreater = CreaCir(self.figs)
        while True:
            self.check_events()

            cirCreater.update()
            for fig in self.figs:
                fig.dibujar(self.ven)

            self.reloj.tick(30)

To detect the collision of 2 circles, you need to calculate the distance between the centers of the circles and check if the distance is greater than the sum of the radii of the circles. The 3rd argument of pygame.draw.circle is the center of the circle, but not the top left of the bounding box of the circle:

pg.draw.circle(ventana, "white", (self.x, self.y), self.radio, 1)

pg.draw.circle(ventana, "white", (self.cx, self.cy), self.radio, 1)

Complete example:

import pygame as pg
import math, random

class Circulo:
    def __init__(self, x, y, r):
        self.x, self.y = x, y
        self.radio = r
        self.cx, self.cy = x+r, y+r

    def dibujar(self, ventana):
        pg.draw.circle(ventana, "white", (self.cx, self.cy), self.radio, 1)

    def colisionC(self, c2):
        dx = self.cx - c2.cx
        dy = self.cy - c2.cy
        return self.radio + c2.radio > math.sqrt(dx*dx + dy*dy)

class CreaCir:
    def __init__(self, figs):
        self.figs = figs
        
    def update(self):
        if len(self.figs) < 100:
            choca = False
            r = random.randint(5, 104)
            x = random.randint(0, 700 - r*2)
            y = random.randint(0, 500 - r*2) 
            creOne = Circulo(x, y, r)
            for fig in self.figs:
                choca = creOne.colisionC(fig)
                if choca == True:
                    break
            if choca == False:
                self.figs.append(creOne)

class Ventana:
    def __init__(self, Ven_Tam= (700, 500)):
        
        pg.init()
        self.ven_tam = Ven_Tam

        self.ven = pg.display.set_caption("Linea")
        self.ven = pg.display.set_mode(self.ven_tam)
        self.figs = []
        self.reloj = pg.time.Clock()
        
    def check_events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
                quit()

    def run(self):

        cirCreater = CreaCir(self.figs)
        while True:
            self.check_events()
            cirCreater.update()

            self.ven.fill(pg.Color('#404040'))
            for fig in self.figs:
                fig.dibujar(self.ven)
            pg.display.flip()
            self.reloj.tick(30)
                 
if __name__ == '__main__':
    ven = Ventana()
    ven.run()
Answered By: Rabbid76
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.