Pygame - How to Fill an object gradually from bottom to top? - python

I'm currently working on a game based around working a restaurant, and one of the aspects im working on is filling a cup up with water, i'm choosing not to do water simulations as i'm no expert ahah but my idea of filling a cup up using rectangles one a top another when the mouse button is held is not working. Here's the section of code im trying to fix, any and all feedback is appreciated : ).
while True:
e = pygame.event.wait()
if e.type == pygame.MOUSEBUTTONDOWN:
DrawWater = True
if e.type == pygame.MOUSEBUTTONUP:
print("Lol")
WaterLine = False
if DrawWater:
pygame.draw.rect(screen, [0, 0, 255], [300, WaterLine, 400, 1])
WaterLine -= 1
pygame.display.flip()

pygame.event.wait() wait for a single event from the queue and halts the application loop. Implement an event loop and use pygame.event.get:
Use pygame.time.Clock to control the frames per second and thus the game speed.
The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time. See pygame.time.Clock.tick().
This method should be called once per frame.
That means that the loop:
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
runs 60 times per second.
clock = pygame.time.Clock()
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:
DrawWater = True
if event.type == pygame.MOUSEBUTTONUP:
print("Lol")
WaterLine = False
if DrawWater:
pygame.draw.rect(screen, [0, 0, 255], [300, WaterLine, 400, 1])
WaterLine -= 1
pygame.display.flip()
Alternatively you can use pygame.mouse.get_pressed():
import pygame
pygame.init()
screen = pygame.display.set_mode((300, 400))
WaterLine = 300
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if any(pygame.mouse.get_pressed()):
pygame.draw.rect(screen, [0, 0, 255], [100, WaterLine, 100, 1])
WaterLine -= 1
pygame.display.flip()
The MOUSEBUTTONDOWN event occurs once when you click the mouse button and the MOUSEBUTTONUP event occurs once when the mouse button is released.
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.

Related

How do I stop the screen from updating?

I'm making a calculator in pygame but when I click the button, I want the number to stay on the screen but instead of staying on the screen, the number just appears when my mouse is clicked. When I release it, the numbers disappears. Does anyone know a solution for this?
My code:
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((600,800))
pygame.display.set_caption("Calculator")
clock = pygame.time.Clock()
font1 = pygame.font.Font("c:/Users/oreni/OneDrive/Masaüstü/sprites/minecraft.ttf", 100)
one = 1
one_main = font1.render(str(one), False, "black")
one_main_r = one_main.get_rect(center = (75,100))
one_button = pygame.Surface((142.5,142.5))
one_button.fill("white")
one_button_r = one_button.get_rect(topleft = (0,160))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
screen.fill("black")
screen.blit(one_button,one_button_r)
if event.type == pygame.MOUSEBUTTONDOWN:
if one_button_r.collidepoint(event.pos):
screen.blit(one_main,one_main_r)
pygame.display.update()
clock.tick(60)
The usual way is to redraw the scene in each frame. You need to draw the text in the application loop. Set a variable that indicates that the image should be drawn when the mouse is clicked, and draw the image according to that variable:
draw_r = False
run = True
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
if one_button_r.collidepoint(event.pos):
draw_r = True
screen.fill("black")
screen.blit(one_button,one_button_r)
if draw_r:
screen.blit(one_main, one_main_r)
pygame.display.update()
clock.tick(60)
pygame.quit()
exit()
The typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()

Is there a way to close the pygame window with a MOUSEBUTTONDOWN event?

