I am using pygame to create a fully customizable enigma machine in python. One thing I decided to implement early is a help function. When I was testing this, nothing would show up on the console. Here is the code for the image clicking (not all of the code)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
pygame.display.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = event.pos
if img.get_rect().collidepoint(x, y):
print('test')
How do I make this work? All help would be useful.
When you call img.get_rect() you create a pygame.Rect with the size of the image/surface and the default topleft coordinates (0, 0), i.e. your rect is positioned at the top left corner of your screen. I suggest creating a rect instance for the img at the beginning of the program and use it as the blit position and for the collision detection. You can pass the topleft, center, x, y, etc., coordinates directly as an argument to get_rect: rect = img.get_rect(topleft=(200, 300)).
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')
img = pg.Surface((100, 50))
img.fill((0, 100, 200))
# Create a pygame.Rect with the size of the surface and
# the `topleft` coordinates (200, 300).
rect = img.get_rect(topleft=(200, 300))
# You could also set the coords afterwards.
# rect.topleft = (200, 300)
# rect.center = (250, 325)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.MOUSEBUTTONDOWN:
if rect.collidepoint(event.pos):
print('test')
screen.fill(BG_COLOR)
# Blit the image/surface at the rect.topleft coords.
screen.blit(img, rect)
pg.display.flip()
clock.tick(60)
pg.quit()
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()
I want to make a kind of "level editor" as an exercise.
I've got this code:
import pygame
running = True
pygame.init()
screen = pygame.display.set_mode((800, 500))
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 50, 50)
def draw(self):
pygame.draw.rect(screen, (255, 0, 0), self.square)
cube = Cube()
drawing_cube = False
drawing_cube2 = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
cube.update()
drawing_cube = True
screen.fill((0, 255, 0))
if drawing_cube:
cube.draw()
pygame.display.flip()
pygame.quit()
However, it doesn't create multiple squares; it just re-locates the already created square.
It's doing exactly what you told it to do: update the one and only Cube object in the game, and then redraw the screen and that one object. If you want multiple cubes, you have to create each one. Perhaps something like this:
cube_list = [] # List of all cubes
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN: # Make a new cube
cube = Cube()
cube.update()
cube_list.append(cube)
drawing_cube = True
screen.fill((0, 255, 0))
if drawing_cube: #New cube made; draw them all.
for cube in cube_list:
cube.draw()
pygame.display.flip()
Now, as an exercise for the student, can you simplify this so that it merely adds the most recent cube to the existing screen, instead of redrawing the entire game area for each new cube?
Thanks, Prune! but for anyone that is reading this after me, here is the full code:
import pygame
cube_list = []
running = True
pygame.init()
screen = pygame.display.set_mode((800, 500))
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 50, 50)
def draw(self):
pygame.draw.rect(screen, (255, 0, 0), self.square)
cube = Cube()
drawing_cube = False
drawing_cube2 = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN: # Make a new cube
cube = Cube()
cube.update()
cube_list.append(cube)
drawing_cube = True
screen.fill((0, 255, 0))
if drawing_cube: #New cube made; draw them all.
for cube in cube_list:
cube.draw()
pygame.display.flip()
pygame.quit()
Cheers!
P.S I've marked your answer as accepted
I've just recently become interested in pygame and the thing is my code doesn't work as what I intended: the image that I want to move with my mouse doesn't moving at all. So here's mine (contains code from previous question I saw):
import pygame,sys,os
WHITE = (255,255,255)
BLACK = (0,0,0)
GREY = (128,128,128)
class SilverGeneral:
def __init__(self,rect):
self.click = False
self.rect = pygame.Rect(rect)
def update(self,screen):
if self.click:
self.rect.center = pygame.mouse.get_pos()
pygame.init()
screen=pygame.display.set_mode([1000,600])
pygame.display.set_caption("Test")
silv = SilverGeneral((5,5,40,20))
silv.rect.center=screen.get_rect().center
clock = pygame.time.Clock()
image = pygame.image.load("c:\game\silvergeneral.bmp").convert()
while 1:
screen.fill(WHITE)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
print(silv.rect.collidepoint(event.pos))
if silv.rect.collidepoint(event.pos):
print("True")
silv.click=True
elif event.type == pygame.MOUSEBUTTONDOWN:
print("False")
silv.click=False
elif event.type == pygame.QUIT:
pygame.quit()
sys.exit()
print (pygame.mouse.get_pos())
print (silv.rect.center)
silv.update(screen)
screen.blit(image,silv.rect)
clock.tick(10)
pygame.display.update()
I have been thinking for a whole hour and don't know why the collidepoint(event.pos) doesn't work. Also even if it's tested, the console never prints True.
collidepoint(event.pos) works just fine.
It seems that you want to be able to move the image once you click on it.
I guess your problem is that you expect it to work with clicking anywhere on that image, but you actually check if the mouse position is in the top left 40x20 pixel box of the image.
You can easily verify that by changing
screen.blit(image,silv.rect)
to
pygame.draw.rect(screen, pygame.color.THECOLORS['blue'], silv.rect, 0)
A good starting point is to use pygame's Sprite class and change your code to something like this:
class SilverGeneral(pygame.sprite.Sprite):
def __init__(self, *groups):
pygame.sprite.Sprite.__init__(self, *groups)
self.click = False
self.image = pygame.image.load("image.jpg").convert()
self.rect = self.image.get_rect()
def update(self):
if self.click:
self.rect.center = pygame.mouse.get_pos()
pygame.init()
screen=pygame.display.set_mode([1000,600])
pygame.display.set_caption("Test")
sprites = pygame.sprite.Group()
silv = SilverGeneral(sprites)
silv.rect.center = screen.get_rect().center
clock = pygame.time.Clock()
while 1:
screen.fill(WHITE)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
silv.click = silv.rect.collidepoint(event.pos) and not silv.click
elif event.type == pygame.QUIT:
pygame.quit()
sys.exit()
sprites.update()
sprites.draw(screen)
clock.tick(60)
pygame.display.update()
The important thing here is that the rect is set to the rect of the image, so it will have the right size.
I'm trying to understand how get_rect() works. In this simple example, I have two images and want to obtain the location of the second and move the first image to the second image.
I have looked at a variety of examples online and cannot get this to work. What am I doing wrong?
import pygame, sys
from pygame.locals import *
import time
pygame.init()
FPS = 10 # frames per second setting
fpsClock = pygame.time.Clock()
# Set up the window
DISPLAYSURF = pygame.display.set_mode((600, 400), 0, 32)
pygame.display.set_caption('Test program for get_rect()')
WHITE = (255, 255, 255)
# Load two images
baseImg = pygame.image.load('image1.jpg')
spaceshipImg = pygame.image.load('image2.jpg')
DISPLAYSURF.fill(WHITE)
# Place one image at the bottom of the screen
DISPLAYSURF.blit(baseImg, (300, 300))
pygame.display.update()
# Place the second image at the top of the screen
DISPLAYSURF.blit(spaceshipImg, (300, 0))
pygame.display.update()
# Wait for one second
time.sleep(1)
# Obtain the rectangle for each image
baseRect = baseImg.get_rect()
spaceshipRect = spaceshipImg.get_rect()
# This is where I believe I'm going wrong
# I understand this to obtain the x,y of the spaceship image
# Set the xy coordinates for the top image to the xy of the bottom image
spaceshipRect.x = baseRect.x
spaceshipRect.y = baseRect.y
# Move the top image to new xy position
# However this doesn't work
DISPLAYSURF.blit(spaceshipImg, (spaceshipRect.x, spaceshipRect.y))
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
First, images/pygame.Surfaces don't have a position, so you have to store the blit position in the rect. When you call the get_rect method of a pygame.Surface, Pygame creates a new rect with the size of the image and the x, y coordinates (0, 0). To give the rect other coords during the instantiation you can pass an argument to get_rect, mostly center or topleft is used. To move the rect later, you can change any of these attributes of the rect:
x,y
top, left, bottom, right
topleft, bottomleft, topright, bottomright
midtop, midleft, midbottom, midright
center, centerx, centery
size, width, height
w,h
Here's an example (press a or d to change the position of the rect and thereby the blit pos of the image):
import sys
import pygame as pg
BG_COLOR = pg.Color(80, 60, 70)
PLAYER_COLOR = pg.Color(90, 140, 190)
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
player_img = pg.Surface((40, 60))
player_img.fill(PLAYER_COLOR)
# Create a rect with the size of the image/pygame.Surface
# and immediately set it's topleft coords to (100, 300).
player_rect = player_img.get_rect(topleft=(100, 300))
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
if event.type == pg.KEYDOWN:
if event.key == pg.K_d:
# Set the center to these new coords.
player_rect.center = (400, 200)
if event.key == pg.K_a:
# Set the x coord to 300.
player_rect.x = 300
screen.fill(BG_COLOR)
screen.blit(player_img, player_rect)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
sys.exit()
Basically, the question is asking how to get the mouse location for a rectangular area.
So, instead of just finding if the mouse is on, for example, the coordinates 100, 100, it would find if the mouse is inside a rectangular area with the corners being at 100, 100, or where ever the rectangle is.
Sorry if this is a really simple question to answer, I just couldn't find it anywhere. Thanks
import pygame, sys
pygame.init(); clock = pygame.time.Clock()
scr = pygame.display.set_mode((640, 480))
image = pygame.image.load('image.png')
rect = image.get_rect()
rect.center = (320, 240)
while True:
pygame.display.flip()
clock.tick(60)
scr.fill((0, 0, 0))
scr.blit(image, rect)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit()
if pygame.mouse.get_pressed()[0]:
if rect.collidepoint(pygame.mouse.get_pos()):
print 'The mouse was click inside the image.'