Why does pygame.time.wait kick in before display update? - python-3.x

I have written a code for a game where you slide 15 tiles to set them in order. At the end of the game, I want the screen to just wait for 5 seconds before closing (also want to give a message but that later).
When the game ends, it first pauses and then shows the last move and then closes out. Is there a lag in the display. How do I make it complete the display, and then wait. I tried reading similar posts, but couldn't quite understand.
Here is the relevant code.
> def run_game(self):
"""Start the main loop for the game"""
self._shuffle_grid()
self._show_board()
game_over = False
while True:
change = self._check_events()
if change:
self._show_board()
game_over = self.end_of_game()
if game_over:
pygame.time.wait(5000)
sys.exit()
def _check_events(self):
# Watch for keyboard and mouse events
change = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
key = "U"
elif event.key == pygame.K_DOWN:
key = "D"
elif event.key == pygame.K_LEFT:
key = "L"
elif event.key == pygame.K_RIGHT:
key = "R"
if key == "U" or "D" or "L" or "R":
change = self.key_check(key)
return(change)

I actually tried this and it worked. I still don't know how to show a message and then wait 5 seconds. Working on it.
def celebrate(self):
""" does end of game thing"""
game_clock = pygame.time.Clock()
time_passed = pygame.time.get_ticks()
self._show_board()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
sys.exit()
if pygame.time.get_ticks() > time_passed + 5000:
sys.exit()
def run_game(self):
"""Start the main loop for the game"""
self._shuffle_grid()
self._show_board()
game_over = False
while True:
change = self._check_events()
if change:
game_over = self.end_of_game()
if not game_over:
self._show_board()
else:
self.celebrate()

Related

How do you break out of while loop by pressing a gamepad button (User Input)

I am using pygame just so that I can use the xbox controller on my script. My goal is to press a button to start a repeating task, and then be able to press another button to break out of the repeating task. I should then be able to press the original button to resume the task.
Before I even post the code, I know the crux of my problem is this part here: (something wrong with my indentation but the code works).
while True:
schedule.run_pending()
time.sleep(1)
How do I break out of this while loop so that I can use the next button JOYHATMOTION: Basically I would be using JOYHATMOTION to pause the job function.
Here is the code. It prints "Hello World" every five seconds for 200 seconds.
import schedule
from datetime import datetime, timedelta, time
import time
import sys
import pygame
from pygame.locals import *
pygame.init()
def job():
print('Hello World')
pygame.joystick.init()
joysticks = [pygame.joystick.Joystick(i) for i in range(pygame.joystick.get_count())]
for joystick in joysticks:
print(joystick.get_name())
while True:
for event in pygame.event.get():
if event.type == JOYBUTTONDOWN:
print(event)
if event.button == 8:
schedule.every(5).seconds.until(timedelta(seconds=200)).do(job)
while True:
schedule.run_pending()
time.sleep(1)
if event.type == JOYHATMOTION:
if event.value[0] == 1:
print(event)
if event.value[0] == -1:
print(event)
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
I have tried:
while True:
if event.type == JOYHATMOTION:
if event.value[0] == 1:
break
else:
schedule.run_pending()
time.sleep(1)
but this dosent seem to work. Thank You in advance.
Never try to control the application with a loop inside the application loop. Use the application loop. The application loop is continuously executed. Use a game_state variable that indicates the current state of the application. Execute the code in the application depending on the state of the variable.
With this approach, you can easily change the state back when another key is pressed.
game_state = ""
run = True
while run:
for event in pygame.event.get():
if event.type == QUIT:
run = False
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
run = False
if event.type == JOYBUTTONDOWN:
print(event)
if event.button == 8:
if game_state == "schedule":
game_state = "" # schedule off
else:
game_state = "schedule" # schedule on
schedule.every(5).seconds.until(timedelta(seconds=200)).do(job)
if event.type == JOYHATMOTION:
if event.value[0] == 1:
print(event)
if event.value[0] == -1:
print(event)
if game_state == "schedule":
schedule.run_pending()
# [...]
pygame.quit()
sys.exit()

My space ship won't move towards right in pygame

import pygame
#initialize the screen
pygame.init()
#create the screen
screen = pygame.display.set_mode((800, 700))
#tile and icon
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load("spaceship.png")
pygame.display.set_icon(icon)
#Player
playerImg = pygame.image.load("player.png")
playerx = 370
playery = 600
playerx_change = 0.1
def player(x,y):
screen.blit(playerImg, (x,y))
running = True
while running:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#keystroke
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerx_change = -0.1
if event.type == pygame.K_RIGHT:
playerx_change = 0.1
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerx_change = 0
playerx += playerx_change
player(playerx,playery)
pygame.display.update()
my spaceship won't move towards right side when i press the riht key. but it will move towards the left side if i press the left key and no error is displayed in the terminal. i use the community version of visual studio 2019.
You need to change this:
if event.type == pygame.K_RIGHT:
to this ("type" --> "key"):
if event.key == pygame.K_RIGHT:

pipes spawning too fast in flappy bird pygame