I am trying to make a clickable image that exits pygame, but im not sure how to make it close. I have tried using the pygame.quit() and sys.exit() but that loads for a second but doesn't do anyhting. I will show the code I have here(the only relevant code is the x and y variables nad the exit button down the bottom):
import pygame, sys
clock = pygame.time.Clock()
from pygame.locals import *
pygame.init() # inititates Pygame
pygame.display.set_caption('Lightmind')
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN) # initiates the window
logo = pygame.image.load("GameLogo.png").convert()
logo = pygame.transform.scale(logo, (256, 256))
start_button = pygame.image.load("StartButton.png").convert()
start_button = pygame.transform.scale(start_button, (256, 256))
exit_button = pygame.image.load("ExitButton.png").convert()
exit_button = pygame.transform.scale(exit_button, (256, 100))
x_2 = 560
y_2 = 400
fade_in = True
fade_out = True
fade_in_ball = True
fade_in_start = True
fade_in_exit = True
running = True
while running: # game loop
for event in pygame.event.get():
if event.type == QUIT:
running = False
pygame.quit()
sys.exit()
# fade in the logo
if fade_in == True:
for i in range(255):
screen.fill((0,0,0))
logo.set_alpha(i)
screen.blit(logo, (560,260))
pygame.display.flip()
clock.tick(60)
fade_in = False
# fade out the logo
if fade_out == True:
for i in range(255):
screen.fill((0,0,0))
logo.set_alpha(255-i)
screen.blit(logo, (560,260))
pygame.display.flip()
clock.tick(60)
fade_out = False
# fade in the start button
if fade_in_start == True:
for i in range(255):
start_button.set_alpha(i)
screen.blit(start_button, (560, 240))
pygame.display.flip()
clock.tick(60)
fade_in_start = False
# fade in the exit button
if fade_in_exit == True:
for i in range(255):
exit_button.set_alpha(i)
screen.blit(exit_button, (x_2, y_2))
pygame.display.flip()
clock.tick(60)
fade_in_exit = False
# make exit button exit game
if event.type == pygame.MOUSEBUTTONDOWN:
x_2, y_2 = event.pos
if exit_button.get_rect().collidepoint(x_2, y_2):
pygame.quit()
sys.exit()
pygame.display.update()
Any help is appreciated!
You're checking the event outside of your event loop. Move it up instead:
for event in pygame.event.get():
if event.type == QUIT:
running = False
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
x_2, y_2 = event.pos
if exit_button.get_rect().collidepoint(x_2, y_2):
pygame.quit()
pygame.event.get() get all the messages and remove them from the queue. See the documentation:
This will get all the messages and remove them from the queue. [...]
If pygame.event.get() is called in multiple event loops, only one loop receives the events, but never all loops receive all events. As a result, some events appear to be missed.
You must handle the click detection in the event loop.
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, but it returns a rectangle that always starts at (0, 0) since a Surface object has no position.
The Surface is placed at a position on the display with the blit function.
You've to set the location of the rectangle, either by a keyword argument, e.g:
running = True
while running: # game loop
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
extit_button_rect = exit_button.get_rect(topleft = (x_2, y_2))
if extit_button_rect.collidepoint(event.pos):
running = False
# [...]
pygame.quit()
sys.exit()

Why does pygame window animationonly work when i am moving my cursor

I am making flappy bird following this guide https://www.youtube.com/watch?v=UZg49z76cLw&t=1309s
but the screen only updates when i move my cursor does anyone know how to fix this
import pygame, sys
def draw_floor():
screen.blit(floor_surface, (floor_animation, 400))
screen.blit(floor_surface, (floor_animation + 275,400))
pygame.init()
screen = pygame.display.set_mode((275,512))
clock = pygame.time.Clock()
bg_surface = pygame.image.load('C:/Users/cuerv/Downloads/flappy-bird-assets-master/flappy-bird-assets-master/sprites/background-day.png').convert()
floor_surface = pygame.image.load('C:/Users/cuerv/Downloads/flappy-bird-assets-master/flappy-bird-assets-master/sprites/base.png').convert()
floor_animation = 0
bird_surface = pygame.image.load('C:/Users/cuerv/Downloads/flappy-bird-assets-master/flappy-bird-assets-master/sprites/bluebird-midflap.png').convert()
bird_rect = bird_surface.get_rect(center = (100,256))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.blit(bg_surface, (0, 0))
screen.blit(bird_surface, (bird_rect))
floor_animation -= 1
draw_floor()
if floor_animation <= -275:
floor_animation = 0
screen.blit(floor_surface, (floor_animation, 400))
pygame.display.update()
clock.tick(120)
enter code here
Its a matter of Indentation. Draw the scene in the application loop rather than the event loop:
# application loop
while True:
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#<--| INDENTATION
screen.blit(bg_surface, (0, 0))
screen.blit(bird_surface, (bird_rect))
floor_animation -= 1
draw_floor()
if floor_animation <= -275:
floor_animation = 0
screen.blit(floor_surface, (floor_animation, 400))
pygame.display.update()
Note, the event loop is only executed when an event occurs, but the application loop is executed continuously.
I guess in your function action is happening just when the mouse is hovering over the image or when position of mouse at time t1 != position at t2. Also provide the code so we can check what may be the problem :)
https://www.pygame.org/docs/ref/mouse.html

