Why won't my Pygame window background load? - python-3.x

Whenever I run my code, the window opens just fine but the background image will not load. Although the image won't load immediately, if I minimize the window and open it again, the image loads just fine.
This is my code:
import pygame
import os
pygame.init()
WIDTH, HEIGHT = 500, 365
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
BG = pygame.transform.scale(pygame.image.load(os.path.join("GameMap3.png")).convert_alpha(), (WIDTH, HEIGHT))
PLAYER1 = pygame.image.load(os.path.join("PlayerType1.gif"))
fps = 60
main_font = pygame.font.SysFont("comicsans", 50)
player_vel = 5
clock = pygame.time.Clock()
def Main():
global BG
while True:
WIN.blit(BG, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
Main()

You missed to update the display with either pygame.display.update() or pygame.display.flip()
def Main():
global BG
while True:
WIN.blit(BG, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
pygame.display.update() # <--- this is missing
Main()
The typical PyGame application loop has to:
handle the events with 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 with either pygame.display.update() or pygame.display.flip()
limit the frames per second to limit CPU usage with pygame.time.Clock.tick

Related

Pygame gamepad won't run anymore with an Xbox 360 controller and an Ubuntu machine [duplicate]

This code goes into infinite loop. I cant use A button on xbox 360 controller
import pygame
from pygame import joystick
pygame.init()
joystick = pygame.joystick.Joystick(0)
pygame.joystick.init()
print("start")
while True:
if joystick.get_button(0) == 1 :
print("stoped")
break
I cant use A button on xbox 360 controller
Personnaly, I can, so this seems to be possible. You are just missing that pretty much every user input needs to be updated by pygame through pygame.event.get().
From the pygame documentation:
Once the device is initialized the pygame event queue will start receiving events about its input.
So, apparently you need to get the events in the while loop like such to make the joystick work:
import pygame
from pygame.locals import *
pygame.init()
joystick = pygame.joystick.Joystick(0)
while True:
for event in pygame.event.get(): # get the events (update the joystick)
if event.type == QUIT: # allow to click on the X button to close the window
pygame.quit()
exit()
if joystick.get_button(0):
print("stopped")
break
Also,
In the line if joystick.get_button(0) == 1, you don't need to type == 1 because the statement is already True.
You are initializing pygame.joystick twice: through the line pygame.init() and pygame.joystick.init().
You don't need to type from pygame import joystick because you already already have it in the line import pygame.
You can take this as reference and use it in your own way.
import pygame
import sys
pygame.init()
pygame.joystick.init()
clock = pygame.time.Clock()
WIDTH,HEIGHT = 500,500
WHITE = (255,255,255)
BLUE = (0,0,255)
BLUISH = (75,75,255)
YELLOW =(255,255,0)
screen = pygame.display.set_mode((WIDTH,HEIGHT))
smile = pygame.image.load("smile.jpg")
smile = pygame.transform.scale(smile,(WIDTH,HEIGHT))
idle = pygame.image.load("idle.jpg")
idle = pygame.transform.scale(idle,(WIDTH,HEIGHT))
joysticks = [pygame.joystick.Joystick(x) for x in range(pygame.joystick.get_count())]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.JOYBUTTONDOWN:
if event.button == 0: #press A button to smile
screen.fill(WHITE)
screen.blit(smile,(0,0))
pygame.display.update()
clock.tick(10)
elif event.type == pygame.JOYBUTTONUP:
if event.button == 0:
screen.fill(WHITE)
screen.blit(idle,(0,0))
pygame.display.update()
clock.tick(10)

What can I do to make my PyGame window respond?

I am trying to make a window open every time I run my code, but every time I run the code, it shows the window as unresponsive.
My code is as follows:
import os
import time
import sys
pygame.font.init()
WIDTH, HEIGHT = 500, 400
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("EscapeGame")
BG = pygame.transform.scale(pygame.image.load(os.path.join("GameMap1.png")), (WIDTH, HEIGHT))
def main():
fps = 60
clock = pygame.time.Clock()
def redraw_window():
WIN.blit(BG, (0,0))
pygame.display.update()
while True:
clock.tick(fps)
redraw_window()
for event in pygame.event.get():
if event.type == sys.exit:
sys.exit()
input()
main()
I've already tried a few thing with event.get and event.pump, I'm probably missing something very basic. Could someone tell me what else I could try?
Also, I'm new at pygame, so if anyone sees another mistake, please tell me about. I would greatly appreciate it.
The window is unresponsive because you don't handle the events by calling pygame.event.get().
While pygame.event.get() is in your code, it's never executed because
a) it's in a function you never call
b) your code blocks on the input() call
You're code should look like this:
import os
pygame.init()
WIDTH, HEIGHT = 500, 400
def main():
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("EscapeGame")
BG = pygame.transform.scale(pygame.image.load(os.path.join("GameMap1.png")).convert_alpha(), (WIDTH, HEIGHT))
fps = 60
clock = pygame.time.Clock()
while True:
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
WIN.blit(BG, (0,0))
pygame.display.flip()
main()