Im working on this flappy bird pygame tutorial and when I tested the code the pipes spawned in too fast. I'm using a tutorial since I'm fairly new to python and would appreciate any help. Thanks. Here is the link to the tutorial website: https://github.com/clear-code- projects/FlappyBird_Python/blob/master/flappy.py
Here is the code I have so far.
import pygame
import sys
import os
from random import randint
def draw_floor():
screen.blit(floor_surface,(floor_x_pos,750))
screen.blit(floor_surface,(floor_x_pos + 576,750))
def create_pipe():
new_pipe = pipe_surface.get_rect(midtop = (288,375))
return new_pipe
def move_pipes(pipes):
for pipe in pipes:
pipe.centerx -= 5
return pipes
def draw_pipes(pipes):
for pipe in pipes:
if pipe.bottom >= 750:
screen.blit(pipe_surface,pipe)
pygame.init()
screen = pygame.display.set_mode((576,855))
clock = pygame.time.Clock()
# Game variables
gravity = 0.25
bird_movement = 0
bg_surface = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs','bg.png')).convert_alpha())
floor_surface = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs','base.png')).convert_alpha())
floor_x_pos = 0
bird_surface = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs','bird2.png')).convert_alpha())
bird_rect = bird_surface.get_rect(center = (100,427))
pipe_surface = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs','pipe.png')))
pipe_list = []
SPAWNPIPE = pygame.USEREVENT
pygame.time.set_timer(SPAWNPIPE,5000)
pipe_height = [300,500,700]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bird_movement = 0
bird_movement -= 12
if event.type == SPAWNPIPE:
pipe_list.extend(create_pipe())
# bird
screen.blit(bg_surface,(0,0))
bird_movement += gravity
bird_rect.centery += int(bird_movement)
screen.blit(bird_surface,bird_rect)
# pipes
pipe_list = move_pipes(pipe_list)
draw_pipes(pipe_list)
floor_x_pos -= 1
draw_floor()
if floor_x_pos <= -576:
floor_x_pos = 0
pygame.display.update()
clock.tick(120)`
Indent the SPAWNPIPE check:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bird_movement = 0
bird_movement -= 12
if event.type == SPAWNPIPE: # indent this
pipe_list.extend(create_pipe())
The issue is that once you get the first SPAWNPIPE event, the event.type condition for adding a new pipe becomes True.
However, due to improper indentation, that condition is repeatedly checked every frame until the next event is received. This means the code is continually spawning pipes every frame during this time.
Fix the indentation, to bring the pipe-event check back inside the event for-loop:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bird_movement = 0
bird_movement -= 12
if event.type == SPAWNPIPE: # <<-- HERE
pipe_list.extend(create_pipe()) # <<-- AND HERE
Which makes the SPAWNPIPE check be performed only when the event is actually received.

How can I make the character moving when I press a key?

I know it has been asked before but I couldn't get it to work, I'm using idle 3.6 and PyGame.
Here is the code.(I just started I have been watching some tutorials but apart from that I'm new to PyGame)
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
location += 1
You can use a boolean flag to keep track of which key was pressed and released. Something like:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
pressedRight = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
pressedRight = False
# Now in your game loop
if pressedRight:
location += 1
Basically, this code emulates a way to check if the key is pressed at the current time or not, allowing you to use continuous movement.

Is there a way in pygame to make a programme pause when it's minimized?

I was playing Terraria the other day and in a new update they make the game pause when it's minimized. Obviously it's written in a different programme to python, but I was wondering if it was possible to replicate the effects.
You can use pygame.display.get_active() to check if window is minimized.
In example you can press SPACE to minimize window.
import pygame
import pygame.locals
pygame.init()
screen = pygame.display.set_mode((800,600))
count = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.key == pygame.K_SPACE:
pygame.display.iconify()
if pygame.display.get_active():
print count
count +=1
else:
print "minimized"
pygame.quit()
Or you can use pygame.ACTIVEEVENT to get information about more events - like minimize, mouse out of the window, etc.
import pygame
import pygame.locals
pygame.init()
screen = pygame.display.set_mode((800,600))
count = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.key == pygame.K_SPACE:
pygame.display.iconify()
elif event.type == pygame.ACTIVEEVENT:
print 'state:', event.state, '| gain:', event.gain,
if event.state == 1:
if event.gain == 0:
print "| mouse out",
elif event.gain == 1:
print "| mouse in",
elif event.state == 2:
if event.gain == 0:
print "| titlebar pressed",
elif event.gain == 1:
print "| titlebar unpressed",
elif event.state == 6:
if event.gain == 0:
print "| window minimized",
elif event.state == 4:
if event.gain == 1:
print "| window normal",
print
pygame.quit()
Both method work correctly only if pygame.event.get() was executed.
You can use the pygame.APPACTIVE event. From the documentation for the pygame.display.iconify:
Then the display mode is set, several events are placed on the pygame event queue. pygame.QUIT is sent when the user has requested the program to shutdown. The window will receive pygame.ACTIVEEVENT events as the display gains and loses input focus [This is when the window is minimized]. If the display is set with the pygame.RESIZABLE flag, pygame.VIDEORESIZE events will be sent when the user adjusts the window dimensions. Hardware displays that draw direct to the screen will get pygame.VIDEOEXPOSE events when portions of the window must be redrawn.
Look at the second example in furas' answer below, but don't use the polling approach of the first example for something like this, you don't want to spend time every frame trying to check if the window has been minimized.

Resources