Updating the position of a rectangle

I am trying to get familiar with pygame so am starting with a simple program that draws a rectangle and moves it around with the mouse. The rectangle draws fine however it does not move with the mouse position and I cannot think why.
I found one other with this problem however this fix didnt work for me and was much more long winded than I felt it needed to be.
pygame.init()
screen = pygame.display.set_mode((500,300))
# --- mainloop / event loop ---
running = True
playerstartposX = 100
playerstartposY = 100
playerwidth = 50
playerheight = 50
screen.fill((30,30,30))
newrect = pygame.draw.rect(screen, (255,0,0) , ( playerstartposX ,
playerstartposY ,
playerwidth ,
playerheight))
pygame.display.update()
while running:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == 4: #if event is mouse motion
newrect.move(event.pos) #move the rectangle to mouse pos
pygame.display.update()
pygame.quit()
4 is not an event type. An event type is MOUSEMOTION (see pygame.event).
Create a pygame.Rect object:
newrect = pygame.Rect(playerstartposX, playerstartposY, playerwidth, playerheight)
Change its position when the event occurs:
if event.type == pygame.MOUSEMOTION:
newrect.center = event.pos
In the main application loop you've to continuously
handle the events
clear the display
draw the scene respectively rectangle
update the display
If you want to control the frames per second, then you can pass a parameter to the method .tick() of pygame.time.Clock rather than pygame.time.delay:
import pygame
pygame.init()
screen = pygame.display.set_mode((500,300))
clock = pygame.time.Clock()
running = True
playerstartposX = 100
playerstartposY = 100
playerwidth = 50
playerheight = 50
newrect = pygame.Rect(playerstartposX, playerstartposY, playerwidth, playerheight)
while running:
clock.tick(60)
# handle the events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEMOTION:
newrect.center = event.pos
# clear the display
screen.fill((30,30,30))
# draw the rectangle
pygame.draw.rect(screen, (255,0,0), newrect)
# update the display
pygame.display.update()
pygame.quit()
First, the event type you need to check against is pygame.MOUSEMOTION (I believe it's 1024?) and you are checking with 4.
Then you have to redraw the rect on every iteration of the main loop to reflect the updated position

Pygame: getting a loop to run after mouse click

I want to get a certain loop to run after the mouse has previously been clicked.
I initiated a variable called mouse_clicked to false, and then change it to True after the mouse has been clicked. However, this doesn't seem to get things going afterwards.
Here's my code:
import sys, pygame
size = width, height = 320, 240
screen = pygame.display.set_mode(size)
running = True
mouse_pressed = False
while running:
while mouse_pressed:
rect = pygame.Rect(10, 20, 30, 30)
pygame.draw.rect(screen, (255,0,0), rect)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pressed = True
if event.type == pygame.QUIT:
running = False
sys.exit(0)
Thanks!
omer
EDITED after answering too quickly
move your loop around:
while running:
rect = pygame.Rect(10, 20, 30, 30)
pygame.draw.rect(screen, (255,0,0), rect)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pressed = True
if event.type == pygame.QUIT:
running = False
while mouse_pressed:
# do your stuff
mouse_pressed = False
In your version, the whole loop never starts, since mouse_pressed is initialized to False.
It looks like your second loop is not even starting: you are initiating mouse_pressed as False. Therefore,
while mouse_pressed
will necessarily stop the loop before it ever began.
Hope this helps!

Categories