I have the following code in pygame (irrelevant stuff removed):
import pygame, sys
from pygame.locals import *
pygame.init()
resolution = 1360,768
screen = pygame.display.set_mode((resolution),0,32)
font = pygame.font.SysFont("arial", 24)
black = 0,0,0
white = 255,255,255
x = 200
y = 200
while True:
image = pygame.Surface([3,3],SRCALPHA) # creates a surface to draw the protagonist on
protagonist=pygame.draw.circle(image, white, (x,y), 3, 3) # draws the protagonist on the surface image
for event in pygame.event.get():
keystate = pygame.key.get_pressed()
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if keystate[K_ESCAPE]:
pygame.quit()
sys.exit()
screen.fill(black)
text = font.render("This text appears on the screen", 1, (white))
screen.blit(text, (100, 100))
screen.blit(image,(x, y)) # This does not appear on the screen
pygame.display.flip()
pygame.display.update()
The text appears on the screen as intended, but not the image. What am I doing wrong?
The surface you draw the circle on:
image = pygame.Surface([3,3],SRCALPHA)
is only 3x3 pixels in size.
Then you draw the circle:
pygame.draw.circle(image, white, (x,y), 3, 3)
at position x, y, but x, y is actually 200, 200, so you draw it way outside the visible area of the image surface.
You can skip creating the image surface altogether and draw directly to the screen surface:
while True:
for event in pygame.event.get():
keystate = pygame.key.get_pressed()
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if keystate[K_ESCAPE]:
pygame.quit()
sys.exit()
screen.fill(black)
pygame.draw.circle(image, white, (x,y), 3, 3)
text = font.render("This text appears on the screen", 1, (white))
screen.blit(text, (100, 100))
pygame.display.update()
Also, you don't need to call pygame.display.flip() and pygame.display.update()
Surface instances are black in color by default, so you must fill to see it in a black background:
image.fill((255, 255, 255)) # fill the image Surface to white instead of default black
Related
I have an image in pygame and my code detects if this image is clicked on. It worked fine and I decided to resize the image, but when I did that the image randomly disappeared. Here was the code before the image disappeared:
import pygame
pygame.init()
width = 500
height = 500
screen = pygame.display.set_mode((width, height))
white = (255, 255, 255)
screen.fill(white)
pygame.display.set_caption('Aim Trainer')
target = pygame.image.load("aim target.png").convert_alpha()
x = 20 # x coordinate of image
y = 30 # y coordinate of image
screen.blit(target, (x, y)) # paint to screen
pygame.display.flip() # paint screen one time
targetSize = pygame.transform.scale(target, (5, 3))
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 positions of the mouse click
x, y = event.pos
if target.get_rect().collidepoint(x, y):
print('clicked on image')
# loop over, quite pygame
pygame.quit()
and here is my code after:
import pygame
pygame.init()
width = 500
height = 500
screen = pygame.display.set_mode((width, height))
white = (255, 255, 255)
screen.fill(white)
pygame.display.set_caption('Aim Trainer')
target = pygame.image.load("aim target.png").convert_alpha()
x = 20 # x coordinate of image
y = 30 # y coordinate of image
pygame.display.flip() # paint screen one time
targetSize = pygame.transform.scale(target, (5, 3))
screen.blit(targetSize, (x, y)) # paint to screen
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 positions of the mouse click
x, y = event.pos
if target.get_rect().collidepoint(x, y):
print('clicked on image')
# loop over, quite pygame
pygame.quit()
As you can see, the only thing that changed was me renaming screen.blit(target, (x, y)) to screen.blit(targetSize, (x, y)), and me moving this line of code a few lines furthur down to avoid a 'TargetSize is not defined' error. But for some reason, this change makes the image disappear. The program still detects it when I click on the image, it's just that the image isn't visible.
You have to get the rectangle from the scaled iamge
pygame.Surface.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. A Surface is blit at a position on the screen. The position of the rectangle can be specified by a keyword argument. For example, the top left of the rectangle can be specified with the keyword argument topleft. These keyword argument are applied to the attributes of the pygame.Rect before it is returned (see pygame.Rect for a full list of the keyword arguments).
Update the display after drawing the image
targetSize = pygame.transform.scale(target, (5, 3))
target_rect = targetSize.get_rect(topleft = (x, y))
screen.blit(targetSize, (x, y))
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
if target_rect.collidepoint(event.pos):
print('clicked on image')
This is my code atm. It outputs a square right on top of a circle. I want to make the square sort of "turn into" the circle.
import pygame
GREEN = (0,255,0)
pygame.init()
pygame.display.set_caption("Game TITLE")
screen = pygame.display.set_mode((400,400))
quitVar = True
while quitVar == True:
screen.fill(WHITE)
pygame.draw.rect(screen, GREEN, (100,100,200,200))
pygame.draw.circle(screen, GREEN, (200,200),100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quitVar = False
pygame.display.update()
pygame.quit()
You can draw a rectangle with round corners in Pygame (see Setting a pygame surface to have rounded corners). Animate the corner radius from 0 to the radius of the circle:
import pygame
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
pygame.init()
pygame.display.set_caption("Game TITLE")
screen = pygame.display.set_mode((400,400))
clock = pygame.time.Clock()
radius = 0
step = 1
quitVar = True
while quitVar == True:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quitVar = False
screen.fill(WHITE)
pygame.draw.rect(screen, GREEN, (100, 100, 200, 200), border_radius = radius)
pygame.display.update()
radius += step
if radius <= 0 or radius >= 100:
step *= -1
pygame.quit()
How can I detect if an image has been touched in pygame on a touch screen? I have searched but I can not find how to detect if a particular image is touched.
To detect if an image has been touched, you can use the MOUSEBUTTONDOWN event. See Pygame mouse clicking detection.
Load the image with pygame.image.load(). Crate the bounding rectangle (pygame.Rect). Create a pygame.Mask from the image with pygame.mask.from_surface:
image = pygame.image.load('image.png').convert_alpha()
image _rect = image.get_rect(topleft = (x, y))
image_mask = pygame.mask.from_surface(image)
Use the MOUSEBUTTONDOWN event to detect if the mouse is clicked in the rectangular area of the image. Check if the corresponding bit in the image mask is set:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
image_x, image_y = event.pos[0] - image_rect.x, event.pos[1] - image_rect.y
if image_rect.collidepoint(event.pos) and image_mask.get_at((image_x, image_y)):
print("touched")
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((400, 400))
font = pygame.font.SysFont(None, 100)
clock = pygame.time.Clock()
text = font.render("Text", True, (255, 255, 0))
bomb = pygame.image.load('Bomb-256.png').convert_alpha()
bomb_rect = bomb.get_rect(center = window.get_rect().center)
bomb_mask = pygame.mask.from_surface(bomb)
click_count = 0
click_text = font.render('touch: ' + str(click_count), True, "black")
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
image_x, image_y = event.pos[0] - bomb_rect.x, event.pos[1] - bomb_rect.y
if bomb_rect.collidepoint(event.pos) and bomb_mask.get_at((image_x, image_y)):
click_count += 1
click_text = font.render('touch: ' + str(click_count), True, "black")
window.fill((255, 255, 255))
window.blit(bomb, bomb_rect)
window.blit(click_text, click_text.get_rect(topleft = (20, 20)))
pygame.display.flip()
pygame.quit()
exit()
If I run this from the raspberry pi desktop the touch is not detected.
But if I execute this from ssh remote it works fine
With pygame, I created a 20x20 pixel window and added a 2x2 pixel rectangle.
When I run the program, the window size is super small and I can barely see the rectangle. How can I increase the window size whilst keeping the number of pixels constant, i.e. increase the pixel size? I am aware of this similar question, but there a somewhat more complicated case is discussed.
import pygame
screen_width, screen_height = 20, 20
x, y = 10, 10
rect_width, rect_height = 2, 2
vel = 2
black = (0, 0, 0)
white = (255, 255, 255)
pygame.init()
win = pygame.display.set_mode((screen_width, screen_height))
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
win.fill(black)
pygame.draw.rect(win, white, (x, y, rect_width, rect_height))
pygame.display.update()
pygame.quit()
Don't draw directly to the screen, but to another Surface.
Then scale that new Surface to the size of the screen and blit it onto the real screen surface.
Here's an example:
import pygame
screen_width, screen_height = 20, 20
scaling_factor = 6
x, y = 10, 10
rect_width, rect_height = 2, 2
vel = 2
black = (0, 0, 0)
white = (255, 255, 255)
pygame.init()
win = pygame.display.set_mode((screen_width*scaling_factor, screen_height*scaling_factor))
screen = pygame.Surface((screen_width, screen_height))
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.fill(black)
pygame.draw.rect(screen, white, (x, y, rect_width, rect_height))
win.blit(pygame.transform.scale(screen, win.get_rect().size), (0, 0))
pygame.display.update()
pygame.quit()
How can I detect if an image has been touched in pygame on a touch screen? I have searched but I can not find how to detect if a particular image is touched.
To detect if an image has been touched, you can use the MOUSEBUTTONDOWN event. See Pygame mouse clicking detection.
Load the image with pygame.image.load(). Crate the bounding rectangle (pygame.Rect). Create a pygame.Mask from the image with pygame.mask.from_surface:
image = pygame.image.load('image.png').convert_alpha()
image _rect = image.get_rect(topleft = (x, y))
image_mask = pygame.mask.from_surface(image)
Use the MOUSEBUTTONDOWN event to detect if the mouse is clicked in the rectangular area of the image. Check if the corresponding bit in the image mask is set:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
image_x, image_y = event.pos[0] - image_rect.x, event.pos[1] - image_rect.y
if image_rect.collidepoint(event.pos) and image_mask.get_at((image_x, image_y)):
print("touched")
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((400, 400))
font = pygame.font.SysFont(None, 100)
clock = pygame.time.Clock()
text = font.render("Text", True, (255, 255, 0))
bomb = pygame.image.load('Bomb-256.png').convert_alpha()
bomb_rect = bomb.get_rect(center = window.get_rect().center)
bomb_mask = pygame.mask.from_surface(bomb)
click_count = 0
click_text = font.render('touch: ' + str(click_count), True, "black")
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
image_x, image_y = event.pos[0] - bomb_rect.x, event.pos[1] - bomb_rect.y
if bomb_rect.collidepoint(event.pos) and bomb_mask.get_at((image_x, image_y)):
click_count += 1
click_text = font.render('touch: ' + str(click_count), True, "black")
window.fill((255, 255, 255))
window.blit(bomb, bomb_rect)
window.blit(click_text, click_text.get_rect(topleft = (20, 20)))
pygame.display.flip()
pygame.quit()
exit()
If I run this from the raspberry pi desktop the touch is not detected.
But if I execute this from ssh remote it works fine