Проблемы кругового столкновения PyGame - Интерьер круга - PullRequest
1 голос
/ 04 мая 2011

Я делаю игру-головоломку, которая требует, чтобы пользователь «рисовал» круги на заднем плане, чтобы получить мяч к выходу. Они создают круги, удерживая кнопку мыши, круг увеличивается; когда он достаточно велик, его отпускают, и он «пробивается» в физическое пространство, и шары реагируют на него.

У меня, однако, проблема в том, что когда два круга пересекаются (таким образом, шар должен пройти ), если пересечение не превышает диаметр шара, шар сталкивается с внутренней частью круг как обычно.

Это может быть немного трудно понять, поэтому вот ссылка на скринкаст, показывающий проблему (Вы не можете вставлять видео в переполнение стека): http://www.youtube.com/watch?v=3dKyPzqTDhs

Надеюсь, это прояснило мою проблему. Вот код Python / PyGame для классов Ball и Circle:

class Ball():
    def __init__(self, (x,y), size, colourID):
        """Setting up the new instance"""
        self.x = x
        self.y = y
        self.size = size
        self.exited = False
        self.colour = setColour(colourID)
        self.thickness = 0
        self.speed = 0.01
        self.angle = math.pi/2

    def display(self, surface):
        """Draw the ball"""
        # pygame.gfxdraw.aacircle(screen,cx,cy,new_dist,settings['MINIMAP_RINGS'])
        if self.exited != True:
            pygame.draw.circle(surface, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)

    def move(self):
        """Move the ball according to angle and speed"""
        self.x += math.sin(self.angle) * self.speed
        self.y -= math.cos(self.angle) * self.speed
        (self.angle, self.speed) = module_physicsEngine.addVectors((self.angle, self.speed), gravity)
        self.speed *= drag

И Circle класс:

class Circle():
    def __init__(self, (x,y), size, colourID):
        """Set up the new instance of the Circle class"""
        self.x = x
        self.y = y
        self.size = size
        self.colour = setColour(colourID)
        self.thickness = 2
        self.angle = 0 # Needed for collision...
        self.speed = 0 # detection against balls

    def display(self, surface):
        """Draw the circle"""
        pygame.draw.circle(surface, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)

В основном цикле игры (while running == True: и т. Д.) Этот код используется для выполнения действий над каждым мячом:

for b in balls:
    b.move()
    for i, ball in enumerate(balls):
        for ball2 in balls[i+1:]:
            collideBalls(ball, ball2)
        collideCircle(b) #      <---------------- This is the important line
        collideExit(b)
        b.display(screen)

И, наконец, функция collideCircle(b), которая вызывается один раз для каждого шара, чтобы проверить наличие столкновений с внутренней частью круга, а также проверить, пересекаются ли круги.

def collideCircle(ball):
    """Check for collision between a ball and a circle"""

    hit = False
    closestDist = 0

    for c in circles:
        # Code cannot be replaced with physicsEngine.collideTest because it
        # is slightly differnt, testing if ball [ball] inside a circle [c]
        dx = c.x - ball.x
        dy = c.y - ball.y
        distance = math.hypot(dx, dy)

        if distance <= c.size - ball.size:
            # If BALL inside any CIRCLE
            hit = False
            break
        else:
            # If we're outside of a circle.
            if closestDist < c.size - (distance - ball.size):
                hit = c
                closestDist = (c.size - (distance - ball.size))

    if hit:

        module_physicsEngine.circleBounce(hit, ball)

Хорошо, я знаю, что это был довольно долгий и разговорчивый вопрос, но я думаю, что у вас есть вся необходимая информация. Является ли решение для правильного взаимодействия шаров с линией if distance <= c.size - ball.size:?

В любом случае, спасибо заранее!

Натан вышел.

TL; DR - Посмотрите видео на YouTube и дайте мне знать, почему оно не работает.

Ответы [ 2 ]

1 голос
/ 04 мая 2011

Проблема с непреднамеренными попаданиями, а не пропущенными.Что вы действительно хотите проверить, так это то, что все части шара покрыты каким-либо кругом, в то время как проверка, которую вы делаете, заключается в том, если какой-либо круг перекрывает только частично - но переопределение, если какой-либо круг полностью покрывает шар.

Я рассчитываю на любую потенциальную точку попадания, то есть на ближайшую внутреннюю стенку круга, пусть эта точка «прогуливается» вдоль стены, проверяя ее расстояние от всех остальных кругов.Если он затем покинул мяч, это был ложный удар.

Сначала вы найдете список кругов, которые касаются мяча вообще.Как и раньше, если кто-то из них покрывает это, вы можете пропустить остальные проверки.Также найдите ближайшую точку стены к шару для кругов.Для каждой из этих ближайших точек стены, если она перекрывает другую окружность, переместите ее в точку пересечения, которая находится ближе всего к шару, но дальше, чем текущая точка.Откажитесь, если это вне шара.Повторите процедуру для всех кругов, так как более двух могут перекрываться.Также обратите внимание, что перемещение точки может привести к появлению новых кругов.

Вы можете заранее вычислить точки пересечения и отбросить любые точки, радиус которых находится внутри любого другого круга.

Это, безусловно, можно улучшить, но я думаю, это начало.Я подозреваю ошибку, связанную с тем, что обе точки пересечения пары окружностей перекрывают мяч, но прогулочная цепь выводит одну из них за пределы шара.Возможно, начальные точки столкновения следует заменить только обеими точками пересечения, а не ближайшими.

0 голосов
/ 04 мая 2011

Я смотрел видео, и мне нравится принцип игры. :)

Возможно, проблема в том, что вы break выходите из цикла, как только вы сталкиваетесь с кругом, который окружает мяч. Я имею в виду фрагмент

if distance <= c.size - ball.size:
    # If BALL inside any CIRCLE
    hit = False
    break

Почему бы вам не проверить все остальные круги, в этом случае? Может быть еще один не проверенный круг, который вызывает hit.

Кстати, я бы не сказал if condition == True:, это не пифонично. Просто скажите if condition:.

...