This question already has answers here:
Pygame mouse clicking detection
(4 answers)
How do I detect if the mouse is hovering over a button? PyGame button class is not displaying the text or changing colour on hover
(1 answer)
Closed 2 years ago.
I'm new to using Pygame and have a question about MOUSEBUTTONDOWN and pygame.draw.circle()
When clicking the 62.5x62.5 square inside of the screen , I want it to show a green circle and when
clicking it again, I want it to disappear. I don't know how to do it and in my code I have to spam click the square for the circle to appear for a split second then it disappears again. I've also tried using a while loop but couldn't make it work.
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
running = True
while running:
screen.fill((0, 0, 0))
mouse_pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN and mouse_pos[0] >= 150 and mouse_pos[0] <= 212.5 \
and mouse_pos[1] >= 425 and mouse_pos[1] <= 487.5:
pygame.draw.circle(screen, (152, 251, 152), (181.25, 393.75), 20)
pygame.display.update()
You need to draw the circle in the event loop rather than in the event loop. Add a Boolean variable draw_circle and toggle the state of the variable when you click the mouse.
You can't draw with floating point accuracy. Pixels and the mouse position have integral units.
Use a pygame.Rect object and collidepoint() for the click test. The position of the mouse click is stored in the pos attribute of the pygame.event.Event() object:
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
draw_circle = False
test_rect = pygame.Rect(0, 0, 40, 40)
test_rect.center = (181, 393)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
if test_rect.collidepoint(event.pos):
draw_circle = not draw_circle
screen.fill((0, 0, 0))
pygame.draw.rect(screen, (127, 127, 127), test_rect, 1) # for debugging
if draw_circle:
pygame.draw.circle(screen, (152, 251, 152), (181, 393), 20)
pygame.display.update()
Related
I'm working on this pygame game and i'm just getting started but got a bit confused because i want the image to move in the x-axis along with the mouse but when i run the program i want the image to show up at the center or the 'floor' but appears at the left side instead. This is my code and a screenshot of what's happening.
import pygame
import sys
pygame.init()
pygame.mixer.init()
WIDTH, HEIGHT = 400, 500
FPS = 60
TITLE = 'FOOD DROP'
SIZE = 190
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE_SKY = (152, 166, 255)
# Display
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(TITLE)
# Surfaces
floor_surface = pygame.Surface((WIDTH, 100))
floor_surface.fill(BLUE_SKY)
floor_rect = floor_surface.get_rect(midbottom=(200, 500))
# Images
LOAD_DITTO = pygame.image.load('Graphics/ditto.png')
DITTO = pygame.transform.scale(LOAD_DITTO, (SIZE, SIZE))
# Time
CLOCK = pygame.time.Clock()
class Figure:
def draw_figure(self, mouse_x):
SCREEN.blit(DITTO, (mouse_x - 90, 330))
# Game loop
SCREEN_UPDATE = pygame.USEREVENT
# main_game = Main()
figure = Figure()
running = True
while running:
CLOCK.tick(FPS)
mx, my = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
SCREEN.fill(WHITE)
SCREEN.blit(floor_surface, floor_rect)
figure.draw_figure(mx)
pygame.display.update()
When i run the program, this happens:
And i want the image to appear right at the center or the x-axis, not the border, i don't know why is this happening. Just to state, that screenshot was taken when the mouse hadn't been placed over the display.
If the mouse pointer is not in the window (out of focus), the initial position of the mouse pointer is (0, 0). Therefore pygame.mouse.get_pos returns (0, 0). It is also not possible to set the mouse position with pygame.mouse.set_pos if it is not in the window.
Initialize the variables mx and mx with the center of the window. Change the mouse position only when the mouse pointer is in the window (in focus). pygame.mouse.get_focused can be used to test whether the mouse is in the window.
mx, my = SCREEN.get_rect().center
running = True
while running:
CLOCK.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if pygame.mouse.get_focused():
mx, my = pygame.mouse.get_pos()
SCREEN.fill(WHITE)
SCREEN.blit(floor_surface, floor_rect)
figure.draw_figure(mx)
pygame.display.update()
pygame.quit()
sys.exit()
This question already has an answer here:
How can I make a button that goes to website in pygame?
(1 answer)
Closed 1 year ago.
Can I add a link into a Pygame? Like in HTML; once it was clicked, we will be redirected to the URL.
I have the game 'Turn Based Battle' -> https://www.pygame.org/project/5492/7939
I want to add a text somewhere on the screen with the link they can press on.
If you want to look at the code you can check on the Github page from the creator, it's basically the same like the game I have now. -> https://github.com/russs123/Battle
All you have to do is check if the mouse press event happened inside the text's rect. Then you can use webbrowser.open() to open the link in a browser.
Sample Code:
import pygame
import webbrowser
pygame.init()
screen = pygame.display.set_mode((1000, 800))
link_font = pygame.font.SysFont('Consolas', 50)
link_color = (0, 0, 0)
running = True
while running:
screen.fill((255, 255, 255))
rect = screen.blit(link_font.render("Sample Link", True, link_color), (50, 50))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
pos = event.pos
if rect.collidepoint(pos):
webbrowser.open(r"https://stackoverflow.com/")
if rect.collidepoint(pygame.mouse.get_pos()):
link_color = (70, 29, 219)
else:
link_color = (0, 0, 0)
pygame.display.update()
This question already has answers here:
Why is my pygame application loop not working properly?
(1 answer)
Pygame window not responding after a few seconds
(3 answers)
Closed 2 years ago.
I've look for the docs, many video on YouTube, questions on stackoverflow but I still can't fix it.This is my code:
import pygame
pygame.init()
run = True
#color def
BK = (0, 0, 0)
WT = (255, 255, 255)
GY = (127, 127, 127)
#create screen
screen = pygame.display.set_mode((800,600))
#title, icon
pygame.display.set_caption("Clock")
icon = pygame.image.load("clock.png")
pygame.display.set_icon(icon)
#loop
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.draw.circle(screen, WT, (0, 0), 175, width=1)
You missed to update the display by by either pygame.display.update() or pygame.display.flip(). And you need to draw circle in the application loop. Care about the Indentation:
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#-->| INDENTATION
# clear display
screen.fill(0)
# draw scene (circle)
pygame.draw.circle(screen, WT, (0, 0), 175, width=1)
# update display
pygame.display.flip()
This question already has an answer here:
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
Closed 2 years ago.
Trying to make a menu screen with multiple clickable images using pygame
based around this
https://blog.penjee.com/mouse-clicked-on-image-in-pygame/
however when i insert more than one image it prints both statements instead of one statement depending on which image is clicked
import pygame
pygame.init()
width=350;
height=400
screen = pygame.display.set_mode( (width, height ) )
pygame.display.set_caption('clicked on image')
buttonone = pygame.image.load("buttonone.png").convert()
buttontwo = pygame.image.load("buttontwo.png").convert()
screen.blit(buttonone , ( 30,40)) # paint to screen
screen.blit(buttontwo , ( 120,150)) # 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 buttonone.get_rect().collidepoint(x,y):
print('clicked on image')
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if buttontwo.get_rect().collidepoint(x,y):
print('clicked on image2')
pygame.quit()
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface, but the origin of the rectangle is at (0, 0), because the Surface object has no location. The Surface is placed at a position when it is blit to the display.
You've to set the .topleft position, which is used to blit the Surface, to the pygame.Rect objects:
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
buttonone_rect = buttonone.get_rect(topleft = (30, 40))
if buttonone_rect.collidepoint(x,y):
print('clicked on image')
buttontwo_rect = buttonone.get_rect(topleft = (120, 150))
if buttontwo_rect.collidepoint(x,y):
print('clicked on image2')
Edit: added a longer example code.
I'm having trouble with coding buttons in pygame. I'm a newbie to the pygame module, so be gentle.
Basically, the goal is to make a point-and-click telltale kind of game. The player gets presented with two choices each gameloop, ie "go left" or "go right". Accordingly, there are two buttons in each gameloop, all located at the same coordinates.
Here is the function:
import pygame
import os
import time
pygame.init()
display_width= 1280
display_height = 720
gameDisplay = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
def button(msg,x, y, w, h, ic, ac, action=None): #message, x y location, width, height, inactive and active colour
if action ==None:
pygame.display.update()
clock.tick(15)
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(gameDisplay, ac,(x,y,w,h))
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
pygame.display.update()
clock.tick(15)
if action == "left1":
game_loop("loop1-1.png",0,0,"left2","left2","","")
else:
pygame.draw.rect(gameDisplay, ic,(x,y,w,h))
smallText = pygame.font.SysFont('timesnewroman',20)
textSurf, textRect = text_objects(msg, smallText, silver)
textRect.center = ( (x+(w/2)), (y+(h/2)) )
gameDisplay.blit(textSurf, textRect)
def game_loop(pic,width,heigth,act1,act2,left,right):
intro = True
while intro:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
gameDisplay.blit(get_image(pic), (0, 0)) #MAIN MENU PIC
button(left,440,450,width,heigth, dark_gray, gray, action=act1)#start nupp
button(right,740,450,width,heigth, dark_gray, gray, action=act2)#exit nupp
pygame.display.update()
clock.tick(15)
The problem occurs when I click the button carelessly, meaning if I don't purposefully click on the left mouse button as fast as I can. Once game_loop1 is called and if I click for a bit longer, the program will read the first click again in this game_loop1 and run the next game_loop and then the next etc. This means the player can accidentally skip through gameloops.
Is there a way to delay the program after the first click(however long it is)? Or maybe a way to include keyup in the function, so it won't count the click in the next gameloop?
Thanks!
I think your original code is a bit too convoluted to fix it and I'll rather show you some better ways to do what you want. You need a finite-state machine to transition between different states/scenes. You can find a simple example with functions as scenes here.
If the logic in your scenes is mostly the same, you could also try to just swap out the data for the scene, for example the background image. Each state/scene needs to know to which new states it can switch, so I put the data into a dictionary of dictionaries. The nested dicts contain the background image of the scene and the connected left and right scenes. When the user presses a button/rect I check if it was the left or right button and then switch to the corresponding scene (subdict) in the states dictionary.
import pygame
pygame.init()
display_width= 1280
display_height = 720
gameDisplay = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
# Use uppercase names for constants that should never be changed.
DARK_GRAY = pygame.Color('gray13')
BACKGROUND1 = pygame.Surface((display_width, display_height))
BACKGROUND1.fill((30, 150, 90))
BACKGROUND2 = pygame.Surface((display_width, display_height))
BACKGROUND2.fill((140, 50, 0))
BACKGROUND3 = pygame.Surface((display_width, display_height))
BACKGROUND3.fill((0, 80, 170))
states = {
'scene1': {'background': BACKGROUND1, 'left_scene': 'scene2', 'right_scene': 'scene3'},
'scene2': {'background': BACKGROUND2, 'left_scene': 'scene1', 'right_scene': 'scene3'},
'scene3': {'background': BACKGROUND3, 'left_scene': 'scene1', 'right_scene': 'scene2'},
}
def game_loop():
# The buttons are just pygame.Rects.
left_button = pygame.Rect(440, 450, 60, 40)
right_button = pygame.Rect(740, 450, 60, 40)
# The current_scene is a dictionary with the relevant data.
current_scene = states['scene1']
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEBUTTONDOWN:
# If the left button is clicked we switch to the 'left_scene'
# in the `current_scene` dictionary.
if left_button.collidepoint(event.pos):
current_scene = states[current_scene['left_scene']]
print(current_scene)
# If the right button is clicked we switch to the 'right_scene'.
elif right_button.collidepoint(event.pos):
current_scene = states[current_scene['right_scene']]
print(current_scene)
# Blit the current background.
gameDisplay.blit(current_scene['background'], (0, 0))
# Always draw the button rects.
pygame.draw.rect(gameDisplay, DARK_GRAY, left_button)
pygame.draw.rect(gameDisplay, DARK_GRAY, right_button)
pygame.display.update()
clock.tick(30) # 30 FPS feels more responsive.
game_loop()
pygame.quit()