This question already has answers here:
Why is my pygame application loop not working properly?
(1 answer)
Pygame window freezes when it opens
(1 answer)
Closed 2 years ago.
def game():
running = True
while running:
screen.fill((0, 0, 0))
mx, my = pygame.mouse.get_pos()
button_3 = pygame.Rect(300, 100, 1300, 700)
if button_3.collidepoint((mx, my)):
if click:
begin()
draw_text('game', font, (255, 255, 255), screen, 20, 20)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
# set the pygame window name
img1 = pygame.image.load(r"C:\Users\ga-sa\Downloads\As.png")
img2 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsXOR.png")
img3 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsNOT.png")
img4 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsAND.png")
images = [img1, img2, img3, img4]
current_image = -1
img_rects = [images[i].get_rect(topleft=(20 + 40 * i, 20)) for i in range(len(images))]
LeftButton = 0
while 1:
for e in pygame.event.get():
if e.type == QUIT:
pygame.quit()
exit(0)
if e.type == pygame.MOUSEBUTTONDOWN:
mouse_rect = pygame.Rect(e.pos, (1, 1))
current_image = mouse_rect.collidelist(img_rects)
if e.type == MOUSEMOTION:
if e.buttons[LeftButton]:
rel = e.rel
if 0 <= current_image < len(images):
img_rects[current_image].x += rel[0]
img_rects[current_image].y += rel[1]
screen.fill(0)
for i in range(len(images)):
screen.blit(images[i], img_rects[i])
pygame.display.flip()
pygame.time.delay(30)
screen.blit(BACKGROUND_FASE, (0, 0))
pygame.display.update()
mainClock.tick(60)
I would like to add a background image on this screen, but every time I try to make an error or it doesn't appear, how can I add a background to that part without error , the other part of the code is a menu that when I click on start this screen appears and whole code is here https://pastebin.com/Rb7jh2GH
You have to blit the background before drawing the scene, and you have to draw it in your game loop. When you draw a background, it covers everything that was previously drawn:
Draw background
Draw scene (all the objects)
Update display
Note that there is no need to clear the background when you draw a background image. If the background image covers the entire window, there is no need to clear the background.
screen.fill(0)
while running:
# [...]
while 1:
for e in pygame.event.get():
if e.type == QUIT:
pygame.quit()
exit(0)
# [...]
# draw background
# screen.fill(0) <--- superfluous
screen.blit(BACKGROUND_FASE, (0, 0))
# draw scene (objects)
for i in range(len(images)):
screen.blit(images[i], img_rects[i])
# update display
pygame.display.flip()
Related
I've been trying to make a Chrome Dino Game, however, I'm struggling with this problem:
On every frame, it should draw a new one at the new position and delete the previous one to make it look as if it's moving. HOWEVER, it remains at its previous position and a new image appears on its next position. I did write the pygame.display.update() code at the end of my maintop.
In the last time I ran into a similar problem, I managed to make it work by drawing a background image, but this time, it doesn't work.
following are my codes:
import pygame
import os
from random import randint
import schedule
pygame.init()
assets = os.path.join(os.path.dirname(__file__), "Assets")
screen_size = (screen_width, screen_height) = (1280, 720)
screen = pygame.display.set_mode(screen_size)
clock = pygame.time.Clock()
fps = 120
bg = pygame.image.load(os.path.join(assets, "IMG_15.png"))
ground = 700
running = True
spacebaridx = 0
gamestart = False
tick_on_start = 0
obs1 = pygame.image.load(os.path.join(assets, "colourmat/light_green.png"))
pygame.transform.scale(obs1, (100, 200))
obs2 = pygame.image.load(os.path.join(assets, "colourmat/light_green.png"))
pygame.transform.scale(obs2, (120, 200))
obs3 = pygame.image.load(os.path.join(assets, "colourmat/light_green.png"))
pygame.transform.scale(obs3, (150, 200))
ls_obs = []
def create_obs():
k = randint(1, 3)
if k == 1:
info = {"type":1, "img":obs1, "x":screen_width, "y":ground - 200, "tox":2}
ls_obs.append(info)
if k == 2:
info = {"type":2, "img":obs2, "x":screen_width, "y":ground - 200, "tox":2}
ls_obs.append(info)
else:
info = {"type":3, "img":obs3, "x":screen_width, "y":ground - 200, "tox":2}
ls_obs.append(info)
schedule.every(3).seconds.do(create_obs)
while running:
dt = clock.tick(fps)
if gamestart == True:
game_ticks = pygame.time.get_ticks() - tick_on_start
schedule.run_pending()
else:
game_ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT: running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if spacebaridx == 0: # Press space to start / to tell whether it's the first press
spacebaridx += 1
gamestart = True
tick_on_start = pygame.time.get_ticks()
else:
pass # Jump
for o in ls_obs:
o["x"] += o["tox"] * -1
screen.blit(bg, (0, 0))
for o in ls_obs:
screen.blit(o["img"], (o["x"], o["y"]))
pygame.display.update()
pygame.quit()
This issue is occurring because you aren't clearing the display within each frame. In pygame, in order to clear the display, we need to use the fill method. So in your code, at the top of your game loop before the event loop, add screen.fill((0, 0, 0)). This will fill your screen in the color black. Don't worry, the black won't be shown if you draw the background on top of it. Now, when you add a new image, the previous images won’t be displayed.
Modified Game Loop
while running:
screen.fill((0, 0, 0))
dt = clock.tick(fps)
if gamestart == True:
game_ticks = pygame.time.get_ticks() - tick_on_start
schedule.run_pending()
else:
game_ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT: running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if spacebaridx == 0: # Press space to start / to tell whether it's the first press
spacebaridx += 1
gamestart = True
tick_on_start = pygame.time.get_ticks()
else:
pass # Jump
for o in ls_obs:
o["x"] += o["tox"] * -1
screen.blit(bg, (0, 0))
for o in ls_obs:
screen.blit(o["img"], (o["x"], o["y"]))
pygame.display.update()
pygame.quit()
I am trying to create a pixel-art making program using pygame (yes, I know there are better packages to use). The way that I am drawing pixels is via surface.set_at(). I need to know how to completely delete a pixel from a pygame surface, so that I can have an eraser tool. I do not want to fill the pixel in with the background color of the window, because that would still render when using pygame.image.save() to get an image file from the drawing. Can someone please help? Here is my code:
import pygame
import sys
import math
pygame.init()
clock = pygame.time.Clock()
pygame.display.set_caption("Pixel Studio v1.1")
screen = pygame.display.set_mode((960, 720), pygame.RESIZABLE)
scroll_speed = 5
canvas_size = (32, 16)
color = (255, 255, 255)
canvas_surf = pygame.Surface(canvas_size, pygame.SRCALPHA)
zoom = 12
mouse_down = False
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.image.save(canvas_surf, "canvas.png")
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT:
mouse_down = True
if event.button == pygame.BUTTON_WHEELUP:
if zoom > 2:
zoom -= scroll_speed
if event.button == pygame.BUTTON_WHEELDOWN:
zoom += scroll_speed
if event.type == pygame.MOUSEBUTTONUP:
if event.button == pygame.BUTTON_LEFT:
mouse_down = False
if zoom < 2:
zoom = 2
screen.fill((50, 50, 50))
#canvas_surf.fill((200, 200, 200))
canvas_surf_scaled = pygame.transform.scale(canvas_surf,(canvas_surf.get_width() * zoom, canvas_surf.get_height() * zoom))
canvas_rect = canvas_surf_scaled.get_rect(center=(screen.get_width()/2, screen.get_height()/2))
mouse_pos = pygame.mouse.get_pos()
if mouse_down:
canvas_surf.set_at((math.floor((mouse_pos[0] - canvas_rect.x) / zoom), math.floor((mouse_pos[1] - canvas_rect.y) / zoom)), color)
pygame.draw.rect(screen, ( 75, 75, 75), canvas_rect, 1,)
screen.blit(canvas_surf_scaled, canvas_rect)
pygame.display.flip()
clock.tick(60)
As discussed in the comments, you can make a pixel transparent by setting it to a value whose alpha value is zero.
#r #g #b #a
canvas_surf.set_at((x, y), (0, 0, 0, 0))
I'm trying to do a drag-and-drop mechanic in pygame and I'm being partly successful (thanks to answers to questions like this one and tutorials like this other one). The mechanic I'm using goes as follows: I update in every loop the position of the image once the event of pressing the button is detected (and only if the mouse is over the image). To do so, I created a rectangle object by just calling image.get_rect(), but it seems that this rectangle is shifted, with the center of the image laying in the bottom right of the rectangle. I annex both the code an the result:
import pygame, sys
from pygame.locals import *
FPS = 60
fpsClock = pygame.time.Clock()
def main():
pygame.init()
DS = pygame.display.set_mode((400, 400), 0, 32)
pygame.display.set_caption('Drag-n-drop that cat')
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
catImg = pygame.image.load('cat.png') # I load the image
catImgRectObj = catImg.get_rect() # I create the rect object
catx = 200
caty = 200
catImgRectObj.center = [catx, caty]
IsMousePressed = False
while True:
lastPos = catImgRectObj.center
DS.fill(WHITE)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONDOWN:
IsMousePressed = True
elif event.type == MOUSEBUTTONUP:
IsMousePressed = False
if IsMousePressed and isMouseOverObj(catImgRectObj):
catImgRectObj.center = pygame.mouse.get_pos() #I update the center
else:
catImgRectObj.center = lastPos
pygame.draw.rect(DS, BLACK, catImgRectObj) #draw the rect object
DS.blit(catImg, catImgRectObj.center) #draw the cat.
pygame.display.update()
fpsClock.tick(FPS)
def isMouseOverObj(Obj):
return Obj.collidepoint(pygame.mouse.get_pos())
if __name__ == '__main__':
main()
Use
DS.blit(catImg, catImgRectObj)
instead of
DS.blit(catImg, catImgRectObj.center)
to draw the cat.
The catImgRectObj rect already describes where the cat image is, and if you use catImgRectObj.center to blit it on the screen, but shift its top left corner to the center of the desired area.
Also, I would use something like this:
import pygame, sys
from pygame.locals import *
FPS = 60
fpsClock = pygame.time.Clock()
def main():
pygame.init()
DS = pygame.display.set_mode((400, 400), 0, 32)
pygame.display.set_caption('Drag-n-drop that cat')
catImg = pygame.image.load('cat.png').convert_alpha()
catMask = pygame.mask.from_surface(catImg)
catImgRectObj = catImg.get_rect(center=(200, 200))
IsMousePressed = False
while True:
DS.fill(pygame.color.THECOLORS['white'])
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONDOWN and isMouseOverObj(catMask, catImgRectObj):
IsMousePressed = True
elif event.type == MOUSEBUTTONUP:
IsMousePressed = False
elif event.type == MOUSEMOTION and IsMousePressed:
catImgRectObj.move_ip(event.rel)
DS.blit(catImg, catImgRectObj)
pygame.display.update()
fpsClock.tick(FPS)
def isMouseOverObj(mask, rect):
mouse_pos = pygame.mouse.get_pos()
rel_pos = (mouse_pos[0] - rect.left, mouse_pos[1] - rect.top)
return rect.collidepoint(mouse_pos) and mask.get_at(rel_pos)
if __name__ == '__main__':
main()
to make the collision detection pixel perfect, simplify the code a bit, and to prevent the jumping once you click on the cat.
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
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