Pygame: pygame.mouse.get_pos() tuple out of range? - python

I'm attempting to create a pygame Tic-Tac-Toe game. My issue is in my 'mousemovement()' method. Whenever i use the 'pygame.mouse.getpos()' in my 'collidepoint()' method it gives me a type error and says that my tuples index is out of range. Anyone have any ideas?
import pygame
pygame.init()
pygame.font.init()
pygame.display.set_caption("Tic-Tac-Toe")
pygame.mouse.set_visible(True)
FPS = 60
clock = pygame.time.Clock()
WIDTH,HEIGHT = 500,600
BORDER_THICKNESS = 10
WIN = pygame.display.set_mode((WIDTH,HEIGHT))
#delcare the fonts of the characters
GAME_FONT = pygame.font.SysFont("comicsans",100)
#colors
WHITE = (255,255,255)
BLACK = (0,0,0)
GREEN = (0,255,0)
def display_window(squares,marks,turn):
WIN.fill(WHITE)
starting_pos = WIDTH // 3
for l in range(2): #draws the board
vert = pygame.Rect((starting_pos - BORDER_THICKNESS//2,0),(BORDER_THICKNESS,HEIGHT))
hrzn = pygame.Rect((0,starting_pos - BORDER_THICKNESS//2),(WIDTH,BORDER_THICKNESS))
starting_pos = starting_pos * 2 + BORDER_THICKNESS//2
pygame.draw.rect(WIN,BLACK,vert)
pygame.draw.rect(WIN,BLACK,hrzn)
#draws black background for text box
more_border = pygame.Rect((0,WIDTH),(WIDTH,HEIGHT - WIDTH))
pygame.draw.rect(WIN,BLACK,more_border)
#draws actual text box
text_box = pygame.Rect((0+BORDER_THICKNESS,WIDTH+BORDER_THICKNESS),(WIDTH-BORDER_THICKNESS*2,HEIGHT - WIDTH))
pygame.draw.rect(WIN,WHITE,text_box)
#display game squares
for s in squares:
pygame.draw.rect(WIN,GREEN,s)
#prints the marks of x's and o's
for m in marks:
pass #still working on printing the marks
pygame.display.update()
#use the mouse methods in order to retrive location in which
#mouse is at and see if it collides with a given square
def mouse_movement(squares,mouse_presses,marks,turn):
for s in squares:
if s.collidepoint(pygame.mouse.get_pos()) and mouse_presses[pygame.MOUSEBUTTONDOWN]:
if turn % 2 == 1:
marks[squares.index(s)] = 'X'
elif turn % 2 == 0:
marks[squares.index(s)] = 'O'
else:
raise TypeError("Neither condition is being met")
def main():
turn = 1
x, y = 0,0
squares = []
for c in range(3):
for r in range(3):
squares.append(pygame.Rect((x,y),(WIDTH//3-BORDER_THICKNESS//2,WIDTH//3-BORDER_THICKNESS//2)))
x += WIDTH//3 - BORDER_THICKNESS//2 + BORDER_THICKNESS
x = 0
y += WIDTH//3 - BORDER_THICKNESS//2 + BORDER_THICKNESS
marks = ['','','','','','','','','']
game_going = True
while game_going:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_going = False
pygame.quit()
print(pygame.mouse.get_pos())
mouse_presses = pygame.mouse.get_pressed()
marks = mouse_movement(squares,mouse_presses,marks,turn)
display_window(squares,marks,turn)
if __name__ == '__main__':
main()
I searched the pygame website to make sure that the 'pygame.mouse.get_pos()' method returns a tuple and it does. I'm not quite sure where to go from here.

You get the out of range exception because of mouse_presses[pygame.MOUSEBUTTONDOWN].
pygame.mouse.get_pressed() returns a list of Boolean values ​​that represent the state (True or False) of all mouse buttons. The state of a button is True as long as a button is held down. When multiple buttons are pressed, multiple items in the list are True. The 1st, 2nd and 3rd elements in the list represent the left, middle and right mouse buttons.
If you want to test if the left mouse button is pressed it is:
if mouse_presses[0]:
If you want to test if any button is pressed it is:
if any(mouse_presses):
However, this is not how the MOUSEBUTTONDOWN event works. The MOUSEBUTTONDOWN event occurs once when you click the mouse button and the MOUSEBUTTONUP event occurs once when the mouse button is released. The pygame.event.Event() object has two attributes that provide information about the mouse event. pos is a tuple that stores the position that was clicked. button stores the button that was clicked. Each mouse button is associated a value. For instance the value of the attributes is 1, 2, 3, 4, 5 for the left mouse button, middle mouse button, right mouse button, mouse wheel up respectively mouse wheel down. When multiple keys are pressed, multiple mouse button events occur. Further explanations can be found in the documentation of the module pygame.event.
e.g.:
game_going = True
while game_going:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_going = False
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # left button
print(event.pos) # mouse position
# [...]

Related

Creating a Main Menu for connect 4 on python

I am trying to create a main menu (starting page) for a 3 player connect 4 but I am unable to create one I want 5 buttons (3 player game, 2 player game, single player, options, Quit).
Can anyone help? If possible can anyone give me example code which I could adapt to my game.
I haven't created a main menu before.
I don't mid use of tkinter or pygame.
A small example of a yellow button, that when clicked prints some text (more explanation in code comments):
import pygame
pygame.init()
screen = pygame.display.set_mode((500, 400))
clock = pygame.time.Clock()
# create the surface that will be the button
btn = pygame.Surface((300, 200))
btn.fill((255, 255, 0))
rect = btn.get_rect(center=(250, 200))
clicked = False
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.fill((0, 0, 0))
# get mouse pos
mouse_pos = pygame.mouse.get_pos()
# get the state of left mouse button
left, *_ = pygame.mouse.get_pressed()
# check if mouse is in the button and if the mouse button has been clicked
# the flag `clicked` is for registering the click once when button is pressed
# otherwise it will loop again and the conditions will be true again
# you can also use the event loop above to detect whether the
# mouse button has been pressed, then the flag is not needed
if rect.collidepoint(mouse_pos) and left and not clicked:
clicked = True
print('clicked')
# reset flag
if not left:
clicked = False
# show the button
screen.blit(btn, rect)
pygame.display.update()
Useful:
pygame.Rect.collidepoint
Here’s a small example using Tkinter:
from tkinter import *
def click():
# Make another window.
top = Toplevel()
# You can add more elements here.
# Creating the Main Window
root = Tk()
root.title(“Connect 4”) # You can replace the title with your own
btn = Button(root, text=“Place Your Text”, command=click).pack()
# You can add as many of these buttons
root.mainloop()

Can't click on image again, what's wrong with my pygame code?

Okay, I'am trying to create a Tom and Jerry game with the pygame library.
The game focuses on catching mice by clicking on them as they appear in their holes. The problem
is that sometimes a cat appears instead of a mouse and should the player erroneously click on the
cat (s)he looses all earned points, but the game continues.
The mouse is an image of a mouse and the cat is an image of an cat.
If you click on the mouse, you get mouse, otherwise the cat gets the points.
The code is a mess, that's because I don't know what I'am doing and just set an another event loop because then it works, because it runs after I create the mouse. It works to click on the mouse but then you click somewhere else and after that it's like you did not clicked on the mouse.
The mouse is created in a loop and is supposed to wait for 5 seconds and if you click on the mouse within these seconds then an appropriate message prints out in the console ,,Jerry clicked!" else "1 click". If you don't click on the mouse within 5 seconds a image covers the mouse so she disappears.
Now, what I'am trying to do right now is to print the message 1 click when the player does not click on anything but print 1 click jerry clicked when the player clicks on the mouse. I have a image of the mousehole and then I put the mouse on the mousehole, that is, on an another image.
This code works with one image at least:
pygame.init()
width=350;
height=400
screen = pygame.display.set_mode( (width, height ) )
pygame.display.set_caption('clicked on image')
redSquare = pygame.image.load("images/red-square.png").convert()
x = 20; # x coordnate of image
y = 30; # y coordinate of image
screen.blit(redSquare , ( x,y)) # paint to screen
pygame.display.flip() # paint screen one time
running = True
while (running):
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if redSquare.get_rect().collidepoint(x, y):
print('clicked on image')
#loop over, quite pygame
pygame.quit()
My problem is that, when I click on the mouse and then I don't click on the mouse I can't click on the mouse again at another position.
So what's wrong? What I'am doing wrong here?
Here is my code:
import pygame
from pygame import *
from random import *
init()
run = True
screen = (800,800)
screen = display.set_mode(screen)
xpos = 0
ypos = 0
mouseorcatxpos = 5
mouseorcatypos = 0
mousehole = image.load("mousehole.png").convert()
cat = image.load("tom.png")
jerry = image.load("jerry.png")
def makeholes():
global ypos
global xpos
for holey in range(1,9):
for holex in range(1,9):
screen.blit(mousehole,(xpos,ypos))
display.flip()
xpos += 100
ypos += 100
xpos = 0
def mouseorcat():
global xpos
mouseorcatxpos = 5
ypos = 0
for mousecaty in range(1,9):
pygame.event.pump()
for mousecatx in range(1,9):
randommouse = randint(1, 3)
randomcat = randint(1, 10)
if(randommouse == 2):
screen.blit(jerry, (mouseorcatxpos, ypos))
display.flip()
for event in pygame.event.get():
if (event.type == MOUSEBUTTONDOWN):
if jerry.get_rect().collidepoint(xpos, ypos) == False:
print("l clicked!")
x, y = event.pos
if jerry.get_rect().collidepoint(xpos, y):
print("JERRY CLICKED!!")
x, y = event.pos
print(x, y)
time.wait(5000)
#screen.blit(mousehole, (mouseorcatxpos - 5, ypos))
display.flip()
elif(randomcat == 2):
screen.blit(cat, (mouseorcatxpos, ypos))
display.flip()
time.wait(1500)
screen.blit(mousehole, (mouseorcatxpos-5, ypos))
display.flip()
mouseorcatxpos += 100
mouseorcatxpos = 0
ypos += 100
makeholes()
while run == True:
for event in pygame.event.get():
mouseorcat()
if event.type == QUIT:
run = False
I rewrote your game to show you how I would do it.
To keep track of the time and to limit the framerate I used a pygame.time.Clock and a timer variable. The clock returns the time in milliseconds since clock.tick was called the last time, which is used to increase the timer variable. The cat just replaces the mouse after two seconds and the mouse is set to a new position. I use pygame.Rects to store the positions, but you could also use lists or tuples.
import sys
import random
import pygame
pygame.init()
size = (800, 800)
screen = pygame.display.set_mode(size)
# Images replaced by pygame.Surface. Do that too
# in the future before you post your code.
mousehole = pygame.Surface((40, 40)).convert()
mousehole.fill(pygame.Color(30, 30, 30))
cat = pygame.Surface((40, 40)).convert()
cat.fill(pygame.Color(110, 110, 130))
jerry = pygame.Surface((40, 40)).convert()
jerry.fill(pygame.Color(190, 130, 0))
# Create the background image and blit the holes.
background = pygame.Surface(size).convert()
for holey in range(8):
for holex in range(8):
background.blit(mousehole, (holex*100, holey*100))
def new_position():
"""Return a random position between 0-700 in steps of 100."""
return (random.randrange(0, 701, 100), random.randrange(0, 701, 100))
def main():
fps = 30
clock = pygame.time.Clock()
jerry_rect = jerry.get_rect() # Stores jerry's position and size.
jerry_rect.topleft = new_position() # New random position.
# The cat is outside of the screen first.
cat_rect = cat.get_rect(topleft=(-100, -100))
points = 0
timer = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
if jerry_rect.collidepoint(event.pos):
points += 1
print('Jerry caught! Points:', points)
timer = 0
jerry_rect.topleft = new_position()
else:
print('Missed. Points:', points)
# Run logic.
timer += clock.tick(fps) / 1000 # timer + seconds since last tick.
if timer > 2: # Cat catches mouse after 2 seconds.
cat_rect.topleft = jerry_rect.topleft
jerry_rect.topleft = new_position()
timer = 0
points = 0
print('Tom caught Jerry.')
# Draw.
# Clear the screen by blitting the bg.
screen.blit(background, (0, 0))
screen.blit(jerry, jerry_rect)
screen.blit(cat, cat_rect)
pygame.display.flip()
if __name__ == '__main__':
main()
pygame.quit()
sys.exit()
Side notes:
Don't use star imports (from module import *), because that can make code harder to read. If you want you can use from pygame.locals import *, if it's the only star import.
Don't use global variables, because they can make code harder to read, understand and maintain. Pass variables to functions as arguments and then return the result.
Update: Some notes about your program:
The first big problem is that your game has two event loops and the important one is deeply nested inside of two other for loops and a if. The event loop should be directly under the main while loop (one indentation level (when you have more experience you can put it into a function or class method)).
The two for loops seem to have the purpose to let the code run until randommouse or randomcat are 2. To run code until a condition is met is the purpose of a while loop. But in this case you should better just pick a random number and write the if/elif conditions so that they always apply. For example, you want a 2/3 chance for mouse and 1/3 for a cat,
random_number = random.randint(1, 3)
if random_number < 3:
print("2/3 probability. It's a mouse")
else:
print("1/3 probability. It's a cat")
Or use random.choice with a list:
>>> random.choice(['mouse', 'mouse', 'cat'])
'mouse'
time.wait(5000) shouldn't be used because the game just hangs in this time. You can't even close the window. Limit the framerate and get the time since the last tick with a pygame.time.Clock.
pygame.event.pump() is not needed.
If you call get_rect() without an argument, the rect is positioned at (0, 0).
if jerry.get_rect().collidepoint(xpos, y):
That's the reason why clicking on jerry only works in the top row, and because you use the global xpos here. Since xpos is 0, the whole top row counts as Jerry.
You can pass coordinates to get_rect like so (you can also use center or other args instead of topleft):
jerry_rect = jerry.get_rect(topleft=(50, 100))
I'm sorry but I don't think I can simply fix your code. I've tried it several times, but I always end up re-writing it completely.
I begin by extracting the event loop out of the two nested for loops, then remove these loops, create rects for the mouse and cat, fix the collision detection, add a timer and so on. Take a close look at my example and try to rewrite your game in a similar way, and keep asking questions if you don't understand something.

text not showing up dynamically, pygame

The code below is supposed to create a green button that makes a score text appear. unfortunately the button does nothing, and the only way I've managed to get it to work is by putting the function call for makeText in the while loop instead of in the clickButton function, but if I do that it's no longer dynamic. Can someone explain why the text isn't showing up when I press the button and fix my code so it does show up?
import pygame
import sys
#game stuff
pygame.init()
screen = pygame.display.set_mode((640, 480),0,32)
clock = pygame.time.Clock()
#functions
def makeText(title,text,posx,posy):
font=pygame.font.Font(None,30)
scoretext=font.render(str(title)+ ": " +str(text), 1,(0,0,0))
screen.blit(scoretext, (posx, posy))
def clickButton(name,x,y,width,height):
if x + width > cur[0] > x and y + height > cur[1] > y:
if click == (1,0,0):
makeText("score",300,100,10)
#objects
button1 = pygame.Rect((0,0), (32,32))
while True:
screen.fill((255,255,255))
screen.fill((55,155,0), button1)
#update display
pygame.display.update()
clock.tick(60)
#event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
cur = event.pos
click = pygame.mouse.get_pressed()
clickButton("button1",button1.left,button1.top,button1.width,button1.height)
The problem is that once you created the text, your main loop keeps going and calls screen.fill, overdrawing the text even before pygame.display.update() is called.
You could change it to:
...
def clickButton(name,x,y,width,height):
print x + width > cur[0] > x and y + height > cur[1] > y
if x + width > cur[0] > x and y + height > cur[1] > y:
if click == (1,0,0):
makeText("score",300,100,10)
#objects
button1 = pygame.Rect((0,0), (32,32))
while True:
screen.fill((255,255,255))
screen.fill((55,155,0), button1)
#event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
cur = event.pos
click = pygame.mouse.get_pressed()
clickButton("button1",button1.left,button1.top,button1.width,button1.height)
...
so the text is created after filling the screen with the background color and before pygame.display.update() is called, but that does not solve the problem of the screen being filled again the next iteration of the while loop.
So the solution is to keep track of the fact that the button was pressed, a.k.a. keeping track of a state.
Here's an example of a different approach, using classes for the buttons and a dict for the global state (so you don't need global variables, which should you avoid most of the time, because it can get very confusing fast if your game starts becoming more complex).
Click the first button to show or hide the score, and click the second button to change the background color and earn 100 points.
See how easy it becomes to create new buttons; it's just adding a simple function.
import pygame
import sys
import random
pygame.init()
screen = pygame.display.set_mode((640, 480),0,32)
clock = pygame.time.Clock()
# create font only once
font = pygame.font.Font(None,30)
# it's always a good idea to cache all text surfaces, since calling 'Font.render' is
# an expensive function. You'll start to notice once your game becomes more complex
# and uses more text. Also, use python naming conventions
text_cache = {}
def make_text(title, text):
key = "{title}: {text}".format(title=title, text=text)
if not key in text_cache:
text = font.render(key, 1,(0,0,0))
text_cache[key] = text
return text
else:
return text_cache[key]
# we use the 'Sprite' class because that makes drawing easy
class Button(pygame.sprite.Sprite):
def __init__(self, rect, color, on_click):
pygame.sprite.Sprite.__init__(self)
self.rect = rect
self.image = pygame.Surface((rect.w, rect.h))
self.image.fill(color)
self.on_click = on_click
# this happens when the first button is pressed
def toggle_score_handler(state):
state['show_score'] = not state['show_score']
# this happens when the second button is pressed
def toggle_backcolor_handler(state):
state['backcolor'] = random.choice(pygame.color.THECOLORS.values())
state['score'] += 100
# here we create the buttons and keep them in a 'Group'
buttons = pygame.sprite.Group(Button(pygame.Rect(30, 30, 32, 32), (55, 155 ,0), toggle_score_handler),
Button(pygame.Rect(250, 250, 32, 32), (155, 0, 55), toggle_backcolor_handler))
# here's our game state. In a real
# game you probably have a custom class
state = {'show_score': False,
'score': 0,
'backcolor': pygame.color.Color('White')}
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
# you can check for the first mouse button with 'event.button == 1'
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
# to check if the mouse is inside the button, you
# can simple use the 'Rect.collidepoint' function
for button in (b for b in buttons if b.rect.collidepoint(event.pos)):
button.on_click(state)
screen.fill(state['backcolor'])
# draw all buttons by simple calling 'Group.draw'
buttons.draw(screen)
if state['show_score']:
screen.blit(make_text("score", state['score']), (100, 30))
pygame.display.update()
clock.tick(60)
You are checking the value of "click" in the clickButton function, but I don't see click defined anywhere that clickButton would have access to it.
Perhaps you should pass click as an argument in the clickButton function, which would then possibly make the if condition true?

How to display player's score on Pygame?

I'm a new programmer working on a memory game for my computer science summative.The game goes like this: the computer displays random boxes at random positions and then the user has to guess where the boxes are and click on it.
I'm basically done, except right now I'm trying to create 5 different levels that range in level of difficulty. eg level 1 will display 2 boxes and level 2 will display 5, etc. And then if the user gets through all levels they can play again. I know its a lot but I really want to get an A on this.
But right now I'm stuck because it doesn't really work until I try to close the window, and even then it only goes halfway. Any help would be appreciated.
import pygame , sys
import random
import time
size=[500,500]
pygame.init()
screen=pygame.display.set_mode(size)
# Colours
LIME = (0,255,0)
RED = (255, 0, 0)
BLACK = (0,0,0)
PINK = (255,102,178)
SALMON = (255,192,203)
WHITE = (255,255,255)
LIGHT_PINK = (255, 181, 197)
SKY_BLUE = (176, 226, 255)
screen.fill(BLACK)
# Width and Height of game box
width=50
height=50
# Margin between each cell
margin = 5
rows = 20
columns = 20
# Set title of screen
pygame.display.set_caption("Spatial Recall")
# Used to manage how fast the screen updates
clock=pygame.time.Clock()
coord=[]
# Create a 2 dimensional array. A two dimesional
# array is simply a list of lists.
def resetGrid():
grid = []
for row in range(rows):
# Add an empty array that will hold each cell
# in this row
grid.append([])
for column in range(columns):
grid[row].append(0) # Append a cell
return grid
def displayAllPink(pygame):
for row in range(rows):
for column in range(columns):
color = LIGHT_PINK
pygame.draw.rect(screen,color,[(margin+width)*column + margin,(margin+height)*row+margin,width,height])
pygame.display.flip()
def displayOtherColor(pygame,grid):
coord = []
for i in range(random.randint(2,5)):
x = random.randint(2, rows-1)
y = random.randint(2, columns-1)
color = LIME
pygame.draw.rect(screen,color,[(margin+width)*y + margin,(margin+height)*x+margin,width,height])
coord.append((x,y))
grid[x][y] = 1
pygame.display.flip()
time.sleep(1)
return coord
def runGame(gameCount,coord,pygame,grid):
pygame.event.clear()
pygame.display.set_caption("Spatial Recall: Level "+ str(gameCount))
pygame.time.set_timer(pygame.USEREVENT,1000)
time = 0
#clock.tick(
# -------- Main Program Loop -----------
#Loop until the user clicks the close button.
done = False
while done==False:
event = pygame.event.wait() # User did something
if event.type == pygame.QUIT: # If user clicked close
done=True # Flag that we are done so we exit this loop
pygame.event.clear()
print "Game ",gameCount, "ends"
elif event.type == pygame.USEREVENT:
time = time + 1
pygame.display.set_caption("Spatial Recall: Level "+ str(gameCount) + " Time: "+ str(time))
if time == 100:
done = True
pygame.display.set_caption("Time out, moving to next level")
pygame.event.clear()
return False
elif event.type == pygame.MOUSEBUTTONDOWN:
# User clicks the mouse. Get the position
pos = pygame.mouse.get_pos()
# Change the x/y screen coordinates to grid coordinates
column=pos[0] // (width+margin)
row=pos[1] // (height+margin)
if (row,column) in coord:
print coord
coord.remove((row,column))
print coord
color = LIME
pygame.draw.rect(screen,color,[(margin+width)*column + margin,(margin+height)*row+margin,width,height])
if coord == []:
done=True
pygame.display.set_caption("Time out, moving to next level")
pygame.event.clear()
return True
else:
color = RED
pygame.draw.rect(screen,color,[(margin+width)*column + margin,(margin+height)*row+margin,width,height])
pygame.display.flip()
def startTheGame(gameCount):
grid = resetGrid()
displayAllPink(pygame)
coord = displayOtherColor(pygame,grid)
displayAllPink(pygame)
runGame(gameCount,coord,pygame,grid)
for i in range(2):
startTheGame(i+1)
pygame.quit ()
You may want to use the pygame.font module. http://pygame.org/docs/ref/font.html
First, load a font, either from a file or from one of the system font functions.
Call YourFontObject.render(your_text_string). That'll return a Surface that contains the string rendered in the given font. Note, you can't use newline (\n) characters! You'll have to do the spacing yourself.
Blit this Surface onto the screen after everything else so nothing will obscure it.
Also, you don't need the pygame parameter in your functions.
Hope this helps.

Menu problem with PyGame MOUSEBUTTONDOWN event

Yes, that title wasn't worded very properly at all.
Ok, here's what we've got - a Python program using the pyGame library, and we're making a game. We start in a menu environment main.py. When the user clicks on one of the menu buttons, an action is performed. The program checks for clicks on menu items using the following code:
if event.type == pygame.MOUSEBUTTONDOWN:
mousePos = pygame.mouse.get_pos()
for item in buttons: # For each button
X = item.getXPos() # Check if the mouse click was...
Y = item.getYPos() # ...inside the button
if X[0] < mousePos[0] < X[1] and Y[0] < mousePos[1] < Y [1]:
# If it was
item.action(screen) # Do something
When the user clicks on the "Play Game" button, it opens a sub-module, playGame.py. In this sub-module is another pyGame loop etc.
Part of the game is to hold the left mouse button to 'grow' circles out of the current position (It's a puzzle game, and it makes sense in context). Here is my code for doing this:
mouseIsDown == False
r = 10
circleCentre = (0,0)
[...other code...]
if mouseIsDown == True:
# This grown the circle's radius by 1 each frame, and redraws the circle
pygame.draw.circle(screen, setColour(currentColourID), circleCentre, r, 2)
r += 1
for event in pygame.event.get():
if event.type == pygame.QUIT:
runningLevel = False
elif event.type == pygame.MOUSEBUTTONDOWN:
# User has pressed mouse button, wants to draw new circle
circleCentre = pygame.mouse.get_pos()
mouseIsDown = True
elif event.type == pygame.MOUSEBUTTONUP:
# Stop drawing the circle and store it in the circles list
mouseIsDown = False
newCircle = Circle(circleCentre, r, currentColourID)
circles.append(newCircle)
circleCount += 1
r = 10 # Reset radius
The problem I have is that the user's left mouse click from the main menu is persisting into the playGame.py module, and causing it to create and store a new circle, of radius 10 and at position (0,0). Both of these are the default values.
This only happens for the one frame after the menu.
Is there any way to prevent this, or is it a flaw in my code?
All help greatly appreciated, as always. If you need more code or explanation of these snippets, let me know.
If you'd like the full code, it's on GitHub.
You could use MOUSEBUTTONUP instead of MOUSBUTTONDOWN in the menu.
Does adding pygame.event.clear() to the top of Play fix it?

Categories