When I press a button, two buttons are being pressed.
I made images to act like a button but when I press the first button, the second button is pressed too.
I'm new to pygame and trying to make the buttons do separate things when I click each one.
import pygame
import time
pygame.init();
screen = pygame.display.set_mode((340,340));
img = pygame.image.load('3.gif')
iimg = pygame.image.load('2.gif')
mg = pygame.image.load('4.gif').convert()
g = pygame.image.load('5.gif')
waitingForInput = False
pygame.display.set_caption("SIMON");
BEEP1 = pygame.mixer.Sound('beep1.wav')
BEEP2 = pygame.mixer.Sound('beep2.wav')
BEEP3 = pygame.mixer.Sound('beep3.wav')
BEEP4 = pygame.mixer.Sound('beep4.wav')
screen.blit(img,(0,0))
screen.blit(mg,(150,0))
pygame.display.flip()
def main():
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = event.pos
if img.get_rect().collidepoint(mouse_pos):
print ('button was pressed at {0}'.format(mouse_pos))
BEEP1.play()
screen.blit(iimg,(0,0))
pygame.display.flip()
time.sleep(.30)
screen.blit(img,(0,0))
pygame.display.flip()
if mg.get_rect().collidepoint(mouse_pos):
print ('button was pressed at {0}'.format(mouse_pos))
BEEP2.play()
screen.blit(g,(150,0))
pygame.display.flip()
time.sleep(.30)
screen.blit(mg,(150,0))
pygame.display.flip()
main()
If you call get_rect on a Surface, the resulting Rect that is returned will always have an x and y value of 0.
So when you run if img.get_rect().collidepoint(mouse_pos) in your event loop, you're NOT checking if the Surface was a clicked. You check if the mouse position is in the top left corner of the screen.
Maybe use some print statements to check for yourself.
What you can do is to create a Rect for each button outside of your main loop, and then use these rects for blitting:
...
img = pygame.image.load('3.gif')
img_rect = img.get_rect()
...
mg = pygame.image.load('4.gif').convert()
mg_rect = img.get_rect(topleft=(150,0))
...
while True:
...
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = event.pos
if img_rect().collidepoint(mouse_pos):
BEEP1.play()
if mg_rect ().collidepoint(mouse_pos):
BEEP2.play()
screen.blit(img, img_rect)
screen.blit(mg, mg_rect)
Note that you also should avoid time.sleep or multiple calls of pygame.display.flip() in your main loop.
Another solution is to use the pygame's Sprite class, which allows you to combine a Surface and a Rect.
Related
I use this code to get a separate position of each left click on pygame:
for event in pygame.event.get():
if event.type==QUIT:
running=False
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = event.pos
I use mouse_x and mouse_y for drawing , but they are always change. So, how to get an exact position of each click on a screen in pygame and to use them to draw ?
Thank you
1. To get the position when the mouse is clicked
You can use pygame.event.get() to get the position at the exact frame when you begin to press the button like that:
import pygame
from pygame.locals import * # import constants like MOUSEBUTTONDOWN
pygame.init()
screen = pygame.display.set_mode((640, 480))
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == MOUSEBUTTONDOWN and event.button = 0: # detect only left clicks
print(event.pos)
pygame.display.flip()
pygame.quit()
exit()
2. To get the position each frame
In this case, you can use pygame.mouse.get_pos() like that:
import pygame
from pygame.locals import * # import constants like MOUSEBUTTONDOWN
pygame.init()
screen = pygame.display.set_mode((640, 480))
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
print(pygame.mouse.get_pos())
pygame.display.flip()
pygame.quit()
exit()
If you want to get the mouse position only if the left button is pressed:
Place the line print(pygame.mouse.get_pos()) in if pygame.mouse.get_pressed()[0]::
...
if pygame.mouse.get_pressed()[0]: # if left button of the mouse pressed
print(pygame.mouse.get_pos())
...
This code actually detects all kinds of mouse clicks, if you just want the left clicks you can add this to your if statement:
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
You are also not getting the coordinates the right way, you need to write it like this:
mouse_x, mouse_y = pygame.mouse.get_pos()
If you need to use all the clicks that are happening you need to store the x_mouse and y_mouse to a log which you can do like this:
# This outside the pygame loop
mouse_clicks = []
# This inside the pygame loop
for event in pygame.event.get():
if event.type==QUIT:
running=False
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
mouse_clicks.append(pygame.mouse.get_pos())
Now you have a list of tuples with all x,y coordinates for all clicks
This is my python code, using pygame. When I pressed my mouse down, scene 1 does not switch to scene 2. I am coming from Code HS, so the scene switch is from the Tell A Story project. I realized that code is not the same as pygame's. So I used pygame docs and see what I can learn from that, but nothing still. Please can any one help me. Thank you.
import pygame as pg
pg.init()
win = pg.display.set_mode((500,500))
pg.display.set_caption('Scene Switcher')
center_x = 250 - 130
center_y = 250
black= (0,0,0)
red = (255,0,0)
blue = (0,0,255)
def ct(font, size, text, color):
mf = pg.font.Font(font, size)
t = mf.render(text, True, color)
return t
def draw_scene1():
print("This is Scene 1")
txt = ct("SB.ttf", 40, "Hello World!", black)
win.blit(txt, (center_x,center_y))
def draw_scene2():
print("This is scene 2")
txt2 = ct("SB.ttf", 40, "scene2 ", black)
win.blit(txt2, (center_x,center_y))
while True:
win.fill(red)
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
quit()
mouses = pg.mouse.get_pressed()
scene_counter = 0
# When this function is called the next scene is drawn.
def draw_next_screen():
global scene_counter
scene_counter += 1
if scene_counter == 1:
draw_scene1()
else:
draw_scene2()
if mouses:
draw_next_screen()
pg.display.update()
You have to initialize scene_counter before the application loop rather than in the application loop.
The 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. Therefor the scene_counter is continuously incremented in each frame as long a mouse button is hold down.
The MOUSEBUTTONDOWN event occurs once when you click the mouse button and the MOUSEBUTTONUP event occurs once when the mouse button is released. Increment the counter when the MOUSEBUTTONDOWN event occurs:
scene_counter = 0
run = True
while run:
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
elif event.type == pg.MOUSEBUTTONDOWN:
scene_counter += 1
win.fill(red)
if scene_counter == 0:
draw_scene1()
else:
draw_scene2()
pg.display.update()
pg.quit()
So I currently have this code for an airbrush in a drawing app. When the function is active, it should draw on a canvas, basically like an airbrush. But right now, I don't know how to make pygame detect a mouse down or mouse up and make a while loop out of it. Here is the code:
def airbrush():
airbrush = True
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
while click == True:
pygame.draw.circle(gameDisplay, colorChosen, (cur[0] + random.randrange(brushSize), cur[1] + random.randrange(brushSize)), random.randrange(1, 5))
pygame.display.update()
clock.tick(60)
Right now, I have "while click" which doesn't work. What should I replace "click" with to make this work so that while the mouse is held down, it paints, but when the mouse is "up", it stops?
The state which is returned by pygame.mouse.get_pressed() is evaluated once when pygame.event.get() is called. The return value of pygame.mouse.get_pressed() is tuple with th states of the buttons.
Don't implement a separate event handling in a function. Do the event handling in the main loop:
done = False
while not done:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
airbrush()
pygame.display.flip()
Evaluate the current state of a button (e.g. left button), of the current frame, in the function airbrush:
def airbrush():
airbrush = True
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if click[0] == True: # evaluate left button
pygame.draw.circle(gameDisplay, colorChosen, (cur[0] + random.randrange(brushSize), cur[1] + random.randrange(brushSize)), random.randrange(1, 5))
I am trying to create a menu screen for my game. At the moment im using sprites for buttons and everything works well, and I can create an infinite amount of buttons (currently I just have Start and Options), but only the first button I call appears on the screen. I think it has something to do with the while loop in the button class but I am not sure on how to fix it. I am probably making no sense here so if you need me to clarify anything I will. Thanks!
import pygame
import random
import time
pygame.init()
#colours
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,155,0)
blue = (50,50,155)
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Numeracy Ninjas')
clock = pygame.time.Clock()
img_button_start = pygame.image.load('Sprites/Buttons/button_start.png')
img_button_options = pygame.image.load('Sprites/Buttons/button_options.png')
gameDisplay.fill(white)
class Button(pygame.sprite.Sprite):
def __init__(self, sprite, buttonX, buttonY):
super().__init__()
gameDisplay.blit(sprite, (buttonX, buttonY))
pygame.display.update()
running = True
while (running):
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
print(x, y)
if x <= (150 + buttonX) and x >=(0 + buttonX) and y <= (75 + buttonY) and y >= (0 + buttonY):
print('clicked on button')
def gameIntro():
button_start = Button(img_button_start, 27, 0)
button_options = Button(img_button_options, 27, 500)
gameIntro()
In the constructor of your Button class, you have an infinite loop. This means you never get to the code part where you make your second Button.
def gameIntro():
button_start = Button(img_button_start, 27, 0) #stuck in infinite loop
print('This print statement is never reached')
button_options = Button(img_button_options, 27, 500)
Instead, what you want to do is initialize two Buttons, and then have a main game loop in your gameIntro() method that checks for events. If a mousebuttondown event occured, you want to pass the event (or even just the event position, if you don't care which mouse button was clicked) to a function of button that checks whether this instance of button was clicked and then handles the input (possibly by returning something which you handle in the main game loop).
Note that I haven't run the following code, I'm just trying to give you an idea how it should be structured:
class Button(pygame.sprite.Sprite):
def __init__(self, image, buttonX, buttonY):
super().__init__()
self.image = image
self.rect = image.getRect()
self.rect.x = buttonX
self.rect.y = buttonY
def wasClicked(event):
if self.rect.collidepoint(event.pos):
return True
def gameIntro():
#initialize buttons
buttons = pygame.sprite.Group() #make a group to make drawing easier
button_start = Button(img_button_start, 27, 0)
button_options = Button(img_button_options, 27, 500)
#draw buttons to display
buttons.draw(gameDisplay)
pygame.display.update()
#main game loop
running = True
while (running):
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
#check for every button whether it was clicked
for btn in buttons:
if btn.wasClicked():
#do something appropriate
if event.type == pygame.QUIT:
pygame.quit()
This may seem like a really easy question to answer, but I'm just a beginner in need of quick help.
I'm trying to create a program that when you click somewhere on the pyGame window, it'll print out that you hit it with the left button on the mouse, and also print out co-ordinates of where it was pressed. I've got this already. I'm having problems with making it plot the pixel on the pyGame window. Basically, I want it to draw a pixel where I pressed down on the pyGame window.
#!/usr/bin/env python
#import the module for use
import pygame
#setting up some variables
running = 1
LEFT = 1
#Set up the graphics area/screen
screen=pygame.display.set_mode((640,400))
#continuous loop to keep the graphics running
while running==1:
event=pygame.event.poll()
if event.type==pygame.QUIT:
running=0
pygame.quit()
elif event.type==pygame.MOUSEBUTTONDOWN and event.button==LEFT:
print "You pressed the left mouse button at (%d,%d)" %event.pos
elif event.type==pygame.MOUSEBUTTONUP and event.button==LEFT:
print "You released the left mouse button at (%d,%d)" %event.pos
Try setting the color of each pixel when you receive the mouse down event.
elif event.type==pygame.MOUSEBUTTONDOWN and event.button==LEFT:
print "You pressed the left mouse button at (%d,%d)" %event.pos
screen.set_at((event.pos.x, event.pos.y), pygame.Color(255,0,0,255))
Note that this will temporarily lock and unlock the Surface as needed.
I edited Aesthete's code to a working standalone example:
Depending what you are doing, get/setting individual pixels can be slow. ( There is Surfarray and Pixelarray if you need to. )
import pygame
from pygame.locals import *
class Game(object):
done = False
def __init__(self, width=640, height=480):
pygame.init()
self.width, self.height = width, height
self.screen = pygame.display.set_mode((width, height))
# start with empty screen, since we modify it every mouseclick
self.screen.fill(Color("gray50"))
def main_loop(self):
while not self.done:
# events
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT: self.done = True
elif event.type == KEYDOWN:
if event.key == K_ESCAPE: self.done = True
elif event.type == MOUSEMOTION:
pass
elif event.type == MOUSEBUTTONDOWN and event.button == 1:
print "Click: ({})".format(event.pos)
self.screen.set_at(event.pos, Color("white"))
# draw
pygame.display.flip()
if __name__ == "__main__":
g = Game()
g.main_loop()