How to prompt user to open a file with python3?

I'm making a game and I want the user to be able to click a button which opens the file manager and asks them to open a game save file. Is there a module / how could I put this in my game? If there's no good gui way how would I make a text input thing (without using the terminal)? Thanks!
Pygame is a low-level library, so it doesn't have the kind of built-in dialogs you're after. You can create such, but it will be quicker to use the tkinter module which is distributed with Python and provides an interface to the TK GUI libraries. I'd recommend reading the documentation, but here's a function that will pop up a file selection dialog and then return the path selected:
def prompt_file():
"""Create a Tk file dialog and cleanup when finished"""
top = tkinter.Tk()
top.withdraw() # hide window
file_name = tkinter.filedialog.askopenfilename(parent=top)
top.destroy()
return file_name
Here's a small example incorporating this function, pressing Spacebar will popup the dialog:
import tkinter
import tkinter.filedialog
import pygame
WIDTH = 640
HEIGHT = 480
FPS = 30
def prompt_file():
"""Create a Tk file dialog and cleanup when finished"""
top = tkinter.Tk()
top.withdraw() # hide window
file_name = tkinter.filedialog.askopenfilename(parent=top)
top.destroy()
return file_name
pygame.init()
window = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
f = "<No File Selected>"
frames = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
f = prompt_file()
# draw surface - fill background
window.fill(pygame.color.Color("grey"))
## update title to show filename
pygame.display.set_caption(f"Frames: {frames:10}, File: {f}")
# show surface
pygame.display.update()
# limit frames
clock.tick(FPS)
frames += 1
pygame.quit()
Notes: This will pause your game loop, as indicated by the frame counter but as events are being handled by the window manager, this shouldn't be an issue.
I'm not sure why I needed the explicit import tkinter.filedialog, but I get an AttributeError if I don't.
As for string entry in pygame, you might want to do this natively, in which case you'd be handling KEYUP events for letter keys to build the string and perhaps finishing when the user presses Enter or your own drawn button. You could continue down the tk path, in which case you'll want to use something like tkinter.simpledialog.askstring(…)
It is possible to make a file dialogue (though not using the native file explorer) using the pygame_gui module.
Simply create an instance of UIFileDialog and grab the path when the user hits 'ok':
file_selection = UIFileDialog(rect=Rect(0, 0, 300, 300), manager=manager, initial_file_path='C:\\')
if event.ui_element == file_selection.ok_button:
file_path = file_selection.current_file_path
If you want to allow selecting a directory set allow_picking_directories to True, but note that it does not allow picking an initial_file_path.
file_selection = UIFileDialog(rect=Rect(0, 0, 300, 300), manager=manager, allow_picking_directories=True)
Here's the above code in a simple program that allows you to pick a file when the button is clicked:
#!/usr/bin/env python
import pygame
import pygame_gui
from pygame_gui.windows.ui_file_dialog import UIFileDialog
from pygame_gui.elements.ui_button import UIButton
from pygame.rect import Rect
pygame.init()
window_surface = pygame.display.set_mode((800, 600))
background = pygame.Surface((800, 600))
background.fill(pygame.Color('#000000'))
manager = pygame_gui.UIManager((800, 600))
clock = pygame.time.Clock()
file_selection_button = UIButton(relative_rect=Rect(350, 250, 100, 100),
manager=manager, text='Select File')
while 1:
time_delta = clock.tick(60) / 1000.0
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if event.type == pygame.USEREVENT:
if event.user_type == pygame_gui.UI_BUTTON_PRESSED:
if event.ui_element == file_selection_button:
file_selection = UIFileDialog(rect=Rect(0, 0, 300, 300), manager=manager, allow_picking_directories=True)
if event.ui_element == file_selection.ok_button:
print(file_selection.current_file_path)
manager.process_events(event)
manager.update(time_delta)
window_surface.blit(background, (0, 0))
manager.draw_ui(window_surface)
pygame.display.update()

