I have a program that generates circles and lines, where the circles can not collide with each other and the lines can not collide with the circles, the problem is that it only draws a line but not the others, it does not mark any error and as much as I think the reason I do not understand why, (I'm new to python, so excuse me if maybe the error is obvious)
I tried to remove the for
from my CreaLin
class and it does generate the lines but they all collide with the circles, I also thought that the collisionL
function could be the problem since the method does not belong as such to the line class, but I need values from the circle class, so I don't know what would be another way to do it, I would like to know a method.
my code:
class CreaCir:
def __init__(self, figs):
self.figs = figs
def update(self):
if len(self.figs) <70:
choca = False
r = randint(5, 104)
x = randint(0, 600 r)
y = randint(0, 400 r)
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)
def dibujar(self, ventana):
pass
class CreaLin:
def __init__(self, lins):
self.lins = lins
def update(self):
if len(self.lins) <70:
choca = False
x = randint(0, 700)
y = randint(0, 500)
a = randint(0, 700)
b = randint(0, 500)
linOne = Linea(x, y, a, b)
for lin in (self.lins):
choca = linOne.colisionL(lin)
if choca == True:
break
if choca == False:
self.lins.append(linOne)
def dibujar(self, ventana):
pass
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.lins = []
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):
cirCreater = CreaCir(self.figs)
linCreater = CreaLin(self.lins)
while True:
self.check_events()
cirCreater.update()
linCreater.update()
for fig in self.figs:
fig.dibujar(self.ven)
for lin in self.lins:
lin.dibujar(self.ven)
self.reloj.tick(60)
if __name__ == '__main__':
ven = Ventana()
ven.run()
class Circulo:
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 __str__(self):
return f"Circulo, (X: {self.x}, Y: {self.y}), radio: {self.radio}"
def dibujar(self, ventana):
pg.draw.circle(ventana, "white", (self.cx, self.cy), self.radio, 1)
pg.draw.line(ventana, "white", (self.cx 2, self.cy 2),(self.cx-2, self.cy-2))
pg.draw.line(ventana, "white", (self.cx-2, self.cy 2),(self.cx 2, self.cy-2))
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))
def colisionL(self, L2):
l0 = [L2.x, L2.y]
l1 = [L2.a, L2.b]
cp = [self.cx, self.cy]
x1 = l0[0] - cp[0]
y1 = l0[1] - cp[1]
x2 = l1[0] - cp[0]
y2 = l1[1] - cp[1]
dx = x2 - x1
dy = y2 - y1
dr = sqrt(dx*dx dy*dy)
D = x1 * y2 - x2 * y1
discriminant = self.radio*self.radio*dr*dr - D*D
if discriminant < 0:
return False
else:
return True`
and finally my class line:
class Linea(PosGeo):
def __init__(self, x, y, a, b):
super().__init__(x, y)
self.x = x
self.y = y
self.a = a
self.b = b
def dibujar(self, ventana):
pg.draw.line(ventana, "#7B0000", (self.x, self.y), (self.a, self.b))
def update(self):
pass
def colisionL(self, l1):
pass
CodePudding user response:
You need to implement the colisionC
and colisionL
methods in Linea
and Circulo
. See
import pygame as pg
from random import randint
from math import sqrt, hypot
class Linea:
def __init__(self, x, y, a, b):
self.x = x
self.y = y
self.a = a
self.b = b
def dibujar(self, ventana):
pg.draw.line(ventana, "#7B0000", (self.x, self.y), (self.a, self.b))
def update(self):
pass
def colisionC(self, c2):
return c2.colisionL(self)
def colisionL(self, l1):
return Linea.intersect_line_line((self.x, self.y), (self.a, self.b), (l1.x, l1.y), (l1.a, l1.b))
def intersect_line_line(P0, P1, Q0, Q1):
d = (P1[0]-P0[0]) * (Q1[1]-Q0[1]) (P1[1]-P0[1]) * (Q0[0]-Q1[0])
if d == 0:
return None
t = ((Q0[0]-P0[0]) * (Q1[1]-Q0[1]) (Q0[1]-P0[1]) * (Q0[0]-Q1[0])) / d
u = ((Q0[0]-P0[0]) * (P1[1]-P0[1]) (Q0[1]-P0[1]) * (P0[0]-P1[0])) / d
if 0 <= t <= 1 and 0 <= u <= 1:
return P1[0] * t P0[0] * (1-t), P1[1] * t P0[1] * (1-t)
return None
class Circulo:
def __init__(self, x, y, r):
self.x = x
self.y = y
self.radio = r
self.cx = x r
self.cy = y r
def __str__(self):
return f"Circulo, (X: {self.x}, Y: {self.y}), radio: {self.radio}"
def dibujar(self, ventana):
pg.draw.circle(ventana, "white", (self.cx, self.cy), self.radio, 1)
pg.draw.line(ventana, "white", (self.cx 2, self.cy 2),(self.cx-2, self.cy-2))
pg.draw.line(ventana, "white", (self.cx-2, self.cy 2),(self.cx 2, self.cy-2))
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))
def colisionL(self, L2):
l0 = [L2.x, L2.y]
l1 = [L2.a, L2.b]
cp = [self.cx, self.cy]
x1 = l0[0] - cp[0]
y1 = l0[1] - cp[1]
x2 = l1[0] - cp[0]
y2 = l1[1] - cp[1]
if sqrt(x1*x1 y1*y1) < self.radio or sqrt(x2*x2 y2*y2) < self.radio:
return True
dx = x2 - x1
dy = y2 - y1
dr = sqrt(dx*dx dy*dy)
D = x1 * y2 - x2 * y1
discriminant = self.radio*self.radio*dr*dr - D*D
if discriminant < 0:
return False
sign = lambda x: -1 if x < 0 else 1
xa = (D * dy sign(dy) * dx * sqrt(discriminant)) / (dr * dr)
xb = (D * dy - sign(dy) * dx * sqrt(discriminant)) / (dr * dr)
ya = (-D * dx abs(dy) * sqrt(discriminant)) / (dr * dr)
yb = (-D * dx - abs(dy) * sqrt(discriminant)) / (dr * dr)
ta = (xa-x1)*dx/dr (ya-y1)*dy/dr
tb = (xb-x1)*dx/dr (yb-y1)*dy/dr
return 0 < ta < dr or 0 < tb < dr
class CreaObjects:
def __init__(self, figs):
self.figs = figs
self.no_lines = 0
self.no_circles = 0
def update(self):
if self.no_circles <70:
r = randint(5, 104)
creOne = Circulo(randint(0, 600 - 2*r), randint(0, 400 - 2*r), r)
if not any(fig.colisionC(creOne) for fig in self.figs):
self.figs.append(creOne)
self.no_circles = 1
if self.no_lines <70:
linOne = Linea(randint(0, 700), randint(0, 500), randint(0, 700), randint(0, 500))
if not any(fig.colisionL(linOne) for fig in self.figs):
self.figs.append(linOne)
self.no_lines = 1
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 = CreaObjects(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(60)
if __name__ == '__main__':
ven = Ventana()
ven.run()