首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >弹道增宽

弹道增宽
EN

Stack Overflow用户
提问于 2022-11-28 04:27:01
回答 1查看 35关注 0票数 1

我有一个生成圆和线的程序,在这个程序中,圆不能相互碰撞,线不能与圆圈发生碰撞,问题是它只画了一条线,而不是其他的,它没有标记任何错误,正如我认为我不明白原因一样(我对python不熟悉,所以请原谅,如果错误很明显的话)

我尝试将for从我的CreaLin类中删除,它确实生成了行,但它们都与圆圈发生了碰撞,我还认为collisionL函数可能是问题,因为方法本身并不属于line类,但是我需要循环类的值,所以我不知道另一种方法是什么,我想知道一种方法。

我的代码:

代码语言:javascript
复制
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()

巡回班:

代码语言:javascript
复制
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`

最后我的课文是:

代码语言:javascript
复制
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

结果:

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-28 16:58:07

您需要在colisionCCirculo中实现LineaCirculo方法。关于直线相交算法,请参见Problem with calculating line intersections。在检查线条和圆圈之间的冲突时,除了检查圆圈和无止境线之间的冲突外,还必须考虑线段的开始和结束:

代码语言:javascript
复制
class Linea:
    # [...]

    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
代码语言:javascript
复制
class Circulo
    # [...]

    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

将所有对象放入一个容器中。在添加新的Linea之前,您必须检查新的“行”是否与另一个对象与"ColisionL“相交。在添加新Circulo之前,必须检查新“行”是否将另一个对象与CollisionC相交。

代码语言:javascript
复制
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 

完整的例子:

代码语言:javascript
复制
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()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74595968

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档