I am creating a game but I am having a problem with my button class for my gui. There are no compile errors and no runtime errors either. The only problem is that on run it immediately freezes the pygame window. I don't know how to solve this.
I've tried fiddling around with the callback function (which I removed entirely) and with the update and draw loop as well but nothing seems to work.
Python 3.7.0 and Pygame 1.9.4
Button Class:
import sys
import time
import pygame
pygame.init()
class button:
def __init__(self, txt, location, bg=(255,255,255),fg=(0,0,0),size=(80,30),font_name="Times New Roman",font_size=16):
#bg is the colour of the button
#fg is the colour of the text
#location refers to the center points of the button
self.colour = bg
self.bg = bg
self.fg = fg
self.size = size
self.font = pygame.font.SysFont(font_name,font_size)
self.txt = txt
self.txt_surf = self.font.render(self.txt, 1, self.fg)
self.txt_rect = self.txt_surf.get_rect(center=[s//2 for s in self.size])
self.surface = pygame.surface.Surface(size)
self.rect = self.surface.get_rect(center=location)
def mouseover(self):
self.bg = self.colour
pos = pygame.mouse.get_pos()
if self.rect.collidepoint(pos):
self.bg = (200,200,200)
def draw(self, screen):
self.mouseover()
self.surface.fill(self.bg)
self.surface.blit(self.txt_surf, self.txt_rect)
screen.blit(self.surface, self.rect)
Actual update/draw loop
import gui
import pygame
import sys
import time
import win32api
pygame.init()
screen = pygame.display.set_mode((400,400))
button1 = gui.button("No", (200,200))
intro = True
while intro:
screen.fill((255,255,255))
button1.draw(screen)
if win32api.GetKeyState(0x01) == -127 or win32api.GetKeyState(0x01) == -128:
if button1.rect.collidepoint(pygame.mouse.get_pos()):
intro = False
pygame.quit()
sys.exit()
pygame.display.flip()
pygame.time.wait(20)
I really just want the window to stop freezing up on run and to actually have a button press work. What it should do is immediately quit the application when you press the button in the middle. Not actually do that though.
You have to let pygame process the events in the event queue by calling pygame.event.get (or pygame.event.pump, but you should stick to use get).
Otherwise, the queue will fill up and new events will be dropped. This includes internal events that tell your OS to draw the window etc, so your window will freeze.
Also, there's no reason to use win32api to get the state of the keyboard (you can use pygame.key.get_pressed instead), but that's another topic.
Related
i am trying to open settings.py in main.py by importing it like a library, but whenever i run main.py, the setting page opens immediately and im not sure why
whats is meant to happen is when you press the Account button you are supposed to run the settings page and get that the to load however that doesnt happen, instead whenever you run main.py settings.py instantly gets run without the main menu loading. This worked fine with the button but it doesnt work with the settings page i have tried to use exec and os to open it instead but that doesnt work.
the myLibrary is just the button defintion i used to create the account button
main.py
import pygame, sys, os
import myLibrary as lib
import settings
def runSettings():
print(settings.mainloop())
return
script_dir = sys.path[0]
bg_path = os.path.join(script_dir, '../info/images/backgrounds/MainMenu background.png')
bg = pygame.image.load(bg_path)
(width, height) = (1300, 790)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Main Menu')
Account_img = os.path.join(script_dir, '../info/images/MainMenu buttons/account.png')
Account_btn = lib.Button(Account_img, (180,340), runSettings)
while True:
screen.blit(bg, (0, 0))
screen.blit(Account_btn.image, Account_btn.rect)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
Account_btn.on_click(event)
pygame.display.update()
settings.py
import pygame, sys, os
import myLibrary as lib
script_dir = sys.path[0]
bg_path = os.path.join(script_dir, '../info/images/backgrounds/Settings background.png')
bg = pygame.image.load(bg_path)
(width, height) = (1100, 700)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Settings')
#titles
Username_img = pygame.image.load(os.path.join(script_dir, '../info/images/Settings buttons/username.png'))
def mainloop():
while True:
screen.blit(bg, (0,0))
screen.blit(Username_img, (30,20))
for event in pygame.event.get():
pass
pygame.display.update()
mainloop()
button definition, myLibrary as lib
import pygame
#button class will take the image, the position and callback
#function to create and place buttons
class Button:
def __init__(self, image, position, callback):
self.image = pygame.image.load(image)
self.image.convert()
self.rect = self.image.get_rect(topleft=position)
self.callback = callback
def on_click(self, event):
if event.button == 1:
if self.rect.collidepoint(event.pos):
self.callback()
Right now, i am trying to make the turtle graphic screen clear and reset everything when i toggle a new algorithm using the tab key. The toggle part works however i am unable to clear the whole screen when i toggle to a new algorithm.
My codes are as shown below:
from pynput import keyboard
from pynput.keyboard import Listener, Key, Controller
import keyboard
from turtle import Turtle, Screen, clearscreen, clear
import sys
def lefthand_Algo():
execfile('...')
def bfs_Algo():
execfile('...')
# Creates the title
def title():
t = Turtle()
t.color('white')
t.write('Hello, hit tab to start the algorithm!', font=('lemon',20,'normal'), align='center')
t.hideturtle()
screen = Screen()
clearscreen = clearscreen
clear = clear
screen.bgcolor("black") # Set the background colour
screen.setup(width=0.9, height=0.9) # Setup the dimensions of the working window
title = title()
current_state = bfs_Algo
next_state = lefthand_Algo
switch = False
def toggle():
global switch
switch = not switch
if switch:
next_state()
else:
current_state()
screen.onkeypress(toggle, "Tab")
screen.listen()
screen.mainloop()
Note: The algorithms are in separate files and this file is just for the toggling between the two files.
How do i clear the screen each time i toggle? Help will be greatly appreciated! :)
From #RhinoRunner in the comments:
Use turtle.reset().
I would like to add a background image as a step to creating a basic game but it seems that I can't find a way. The image I am trying to import is the same size as the screen and it's a bmp image.
I also have in my settings folder this line of code which I am sure but not 100% needs to be removed (self.bg_color = (230, 230,230)) if I want to blit the image in background.
import sys
import pygame
from altarboy import Altarboy
from Ship import Ship
from bullet import bullet
from bullet1 import bullet1
from settings import Settings
class SpiritualWar:
def __init__(self):
pygame.init()
self.settings = Settings()
self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("SpiritualWar")
self.Ship = Ship(self)
self.bullets = pygame.sprite.Group()
self.bullet1s = pygame.sprite.Group()
self.altarboys = pygame.sprite.Group()
self._create_fleet()
…
…
def _update_screen(self):
self.screen.fill(self.settings.bg_color)
self.Ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
for bullet1 in self.bullet1s.sprites():
bullet1.draw_bullet1()
self.altarboys.draw(self.screen)
pygame.display.flip()
Possible duplicate of How to add a background image in python-pygame. I also recommend you to see Pygame: Adding a background. Next time, spend some minutes searching your question in StackOverflow before asking it. This way there will be less posts and SO will be cleaner, which helps to find solutions with ease.
I could not test the solution myself, but you can try adding the next line to the funciton __init__():
self.bg_image = pygame.image.load("player1.png")
And then changing your first line in function _update_screen():
self.screen.fill(self.settings.bg_color)
for:
self.screen.blit(self.bg_image, (0, 0))
I have a Raspberry Pi with a PiTFT module. I'm wanting to use Pygame to display information on the module using the framebuffer (without X). I have all the display stuff working but the problem is that pygame is grabbing the input from the keyboard so that I can't even change the terminal with alt 1-7.
This task is supposed to run in the background so this is not desired behavior. I can't find any way to disable it though. It looked like pygame.event.set_grab() might have been appropriate but did not help. Here is a cut-down version of my code which exhibits the same issue.
import os
import pygame
import time
from time import gmtime,strftime,localtime
class pytest :
screen = None
def __init__(self):
os.environ["SDL_FBDEV"] = "/dev/fb1"
try:
pygame.display.init()
except pygame.error:
print 'Init failed.'
size = (pygame.display.Info().current_w, pygame.display.Info().current_h)
self.screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
pygame.event.set_grab(0)
pygame.font.init()
self.font = pygame.font.SysFont("", 30)
def __del__(self):
"Destructor to make sure pygame shuts down, etc."
def test(self):
lightblue = (92, 92, 176)
self.screen.fill(lightblue)
tm=time.strftime("%H:%M:%S",localtime())
t=self.font.render(tm,1,(255,255,155))
self.screen.blit(t,(240,00))
pygame.display.update()
scope = pytest()
while 1:
scope.test()
pygame.event.pump()
time.sleep(1)
When i run the code it play only the .wav file
import pygame, sys
from pygame.locals import *
pygame.init()
DISPLAYSURF = pygame.display.set_mode((500, 400), 0, 32)
pygame.mixer.music.load('background.ogg')
pygame.mixer.music.play()
soundObj = pygame.mixer.Sound('bird.wav')
soundObj.play()
pygame.mixer.music.stop()
someone know what i should do for the background.ogg to be played too?
Remove this line:
pygame.mixer.music.stop()
Basically, you're loading and playing the background noise, and then immediately stopping it. I also suggest you create a main loop, like so:
import pygame
from pygame.locals import *
# This makes sure that you're not importing the module.
if __name__ == "__main__":
# Create surface
size = width, height = (500, 400)
# You don't need the extra arguments
window = pygame.display.set_mode(size)
# Do sound stuff
pygame.mixer.music.load('background.ogg')
pygame.mixer.music.play()
soundObj = pygame.mixer.Sound('bird.wav')
soundObj.play()
# This is your main loop.
running = True
while running:
# Check if escape was pressed
Most of the time people just check if Escape was pressed in their main loop (if it was pressed, they set running = False and exit the program).