Gerald Leese
Gerald Leese

Reputation: 415

checking for mouse collison pygame.draw.circle()

I'm making a CheckButton Widget to be able to use in game menus. Wondering how I might be able to check if the mouse is colliding with the circle? Using the self.surface.get_rect() method doesn't seem to work. is there a way to calculate where the circle is based on its location in its surface object? I was just going to just draw a smaller black circle inside the circle when self.active == True then back to its default color if its False. should I be using Sprites for this?

class CheckButton():

"""add label?"""

def __init__(self, screen, pos,size=(10,10),color=GREY):

    self.screen = screen
    self.pos = pos
    self.size = size
    self.color = color

    self.active = False

    self.surface = pygame.surface.Surface(self.size)
    self.rect = self.surface.get_rect()
    self.center = (5,5)

def check_for_click(self):

    pos = pygame.mouse.get_pos()
    mouseClicked = pygame.mouse.get_pressed()
    if self.rect.collidepoint(pos) and mouseClicked == (1,0,0):
        self.active = True
        print(self.active)





def draw(self):

    self.surface.fill(BG_COLOR)
    pygame.draw.circle(self.surface,self.color, self.center,5, 0)
    self.screen.blit(self.surface, self.pos)

Upvotes: 1

Views: 376

Answers (1)

sloth
sloth

Reputation: 101052

When using pygame, don't give your objects attributes like pos or center (if you don't have to for whatever reasons). Just use the pygame's Sprite and Rect classes, which will handle all these things for you.

Here's a running example. Note the comments for further explanations:

import pygame
from math import hypot

pygame.init()
screen = pygame.display.set_mode((400, 400))

BG_COLOR=(55,0,200)

# note that pygame comes with a lot of colors already defined in THECOLORS
GREY=pygame.color.THECOLORS['grey']

# pygame's Group is great for sprite handling, but it does not offer a function for event handling
# so we create our own simple Group
class EventAwareGroup(pygame.sprite.Group):

    def handle(self, event):
        for spr in self.sprites():
            if hasattr(spr, 'handle'):
               spr.handle(event)

class CheckButton(pygame.sprite.Sprite):

    def __init__(self, pos, size=(10,10), color=(255,100,200)):
        super().__init__()
        self.image = pygame.surface.Surface(size)

        # we use a random color as colorkey, which means this color acts
        # as a substitute for 'transparent'; so we don't have to care about the
        # actual background
        self.image.set_colorkey((99,32,127))
        self.image.fill((99,32,127))

        self.rect = self.image.get_rect()

        # our image is a simple circle
        # note how we can use the attributes of Rect to easily find the center of our Surface
        pygame.draw.circle(self.image, color, self.rect.center, size[0]//2, 0)

        # when the checkbox is active, we want to show another image, so let's create it here
        # we want to do the drawing once, so we do it in the __init__ function
        self.toggle_image = self.image.copy()
        pygame.draw.circle(self.toggle_image, (0, 0, 0), self.rect.center, size[0]//3, 0)

        # now let's position our checkbox at 'pos'
        self.rect.center = pos
        self.active = False

    def handle(self, event):
        # since we want to toggle the active state of the checkbox when a mouse click occurs,
        # it's better to listen for the MOUSEBUTTONDOWN event
        if event.type == pygame.MOUSEBUTTONDOWN:
            # to check if the mouse click was actually in the circle, we simple calculate the distance
            d = hypot(event.pos[0] - self.rect.center[0], event.pos[1] - self.rect.center[1])
            if d <= self.rect.width/2 and event.button == 1:
                # now let's toggle the active flag and the images
                self.active = not self.active
                self.image, self.toggle_image = self.toggle_image, self.image

c = CheckButton([150, 100], [100, 100])
g = EventAwareGroup(c)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        g.handle(event)

    # note how simple and clean our main loop is
    # when we need other sprites, just add them to the g Group
    # no need to change the main loop for that
    screen.fill(BG_COLOR)
    g.update()
    g.draw(screen)

    pygame.display.update()

Upvotes: 2

Related Questions