import pygame
def main():
while True:
print(window_size) # works for some reason
print(window_flag) # works for some reason
print(color_flag) # nope python says no
print(current_fps) # python says no
print(previous_fps) # python says no
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
if color_flag:
... # s.o format issue
if __name__ == "__main__":
window_size = (500, 500)
window_flag = pygame.RESIZABLE
# the rejected trio
color_flag = 0
current_fps = 0.0
previous_fps = 0.0
# :(
window = pygame.display.set_mode(window_size, window_flag)
clock = pygame.time.Clock()
main()
When I attempt to print the color_key and subsequent variables I encounter an UnboundLocalError which confuses me, since window_size and window_flag are output without issue. Could someone provide insight into why this is the case?
This question already has answers here:
How to run multiple while loops at a time in Pygame
(1 answer)
Spawning multiple instances of the same object concurrently in python
(1 answer)
Closed 1 year ago.
Below is a working skeleton of my actual code. What I am attempting to do is to obtain the JOYAXISMOTION, event.value, y so that I can use it in different function outside of the loop. I have already defined the variable y.
import time
import sys
import pygame
import subprocess
import random
from pygame.locals import *
pygame.init()
y = 0
def get_percent_change(current, previous):
if current == previous:
return 0
try:
return ((float(current) - float(previous)) /abs(previous)) * 100.0
except ZeroDivisionError:
return float('inf')
def sendCommands():
time.sleep(5)
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())
game_state = False
run = True
while run:
for event in pygame.event.get():
if event.type == JOYBUTTONDOWN:
print(event)
if game_state == False and event.button == 8:
game_state = True
if event.button == 4:
game_state = False
if event.type == JOYHATMOTION:
if event.value[0] == 1 or event.value[0] == -1:
game_state = False
if event.type == JOYAXISMOTION:
if event.axis == 4:
current = event.value
y = get_percent_change(current, -1.0001)
print(y)
if event.type == JOYDEVICEADDED:
joysticks = [pygame.joystick.Joystick(i) for i in range(pygame.joystick.get_count())]
for joystick in joysticks:
print(joystick.get_name())
if event.type == JOYDEVICEREMOVED:
joysticks = [pygame.joystick.Joystick(i) for i in range(pygame.joystick.get_count())]
if game_state == True:
sendCommands()
pygame.quit()
sys.exit()
The main problem I am running into is the time.sleep(5) that the sendCommands requires. It is blocking the script while sleeping. I have tried asyncio with no success. Threading is also very confusing to me here. I have also tried the delay logic in the answer provided to a closely related question here but that also blocks the code from running.
Allow me to pick your brain on how:
I can run the script without it being blocked
and how I can access and use the event.value, y outside of the loop
To use y outside of the loop, you could declare it as global but a better alternative is to make a function to get the value. You can implement a timer to execute your subprocess every 5 seconds instead of blocking the entire thread. The following code prints None every 5 seconds for me since I don't have any controllers connected but I think it will work for you.
import time
import sys
import pygame
from pygame.locals import *
pygame.init()
def sendCommands(waitTime, y):
global sendCommandsStart
#count how many seconds have passed since sendCommandsStart
#variable was last updated
if time.time() - sendCommandsStart > waitTime:
sendCommandsStart = time.time() #reset the timer
print(y)#call your subpreocess here
def getJoyStickY(events):
for event in events:
if event.type == JOYAXISMOTION:
if event.axis == 4:
return get_percent_change(current, -1.0001)
return None
pygame.joystick.init()
run = True
sendCommandsStart = time.time() #get the current time - its just a number (time since last epoh)
while run:
allEvents = pygame.event.get()
sendCommands(5, getJoyStickY(allEvents))
pygame.quit()
sys.exit()
Relatively new to Pygame. I'm trying to make a rectangle move from a character (xeon) like a bullet, horizontally when pressing the downarrow key. I keep getting this error.
"UnboundLocalError: local variable 'bullets' referenced before assignment"
Any feedback is much appreciated. Excuse the mess...........................
import pygame
import time
import random
import sys
import os
pygame.init()
display_width=800
display_height=600
black=(0,0,0)
white=(255,255,255)
red=(200,0,0)
green=(0,200,0)
blue=(0,0,200)
bright_green=(0,255,0)
bright_red=(255,0,0)
gameDisplay=pygame.display.set_mode((800,600))
pygame.display.set_caption("Xeongame")
clock=pygame.time.Clock()
zheImg=pygame.image.load("xeon.png").convert()
bgImg=pygame.image.load("Spacebackground.jpg").convert()
xeon_width=300
def xeon(x,y):
gameDisplay.blit(zheImg,(x,y))
def bullets(x,y,bx,by,bw,bh,color):
while True:
pygame.draw.rect(gameDisplay,color,[bx,by,bw,bh])
def quitgame():
pygame.quit()
quit()
def text_objects(text,font):
textSurface=font.render(text,True,black)
return textSurface,textSurface.get_rect()
def obstacles(obstaclex,obstacley,obstaclew,obstacleh,color):
pygame.draw.rect(gameDisplay,color,[obstaclex,obstacley,obstaclew,obstacleh])
def message_display(text):
largeText=pygame.font.Font("freesansbold.ttf",115)
TextSurf,TextRect=text_objects(text,largeText)
TextRect.center=((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf,TextRect)
pygame.display.update()
time.sleep(1)
game_loop()
def button(msg,x,y,w,h,ic,ac,action=None):
mouse=pygame.mouse.get_pos()
click=pygame.mouse.get_pressed()
if x+w>mouse[0]>x and y+h>mouse[1]>y:
pygame.draw.rect(gameDisplay,ac,(x,y,w,h))
if click[0]==1 and action !=None:
action()
if action=="Play":
game_loop()
elif action=="Quit":
pygame.quit()
quit()
else:
pygame.draw.rect(gameDisplay,ic,(x,y,w,h))
smallText=pygame.font.Font("freesansbold.ttf",20)
textSurf,textRect=text_objects(msg,smallText)
textRect.center=( (x+(w/2)),(y+(h/2)) )
gameDisplay.blit(textSurf,textRect)
largeText=pygame.font.Font("freesansbold.ttf",115)
def game_intro():
intro=True
while intro:
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
largeText=pygame.font.Font("freesansbold.ttf",115)
TextSurf,TextRect=text_objects("Xeon",largeText)
TextRect.center=((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf,TextRect)
xeon(10,100)
button("Play",150,450,100,50,green,bright_green,game_loop)
button("Quit",550,450,100,50,red,bright_red,quitgame)
pygame.display.update()
clock.tick(15)
def game_loop():
x=(display_width*.10)
y=(display_height*0.50)
x_change=0
y_change=0
x+=x_change
y+=y_change
##ALTERNATIVE JUMPING
#xeon_gravity=0.8
#xeon_acc=0.5
obstacle_speed=7
obstacle_height=100
obstacle_width=50
obstacle_startx=random.randrange(300,display_width)
obstacle_starty=-100
##bullets
bullets_height=10
bullets_width=50
bullets_startx=xeon_width
bullets_starty=xeon_width
bullets_speed=0.7
bullets_x_change=0
####KEYS
gameExit=False
while not gameExit:
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
quit()
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_RIGHT:
x_change=-5
if event.key==pygame.K_LEFT:
x_change=+5
if event.key==pygame.K_UP:
y_change=-5
if event.key==pygame.K_DOWN:
bullets=True
pygame.draw.rect(gameDisplay,[bx,by,bw,bh,color])
bullets_x_change=-5
if event.type==pygame.KEYUP:
if event.key==pygame.K_LEFT or event.key==pygame.K_RIGHT:
x_change=0
x+=x_change
y+=y_change
rel_x=x%bgImg.get_rect().width
gameDisplay.blit(bgImg,(rel_x-bgImg.get_rect().width,0))
gameDisplay.blit(bgImg,(rel_x,0))
xeon(x_change,y)
bullets(bullets_startx,bullets_starty,bullets_width,bullets_height,blue)
bullets_starty+=bullets_speed
obstacles(obstacle_startx,obstacle_starty,obstacle_width,obstacle_height,red)
obstacle_starty+=obstacle_speed
if obstacle_starty>display_height:
obstacle_starty=0-obstacle_height
obstacle_startx=random.randrange(300,display_width)
pygame.display.update()
clock.tick(60)
game_intro()
game_loop()
pygame.quit()
quit()
The problem is that you have a local variable named bullets (in the game_loop function) and a global function with the same name. When you call the function bullets() in game_loop, Python thinks you mean the local variable to which you haven't assigned anything yet, so the UnboundLocalError is raised.
Rename the function or the variable to avoid the UnboundLocalError.
Here's an answer with more information.
You're also not passing enough arguments to the bullets function.
i am creating a program for my little brother on pygame where numbers 1-20 will come up in order and each number will be pronounced by mp3 files which i have already created.what i am stuck on now is how to make it so that the sound being played for each number will change as the next button is pressed. i didn't want do it one by one as it will take too long. is there a way to make like a list of all the mp3 sounds together so that the sounds played matches the number showing on the screen.
Sorry it was a long question. This is my first time asking a question and i couldn't find a way to shorten it.
If I understand you correctly, you just need to put the sounds into a list and use the number as the index.
import pygame as pg
pg.init()
SOUNDS = [
pg.mixer.Sound('1.mp3'),
pg.mixer.Sound('2.mp3'),
pg.mixer.Sound('3.mp3'),
]
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
number = 0
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
# Just use the number as the index.
SOUNDS[number].play()
# Increment the number and keep it in the range.
number += 1
number %= len(SOUND_LIST)
screen.fill((30, 30, 30))
print(number)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
main()
pg.quit()
I'm making a game that is for teaching people python, so I'm controlling it by assigning variables, calling functions etc. screeps.com is a similar concept, except it's Javascript, and this is Python. The problem I'm having though, is that I have to use a while loop to refresh the screen, but commands given through the shell can't be executed while the while loop is running. For example, I want to be able to input x += 5, and have the player move to the right. So what I need is a way to refresh the screen at the same time as executing shell commands. Also, I'm using Python 3.4. Thanks in advance.
import pygame
pygame.init()
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('My game')
black = (0,0,0)
white = (255,255,255)
clock = pygame.time.Clock()
crashed = False
pImg = pygame.image.load('player.png')
def car(x,y):
gameDisplay.blit(pImg, (x,y))
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
car_speed = 0
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
gameDisplay.fill(black)
car(x,y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
Why don't you use two threads
1) Thread - Update the display periodically based on inputs
2) Thread - Process inputs and update the shared variables
Threads are the right way to do this. Make sure you import thread at the top.
import thread
consoling = False
def threadedConsole():
global consoling
consoling = True
exec(raw_input(">>> "))
consoling = False
while True:
#Game loop
if not consoling:
thread.start_new_thread(threadedConsole,())