3
\$\begingroup\$

This is my first ever try at making reusable code. The function makes use of two images to give the illusion of turning on and turning off a button in pygame.

I would like to know what would you do differently and if I did a good job? Thanks everyone.

Also, this is assuming you already loaded your images and gave it a name using pygame.image.load() function in pygame.

"""
    The function `mouse_on_button() takes all the arguments needed 
to produce a light-able button. For example, you have an image 
of a thumbs up in grey and another image of a thumbs up in bright red and stack the on top of each other. 
They are called by clicking the position of the image. By clicking they dark image will get transformed into the lit up image and vice-versa.

thumbs_up_img = pygame.image.load('thumbsup.png')
thumbs_up_lit_up_img = pygame.image.load('thumbsupred.png')

thumbs_up = Buttons(60, 240, 50, 50) # X, Y, Width, Height

mouse_on_button(pygame, screen, thumbs_up_img, thumbs_up_lit_up_img,thumbs_up.btn_x, thumbs_up.btn_y, thumbs_up.width, thumbs_up.height, SCREEN_HEIGHT, SCREEN_WIDTH)
"""




class Buttons:

    """
    This class takes the x-position and the y-position, width and height of an image.
    """
    def __init__(self, btn_x, btn_y, width, height):

        self.btn_x = btn_x
        self.btn_y = btn_y
        self.width = width
        self.height = height

def mouse_on_button(pygame, screen, off_btn, on_btn, btn_x, btn_y, width, height, SCREEN_HEIGHT, SCREEN_WIDTH):
    """
    This function takes a dark image and a bright image to give the illusion of turning on a button.
    """

    # Get mouse position.
    mouse = pygame.mouse.get_pos()

    # Setting up the boundries to light up or turn off around the button.
    if (mouse[0] >= btn_x and mouse[0] <=  btn_x + width) and (mouse[1] >= btn_y and mouse[1] <= btn_y + height):
        # This will return the ON value of an image in the screen.
        return screen.blit(on_btn,(btn_x, btn_y, SCREEN_HEIGHT, SCREEN_WIDTH))
    else:
        # This will return the OFF value of an image in the screen.
        return screen.blit(off_btn,(btn_x, btn_y, SCREEN_HEIGHT, SCREEN_WIDTH))
\$\endgroup\$
4
  • \$\begingroup\$ please post some context, usages/calling your mouse_on_button function \$\endgroup\$ Commented Oct 16, 2019 at 18:33
  • \$\begingroup\$ Added a comment describing the func through an example. \$\endgroup\$ Commented Oct 16, 2019 at 20:03
  • \$\begingroup\$ Are DISPLAY_HEIGHT and DISPLAY_WIDTH global constant values? \$\endgroup\$ Commented Oct 16, 2019 at 20:38
  • \$\begingroup\$ Yes, they describe the window size of the program. For example, 600px x 600px without the PX of course. I will take notes about all the missing info so it won't happen again. Edit: I should've said screen size for better readability. I will change it. \$\endgroup\$ Commented Oct 16, 2019 at 21:06

1 Answer 1

1
\$\begingroup\$

I think your button class should do more. It should know if a point is within it's boundaries or not and what its image(s) is (are). It should probably also have an update method that can optionally be called with the mouse position. I would also rename it to singular Button, since each instance of the class is a single button and not a collection of buttons.

class Button:
    """
    This class takes the x-position and the y-position, width and height of an image.
    """
    def __init__(self, x, y, width, height, image, hover_image=None):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.image = on_image
        self.hover_image = hover_image

def point_inside(self, pos=None):
    if pos is None:
        return False
    return (self.x <= pos[0] <=  self.x + self.width \
            and self.y <= pos[1] <= self.y + self.height)

def update(self, screen, mouse_pos=None):
    if self.hover_image is not None and self.point_inside(mouse_pos):
        screen.blit(self.hover_image, (self.x, self.y, SCREEN_HEIGHT, SCREEN_WIDTH))
    else:
        screen.blit(self.image, (self.x, self.y, SCREEN_HEIGHT, SCREEN_WIDTH))


if __name__ == "__main__":
    thumbs_up_img = pygame.image.load('thumbsup.png')
    thumbs_up_lit_up_img = pygame.image.load('thumbsupred.png')
    thumbs_up = Button(60, 240, 50, 50, thumbs_up_img, thumbs_up_lit_up_img)

    # some pygame setup
    ...

    while True:
        mouse = pygame.mouse.get_pos()
        button.update(screen, mouse)
        pygame.display.flip()

This is a bit more generic, in that it allows a button not to have a hover image and it has an update method, which is quite common for objects in pygame. You could think about off-loading the point in button boundary check to a Rectangle class, which might help since you will probably encounter rectangles and checking if a point is inside quite often in pygame.

And would you look at that, there is already pygame.Rect, from which you could inherit. It even has the pygame.Rect.collidepoint method to check if a point is inside it.

class Button(pygame.Rect):
    """
    This class takes the x-position and the y-position, width and height of an image.
    """
    def __init__(self, x, y, width, height, image, hover_image=None):
        super().__init__(x, y, width, height)
        self.image = on_image
        self.hover_image = hover_image

def update(self, screen, mouse_pos=None):
    if self.hover_image is not None \
       and mouse_pos is not None \
       and self.collidepoint(mouse_pos):
        screen.blit(self.hover_image, (self.x, self.y, SCREEN_HEIGHT, SCREEN_WIDTH))
    else:
        screen.blit(self.image, (self.x, self.y, SCREEN_HEIGHT, SCREEN_WIDTH))
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.