2

So i am making this whack a mole game. I am able to make mole appear in random locations in the game however i cant understand how to award the player a point when he clicks on the mole. As the mole appears randomly it is possible that it appears on the same location twice. How would i stop this from happening. Here is the code:

import pygame
from pygame.locals import MOUSEBUTTONDOWN
import random
import time

pygame.init()

# constants
width = 300
height = 300
z = 2
Radius = 21

# loading mole image
mole_image = pygame.image.load("mole image2.png")
modified_image = pygame.transform.scale(mole_image, (40, 40))

# burrow and mole positions
burrow_x = -50
burrow_y = 50
count = int(0)
burrow_positions_list = []
mole_positions_list = []
while count != 9:
    count += 1
    burrow_x += 100
    if burrow_x == 350:
        burrow_x -= 300
        burrow_y += 100
    tuple1 = (burrow_x, burrow_y)
    tuple2 = (burrow_x - 20, burrow_y - 20)
    burrow_positions_list.append(tuple1)
    mole_positions_list.append(tuple2)

# colours
white = (255, 255, 255)
blue = (0, 0, 255)
black = (0, 0, 0)

# setting up the display
display = pygame.display.set_mode((width, height))
pygame.display.set_caption("Whack A Mole")


# creating burrows for the moles
def Burrows():
    circle_count = int(-1)
    while circle_count != len(burrow_positions_list) - 1:
        circle_count += 1
        pygame.draw.circle(display, black, burrow_positions_list[circle_count], 30)


def Moles():
    display.blit(modified_image, random.choice(mole_positions_list))
    time.sleep(z)


# running pygame until quit
run = True
while run:
    # speeding up mole blitting
    z -= 0.05
    if z < 0.4:
        z += 0.05
    display.fill(white)
    Burrows()
    Moles()
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == MOUSEBUTTONDOWN:
            pos = pygame.mouse.get_pos()


pygame.quit()

  • 1
    Does this answer your question? [how to detect if the sprite has been clicked in pygame](https://stackoverflow.com/questions/6356840/how-to-detect-if-the-sprite-has-been-clicked-in-pygame) – Kexus Jun 24 '20 at 18:18

1 Answers1

4

You already have the list of burrow positions:

burrow_positions_list[]

At each of which you draw a circle, radius 30. First let's convert that 30 into a constant.

BURROW_RADIUS = WINDOW_WIDTH // 10  # scales with window size, default 30

You already know the position when the mouse is clicked:

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        run = False
    elif event.type == MOUSEBUTTONDOWN:
        pos = pygame.mouse.get_pos()          # <-- HERE

So now we need to marry the two together. We know where the burrow centre is, so if the mouse-click is within BURROW_RADIUS pixels of this point, it's a hit.

There's a formula for calculating the line distance between points known as the Euclidian Distance. For 2 points it's pretty easy:

def twoPointDistance( point_a, point_b ):
    x1, y1 = point_a
    x2, y2 = point_b
    x_squared = (x2 - x1) * (x2 - x1)
    y_squared = (y2 - y1) * (y2 - y1)
    length = math.sqrt( x_squared + y_squared )
    return length

So now we have two points - burrow_point and mouse_click_point, and a way of determining the distance. So when a click happens, we just need to see if it was close enough.

elif event.type == MOUSEBUTTONDOWN:
    mouse_click_point = pygame.mouse.get_pos()          # Mouse was clicked
    # Loop through every burrow point, checking the distance
    for i, burrow_point in enumerate( burrow_positions_list ):
        if ( twoPointDistance( mouse_click_point, burrow_point ) < BURROW_RADIUS ):
            # Burrow was clicked
            print( "Burrow %d was clicked" % ( i ) )

And that's it.

However...

It would be much less CPU-intensive to pre-calculate a bounding square around each burrow, and only check if the point was inside this (which is only a few simple < / > checks) rather than the complicated maths of square-roots. There's even a pre-existing function for it: pygame.Rect.collidepoint(). But this is left as an exercise for the reader!

Kingsley
  • 14,398
  • 5
  • 31
  • 53