Iwan. J Iwan. J - 25 days ago 10
Python Question

Pygame how to change image collision points

I'm trying to make a matching card game in Pygame and I can render all 52 of my cards in the correct positions but the rects of the images will not change.

I create all my card surfaces using the following method;

def generateGrid():
cardB = pygame.image.load(os.path.join('data', 'back.png'))
for i in range(index):
grid.append(cardB)
grid[i] = pygame.transform.scale(cardB, (85,130))


and I render my cards by calling the following in the main method;

generateGrid()
pos = 25

for i in range(index):
print(pos)
if i >0 and i< 14:
r1 = grid[i].get_rect()
r1.move_ip(pos,50)
pos +=95
background.blit(grid[i], r1)
pygame.display.update()
elif i >0 and i<27:
r2 = grid[i].get_rect()
pos -=95
r2.move_ip(pos,195)
background.blit(grid[i], r2)
pygame.display.update()
elif i >0 and i <40:
r3 = grid[i].get_rect()
r3.move_ip(pos,350)
pos +=95

background.blit(grid[i],r3)
pygame.display.update()
elif i >0 and i< 53:
r4 = grid[i].get_rect()
pos -=95
r4.move_ip(pos,500)
background.blit(grid[i],r4)
pygame.display.update()
print("Card", i+1, "rendered")


Finally in my main loop I try to find which card the mouse is hovering over by doing:

for i in range(index):
if grid[i].get_rect().collidepoint(pygame.mouse.get_pos()):
print("Colling with:", i)
else:
pass


My problem is that all the surfaces have the same collision rects:
<rect(0, 0, 85, 130)>
. How can can I change this to match the co-ords of each card?

Answer

The problem is because the rectangles associated with images in grid don't reflect where the code that renders the cards places them. This can be corrected by creating a parallel list of rectangles which contains this information for each one of them. If this additional list was named cardPosn, here's how it could be created:

pos = 25
cardPosn = [None] * len(grid)  # preallocate
for i in range(index):
    print(pos)
    if 0 < i < 14:
        r1 = grid[i].get_rect()
        r1.move_ip(pos, 50)
        pos += 95
        background.blit(grid[i], r1)
        cardPosn[i] = r1
        pygame.display.update()
    elif 0 < i < 27:
        r2 = grid[i].get_rect()
        pos -= 95
        r2.move_ip(pos, 195)
        background.blit(grid[i], r2)
        cardPosn[i] = r2
        pygame.display.update()
    elif 0 < i < 40:
        r3 = grid[i].get_rect()
        r3.move_ip(pos, 350)
        pos += 95
        background.blit(grid[i], r3)
        cardPosn[i] = r3
        pygame.display.update()
    elif 0 < i < 53:
        r4 = grid[i].get_rect()
        pos -= 95
        r4.move_ip(pos, 500)
        background.blit(grid[i], r4)
        cardPosn[i] = r4
        pygame.display.update()
    print("Card", i+1, "rendered")

Once that's done, a loop for checking for collision points could be written like this:

mouse_pos = pygame.mouse.get_pos()
for i in range(index):
    if cardPosn[i] and cardPosn[i].collidepoint(mouse_pos):
        print("Colliding with:", i)