How do I make graphics of this button better in pygame?

import pygame, sys, time
from pygame.locals import*
###################################
screen = "START"
pygame.init()
window_width = 1000
window_height = 650
window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("LOGO QUIZ")
#############################################
def button(normal, activated, x_pos, y_pos, length, height, func=None):
button = pygame.image.load(normal)
mousex, mousey = pygame.mouse.get_pos()
if (mousex>x_pos)and(mousex<(length+x_pos))and(mousey>y_pos)and(mousey<(y_pos+height)):
button = pygame.image.load(activated)
for event in pygame.event.get():
if (event.type == pygame.MOUSEBUTTONDOWN )and (event.button == 1):
if (mousex>x_pos)and(mousex<(mousex+x_pos))and(mousey>y_pos)and(mousey<(y_pos+height)):
func()
window.blit(button,(x_pos, y_pos))
## button = pygame.image.load(activated)
window.blit(button,(x_pos, y_pos))
def START():
global screen
while screen != "QUIT":
for event in pygame.event.get():
if event.type == QUIT:
screen = "QUIT"
bg = pygame.image.load("START.png")
window.blit(bg,(0,0))
button("play_u.png", "play_a.png", 350, 200, 325, 75, game)
pygame.display.update()
def game():
global screen
while screen != "QUIT":
for event in pygame.event.get():
if event.type == QUIT:
screen = "QUIT"
window.fill((20, 20, 20))
pygame.display.update()
pygame.quit()
sys.exit()
START()
pygame.display.update()
The above code is for the start menu of my game, I made a START function to show the start screen and then the game function to run the main game later, in the button function I want to make it as when the mouse is hovered over the picture, it should change the picture(activated pic) but when I do this it takes lots of time it change , how do i shorten the time?
Your code does not work because you call pygame.event.get() multiple times per frame; once in START, and once in button.
Think about what happends when there's a MOUSEBUTTONDOWN event in the queue, then pygame.event.get() is called in START: The event gets removed from the queue, and when pygame.event.get() is called in button, the MOUSEBUTTONDOWN event is already gone and if (event.type == pygame.MOUSEBUTTONDOWN ) will never be True.
So instead of calling for event in pygame.event.get(): in START, you could store the result of pygame.event.get() in a variable and iterate over that in START and button. This way, you won't lose events.
Here's an example:
...
def button(events, normal, activated, x_pos, y_pos, length, height, func=None):
button = pygame.image.load(normal)
mousex, mousey = pygame.mouse.get_pos()
if (mousex>x_pos)and(mousex<(length+x_pos))and(mousey>y_pos)and(mousey<(y_pos+height)):
button = pygame.image.load(activated)
# iterate over the list if events instead of calling pygame.event.get
for event in events:
if (event.type == pygame.MOUSEBUTTONDOWN )and (event.button == 1):
if (mousex>x_pos)and(mousex<(mousex+x_pos))and(mousey>y_pos)and(mousey<(y_pos+height)):
func()
window.blit(button,(x_pos, y_pos))
...
def START():
global screen
while screen != "QUIT":
# store the list of events in a variable
events = pygame.event.get()
# iterate over the new list
for event in events:
if event.type == QUIT:
screen = "QUIT"
bg = pygame.image.load("START.png")
window.blit(bg,(0,0))
# pass the list of events to the button function
button(events, "play_u.png", "play_a.png", 350, 200, 325, 75, game)
pygame.display.update()

how to store multiple mouse click coordinates python

so Ive been trying to find a way to store multiple click x and y's with no luck, Ive worked with pygame and opencv but I cannot find a way to store multiple x and y's without deleting the previous set.
import pygame
pygame.init()
while True:
for e in pygame.event.get():
if e.type == pygame.MOUSEBUTTONDOWN:
print (pygame.mouse.get_pos())
Just append the event.pos or pygame.mouse.get_pos() to a list or collections.deque if the size should be limited.
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
clicks = []
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.MOUSEBUTTONDOWN:
clicks.append(event.pos)
print(clicks)
screen.fill((30, 30, 30))
pg.display.flip()
clock.tick(30)
pg.quit()

Resources