0
votes

From the code below, I am trying to detect the collision between the horizontal and vertical line classes. However I have no idea how to go about adding this functionality. I typically have the issue that no rectangle attribute is found. I just need some advice on what to add to detect the locations of the collisions. Thanks.

import pygame as pg
import pygame.gfxdraw
import math

pg.init()
windowWidth = 800
windowHeight = 800
surface = pg.display.set_mode((windowWidth, windowHeight))
pg.display.set_caption("Circle")
clock = pg.time.Clock()
black = (0, 0, 0)
white = (255, 255, 255)
gray = (50, 50, 50, 150)
red = (255, 0, 0)


class VerticalCircle(object):
    def __init__(self, posX, posY):
        self.circle_position_x = posX
        self.circle_position_y = posY
        self.radius = 38
        self.v_theta = 0
        self.x = int((self.circle_position_x + (self.radius * math.cos(-self.v_theta))))
        self.y = int((self.circle_position_y + (self.radius * math.sin(-self.v_theta))))

    def draw(self, surface):
        self.x = int((self.circle_position_x + (self.radius * math.cos(-self.v_theta))))
        self.y = int((self.circle_position_y + (self.radius * math.sin(-self.v_theta))))
        pygame.gfxdraw.aacircle(surface, self.circle_position_x, self.circle_position_y, self.radius, white)
        pygame.gfxdraw.filled_circle(surface, self.x, self.y, 2, white)

    def method_circle(self):
        return self.x, self.y


class HorizontalCircle(object):
    def __init__(self, posX, posY):
        self.circle_position_x = posX
        self.circle_position_y = posY
        self.radius = 38
        self.h_theta = 0
        self.x = int((self.circle_position_x + (self.radius * math.cos(self.h_theta))))
        self.y = int((self.circle_position_y + (self.radius * math.sin(self.h_theta))))

    def draw(self, surface):
        self.x = int((self.circle_position_x + (self.radius * math.cos(self.h_theta))))
        self.y = int((self.circle_position_y + (self.radius * math.sin(self.h_theta))))
        pygame.gfxdraw.aacircle(surface, self.circle_position_x, self.circle_position_y, self.radius, white)
        pygame.gfxdraw.filled_circle(surface, self.x, self.y, 2, white)

    def method_circle(self):
        return self.x, self.y


class VerticalLine(HorizontalCircle):
    def __init__(self, Target_Circle):
        self.rect = pg.draw.rect(surface, gray, (Target_Circle.x, 0, 1, 800))
        self.mask = pg.mask.from_surface(surface)

    def draw(self, surface, Target_Circle):
        self.rect = pg.draw.rect(surface, gray, (Target_Circle.x, 0, 1, 800))
        self.mask = pg.mask.from_surface(surface)


class HorizontalLine(VerticalCircle):
    def __init__(self, Target_Circle):
        self.rect = pg.draw.rect(surface, gray, (0, Target_Circle.y, 800, 1))
        self.mask = pg.mask.from_surface(surface)


    def draw(self, surface, Target_Circle):
        self.rect = pg.draw.rect(surface, gray, (0, Target_Circle.y, 800, 1))
        self.mask = pg.mask.from_surface(surface)


h_circle_list = []
v_circle_list = []

h_rect_list = []
v_rect_list = []
x = 120
for i in range(1, 10):
    v_circle = VerticalCircle(40, x)
    v_circle_list.append(v_circle)
    v_circle.draw(surface)

    h_line = HorizontalLine(v_circle)
    h_rect_list.append(h_line)
    h_line.draw(surface, v_circle)

    h_circle = HorizontalCircle(x, 40)
    h_circle_list.append(h_circle)
    h_circle.draw(surface)

    v_line = VerticalLine(h_circle)
    v_rect_list.append(v_line)
    v_line.draw(surface, h_circle)

    x += 80  # offset to place circles

pg.display.update()
loop = 0

run = True
while run:

    clock.tick(160)
    for event in pg.event.get():
        if event.type == pg.QUIT:
            run = False

    if loop == len(h_circle_list):
        loop = 0

    surface.fill(0)
    for i in range(int(len(h_circle_list))):
        h_rect_list[i].draw(surface, v_circle_list[i])
        v_rect_list[i].draw(surface, h_circle_list[i])
        print(pg.sprite.collide_mask(h_rect_list[i], v_rect_list[i]))

        h_circle_list[i].h_theta += .004 + i / 1000
        h_circle_list[i].draw(surface)
        v_circle_list[i].v_theta += .008 + i / 1000
        v_circle_list[i].draw(surface)

    pg.display.update()
    loop += 1

pg.quit()
2
I would suggest reading a little first, maybe try googling rectangle collision detection. You might want to think about the problem first and try what you come up with. Grab some paper and draw some rectangles in different configurations, when do you think they intersect? What do you know about them and what do you need to know? Here's a link that might help. - Nathan Wride
You mean other than pygame.Rect.colliderect() ? Ref: web.archive.org/web/20200203044423/https://www.pygame.org/docs/… - Kingsley

2 Answers

1
votes

You could basically make a rect object like this:

surface1 = pygame.image.load('smth.png')
surface2 = pygame.image.load('smth2.png')
surface1Rect = surface.get_rect(topleft = x, y)
surface2Rect = surface.get_rect(topleft = x2, y2)

Then return boolean whether it's True or not

def Collision():
    return surface1Rect.colliderect(surface2Rect)

And do something if it's True

if Collision():
    print('Do something.')


0
votes

The comment above by Nathan held the answer.. in the end I didn't need to detect a collision at all. I already had the locations of the collisions within the classes. All I needed to do from there was draw at the proper locations.